Update decrypt for 4.4

Change-Id: I8d5d7b6a49890e4707d70de8b429563de0d2ad99
diff --git a/crypto/scrypt/Android.mk b/crypto/scrypt/Android.mk
new file mode 100644
index 0000000..7fa96d0
--- /dev/null
+++ b/crypto/scrypt/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH := $(call my-dir)
+
+# Enable to be able to use ALOG* with #include "cutils/log.h"
+#log_c_includes += system/core/include
+#log_shared_libraries := liblog
+
+# These makefiles are here instead of being Android.mk files in the
+# respective crypto, ssl, and apps directories so
+# that import_openssl.sh import won't remove them.
+include $(LOCAL_PATH)/build-config.mk
+include $(LOCAL_PATH)/Scrypt.mk
+
+include $(call all-named-subdir-makefiles,tests)
diff --git a/crypto/scrypt/MODULE_LICENSE_BSD_LIKE b/crypto/scrypt/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crypto/scrypt/MODULE_LICENSE_BSD_LIKE
diff --git a/crypto/scrypt/NOTICE b/crypto/scrypt/NOTICE
new file mode 100644
index 0000000..b0b9311
--- /dev/null
+++ b/crypto/scrypt/NOTICE
@@ -0,0 +1,36 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+
+/*
+ * version 20110505
+ * D. J. Bernstein
+ * Public domain.
+ *
+ * Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
+ */
diff --git a/crypto/scrypt/Scrypt-config.mk b/crypto/scrypt/Scrypt-config.mk
new file mode 100644
index 0000000..bdaeccf
--- /dev/null
+++ b/crypto/scrypt/Scrypt-config.mk
@@ -0,0 +1,105 @@
+# Auto-generated - DO NOT EDIT!
+# To regenerate, edit scrypt.config, then run:
+#     ./import_scrypt.sh import /path/to/scrypt-1.1.6.tar.gz
+#
+# Before including this file, the local Android.mk must define the following
+# variables:
+#
+#    local_c_flags
+#    local_c_includes
+#    local_additional_dependencies
+#
+# This script will define the following variables:
+#
+#    target_c_flags
+#    target_c_includes
+#    target_src_files
+#
+#    host_c_flags
+#    host_c_includes
+#    host_src_files
+#
+
+# Ensure these are empty.
+unknown_arch_c_flags :=
+unknown_arch_src_files :=
+unknown_arch_exclude_files :=
+
+
+common_c_flags :=
+
+common_src_files := \
+  lib/crypto/crypto_scrypt-ref.c \
+
+common_c_includes := \
+  lib/crypto \
+  lib/util \
+
+arm_c_flags :=
+
+arm_src_files :=
+
+arm_exclude_files :=
+
+arm_neon_c_flags :=
+
+arm_neon_src_files := \
+  lib/crypto/crypto_scrypt-neon.c \
+
+arm_neon_exclude_files := \
+  lib/crypto/crypto_scrypt-ref.c \
+
+x86_c_flags :=
+
+x86_src_files := \
+  lib/crypto/crypto_scrypt-sse.c \
+
+x86_exclude_files := \
+  lib/crypto/crypto_scrypt-ref.c \
+
+x86_64_c_flags :=
+
+x86_64_src_files := \
+  lib/crypto/crypto_scrypt-sse.c \
+
+x86_64_exclude_files := \
+  lib/crypto/crypto_scrypt-ref.c \
+
+mips_c_flags :=
+
+mips_src_files :=
+
+mips_exclude_files :=
+
+target_arch := $(TARGET_ARCH)
+ifeq ($(target_arch)-$(TARGET_HAS_BIGENDIAN),mips-true)
+target_arch := unknown_arch
+endif
+
+target_c_flags    := $(common_c_flags) $($(target_arch)_c_flags) $(local_c_flags)
+target_c_includes := $(addprefix bootable/recovery/crypto/scrypt/,$(common_c_includes)) $(local_c_includes)
+target_src_files  := $(common_src_files) $($(target_arch)_src_files)
+target_src_files  := $(filter-out $($(target_arch)_exclude_files), $(target_src_files))
+
+# Hacks for ARM NEON support
+ifeq ($(target_arch),arm)
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+target_c_flags   += $(arm_neon_c_flags)
+target_src_files += $(arm_neon_src_files)
+target_src_files := $(filter-out $(arm_neon_exclude_files), $(target_src_files))
+endif
+endif
+
+ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+host_arch := x86
+else
+host_arch := unknown_arch
+endif
+
+host_c_flags    := $(common_c_flags) $($(host_arch)_c_flags) $(local_c_flags)
+host_c_includes := $(addprefix bootable/recovery/crypto/scrypt/,$(common_c_includes)) $(local_c_includes)
+host_src_files  := $(common_src_files) $($(host_arch)_src_files)
+host_src_files  := $(filter-out $($(host_arch)_exclude_files), $(host_src_files))
+
+local_additional_dependencies += $(LOCAL_PATH)/Scrypt-config.mk
+
diff --git a/crypto/scrypt/Scrypt.mk b/crypto/scrypt/Scrypt.mk
new file mode 100644
index 0000000..45af97f
--- /dev/null
+++ b/crypto/scrypt/Scrypt.mk
@@ -0,0 +1,46 @@
+local_c_flags := -DUSE_OPENSSL_PBKDF2
+
+local_c_includes := $(log_c_includes) external/openssl/include
+
+local_additional_dependencies := $(LOCAL_PATH)/android-config.mk $(LOCAL_PATH)/Scrypt.mk
+
+include $(LOCAL_PATH)/Scrypt-config.mk
+
+#######################################
+# target static library
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/android-config.mk
+
+LOCAL_SHARED_LIBRARIES := $(log_shared_libraries)
+
+# If we're building an unbundled build, don't try to use clang since it's not
+# in the NDK yet. This can be removed when a clang version that is fast enough
+# in the NDK.
+ifeq (,$(TARGET_BUILD_APPS))
+LOCAL_CLANG := true
+else
+LOCAL_SDK_VERSION := 9
+endif
+
+LOCAL_SRC_FILES += $(target_src_files)
+LOCAL_CFLAGS += $(target_c_flags)
+LOCAL_C_INCLUDES += $(target_c_includes)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= libscrypttwrp_static
+LOCAL_ADDITIONAL_DEPENDENCIES := $(local_additional_dependencies)
+include $(BUILD_STATIC_LIBRARY)
+
+########################################
+# host static library
+
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/android-config.mk
+LOCAL_SHARED_LIBRARIES := $(log_shared_libraries)
+LOCAL_SRC_FILES += $(host_src_files)
+LOCAL_CFLAGS += $(host_c_flags)
+LOCAL_C_INCLUDES += $(host_c_includes)
+LOCAL_LDLIBS += -ldl
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= libscrypttwrp_static
+LOCAL_ADDITIONAL_DEPENDENCIES := $(local_additional_dependencies)
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/crypto/scrypt/android-config.mk b/crypto/scrypt/android-config.mk
new file mode 100644
index 0000000..326e113
--- /dev/null
+++ b/crypto/scrypt/android-config.mk
@@ -0,0 +1,16 @@
+#
+# These flags represent the build-time configuration of scrypt for Android
+#
+# The value of $(scrypt_cflags) was pruned from the Makefile generated
+# by running ./configure from import_scrypt.sh.
+#
+# This script performs minor but required patching for the Android build.
+#
+
+LOCAL_CFLAGS += $(scrypt_cflags)
+
+# Add in flags to let config.h be read properly
+LOCAL_CFLAGS += "-DHAVE_CONFIG_H"
+
+# Add clang here when it works on host
+# LOCAL_CLANG := true
diff --git a/crypto/scrypt/build-config.mk b/crypto/scrypt/build-config.mk
new file mode 100644
index 0000000..3d2ab91
--- /dev/null
+++ b/crypto/scrypt/build-config.mk
@@ -0,0 +1,6 @@
+# Auto-generated - DO NOT EDIT!
+# To regenerate, edit scrypt.config, then run:
+#     ./import_scrypt.sh import /path/to/scrypt-1.1.6.tar.gz
+#
+scrypt_cflags := \
+
diff --git a/crypto/scrypt/config.h b/crypto/scrypt/config.h
new file mode 100644
index 0000000..3514f39
--- /dev/null
+++ b/crypto/scrypt/config.h
@@ -0,0 +1,99 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the declaration of `be64enc', and to 0 if you
+   don't. */
+#define HAVE_DECL_BE64ENC 0
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+#define HAVE_LIBRT 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#define HAVE_POSIX_MEMALIGN 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct sysinfo'. */
+#define HAVE_STRUCT_SYSINFO 1
+
+/* Define to 1 if `mem_unit' is member of `struct sysinfo'. */
+#define HAVE_STRUCT_SYSINFO_MEM_UNIT 1
+
+/* Define to 1 if `totalram' is member of `struct sysinfo'. */
+#define HAVE_STRUCT_SYSINFO_TOTALRAM 1
+
+/* Define to 1 if the OS has a hw.usermem sysctl */
+/* #undef HAVE_SYSCTL_HW_USERMEM */
+
+/* Define to 1 if you have the `sysinfo' function. */
+#define HAVE_SYSINFO 1
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+/* #undef HAVE_SYS_ENDIAN_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysinfo.h> header file. */
+#define HAVE_SYS_SYSINFO_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "scrypt"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "scrypt"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "scrypt 1.1.6"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "scrypt"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.1.6"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "1.1.6"
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
diff --git a/crypto/scrypt/import_scrypt.sh b/crypto/scrypt/import_scrypt.sh
new file mode 100755
index 0000000..324eae6
--- /dev/null
+++ b/crypto/scrypt/import_scrypt.sh
@@ -0,0 +1,493 @@
+#!/bin/bash
+#
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# This script imports new versions of scrypt (http://www.tarsnap.com/scrypt/) into the
+# Android source tree.  To run, (1) fetch the appropriate tarball from the scrypt repository,
+# (2) check the gpg/pgp signature, and then (3) run:
+#   ./import_scrypt.sh import scrypt-*.tar.gz
+#
+# IMPORTANT: See README.android for additional details.
+
+# turn on exit on error as well as a warning when it happens
+set -e
+set -x
+trap  "echo WARNING: Exiting on non-zero subprocess exit code" ERR;
+
+# Ensure consistent sorting order / tool output.
+export LANG=C
+export LC_ALL=C
+
+export DIRNAME=$(dirname $0)
+
+function die() {
+  declare -r message=$1
+
+  echo $message
+  exit 1
+}
+
+function usage() {
+  declare -r message=$1
+
+  if [ ! "$message" = "" ]; then
+    echo $message
+  fi
+  echo "Usage:"
+  echo "  ./import_scrypt.sh import </path/to/scrypt-*.tar.gz>"
+  echo "  ./import_scrypt.sh regenerate <patch/*.patch>"
+  echo "  ./import_scrypt.sh generate <patch/*.patch> </path/to/scrypt-*.tar.gz>"
+  exit 1
+}
+
+function main() {
+  if [ ! -d patches ]; then
+    die "scrypt patch directory patches/ not found"
+  fi
+
+  if [ ! -f scrypt.version ]; then
+    die "scrypt.version not found"
+  fi
+
+  source $DIRNAME/scrypt.version
+  if [ "$SCRYPT_VERSION" == "" ]; then
+    die "Invalid scrypt.version; see README.android for more information"
+  fi
+
+  SCRYPT_DIR=scrypt-$SCRYPT_VERSION
+  SCRYPT_DIR_ORIG=$SCRYPT_DIR.orig
+
+  if [ ! -f scrypt.config ]; then
+    die "scrypt.config not found"
+  fi
+
+  source $DIRNAME/scrypt.config
+  if [ "$CONFIGURE_ARGS" == "" -o "$UNNEEDED_SOURCES" == "" -o "$NEEDED_SOURCES" == "" ]; then
+    die "Invalid scrypt.config; see README.android for more information"
+  fi
+
+  declare -r command=$1
+  shift || usage "No command specified. Try import, regenerate, or generate."
+  if [ "$command" = "import" ]; then
+    declare -r tar=$1
+    shift || usage "No tar file specified."
+    import $tar
+  elif [ "$command" = "regenerate" ]; then
+    declare -r patch=$1
+    shift || usage "No patch file specified."
+    [ -d $SCRYPT_DIR ] || usage "$SCRYPT_DIR not found, did you mean to use generate?"
+    [ -d $SCRYPT_DIR_ORIG_ORIG ] || usage "$SCRYPT_DIR_ORIG not found, did you mean to use generate?"
+    regenerate $patch
+  elif [ "$command" = "generate" ]; then
+    declare -r patch=$1
+    shift || usage "No patch file specified."
+    declare -r tar=$1
+    shift || usage "No tar file specified."
+    generate $patch $tar
+  else
+    usage "Unknown command specified $command. Try import, regenerate, or generate."
+  fi
+}
+
+# Compute the name of an assembly source file generated by one of the
+# gen_asm_xxxx() functions below. The logic is the following:
+# - if "$2" is not empty, output it directly
+# - otherwise, change the file extension of $1 from .pl to .S and output
+#   it.
+# Usage: default_asm_file "$1" "$2"
+#     or default_asm_file "$@"
+#
+# $1: generator path (perl script)
+# $2: optional output file name.
+function default_asm_file () {
+  if [ "$2" ]; then
+    echo "$2"
+  else
+    echo "${1%%.pl}.S"
+  fi
+}
+
+# Generate an ARM assembly file.
+# $1: generator (perl script)
+# $2: [optional] output file name
+function gen_asm_arm () {
+  local OUT
+  OUT=$(default_asm_file "$@")
+  perl "$1" > "$OUT"
+}
+
+function gen_asm_mips () {
+  local OUT
+  OUT=$(default_asm_file "$@")
+  # The perl scripts expect to run the target compiler as $CC to determine
+  # the endianess of the target. Setting CC to true is a hack that forces the scripts
+  # to generate little endian output
+  CC=true perl "$1" o32 > "$OUT"
+}
+
+function gen_asm_x86 () {
+  local OUT
+  OUT=$(default_asm_file "$@")
+  perl "$1" elf -fPIC > "$OUT"
+}
+
+function gen_asm_x86_64 () {
+  local OUT
+  OUT=$(default_asm_file "$@")
+  perl "$1" elf "$OUT" > "$OUT"
+}
+
+
+# Filter all items in a list that match a given pattern.
+# $1: space-separated list
+# $2: egrep pattern.
+# Out: items in $1 that match $2
+function filter_by_egrep() {
+  declare -r pattern=$1
+  shift
+  echo "$@" | tr ' ' '\n' | grep -e "$pattern" | tr '\n' ' '
+}
+
+# Sort and remove duplicates in a space-separated list
+# $1: space-separated list
+# Out: new space-separated list
+function uniq_sort () {
+  echo "$@" | tr ' ' '\n' | sort -u | tr '\n' ' '
+}
+
+function print_autogenerated_header() {
+  echo "# Auto-generated - DO NOT EDIT!"
+  echo "# To regenerate, edit scrypt.config, then run:"
+  echo "#     ./import_scrypt.sh import /path/to/scrypt-$SCRYPT_VERSION.tar.gz"
+  echo "#"
+}
+
+function generate_build_config_mk() {
+  ./configure $CONFIGURE_ARGS
+  #rm -f apps/CA.pl.bak crypto/scryptconf.h.bak
+
+  declare -r tmpfile=$(mktemp)
+  (grep -e -D Makefile | grep -v CONFIGURE_ARGS= | grep -v OPTIONS=) > $tmpfile
+
+  declare -r cflags=$(filter_by_egrep "^-D" $(grep -e "^CFLAG=" $tmpfile))
+  declare -r depflags=$(filter_by_egrep "^-D" $(grep -e "^DEPFLAG=" $tmpfile))
+  rm -f $tmpfile
+
+  echo "Generating $(basename $1)"
+  (
+    print_autogenerated_header
+
+    echo "scrypt_cflags := \\"
+    for cflag in $cflags $depflags; do
+      echo "  $cflag \\"
+    done
+    echo ""
+  ) > $1
+}
+
+# Return the value of a computed variable name.
+# E.g.:
+#   FOO=foo
+#   BAR=bar
+#   echo $(var_value FOO_$BAR)   -> prints the value of ${FOO_bar}
+# $1: Variable name
+# Out: variable value
+var_value() {
+  # Note: don't use 'echo' here, because it's sensitive to values
+  #       that begin with an underscore (e.g. "-n")
+  eval printf \"%s\\n\" \$$1
+}
+
+# Same as var_value, but returns sorted output without duplicates.
+# $1: Variable name
+# Out: variable value (if space-separated list, sorted with no duplicates)
+var_sorted_value() {
+  uniq_sort $(var_value $1)
+}
+
+# Print the definition of a given variable in a GNU Make build file.
+# $1: Variable name (e.g. common_src_files)
+# $2+: Variable value (e.g. list of sources)
+print_vardef_in_mk() {
+  declare -r varname=$1
+  shift
+  if [ -z "$1" ]; then
+    echo "$varname :="
+  else
+    echo "$varname := \\"
+    for src; do
+      echo "  $src \\"
+    done
+  fi
+  echo ""
+}
+
+# Same as print_vardef_in_mk, but print a CFLAGS definition from
+# a list of compiler defines.
+# $1: Variable name (e.g. common_c_flags)
+# $2: List of defines (e.g. SCRYPT_NO_DONKEYS ...)
+print_defines_in_mk() {
+  declare -r varname=$1
+  shift
+  if [ -z "$1" ]; then
+    echo "$varname :="
+  else
+    echo "$varname := \\"
+    for def; do
+    echo "  -D$def \\"
+    done
+  fi
+  echo ""
+}
+
+# Generate a configuration file like Scrypt-config.mk
+# This uses variable definitions from scrypt.config to build a config
+# file that can compute the list of target- and host-specific sources /
+# compiler flags for a given component.
+#
+# $1: Target file name.  (e.g. Scrypt-config.mk)
+function generate_config_mk() {
+  declare -r output="$1"
+  declare -r all_archs="arm arm_neon x86 x86_64 mips"
+
+  echo "Generating $(basename $output)"
+  (
+    print_autogenerated_header
+    echo \
+"# Before including this file, the local Android.mk must define the following
+# variables:
+#
+#    local_c_flags
+#    local_c_includes
+#    local_additional_dependencies
+#
+# This script will define the following variables:
+#
+#    target_c_flags
+#    target_c_includes
+#    target_src_files
+#
+#    host_c_flags
+#    host_c_includes
+#    host_src_files
+#
+
+# Ensure these are empty.
+unknown_arch_c_flags :=
+unknown_arch_src_files :=
+unknown_arch_exclude_files :=
+
+"
+    common_defines=$(var_sorted_value SCRYPT_DEFINES)
+    print_defines_in_mk common_c_flags $common_defines
+
+    common_sources=$(var_sorted_value SCRYPT_SOURCES)
+    print_vardef_in_mk common_src_files $common_sources
+
+    common_includes=$(var_sorted_value SCRYPT_INCLUDES)
+    print_vardef_in_mk common_c_includes $common_includes
+
+    for arch in $all_archs; do
+      arch_defines=$(var_sorted_value SCRYPT_DEFINES_${arch})
+      print_defines_in_mk ${arch}_c_flags $arch_defines
+
+      arch_sources=$(var_sorted_value SCRYPT_SOURCES_${arch})
+      print_vardef_in_mk ${arch}_src_files $arch_sources
+
+      arch_exclude_sources=$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch})
+      print_vardef_in_mk ${arch}_exclude_files $arch_exclude_sources
+
+    done
+
+    echo "\
+target_arch := \$(TARGET_ARCH)
+ifeq (\$(target_arch)-\$(TARGET_HAS_BIGENDIAN),mips-true)
+target_arch := unknown_arch
+endif
+
+target_c_flags    := \$(common_c_flags) \$(\$(target_arch)_c_flags) \$(local_c_flags)
+target_c_includes := \$(addprefix external/scrypt/,\$(common_c_includes)) \$(local_c_includes)
+target_src_files  := \$(common_src_files) \$(\$(target_arch)_src_files)
+target_src_files  := \$(filter-out \$(\$(target_arch)_exclude_files), \$(target_src_files))
+
+# Hacks for ARM NEON support
+ifeq (\$(target_arch),arm)
+ifeq (\$(ARCH_ARM_HAVE_NEON),true)
+target_c_flags   += \$(arm_neon_c_flags)
+target_src_files += \$(arm_neon_src_files)
+target_src_files := \$(filter-out \$(arm_neon_exclude_files), \$(target_src_files))
+endif
+endif
+
+ifeq (\$(HOST_OS)-\$(HOST_ARCH),linux-x86)
+host_arch := x86
+else
+host_arch := unknown_arch
+endif
+
+host_c_flags    := \$(common_c_flags) \$(\$(host_arch)_c_flags) \$(local_c_flags)
+host_c_includes := \$(addprefix external/scrypt/,\$(common_c_includes)) \$(local_c_includes)
+host_src_files  := \$(common_src_files) \$(\$(host_arch)_src_files)
+host_src_files  := \$(filter-out \$(\$(host_arch)_exclude_files), \$(host_src_files))
+
+local_additional_dependencies += \$(LOCAL_PATH)/$(basename $output)
+"
+
+  ) > "$output"
+}
+
+function import() {
+  declare -r SCRYPT_SOURCE=$1
+
+  untar $SCRYPT_SOURCE readonly
+  applypatches $SCRYPT_DIR
+
+  cd $SCRYPT_DIR
+
+  generate_build_config_mk ../build-config.mk
+
+  touch ../MODULE_LICENSE_BSD_LIKE
+
+  cd ..
+
+  generate_config_mk Scrypt-config.mk
+
+  # Prune unnecessary sources
+  prune
+
+  NEEDED_SOURCES="$NEEDED_SOURCES"
+  for i in $NEEDED_SOURCES; do
+    echo "Updating $i"
+    rm -r $i
+    mv $SCRYPT_DIR/$i .
+  done
+
+  cleantar
+}
+
+function regenerate() {
+  declare -r patch=$1
+
+  generatepatch $patch
+}
+
+function generate() {
+  declare -r patch=$1
+  declare -r SCRYPT_SOURCE=$2
+
+  untar $SCRYPT_SOURCE
+  applypatches $SCRYPT_DIR_ORIG $patch
+  prune
+
+  for i in $NEEDED_SOURCES; do
+    echo "Restoring $i"
+    rm -r $SCRYPT_DIR/$i
+    cp -rf $i $SCRYPT_DIR/$i
+  done
+
+  generatepatch $patch
+  cleantar
+}
+
+# Find all files in a sub-directory that are encoded in ISO-8859
+# $1: Directory.
+# Out: list of files in $1 that are encoded as ISO-8859.
+function find_iso8859_files() {
+  find $1 -type f -print0 | xargs -0 file | fgrep "ISO-8859" | cut -d: -f1
+}
+
+# Convert all ISO-8859 files in a given subdirectory to UTF-8
+# $1: Directory name
+function convert_iso8859_to_utf8() {
+  declare -r iso_files=$(find_iso8859_files "$1")
+  for iso_file in $iso_files; do
+    iconv --from-code iso-8859-1 --to-code utf-8 $iso_file > $iso_file.tmp
+    rm -f $iso_file
+    mv $iso_file.tmp $iso_file
+  done
+}
+
+function untar() {
+  declare -r SCRYPT_SOURCE=$1
+  declare -r readonly=$2
+
+  # Remove old source
+  cleantar
+
+  # Process new source
+  tar -zxf $SCRYPT_SOURCE
+  convert_iso8859_to_utf8 $SCRYPT_DIR
+  cp -rfP $SCRYPT_DIR $SCRYPT_DIR_ORIG
+  if [ ! -z $readonly ]; then
+    find $SCRYPT_DIR_ORIG -type f -print0 | xargs -0 chmod a-w
+  fi
+}
+
+function prune() {
+  echo "Removing $UNNEEDED_SOURCES"
+  (cd $SCRYPT_DIR_ORIG && rm -rf $UNNEEDED_SOURCES)
+  (cd $SCRYPT_DIR      && rm -r  $UNNEEDED_SOURCES)
+}
+
+function cleantar() {
+  rm -rf $SCRYPT_DIR_ORIG
+  rm -rf $SCRYPT_DIR
+}
+
+function applypatches () {
+  declare -r dir=$1
+  declare -r skip_patch=$2
+
+  cd $dir
+
+  # Apply appropriate patches
+  for i in $SCRYPT_PATCHES; do
+    if [ ! "$skip_patch" = "patches/$i" ]; then
+      echo "Applying patch $i"
+      patch -p1 --merge < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i"
+    else
+      echo "Skiping patch $i"
+    fi
+
+  done
+
+  # Cleanup patch output
+  find . \( -type f -o -type l \) -name "*.orig" -print0 | xargs -0 rm -f
+
+  cd ..
+}
+
+function generatepatch() {
+  declare -r patch=$1
+
+  # Cleanup stray files before generating patch
+  find $SCRYPT_DIR -type f -name "*.orig" -print0 | xargs -0 rm -f
+  find $SCRYPT_DIR -type f -name "*~" -print0 | xargs -0 rm -f
+
+  declare -r variable_name=SCRYPT_PATCHES_`basename $patch .patch | sed s/-/_/`_SOURCES
+  # http://tldp.org/LDP/abs/html/ivr.html
+  eval declare -r sources=\$$variable_name
+  rm -f $patch
+  touch $patch
+  for i in $sources; do
+    LC_ALL=C TZ=UTC0 diff -aup $SCRYPT_DIR_ORIG/$i $SCRYPT_DIR/$i >> $patch && die "ERROR: No diff for patch $path in file $i"
+  done
+  echo "Generated patch $patch"
+  echo "NOTE To make sure there are not unwanted changes from conflicting patches, be sure to review the generated patch."
+}
+
+main $@
diff --git a/crypto/scrypt/lib/README b/crypto/scrypt/lib/README
new file mode 100644
index 0000000..3bb211e
--- /dev/null
+++ b/crypto/scrypt/lib/README
@@ -0,0 +1,6 @@
+The source code under this directory is taken from the client for the
+Tarsnap online backup system (and released under the 2-clause BSD license
+with permission of the author); keeping this code in sync with the Tarsnap
+code is highly desirable and explains why there is some functionality
+included here which is not actually used by the scrypt file encryption
+utility.
diff --git a/crypto/scrypt/lib/crypto/crypto_scrypt-neon-salsa208.h b/crypto/scrypt/lib/crypto/crypto_scrypt-neon-salsa208.h
new file mode 100644
index 0000000..a3b1019
--- /dev/null
+++ b/crypto/scrypt/lib/crypto/crypto_scrypt-neon-salsa208.h
@@ -0,0 +1,120 @@
+/*
+ * version 20110505
+ * D. J. Bernstein
+ * Public domain.
+ *
+ * Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
+ */
+
+#define ROUNDS 8
+static void
+salsa20_8_intrinsic(void * input)
+{
+  int i;
+
+  const uint32x4_t abab = {-1,0,-1,0};
+
+  /*
+   * This is modified since we only have one argument. Usually you'd rearrange
+   * the constant, key, and input bytes, but we just have one linear array to
+   * rearrange which is a bit easier.
+   */
+
+  /*
+   * Change the input to be diagonals as if it's a 4x4 matrix of 32-bit values.
+   */
+  uint32x4_t x0x5x10x15;
+  uint32x4_t x12x1x6x11;
+  uint32x4_t x8x13x2x7;
+  uint32x4_t x4x9x14x3;
+
+  uint32x4_t x0x1x10x11;
+  uint32x4_t x12x13x6x7;
+  uint32x4_t x8x9x2x3;
+  uint32x4_t x4x5x14x15;
+
+  uint32x4_t x0x1x2x3;
+  uint32x4_t x4x5x6x7;
+  uint32x4_t x8x9x10x11;
+  uint32x4_t x12x13x14x15;
+
+  x0x1x2x3 = vld1q_u8((uint8_t *) input);
+  x4x5x6x7 = vld1q_u8(16 + (uint8_t *) input);
+  x8x9x10x11 = vld1q_u8(32 + (uint8_t *) input);
+  x12x13x14x15 = vld1q_u8(48 + (uint8_t *) input);
+
+  x0x1x10x11 = vcombine_u32(vget_low_u32(x0x1x2x3), vget_high_u32(x8x9x10x11));
+  x4x5x14x15 = vcombine_u32(vget_low_u32(x4x5x6x7), vget_high_u32(x12x13x14x15));
+  x8x9x2x3 = vcombine_u32(vget_low_u32(x8x9x10x11), vget_high_u32(x0x1x2x3));
+  x12x13x6x7 = vcombine_u32(vget_low_u32(x12x13x14x15), vget_high_u32(x4x5x6x7));
+
+  x0x5x10x15 = vbslq_u32(abab,x0x1x10x11,x4x5x14x15);
+  x8x13x2x7 = vbslq_u32(abab,x8x9x2x3,x12x13x6x7);
+  x4x9x14x3 = vbslq_u32(abab,x4x5x14x15,x8x9x2x3);
+  x12x1x6x11 = vbslq_u32(abab,x12x13x6x7,x0x1x10x11);
+
+  uint32x4_t start0 = x0x5x10x15;
+  uint32x4_t start1 = x12x1x6x11;
+  uint32x4_t start3 = x4x9x14x3;
+  uint32x4_t start2 = x8x13x2x7;
+
+  /* From here on this should be the same as the SUPERCOP version. */
+
+  uint32x4_t diag0 = start0;
+  uint32x4_t diag1 = start1;
+  uint32x4_t diag2 = start2;
+  uint32x4_t diag3 = start3;
+
+  uint32x4_t a0;
+  uint32x4_t a1;
+  uint32x4_t a2;
+  uint32x4_t a3;
+
+  for (i = ROUNDS;i > 0;i -= 2) {
+    a0 = diag1 + diag0;
+    diag3 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
+    a1 = diag0 + diag3;
+    diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
+    a2 = diag3 + diag2;
+    diag1 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
+    a3 = diag2 + diag1;
+    diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
+
+    diag3 = vextq_u32(diag3,diag3,3);
+    diag2 = vextq_u32(diag2,diag2,2);
+    diag1 = vextq_u32(diag1,diag1,1);
+
+    a0 = diag3 + diag0;
+    diag1 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
+    a1 = diag0 + diag1;
+    diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
+    a2 = diag1 + diag2;
+    diag3 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
+    a3 = diag2 + diag3;
+    diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
+
+    diag1 = vextq_u32(diag1,diag1,3);
+    diag2 = vextq_u32(diag2,diag2,2);
+    diag3 = vextq_u32(diag3,diag3,1);
+  }
+
+  x0x5x10x15 = diag0 + start0;
+  x12x1x6x11 = diag1 + start1;
+  x8x13x2x7 = diag2 + start2;
+  x4x9x14x3 = diag3 + start3;
+
+  x0x1x10x11 = vbslq_u32(abab,x0x5x10x15,x12x1x6x11);
+  x12x13x6x7 = vbslq_u32(abab,x12x1x6x11,x8x13x2x7);
+  x8x9x2x3 = vbslq_u32(abab,x8x13x2x7,x4x9x14x3);
+  x4x5x14x15 = vbslq_u32(abab,x4x9x14x3,x0x5x10x15);
+
+  x0x1x2x3 = vcombine_u32(vget_low_u32(x0x1x10x11),vget_high_u32(x8x9x2x3));
+  x4x5x6x7 = vcombine_u32(vget_low_u32(x4x5x14x15),vget_high_u32(x12x13x6x7));
+  x8x9x10x11 = vcombine_u32(vget_low_u32(x8x9x2x3),vget_high_u32(x0x1x10x11));
+  x12x13x14x15 = vcombine_u32(vget_low_u32(x12x13x6x7),vget_high_u32(x4x5x14x15));
+
+  vst1q_u8((uint8_t *) input,(uint8x16_t) x0x1x2x3);
+  vst1q_u8(16 + (uint8_t *) input,(uint8x16_t) x4x5x6x7);
+  vst1q_u8(32 + (uint8_t *) input,(uint8x16_t) x8x9x10x11);
+  vst1q_u8(48 + (uint8_t *) input,(uint8x16_t) x12x13x14x15);
+}
diff --git a/crypto/scrypt/lib/crypto/crypto_scrypt-neon.c b/crypto/scrypt/lib/crypto/crypto_scrypt-neon.c
new file mode 100644
index 0000000..a3bf052
--- /dev/null
+++ b/crypto/scrypt/lib/crypto/crypto_scrypt-neon.c
@@ -0,0 +1,305 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <machine/cpu-features.h>
+#include <arm_neon.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_OPENSSL_PBKDF2
+#include <openssl/evp.h>
+#else
+#include "sha256.h"
+#endif
+#include "sysendian.h"
+
+#include "crypto_scrypt.h"
+
+#include "crypto_scrypt-neon-salsa208.h"
+
+static void blkcpy(void *, void *, size_t);
+static void blkxor(void *, void *, size_t);
+void crypto_core_salsa208_armneon2(void *);
+static void blockmix_salsa8(uint8x16_t *, uint8x16_t *, uint8x16_t *, size_t);
+static uint64_t integerify(void *, size_t);
+static void smix(uint8_t *, size_t, uint64_t, void *, void *);
+
+static void
+blkcpy(void * dest, void * src, size_t len)
+{
+	uint8x16_t * D = dest;
+	uint8x16_t * S = src;
+	size_t L = len / 16;
+	size_t i;
+
+	for (i = 0; i < L; i++)
+		D[i] = S[i];
+}
+
+static void
+blkxor(void * dest, void * src, size_t len)
+{
+	uint8x16_t * D = dest;
+	uint8x16_t * S = src;
+	size_t L = len / 16;
+	size_t i;
+
+	for (i = 0; i < L; i++)
+		D[i] = veorq_u8(D[i], S[i]);
+}
+
+/**
+ * blockmix_salsa8(B, Y, r):
+ * Compute B = BlockMix_{salsa20/8, r}(B).  The input B must be 128r bytes in
+ * length; the temporary space Y must also be the same size.
+ */
+static void
+blockmix_salsa8(uint8x16_t * Bin, uint8x16_t * Bout, uint8x16_t * X, size_t r)
+{
+	size_t i;
+
+	/* 1: X <-- B_{2r - 1} */
+	blkcpy(X, &Bin[8 * r - 4], 64);
+
+	/* 2: for i = 0 to 2r - 1 do */
+	for (i = 0; i < r; i++) {
+		/* 3: X <-- H(X \xor B_i) */
+		blkxor(X, &Bin[i * 8], 64);
+                salsa20_8_intrinsic((void *) X);
+
+		/* 4: Y_i <-- X */
+		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+		blkcpy(&Bout[i * 4], X, 64);
+
+		/* 3: X <-- H(X \xor B_i) */
+		blkxor(X, &Bin[i * 8 + 4], 64);
+                salsa20_8_intrinsic((void *) X);
+
+		/* 4: Y_i <-- X */
+		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+		blkcpy(&Bout[(r + i) * 4], X, 64);
+	}
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static uint64_t
+integerify(void * B, size_t r)
+{
+	uint8_t * X = (void*)((uintptr_t)(B) + (2 * r - 1) * 64);
+
+	return (le64dec(X));
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; the
+ * temporary storage V must be 128rN bytes in length; the temporary storage
+ * XY must be 256r bytes in length.  The value N must be a power of 2.
+ */
+static void
+smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
+{
+	uint8x16_t * X = XY;
+	uint8x16_t * Y = (void *)((uintptr_t)(XY) + 128 * r);
+        uint8x16_t * Z = (void *)((uintptr_t)(XY) + 256 * r);
+        uint32_t * X32 = (void *)X;
+	uint64_t i, j;
+        size_t k;
+
+	/* 1: X <-- B */
+	blkcpy(X, B, 128 * r);
+
+	/* 2: for i = 0 to N - 1 do */
+	for (i = 0; i < N; i += 2) {
+		/* 3: V_i <-- X */
+		blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
+
+		/* 4: X <-- H(X) */
+		blockmix_salsa8(X, Y, Z, r);
+
+		/* 3: V_i <-- X */
+		blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
+		    Y, 128 * r);
+
+		/* 4: X <-- H(X) */
+		blockmix_salsa8(Y, X, Z, r);
+	}
+
+	/* 6: for i = 0 to N - 1 do */
+	for (i = 0; i < N; i += 2) {
+		/* 7: j <-- Integerify(X) mod N */
+		j = integerify(X, r) & (N - 1);
+
+		/* 8: X <-- H(X \xor V_j) */
+		blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
+		blockmix_salsa8(X, Y, Z, r);
+
+		/* 7: j <-- Integerify(X) mod N */
+		j = integerify(Y, r) & (N - 1);
+
+		/* 8: X <-- H(X \xor V_j) */
+		blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
+		blockmix_salsa8(Y, X, Z, r);
+	}
+
+	/* 10: B' <-- X */
+	blkcpy(B, X, 128 * r);
+}
+
+/**
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf.  The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N
+ * must be a power of 2.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
+    uint8_t * buf, size_t buflen)
+{
+	void * B0, * V0, * XY0;
+	uint8_t * B;
+	uint32_t * V;
+	uint32_t * XY;
+	uint32_t i;
+
+	/* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+		errno = EFBIG;
+		goto err0;
+	}
+#endif
+	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
+		errno = EFBIG;
+		goto err0;
+	}
+	if (((N & (N - 1)) != 0) || (N == 0)) {
+		errno = EINVAL;
+		goto err0;
+	}
+	if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+	    (r > SIZE_MAX / 256) ||
+#endif
+	    (N > SIZE_MAX / 128 / r)) {
+		errno = ENOMEM;
+		goto err0;
+	}
+
+	/* Allocate memory. */
+#ifdef HAVE_POSIX_MEMALIGN
+	if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
+		goto err0;
+	B = (uint8_t *)(B0);
+	if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
+		goto err1;
+	XY = (uint32_t *)(XY0);
+#ifndef MAP_ANON
+	if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
+		goto err2;
+	V = (uint32_t *)(V0);
+#endif
+#else
+	if ((B0 = malloc(128 * r * p + 63)) == NULL)
+		goto err0;
+	B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
+	if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
+		goto err1;
+	XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
+#ifndef MAP_ANON
+	if ((V0 = malloc(128 * r * N + 63)) == NULL)
+		goto err2;
+	V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
+#endif
+#endif
+#ifdef MAP_ANON
+	if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
+#ifdef MAP_NOCORE
+	    MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
+#else
+	    MAP_ANON | MAP_PRIVATE,
+#endif
+	    -1, 0)) == MAP_FAILED)
+		goto err2;
+	V = (uint32_t *)(V0);
+#endif
+
+	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+#ifdef USE_OPENSSL_PBKDF2
+	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
+#else
+	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
+#endif
+
+	/* 2: for i = 0 to p - 1 do */
+	for (i = 0; i < p; i++) {
+		/* 3: B_i <-- MF(B_i, N) */
+		smix(&B[i * 128 * r], r, N, V, XY);
+	}
+
+	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+#ifdef USE_OPENSSL_PBKDF2
+	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
+#else
+	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
+#endif
+
+	/* Free memory. */
+#ifdef MAP_ANON
+	if (munmap(V0, 128 * r * N))
+		goto err2;
+#else
+	free(V0);
+#endif
+	free(XY0);
+	free(B0);
+
+	/* Success! */
+	return (0);
+
+err2:
+	free(XY0);
+err1:
+	free(B0);
+err0:
+	/* Failure! */
+	return (-1);
+}
diff --git a/crypto/scrypt/lib/crypto/crypto_scrypt-ref.c b/crypto/scrypt/lib/crypto/crypto_scrypt-ref.c
new file mode 100644
index 0000000..abe23ea
--- /dev/null
+++ b/crypto/scrypt/lib/crypto/crypto_scrypt-ref.c
@@ -0,0 +1,296 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_OPENSSL_PBKDF2
+#include <openssl/evp.h>
+#else
+#include "sha256.h"
+#endif
+#include "sysendian.h"
+
+#include "crypto_scrypt.h"
+
+static void blkcpy(uint8_t *, uint8_t *, size_t);
+static void blkxor(uint8_t *, uint8_t *, size_t);
+static void salsa20_8(uint8_t[64]);
+static void blockmix_salsa8(uint8_t *, uint8_t *, size_t);
+static uint64_t integerify(uint8_t *, size_t);
+static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *);
+
+static void
+blkcpy(uint8_t * dest, uint8_t * src, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		dest[i] = src[i];
+}
+
+static void
+blkxor(uint8_t * dest, uint8_t * src, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		dest[i] ^= src[i];
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(uint8_t B[64])
+{
+	uint32_t B32[16];
+	uint32_t x[16];
+	size_t i;
+
+	/* Convert little-endian values in. */
+	for (i = 0; i < 16; i++)
+		B32[i] = le32dec(&B[i * 4]);
+
+	/* Compute x = doubleround^4(B32). */
+	for (i = 0; i < 16; i++)
+		x[i] = B32[i];
+	for (i = 0; i < 8; i += 2) {
+#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+		/* Operate on columns. */
+		x[ 4] ^= R(x[ 0]+x[12], 7);  x[ 8] ^= R(x[ 4]+x[ 0], 9);
+		x[12] ^= R(x[ 8]+x[ 4],13);  x[ 0] ^= R(x[12]+x[ 8],18);
+
+		x[ 9] ^= R(x[ 5]+x[ 1], 7);  x[13] ^= R(x[ 9]+x[ 5], 9);
+		x[ 1] ^= R(x[13]+x[ 9],13);  x[ 5] ^= R(x[ 1]+x[13],18);
+
+		x[14] ^= R(x[10]+x[ 6], 7);  x[ 2] ^= R(x[14]+x[10], 9);
+		x[ 6] ^= R(x[ 2]+x[14],13);  x[10] ^= R(x[ 6]+x[ 2],18);
+
+		x[ 3] ^= R(x[15]+x[11], 7);  x[ 7] ^= R(x[ 3]+x[15], 9);
+		x[11] ^= R(x[ 7]+x[ 3],13);  x[15] ^= R(x[11]+x[ 7],18);
+
+		/* Operate on rows. */
+		x[ 1] ^= R(x[ 0]+x[ 3], 7);  x[ 2] ^= R(x[ 1]+x[ 0], 9);
+		x[ 3] ^= R(x[ 2]+x[ 1],13);  x[ 0] ^= R(x[ 3]+x[ 2],18);
+
+		x[ 6] ^= R(x[ 5]+x[ 4], 7);  x[ 7] ^= R(x[ 6]+x[ 5], 9);
+		x[ 4] ^= R(x[ 7]+x[ 6],13);  x[ 5] ^= R(x[ 4]+x[ 7],18);
+
+		x[11] ^= R(x[10]+x[ 9], 7);  x[ 8] ^= R(x[11]+x[10], 9);
+		x[ 9] ^= R(x[ 8]+x[11],13);  x[10] ^= R(x[ 9]+x[ 8],18);
+
+		x[12] ^= R(x[15]+x[14], 7);  x[13] ^= R(x[12]+x[15], 9);
+		x[14] ^= R(x[13]+x[12],13);  x[15] ^= R(x[14]+x[13],18);
+#undef R
+	}
+
+	/* Compute B32 = B32 + x. */
+	for (i = 0; i < 16; i++)
+		B32[i] += x[i];
+
+	/* Convert little-endian values out. */
+	for (i = 0; i < 16; i++)
+		le32enc(&B[4 * i], B32[i]);
+}
+
+/**
+ * blockmix_salsa8(B, Y, r):
+ * Compute B = BlockMix_{salsa20/8, r}(B).  The input B must be 128r bytes in
+ * length; the temporary space Y must also be the same size.
+ */
+static void
+blockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r)
+{
+	uint8_t X[64];
+	size_t i;
+
+	/* 1: X <-- B_{2r - 1} */
+	blkcpy(X, &B[(2 * r - 1) * 64], 64);
+
+	/* 2: for i = 0 to 2r - 1 do */
+	for (i = 0; i < 2 * r; i++) {
+		/* 3: X <-- H(X \xor B_i) */
+		blkxor(X, &B[i * 64], 64);
+		salsa20_8(X);
+
+		/* 4: Y_i <-- X */
+		blkcpy(&Y[i * 64], X, 64);
+	}
+
+	/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+	for (i = 0; i < r; i++)
+		blkcpy(&B[i * 64], &Y[(i * 2) * 64], 64);
+	for (i = 0; i < r; i++)
+		blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static uint64_t
+integerify(uint8_t * B, size_t r)
+{
+	uint8_t * X = &B[(2 * r - 1) * 64];
+
+	return (le64dec(X));
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; the
+ * temporary storage V must be 128rN bytes in length; the temporary storage
+ * XY must be 256r bytes in length.  The value N must be a power of 2.
+ */
+static void
+smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY)
+{
+	uint8_t * X = XY;
+	uint8_t * Y = &XY[128 * r];
+	uint64_t i;
+	uint64_t j;
+
+	/* 1: X <-- B */
+	blkcpy(X, B, 128 * r);
+
+	/* 2: for i = 0 to N - 1 do */
+	for (i = 0; i < N; i++) {
+		/* 3: V_i <-- X */
+		blkcpy(&V[i * (128 * r)], X, 128 * r);
+
+		/* 4: X <-- H(X) */
+		blockmix_salsa8(X, Y, r);
+	}
+
+	/* 6: for i = 0 to N - 1 do */
+	for (i = 0; i < N; i++) {
+		/* 7: j <-- Integerify(X) mod N */
+		j = integerify(X, r) & (N - 1);
+
+		/* 8: X <-- H(X \xor V_j) */
+		blkxor(X, &V[j * (128 * r)], 128 * r);
+		blockmix_salsa8(X, Y, r);
+	}
+
+	/* 10: B' <-- X */
+	blkcpy(B, X, 128 * r);
+}
+
+/**
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf.  The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N
+ * must be a power of 2.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
+    uint8_t * buf, size_t buflen)
+{
+	uint8_t * B;
+	uint8_t * V;
+	uint8_t * XY;
+	uint32_t i;
+
+	/* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+		errno = EFBIG;
+		goto err0;
+	}
+#endif
+	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
+		errno = EFBIG;
+		goto err0;
+	}
+	if (((N & (N - 1)) != 0) || (N == 0)) {
+		errno = EINVAL;
+		goto err0;
+	}
+	if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+	    (r > SIZE_MAX / 256) ||
+#endif
+	    (N > SIZE_MAX / 128 / r)) {
+		errno = ENOMEM;
+		goto err0;
+	}
+
+	/* Allocate memory. */
+	if ((B = malloc(128 * r * p)) == NULL)
+		goto err0;
+	if ((XY = malloc(256 * r)) == NULL)
+		goto err1;
+	if ((V = malloc(128 * r * N)) == NULL)
+		goto err2;
+
+	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+#ifdef USE_OPENSSL_PBKDF2
+	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
+#else
+	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
+#endif
+
+	/* 2: for i = 0 to p - 1 do */
+	for (i = 0; i < p; i++) {
+		/* 3: B_i <-- MF(B_i, N) */
+		smix(&B[i * 128 * r], r, N, V, XY);
+	}
+
+	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+#ifdef USE_OPENSSL_PBKDF2
+	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
+#else
+	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
+#endif
+
+	/* Free memory. */
+	free(V);
+	free(XY);
+	free(B);
+
+	/* Success! */
+	return (0);
+
+err2:
+	free(XY);
+err1:
+	free(B);
+err0:
+	/* Failure! */
+	return (-1);
+}
diff --git a/crypto/scrypt/lib/crypto/crypto_scrypt-sse.c b/crypto/scrypt/lib/crypto/crypto_scrypt-sse.c
new file mode 100644
index 0000000..dd18f29
--- /dev/null
+++ b/crypto/scrypt/lib/crypto/crypto_scrypt-sse.c
@@ -0,0 +1,378 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#include "scrypt_platform.h"
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <emmintrin.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_OPENSSL_PBKDF2
+#include <openssl/evp.h>
+#else
+#include "sha256.h"
+#endif
+#include "sysendian.h"
+
+#include "crypto_scrypt.h"
+
+static void blkcpy(void *, void *, size_t);
+static void blkxor(void *, void *, size_t);
+static void salsa20_8(__m128i *);
+static void blockmix_salsa8(__m128i *, __m128i *, __m128i *, size_t);
+static uint64_t integerify(void *, size_t);
+static void smix(uint8_t *, size_t, uint64_t, void *, void *);
+
+static void
+blkcpy(void * dest, void * src, size_t len)
+{
+	__m128i * D = dest;
+	__m128i * S = src;
+	size_t L = len / 16;
+	size_t i;
+
+	for (i = 0; i < L; i++)
+		D[i] = S[i];
+}
+
+static void
+blkxor(void * dest, void * src, size_t len)
+{
+	__m128i * D = dest;
+	__m128i * S = src;
+	size_t L = len / 16;
+	size_t i;
+
+	for (i = 0; i < L; i++)
+		D[i] = _mm_xor_si128(D[i], S[i]);
+}
+
+/**
+ * salsa20_8(B):
+ * Apply the salsa20/8 core to the provided block.
+ */
+static void
+salsa20_8(__m128i B[4])
+{
+	__m128i X0, X1, X2, X3;
+	__m128i T;
+	size_t i;
+
+	X0 = B[0];
+	X1 = B[1];
+	X2 = B[2];
+	X3 = B[3];
+
+	for (i = 0; i < 8; i += 2) {
+		/* Operate on "columns". */
+		T = _mm_add_epi32(X0, X3);
+		X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7));
+		X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25));
+		T = _mm_add_epi32(X1, X0);
+		X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
+		X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
+		T = _mm_add_epi32(X2, X1);
+		X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13));
+		X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19));
+		T = _mm_add_epi32(X3, X2);
+		X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
+		X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
+
+		/* Rearrange data. */
+		X1 = _mm_shuffle_epi32(X1, 0x93);
+		X2 = _mm_shuffle_epi32(X2, 0x4E);
+		X3 = _mm_shuffle_epi32(X3, 0x39);
+
+		/* Operate on "rows". */
+		T = _mm_add_epi32(X0, X1);
+		X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7));
+		X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25));
+		T = _mm_add_epi32(X3, X0);
+		X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
+		X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
+		T = _mm_add_epi32(X2, X3);
+		X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13));
+		X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19));
+		T = _mm_add_epi32(X1, X2);
+		X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
+		X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
+
+		/* Rearrange data. */
+		X1 = _mm_shuffle_epi32(X1, 0x39);
+		X2 = _mm_shuffle_epi32(X2, 0x4E);
+		X3 = _mm_shuffle_epi32(X3, 0x93);
+	}
+
+	B[0] = _mm_add_epi32(B[0], X0);
+	B[1] = _mm_add_epi32(B[1], X1);
+	B[2] = _mm_add_epi32(B[2], X2);
+	B[3] = _mm_add_epi32(B[3], X3);
+}
+
+/**
+ * blockmix_salsa8(Bin, Bout, X, r):
+ * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r
+ * bytes in length; the output Bout must also be the same size.  The
+ * temporary space X must be 64 bytes.
+ */
+static void
+blockmix_salsa8(__m128i * Bin, __m128i * Bout, __m128i * X, size_t r)
+{
+	size_t i;
+
+	/* 1: X <-- B_{2r - 1} */
+	blkcpy(X, &Bin[8 * r - 4], 64);
+
+	/* 2: for i = 0 to 2r - 1 do */
+	for (i = 0; i < r; i++) {
+		/* 3: X <-- H(X \xor B_i) */
+		blkxor(X, &Bin[i * 8], 64);
+		salsa20_8(X);
+
+		/* 4: Y_i <-- X */
+		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+		blkcpy(&Bout[i * 4], X, 64);
+
+		/* 3: X <-- H(X \xor B_i) */
+		blkxor(X, &Bin[i * 8 + 4], 64);
+		salsa20_8(X);
+
+		/* 4: Y_i <-- X */
+		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
+		blkcpy(&Bout[(r + i) * 4], X, 64);
+	}
+}
+
+/**
+ * integerify(B, r):
+ * Return the result of parsing B_{2r-1} as a little-endian integer.
+ */
+static uint64_t
+integerify(void * B, size_t r)
+{
+	uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);
+
+	return (((uint64_t)(X[13]) << 32) + X[0]);
+}
+
+/**
+ * smix(B, r, N, V, XY):
+ * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length;
+ * the temporary storage V must be 128rN bytes in length; the temporary
+ * storage XY must be 256r + 64 bytes in length.  The value N must be a
+ * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a
+ * multiple of 64 bytes.
+ */
+static void
+smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
+{
+	__m128i * X = XY;
+	__m128i * Y = (void *)((uintptr_t)(XY) + 128 * r);
+	__m128i * Z = (void *)((uintptr_t)(XY) + 256 * r);
+	uint32_t * X32 = (void *)X;
+	uint64_t i, j;
+	size_t k;
+
+	/* 1: X <-- B */
+	for (k = 0; k < 2 * r; k++) {
+		for (i = 0; i < 16; i++) {
+			X32[k * 16 + i] =
+			    le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
+		}
+	}
+
+	/* 2: for i = 0 to N - 1 do */
+	for (i = 0; i < N; i += 2) {
+		/* 3: V_i <-- X */
+		blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
+
+		/* 4: X <-- H(X) */
+		blockmix_salsa8(X, Y, Z, r);
+
+		/* 3: V_i <-- X */
+		blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
+		    Y, 128 * r);
+
+		/* 4: X <-- H(X) */
+		blockmix_salsa8(Y, X, Z, r);
+	}
+
+	/* 6: for i = 0 to N - 1 do */
+	for (i = 0; i < N; i += 2) {
+		/* 7: j <-- Integerify(X) mod N */
+		j = integerify(X, r) & (N - 1);
+
+		/* 8: X <-- H(X \xor V_j) */
+		blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
+		blockmix_salsa8(X, Y, Z, r);
+
+		/* 7: j <-- Integerify(X) mod N */
+		j = integerify(Y, r) & (N - 1);
+
+		/* 8: X <-- H(X \xor V_j) */
+		blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
+		blockmix_salsa8(Y, X, Z, r);
+	}
+
+	/* 10: B' <-- X */
+	for (k = 0; k < 2 * r; k++) {
+		for (i = 0; i < 16; i++) {
+			le32enc(&B[(k * 16 + (i * 5 % 16)) * 4],
+			    X32[k * 16 + i]);
+		}
+	}
+}
+
+/**
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf.  The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int
+crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
+    uint8_t * buf, size_t buflen)
+{
+	void * B0, * V0, * XY0;
+	uint8_t * B;
+	uint32_t * V;
+	uint32_t * XY;
+	uint32_t i;
+
+	/* Sanity-check parameters. */
+#if SIZE_MAX > UINT32_MAX
+	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
+		errno = EFBIG;
+		goto err0;
+	}
+#endif
+	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
+		errno = EFBIG;
+		goto err0;
+	}
+	if (((N & (N - 1)) != 0) || (N == 0)) {
+		errno = EINVAL;
+		goto err0;
+	}
+	if ((r > SIZE_MAX / 128 / p) ||
+#if SIZE_MAX / 256 <= UINT32_MAX
+	    (r > (SIZE_MAX - 64) / 256) ||
+#endif
+	    (N > SIZE_MAX / 128 / r)) {
+		errno = ENOMEM;
+		goto err0;
+	}
+
+	/* Allocate memory. */
+#ifdef HAVE_POSIX_MEMALIGN
+	if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
+		goto err0;
+	B = (uint8_t *)(B0);
+	if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
+		goto err1;
+	XY = (uint32_t *)(XY0);
+#ifndef MAP_ANON
+	if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
+		goto err2;
+	V = (uint32_t *)(V0);
+#endif
+#else
+	if ((B0 = malloc(128 * r * p + 63)) == NULL)
+		goto err0;
+	B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
+	if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
+		goto err1;
+	XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
+#ifndef MAP_ANON
+	if ((V0 = malloc(128 * r * N + 63)) == NULL)
+		goto err2;
+	V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
+#endif
+#endif
+#ifdef MAP_ANON
+	if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
+#ifdef MAP_NOCORE
+	    MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
+#else
+	    MAP_ANON | MAP_PRIVATE,
+#endif
+	    -1, 0)) == MAP_FAILED)
+		goto err2;
+	V = (uint32_t *)(V0);
+#endif
+
+	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
+#ifdef USE_OPENSSL_PBKDF2
+	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
+#else
+	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
+#endif
+
+	/* 2: for i = 0 to p - 1 do */
+	for (i = 0; i < p; i++) {
+		/* 3: B_i <-- MF(B_i, N) */
+		smix(&B[i * 128 * r], r, N, V, XY);
+	}
+
+	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
+#ifdef USE_OPENSSL_PBKDF2
+	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
+#else
+	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
+#endif
+
+	/* Free memory. */
+#ifdef MAP_ANON
+	if (munmap(V0, 128 * r * N))
+		goto err2;
+#else
+	free(V0);
+#endif
+	free(XY0);
+	free(B0);
+
+	/* Success! */
+	return (0);
+
+err2:
+	free(XY0);
+err1:
+	free(B0);
+err0:
+	/* Failure! */
+	return (-1);
+}
diff --git a/crypto/scrypt/lib/crypto/crypto_scrypt.h b/crypto/scrypt/lib/crypto/crypto_scrypt.h
new file mode 100644
index 0000000..f72e1f4
--- /dev/null
+++ b/crypto/scrypt/lib/crypto/crypto_scrypt.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright 2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _CRYPTO_SCRYPT_H_
+#define _CRYPTO_SCRYPT_H_
+
+#include <stdint.h>
+
+/**
+ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
+ * p, buflen) and write the result into buf.  The parameters r, p, and buflen
+ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N
+ * must be a power of 2 greater than 1.
+ *
+ * Return 0 on success; or -1 on error.
+ */
+int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
+    uint32_t, uint32_t, uint8_t *, size_t);
+
+#endif /* !_CRYPTO_SCRYPT_H_ */
diff --git a/crypto/scrypt/lib/util/sysendian.h b/crypto/scrypt/lib/util/sysendian.h
new file mode 100644
index 0000000..62ef31a
--- /dev/null
+++ b/crypto/scrypt/lib/util/sysendian.h
@@ -0,0 +1,140 @@
+/*-
+ * Copyright 2007-2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file was originally written by Colin Percival as part of the Tarsnap
+ * online backup system.
+ */
+#ifndef _SYSENDIAN_H_
+#define _SYSENDIAN_H_
+
+#include "scrypt_platform.h"
+
+/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */
+#if !HAVE_DECL_BE64ENC
+#undef HAVE_SYS_ENDIAN_H
+#endif
+
+#ifdef HAVE_SYS_ENDIAN_H
+
+#include <sys/endian.h>
+
+#else
+
+#include <stdint.h>
+
+static inline uint32_t
+be32dec(const void *pp)
+{
+	const uint8_t *p = (uint8_t const *)pp;
+
+	return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
+	    ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
+}
+
+static inline void
+be32enc(void *pp, uint32_t x)
+{
+	uint8_t * p = (uint8_t *)pp;
+
+	p[3] = x & 0xff;
+	p[2] = (x >> 8) & 0xff;
+	p[1] = (x >> 16) & 0xff;
+	p[0] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+be64dec(const void *pp)
+{
+	const uint8_t *p = (uint8_t const *)pp;
+
+	return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
+	    ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
+	    ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
+	    ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
+}
+
+static inline void
+be64enc(void *pp, uint64_t x)
+{
+	uint8_t * p = (uint8_t *)pp;
+
+	p[7] = x & 0xff;
+	p[6] = (x >> 8) & 0xff;
+	p[5] = (x >> 16) & 0xff;
+	p[4] = (x >> 24) & 0xff;
+	p[3] = (x >> 32) & 0xff;
+	p[2] = (x >> 40) & 0xff;
+	p[1] = (x >> 48) & 0xff;
+	p[0] = (x >> 56) & 0xff;
+}
+
+static inline uint32_t
+le32dec(const void *pp)
+{
+	const uint8_t *p = (uint8_t const *)pp;
+
+	return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
+	    ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
+}
+
+static inline void
+le32enc(void *pp, uint32_t x)
+{
+	uint8_t * p = (uint8_t *)pp;
+
+	p[0] = x & 0xff;
+	p[1] = (x >> 8) & 0xff;
+	p[2] = (x >> 16) & 0xff;
+	p[3] = (x >> 24) & 0xff;
+}
+
+static inline uint64_t
+le64dec(const void *pp)
+{
+	const uint8_t *p = (uint8_t const *)pp;
+
+	return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
+	    ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
+	    ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
+	    ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
+}
+
+static inline void
+le64enc(void *pp, uint64_t x)
+{
+	uint8_t * p = (uint8_t *)pp;
+
+	p[0] = x & 0xff;
+	p[1] = (x >> 8) & 0xff;
+	p[2] = (x >> 16) & 0xff;
+	p[3] = (x >> 24) & 0xff;
+	p[4] = (x >> 32) & 0xff;
+	p[5] = (x >> 40) & 0xff;
+	p[6] = (x >> 48) & 0xff;
+	p[7] = (x >> 56) & 0xff;
+}
+#endif /* !HAVE_SYS_ENDIAN_H */
+
+#endif /* !_SYSENDIAN_H_ */
diff --git a/crypto/scrypt/patches/README b/crypto/scrypt/patches/README
new file mode 100644
index 0000000..353ddbb
--- /dev/null
+++ b/crypto/scrypt/patches/README
@@ -0,0 +1,11 @@
+bionic.patch:
+
+Allows scrypt to compile against bionic.
+
+use_openssl_pbkdf2.patch:
+
+Uses the PBKDF2 function from OpenSSL (it uses accelerated SHA256)
+
+arm-neon.patch:
+
+Adds NEON acceleration for the Salsa20/8 mixing function.
diff --git a/crypto/scrypt/patches/arm-neon.patch b/crypto/scrypt/patches/arm-neon.patch
new file mode 100644
index 0000000..7197f99
--- /dev/null
+++ b/crypto/scrypt/patches/arm-neon.patch
@@ -0,0 +1,437 @@
+diff --git a/lib/crypto/crypto_scrypt-neon-salsa208.h b/lib/crypto/crypto_scrypt-neon-salsa208.h
+new file mode 100644
+index 0000000..a3b1019
+--- /dev/null
++++ b/lib/crypto/crypto_scrypt-neon-salsa208.h
+@@ -0,0 +1,120 @@
++/*
++ * version 20110505
++ * D. J. Bernstein
++ * Public domain.
++ *
++ * Based on crypto_core/salsa208/armneon/core.c from SUPERCOP 20130419
++ */
++
++#define ROUNDS 8
++static void
++salsa20_8_intrinsic(void * input)
++{
++  int i;
++
++  const uint32x4_t abab = {-1,0,-1,0};
++
++  /*
++   * This is modified since we only have one argument. Usually you'd rearrange
++   * the constant, key, and input bytes, but we just have one linear array to
++   * rearrange which is a bit easier.
++   */
++
++  /*
++   * Change the input to be diagonals as if it's a 4x4 matrix of 32-bit values.
++   */
++  uint32x4_t x0x5x10x15;
++  uint32x4_t x12x1x6x11;
++  uint32x4_t x8x13x2x7;
++  uint32x4_t x4x9x14x3;
++
++  uint32x4_t x0x1x10x11;
++  uint32x4_t x12x13x6x7;
++  uint32x4_t x8x9x2x3;
++  uint32x4_t x4x5x14x15;
++
++  uint32x4_t x0x1x2x3;
++  uint32x4_t x4x5x6x7;
++  uint32x4_t x8x9x10x11;
++  uint32x4_t x12x13x14x15;
++
++  x0x1x2x3 = vld1q_u8((uint8_t *) input);
++  x4x5x6x7 = vld1q_u8(16 + (uint8_t *) input);
++  x8x9x10x11 = vld1q_u8(32 + (uint8_t *) input);
++  x12x13x14x15 = vld1q_u8(48 + (uint8_t *) input);
++
++  x0x1x10x11 = vcombine_u32(vget_low_u32(x0x1x2x3), vget_high_u32(x8x9x10x11));
++  x4x5x14x15 = vcombine_u32(vget_low_u32(x4x5x6x7), vget_high_u32(x12x13x14x15));
++  x8x9x2x3 = vcombine_u32(vget_low_u32(x8x9x10x11), vget_high_u32(x0x1x2x3));
++  x12x13x6x7 = vcombine_u32(vget_low_u32(x12x13x14x15), vget_high_u32(x4x5x6x7));
++
++  x0x5x10x15 = vbslq_u32(abab,x0x1x10x11,x4x5x14x15);
++  x8x13x2x7 = vbslq_u32(abab,x8x9x2x3,x12x13x6x7);
++  x4x9x14x3 = vbslq_u32(abab,x4x5x14x15,x8x9x2x3);
++  x12x1x6x11 = vbslq_u32(abab,x12x13x6x7,x0x1x10x11);
++
++  uint32x4_t start0 = x0x5x10x15;
++  uint32x4_t start1 = x12x1x6x11;
++  uint32x4_t start3 = x4x9x14x3;
++  uint32x4_t start2 = x8x13x2x7;
++
++  /* From here on this should be the same as the SUPERCOP version. */
++
++  uint32x4_t diag0 = start0;
++  uint32x4_t diag1 = start1;
++  uint32x4_t diag2 = start2;
++  uint32x4_t diag3 = start3;
++
++  uint32x4_t a0;
++  uint32x4_t a1;
++  uint32x4_t a2;
++  uint32x4_t a3;
++
++  for (i = ROUNDS;i > 0;i -= 2) {
++    a0 = diag1 + diag0;
++    diag3 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
++    a1 = diag0 + diag3;
++    diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
++    a2 = diag3 + diag2;
++    diag1 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
++    a3 = diag2 + diag1;
++    diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
++
++    diag3 = vextq_u32(diag3,diag3,3);
++    diag2 = vextq_u32(diag2,diag2,2);
++    diag1 = vextq_u32(diag1,diag1,1);
++
++    a0 = diag3 + diag0;
++    diag1 ^= vsriq_n_u32(vshlq_n_u32(a0,7),a0,25);
++    a1 = diag0 + diag1;
++    diag2 ^= vsriq_n_u32(vshlq_n_u32(a1,9),a1,23);
++    a2 = diag1 + diag2;
++    diag3 ^= vsriq_n_u32(vshlq_n_u32(a2,13),a2,19);
++    a3 = diag2 + diag3;
++    diag0 ^= vsriq_n_u32(vshlq_n_u32(a3,18),a3,14);
++
++    diag1 = vextq_u32(diag1,diag1,3);
++    diag2 = vextq_u32(diag2,diag2,2);
++    diag3 = vextq_u32(diag3,diag3,1);
++  }
++
++  x0x5x10x15 = diag0 + start0;
++  x12x1x6x11 = diag1 + start1;
++  x8x13x2x7 = diag2 + start2;
++  x4x9x14x3 = diag3 + start3;
++
++  x0x1x10x11 = vbslq_u32(abab,x0x5x10x15,x12x1x6x11);
++  x12x13x6x7 = vbslq_u32(abab,x12x1x6x11,x8x13x2x7);
++  x8x9x2x3 = vbslq_u32(abab,x8x13x2x7,x4x9x14x3);
++  x4x5x14x15 = vbslq_u32(abab,x4x9x14x3,x0x5x10x15);
++
++  x0x1x2x3 = vcombine_u32(vget_low_u32(x0x1x10x11),vget_high_u32(x8x9x2x3));
++  x4x5x6x7 = vcombine_u32(vget_low_u32(x4x5x14x15),vget_high_u32(x12x13x6x7));
++  x8x9x10x11 = vcombine_u32(vget_low_u32(x8x9x2x3),vget_high_u32(x0x1x10x11));
++  x12x13x14x15 = vcombine_u32(vget_low_u32(x12x13x6x7),vget_high_u32(x4x5x14x15));
++
++  vst1q_u8((uint8_t *) input,(uint8x16_t) x0x1x2x3);
++  vst1q_u8(16 + (uint8_t *) input,(uint8x16_t) x4x5x6x7);
++  vst1q_u8(32 + (uint8_t *) input,(uint8x16_t) x8x9x10x11);
++  vst1q_u8(48 + (uint8_t *) input,(uint8x16_t) x12x13x14x15);
++}
+diff --git a/lib/crypto/crypto_scrypt-neon.c b/lib/crypto/crypto_scrypt-neon.c
+new file mode 100644
+index 0000000..a3bf052
+--- /dev/null
++++ b/lib/crypto/crypto_scrypt-neon.c
+@@ -0,0 +1,305 @@
++/*-
++ * Copyright 2009 Colin Percival
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * This file was originally written by Colin Percival as part of the Tarsnap
++ * online backup system.
++ */
++#include "scrypt_platform.h"
++
++#include <machine/cpu-features.h>
++#include <arm_neon.h>
++
++#include <errno.h>
++#include <stdint.h>
++#include <limits.h>
++#include <stdlib.h>
++#include <string.h>
++
++#ifdef USE_OPENSSL_PBKDF2
++#include <openssl/evp.h>
++#else
++#include "sha256.h"
++#endif
++#include "sysendian.h"
++
++#include "crypto_scrypt.h"
++
++#include "crypto_scrypt-neon-salsa208.h"
++
++static void blkcpy(void *, void *, size_t);
++static void blkxor(void *, void *, size_t);
++void crypto_core_salsa208_armneon2(void *);
++static void blockmix_salsa8(uint8x16_t *, uint8x16_t *, uint8x16_t *, size_t);
++static uint64_t integerify(void *, size_t);
++static void smix(uint8_t *, size_t, uint64_t, void *, void *);
++
++static void
++blkcpy(void * dest, void * src, size_t len)
++{
++	uint8x16_t * D = dest;
++	uint8x16_t * S = src;
++	size_t L = len / 16;
++	size_t i;
++
++	for (i = 0; i < L; i++)
++		D[i] = S[i];
++}
++
++static void
++blkxor(void * dest, void * src, size_t len)
++{
++	uint8x16_t * D = dest;
++	uint8x16_t * S = src;
++	size_t L = len / 16;
++	size_t i;
++
++	for (i = 0; i < L; i++)
++		D[i] = veorq_u8(D[i], S[i]);
++}
++
++/**
++ * blockmix_salsa8(B, Y, r):
++ * Compute B = BlockMix_{salsa20/8, r}(B).  The input B must be 128r bytes in
++ * length; the temporary space Y must also be the same size.
++ */
++static void
++blockmix_salsa8(uint8x16_t * Bin, uint8x16_t * Bout, uint8x16_t * X, size_t r)
++{
++	size_t i;
++
++	/* 1: X <-- B_{2r - 1} */
++	blkcpy(X, &Bin[8 * r - 4], 64);
++
++	/* 2: for i = 0 to 2r - 1 do */
++	for (i = 0; i < r; i++) {
++		/* 3: X <-- H(X \xor B_i) */
++		blkxor(X, &Bin[i * 8], 64);
++                salsa20_8_intrinsic((void *) X);
++
++		/* 4: Y_i <-- X */
++		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
++		blkcpy(&Bout[i * 4], X, 64);
++
++		/* 3: X <-- H(X \xor B_i) */
++		blkxor(X, &Bin[i * 8 + 4], 64);
++                salsa20_8_intrinsic((void *) X);
++
++		/* 4: Y_i <-- X */
++		/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
++		blkcpy(&Bout[(r + i) * 4], X, 64);
++	}
++}
++
++/**
++ * integerify(B, r):
++ * Return the result of parsing B_{2r-1} as a little-endian integer.
++ */
++static uint64_t
++integerify(void * B, size_t r)
++{
++	uint8_t * X = (void*)((uintptr_t)(B) + (2 * r - 1) * 64);
++
++	return (le64dec(X));
++}
++
++/**
++ * smix(B, r, N, V, XY):
++ * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; the
++ * temporary storage V must be 128rN bytes in length; the temporary storage
++ * XY must be 256r bytes in length.  The value N must be a power of 2.
++ */
++static void
++smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
++{
++	uint8x16_t * X = XY;
++	uint8x16_t * Y = (void *)((uintptr_t)(XY) + 128 * r);
++        uint8x16_t * Z = (void *)((uintptr_t)(XY) + 256 * r);
++        uint32_t * X32 = (void *)X;
++	uint64_t i, j;
++        size_t k;
++
++	/* 1: X <-- B */
++	blkcpy(X, B, 128 * r);
++
++	/* 2: for i = 0 to N - 1 do */
++	for (i = 0; i < N; i += 2) {
++		/* 3: V_i <-- X */
++		blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
++
++		/* 4: X <-- H(X) */
++		blockmix_salsa8(X, Y, Z, r);
++
++		/* 3: V_i <-- X */
++		blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
++		    Y, 128 * r);
++
++		/* 4: X <-- H(X) */
++		blockmix_salsa8(Y, X, Z, r);
++	}
++
++	/* 6: for i = 0 to N - 1 do */
++	for (i = 0; i < N; i += 2) {
++		/* 7: j <-- Integerify(X) mod N */
++		j = integerify(X, r) & (N - 1);
++
++		/* 8: X <-- H(X \xor V_j) */
++		blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
++		blockmix_salsa8(X, Y, Z, r);
++
++		/* 7: j <-- Integerify(X) mod N */
++		j = integerify(Y, r) & (N - 1);
++
++		/* 8: X <-- H(X \xor V_j) */
++		blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
++		blockmix_salsa8(Y, X, Z, r);
++	}
++
++	/* 10: B' <-- X */
++	blkcpy(B, X, 128 * r);
++}
++
++/**
++ * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
++ * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
++ * p, buflen) and write the result into buf.  The parameters r, p, and buflen
++ * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N
++ * must be a power of 2.
++ *
++ * Return 0 on success; or -1 on error.
++ */
++int
++crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
++    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
++    uint8_t * buf, size_t buflen)
++{
++	void * B0, * V0, * XY0;
++	uint8_t * B;
++	uint32_t * V;
++	uint32_t * XY;
++	uint32_t i;
++
++	/* Sanity-check parameters. */
++#if SIZE_MAX > UINT32_MAX
++	if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
++		errno = EFBIG;
++		goto err0;
++	}
++#endif
++	if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
++		errno = EFBIG;
++		goto err0;
++	}
++	if (((N & (N - 1)) != 0) || (N == 0)) {
++		errno = EINVAL;
++		goto err0;
++	}
++	if ((r > SIZE_MAX / 128 / p) ||
++#if SIZE_MAX / 256 <= UINT32_MAX
++	    (r > SIZE_MAX / 256) ||
++#endif
++	    (N > SIZE_MAX / 128 / r)) {
++		errno = ENOMEM;
++		goto err0;
++	}
++
++	/* Allocate memory. */
++#ifdef HAVE_POSIX_MEMALIGN
++	if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
++		goto err0;
++	B = (uint8_t *)(B0);
++	if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
++		goto err1;
++	XY = (uint32_t *)(XY0);
++#ifndef MAP_ANON
++	if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)
++		goto err2;
++	V = (uint32_t *)(V0);
++#endif
++#else
++	if ((B0 = malloc(128 * r * p + 63)) == NULL)
++		goto err0;
++	B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
++	if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
++		goto err1;
++	XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
++#ifndef MAP_ANON
++	if ((V0 = malloc(128 * r * N + 63)) == NULL)
++		goto err2;
++	V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
++#endif
++#endif
++#ifdef MAP_ANON
++	if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
++#ifdef MAP_NOCORE
++	    MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
++#else
++	    MAP_ANON | MAP_PRIVATE,
++#endif
++	    -1, 0)) == MAP_FAILED)
++		goto err2;
++	V = (uint32_t *)(V0);
++#endif
++
++	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
++#ifdef USE_OPENSSL_PBKDF2
++	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
++#else
++	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
++#endif
++
++	/* 2: for i = 0 to p - 1 do */
++	for (i = 0; i < p; i++) {
++		/* 3: B_i <-- MF(B_i, N) */
++		smix(&B[i * 128 * r], r, N, V, XY);
++	}
++
++	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
++#ifdef USE_OPENSSL_PBKDF2
++	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
++#else
++	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
++#endif
++
++	/* Free memory. */
++#ifdef MAP_ANON
++	if (munmap(V0, 128 * r * N))
++		goto err2;
++#else
++	free(V0);
++#endif
++	free(XY0);
++	free(B0);
++
++	/* Success! */
++	return (0);
++
++err2:
++	free(XY0);
++err1:
++	free(B0);
++err0:
++	/* Failure! */
++	return (-1);
++}
diff --git a/crypto/scrypt/patches/use_openssl_pbkdf2.patch b/crypto/scrypt/patches/use_openssl_pbkdf2.patch
new file mode 100644
index 0000000..0a1328c
--- /dev/null
+++ b/crypto/scrypt/patches/use_openssl_pbkdf2.patch
@@ -0,0 +1,80 @@
+diff --git a/lib/crypto/crypto_scrypt-ref.c b/lib/crypto/crypto_scrypt-ref.c
+index 79a6f8f..60ef2aa 100644
+--- a/lib/crypto/crypto_scrypt-ref.c
++++ b/lib/crypto/crypto_scrypt-ref.c
+@@ -34,7 +34,11 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
++#ifdef USE_OPENSSL_PBKDF2
++#include <openssl/evp.h>
++#else
+ #include "sha256.h"
++#endif
+ #include "sysendian.h"
+ 
+ #include "crypto_scrypt.h"
+@@ -256,7 +260,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+ 		goto err2;
+ 
+ 	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
++#ifdef USE_OPENSSL_PBKDF2
++	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
++#else
+ 	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
++#endif
+ 
+ 	/* 2: for i = 0 to p - 1 do */
+ 	for (i = 0; i < p; i++) {
+@@ -265,7 +273,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+ 	}
+ 
+ 	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
++#ifdef USE_OPENSSL_PBKDF2
++	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
++#else
+ 	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
++#endif
+ 
+ 	/* Free memory. */
+ 	free(V);
+diff --git a/lib/crypto/crypto_scrypt-sse.c b/lib/crypto/crypto_scrypt-sse.c
+index 875175e..dd18f29 100644
+--- a/lib/crypto/crypto_scrypt-sse.c
++++ b/lib/crypto/crypto_scrypt-sse.c
+@@ -37,7 +37,11 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
++#ifdef USE_OPENSSL_PBKDF2
++#include <openssl/evp.h>
++#else
+ #include "sha256.h"
++#endif
+ #include "sysendian.h"
+ 
+ #include "crypto_scrypt.h"
+@@ -332,7 +336,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+ #endif
+ 
+ 	/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
++#ifdef USE_OPENSSL_PBKDF2
++	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, salt, saltlen, 1, EVP_sha256(), p * 128 * r, B);
++#else
+ 	PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
++#endif
+ 
+ 	/* 2: for i = 0 to p - 1 do */
+ 	for (i = 0; i < p; i++) {
+@@ -341,7 +349,11 @@ crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
+ 	}
+ 
+ 	/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
++#ifdef USE_OPENSSL_PBKDF2
++	PKCS5_PBKDF2_HMAC((const char *)passwd, passwdlen, B, p * 128 * r, 1, EVP_sha256(), buflen, buf);
++#else
+ 	PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
++#endif
+ 
+ 	/* Free memory. */
+ #ifdef MAP_ANON
diff --git a/crypto/scrypt/scrypt.config b/crypto/scrypt/scrypt.config
new file mode 100644
index 0000000..3ccb4d0
--- /dev/null
+++ b/crypto/scrypt/scrypt.config
@@ -0,0 +1,94 @@
+CONFIGURE_ARGS="\
+ \
+"
+
+# unneeded directories
+UNNEEDED_SOURCES="\
+lib/scryptenc \
+"
+
+# unneeded files
+UNNEEDED_SOURCES+="\
+config.h.in \
+configure \
+FORMAT \
+main.c \
+Makefile.in \
+scrypt.1 \
+lib/crypto/crypto_aesctr.c \
+lib/crypto/crypto_aesctr.h \
+lib/crypto/crypto_scrypt-nosse.c \
+lib/crypto/sha256.c \
+lib/crypto/sha256.h \
+lib/util/memlimit.c \
+lib/util/memlimit.h \
+lib/util/readpass.c \
+lib/util/readpass.h \
+lib/util/warn.c \
+lib/util/warn.h \
+"
+
+NEEDED_SOURCES="\
+config.h \
+lib \
+scrypt_platform.h \
+"
+
+SCRYPT_INCLUDES="\
+lib/crypto \
+lib/util \
+"
+
+SCRYPT_SOURCES="\
+lib/crypto/crypto_scrypt-ref.c \
+"
+
+SCRYPT_SOURCES_arm="\
+"
+
+SCRYPT_SOURCES_EXCLUDES_arm="\
+"
+
+SCRYPT_SOURCES_arm_neon="\
+lib/crypto/crypto_scrypt-neon.c \
+"
+
+SCRYPT_SOURCES_EXCLUDES_arm_neon="\
+lib/crypto/crypto_scrypt-ref.c \
+"
+
+SCRYPT_SOURCES_mips="\
+"
+
+SCRYPT_SOURCES_EXCLUDES_mips="\
+"
+
+SCRYPT_SOURCES_x86="\
+lib/crypto/crypto_scrypt-sse.c \
+"
+
+SCRYPT_SOURCES_EXCLUDES_x86="\
+lib/crypto/crypto_scrypt-ref.c \
+"
+
+SCRYPT_SOURCES_x86_64="\
+lib/crypto/crypto_scrypt-sse.c \
+"
+
+SCRYPT_SOURCES_EXCLUDES_x86_64="\
+lib/crypto/crypto_scrypt-ref.c \
+"
+
+SCRYPT_PATCHES="\
+use_openssl_pbkdf2.patch \
+arm-neon.patch \
+"
+
+SCRYPT_PATCHES_use_openssl_pbkdf2_SOURCES="\
+lib/crypto/crypto_scrypt-ref.c \
+"
+
+SCRYPT_PATCHES_bionic_SOURCES="\
+lib/crypto/crypto_scrypt-neon.c \
+lib/crypto/crypto_scrypt-neon-salsa208.h \
+"
diff --git a/crypto/scrypt/scrypt.version b/crypto/scrypt/scrypt.version
new file mode 100644
index 0000000..155e260
--- /dev/null
+++ b/crypto/scrypt/scrypt.version
@@ -0,0 +1 @@
+SCRYPT_VERSION=1.1.6
diff --git a/crypto/scrypt/scrypt_platform.h b/crypto/scrypt/scrypt_platform.h
new file mode 100644
index 0000000..5cec236
--- /dev/null
+++ b/crypto/scrypt/scrypt_platform.h
@@ -0,0 +1,12 @@
+#ifndef _SCRYPT_PLATFORM_H_
+#define	_SCRYPT_PLATFORM_H_
+
+#if defined(CONFIG_H_FILE)
+#include CONFIG_H_FILE
+#elif defined(HAVE_CONFIG_H)
+#include "config.h"
+#else
+#error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined.
+#endif
+
+#endif /* !_SCRYPT_PLATFORM_H_ */
diff --git a/crypto/scrypt/tests/Android.mk b/crypto/scrypt/tests/Android.mk
new file mode 100644
index 0000000..b25e1c4
--- /dev/null
+++ b/crypto/scrypt/tests/Android.mk
@@ -0,0 +1,25 @@
+# Build the scrypt unit tests
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_SRC_FILES:= \
+    scrypt_test.cpp
+
+LOCAL_C_INCLUDES := \
+    external/gtest/include \
+    external/scrypt/lib/crypto
+
+LOCAL_SHARED_LIBRARIES := \
+    libcrypto
+
+LOCAL_STATIC_LIBRARIES := \
+    libscrypt_static \
+    libgtest \
+    libgtest_main
+
+LOCAL_MODULE := scrypt_test
+
+include $(BUILD_NATIVE_TEST)
diff --git a/crypto/scrypt/tests/scrypt_test.cpp b/crypto/scrypt/tests/scrypt_test.cpp
new file mode 100644
index 0000000..28334d6
--- /dev/null
+++ b/crypto/scrypt/tests/scrypt_test.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "scrypt_test"
+#include <utils/Log.h>
+#include <utils/UniquePtr.h>
+
+#include <gtest/gtest.h>
+
+#include <fstream>
+#include <iostream>
+
+extern "C" {
+#include <crypto_scrypt.h>
+}
+
+namespace android {
+
+typedef struct scrypt_test_setting_t {
+        const char *pw, *salt;
+        uint32_t Nfactor, rfactor, pfactor;
+} scrypt_test_setting;
+
+static const scrypt_test_setting post_settings[] = {
+        {"", "", 16, 1, 1},
+        {"password", "NaCl", 1024, 8, 16},
+        {"pleaseletmein", "SodiumChloride", 16384, 8, 1},
+        {0, 0, 0, 0, 0}
+};
+
+static const uint8_t post_vectors[][64] = {
+        {0x77,0xd6,0x57,0x62,0x38,0x65,0x7b,0x20,0x3b,0x19,0xca,0x42,0xc1,0x8a,0x04,0x97,
+         0xf1,0x6b,0x48,0x44,0xe3,0x07,0x4a,0xe8,0xdf,0xdf,0xfa,0x3f,0xed,0xe2,0x14,0x42,
+         0xfc,0xd0,0x06,0x9d,0xed,0x09,0x48,0xf8,0x32,0x6a,0x75,0x3a,0x0f,0xc8,0x1f,0x17,
+         0xe8,0xd3,0xe0,0xfb,0x2e,0x0d,0x36,0x28,0xcf,0x35,0xe2,0x0c,0x38,0xd1,0x89,0x06},
+        {0xfd,0xba,0xbe,0x1c,0x9d,0x34,0x72,0x00,0x78,0x56,0xe7,0x19,0x0d,0x01,0xe9,0xfe,
+         0x7c,0x6a,0xd7,0xcb,0xc8,0x23,0x78,0x30,0xe7,0x73,0x76,0x63,0x4b,0x37,0x31,0x62,
+         0x2e,0xaf,0x30,0xd9,0x2e,0x22,0xa3,0x88,0x6f,0xf1,0x09,0x27,0x9d,0x98,0x30,0xda,
+         0xc7,0x27,0xaf,0xb9,0x4a,0x83,0xee,0x6d,0x83,0x60,0xcb,0xdf,0xa2,0xcc,0x06,0x40},
+        {0x70,0x23,0xbd,0xcb,0x3a,0xfd,0x73,0x48,0x46,0x1c,0x06,0xcd,0x81,0xfd,0x38,0xeb,
+         0xfd,0xa8,0xfb,0xba,0x90,0x4f,0x8e,0x3e,0xa9,0xb5,0x43,0xf6,0x54,0x5d,0xa1,0xf2,
+         0xd5,0x43,0x29,0x55,0x61,0x3f,0x0f,0xcf,0x62,0xd4,0x97,0x05,0x24,0x2a,0x9a,0xf9,
+         0xe6,0x1e,0x85,0xdc,0x0d,0x65,0x1e,0x40,0xdf,0xcf,0x01,0x7b,0x45,0x57,0x58,0x87},
+};
+
+class ScryptTest : public ::testing::Test {
+};
+
+TEST_F(ScryptTest, TestVectors) {
+    int i;
+
+    for (i = 0; post_settings[i].pw != NULL; i++) {
+        uint8_t output[64];
+
+        scrypt_test_setting_t s = post_settings[i];
+        ASSERT_EQ(0,
+                crypto_scrypt((const uint8_t*) s.pw, strlen(s.pw), (const uint8_t*) s.salt,
+                        strlen(s.salt), s.Nfactor, s.rfactor, s.pfactor, output, sizeof(output)))
+                << "scrypt call should succeed for " << i << "; error=" << strerror(errno);
+        ASSERT_EQ(0, memcmp(post_vectors[i], output, sizeof(output)))
+                << "Should match expected output";
+    }
+}
+
+}