Showing preview only (412K chars total). Download the full file or copy to clipboard to get everything.
Repository: Tarsnap/scrypt
Branch: master
Commit: 7c7ba6160560
Files: 144
Total size: 376.5 KB
Directory structure:
gitextract_hxdnsnbb/
├── .autom4te.cfg
├── .github/
│ └── workflows/
│ ├── compile.yml
│ └── coverity-scan.yml
├── .gitignore
├── BUILDING
├── COPYRIGHT
├── FORMAT
├── Makefile.am
├── README.md
├── STYLE
├── configure.ac
├── get-version.sh
├── lib/
│ ├── README
│ ├── crypto/
│ │ ├── crypto_scrypt-ref.c
│ │ ├── crypto_scrypt_smix.c
│ │ ├── crypto_scrypt_smix.h
│ │ ├── crypto_scrypt_smix_sse2.c
│ │ └── crypto_scrypt_smix_sse2.h
│ ├── scryptenc/
│ │ ├── scryptenc.c
│ │ ├── scryptenc.h
│ │ ├── scryptenc_cpuperf.c
│ │ ├── scryptenc_cpuperf.h
│ │ ├── scryptenc_print_error.c
│ │ └── scryptenc_print_error.h
│ └── util/
│ ├── passphrase_entry.c
│ └── passphrase_entry.h
├── lib-platform/
│ ├── crypto/
│ │ ├── crypto_scrypt.c
│ │ └── crypto_scrypt.h
│ ├── platform.h
│ └── util/
│ ├── memlimit.c
│ └── memlimit.h
├── libcperciva/
│ ├── POSIX/
│ │ ├── README
│ │ ├── posix-abstract-declarator.c
│ │ ├── posix-cflags.sh
│ │ ├── posix-clock_gettime.c
│ │ ├── posix-clock_realtime.c
│ │ ├── posix-inet-addrstrlen.c
│ │ ├── posix-inet6-addrstrlen.c
│ │ ├── posix-l.sh
│ │ ├── posix-msg_nosignal.c
│ │ ├── posix-restrict.c
│ │ ├── posix-stat-st_mtim.c
│ │ └── posix-trivial.c
│ ├── alg/
│ │ ├── sha256.c
│ │ ├── sha256.h
│ │ ├── sha256_arm.c
│ │ ├── sha256_arm.h
│ │ ├── sha256_shani.c
│ │ ├── sha256_shani.h
│ │ ├── sha256_sse2.c
│ │ └── sha256_sse2.h
│ ├── apisupport/
│ │ └── Build/
│ │ ├── apisupport-LIBCRYPTO-LOW_LEVEL_AES.c
│ │ ├── apisupport-NONPOSIX-MEMLIMIT.c
│ │ └── apisupport.sh
│ ├── cpusupport/
│ │ ├── Build/
│ │ │ ├── cpusupport-ARM-AES.c
│ │ │ ├── cpusupport-ARM-SHA256.c
│ │ │ ├── cpusupport-HWCAP-ELF_AUX_INFO.c
│ │ │ ├── cpusupport-HWCAP-GETAUXVAL.c
│ │ │ ├── cpusupport-X86-AESNI.c
│ │ │ ├── cpusupport-X86-CPUID.c
│ │ │ ├── cpusupport-X86-CPUID_COUNT.c
│ │ │ ├── cpusupport-X86-RDRAND.c
│ │ │ ├── cpusupport-X86-SHANI.c
│ │ │ ├── cpusupport-X86-SSE2.c
│ │ │ ├── cpusupport-X86-SSSE3.c
│ │ │ └── cpusupport.sh
│ │ ├── cpusupport.h
│ │ ├── cpusupport_arm_aes.c
│ │ ├── cpusupport_arm_sha256.c
│ │ ├── cpusupport_x86_aesni.c
│ │ ├── cpusupport_x86_rdrand.c
│ │ ├── cpusupport_x86_shani.c
│ │ ├── cpusupport_x86_sse2.c
│ │ └── cpusupport_x86_ssse3.c
│ ├── crypto/
│ │ ├── crypto_aes.c
│ │ ├── crypto_aes.h
│ │ ├── crypto_aes_aesni.c
│ │ ├── crypto_aes_aesni.h
│ │ ├── crypto_aes_aesni_m128i.h
│ │ ├── crypto_aes_arm.c
│ │ ├── crypto_aes_arm.h
│ │ ├── crypto_aes_arm_u8.h
│ │ ├── crypto_aesctr.c
│ │ ├── crypto_aesctr.h
│ │ ├── crypto_aesctr_aesni.c
│ │ ├── crypto_aesctr_aesni.h
│ │ ├── crypto_aesctr_arm.c
│ │ ├── crypto_aesctr_arm.h
│ │ ├── crypto_aesctr_shared.c
│ │ ├── crypto_entropy.c
│ │ ├── crypto_entropy.h
│ │ ├── crypto_entropy_rdrand.c
│ │ ├── crypto_entropy_rdrand.h
│ │ ├── crypto_verify_bytes.c
│ │ └── crypto_verify_bytes.h
│ └── util/
│ ├── align_ptr.h
│ ├── asprintf.c
│ ├── asprintf.h
│ ├── entropy.c
│ ├── entropy.h
│ ├── getopt.c
│ ├── getopt.h
│ ├── humansize.c
│ ├── humansize.h
│ ├── insecure_memzero.c
│ ├── insecure_memzero.h
│ ├── monoclock.c
│ ├── monoclock.h
│ ├── parsenum.h
│ ├── readpass.c
│ ├── readpass.h
│ ├── readpass_file.c
│ ├── sysendian.h
│ ├── warnp.c
│ └── warnp.h
├── libscrypt-kdf/
│ └── scrypt-kdf.h
├── m4/
│ ├── check_darwin_paths.m4
│ ├── check_disable_compiler_warnings.m4
│ ├── check_libcperciva_posix.m4
│ ├── check_memlimit_support.m4
│ ├── check_posix_sh.m4
│ └── check_solaris_c99.m4
├── main.c
├── release-tools/
│ ├── create-sign-tarball.sh
│ └── mktarball.sh
├── scrypt.1
└── tests/
├── 01-known-values.sh
├── 02-decrypt-reference-file.sh
├── 03-encrypt-decrypt-file.sh
├── 04-force-resources.sh
├── 05-system-scrypt-encrypt-decrypt.sh
├── 06-decrypt-fail.sh
├── 07-passphrase-env.sh
├── 08-passphrase-file.sh
├── 09-explicit-params.sh
├── libscrypt-kdf/
│ └── sample-libscrypt-kdf.c
├── shared_test_functions.sh
├── shared_valgrind_functions.sh
├── test_scrypt.sh
├── valgrind/
│ └── potential-memleaks.c
└── verify-strings/
├── test_scrypt.c
├── test_scrypt.good
├── test_scrypt_good.enc
└── test_scrypt_small.good
================================================
FILE CONTENTS
================================================
================================================
FILE: .autom4te.cfg
================================================
## ------------------ ##
## User Preferences. ##
## ------------------ ##
begin-language: "Autoconf-without-aclocal-m4"
args: --no-cache
end-language: "Autoconf-without-aclocal-m4"
================================================
FILE: .github/workflows/compile.yml
================================================
name: Compile & test
# Run whenever we push to any branch without a "/", other than [coverity-scan].
on:
push:
branches:
- '*'
- '!coverity-scan'
env:
# Shared variables amongst all projects / platforms / compilers.
CFLAGS_ALL: -std=c99 -O2
CFLAGS_CLANG_LIBCPERCIVA: -Wall -Wextra -Werror -Weverything
-Wno-#warnings -Wno-pedantic -Wno-padded
-Wno-format-nonliteral
-Wno-disabled-macro-expansion
-Wno-missing-noreturn
-Wno-unused-macros
-Wno-documentation-unknown-command
-Wno-implicit-fallthrough
CFLAGS_GCC_LIBCPERCIVA: -Wall -Wextra -Werror -Wpedantic
-pedantic-errors -Wno-clobbered
# Variables for specific projects / platforms / compilers.
CFLAGS_CLANG_PROJECT: -Wno-reserved-id-macro
CFLAGS_GCC_PROJECT: -Wno-cpp
CFLAGS_OSX: -Wno-poison-system-directories
-Wno-deprecated-declarations
LDFLAGS_OSX:
jobs:
Ubuntu:
name: Ubuntu
runs-on: ubuntu-22.04
steps:
- name: Update apt-get
run: sudo apt-get update
- name: Install software
run: sudo apt-get install --no-install-recommends
valgrind autoconf-archive
- name: Checkout code
uses: actions/checkout@v4
- name: Run autoreconf
run:
autoreconf -i
- name: Configure with clang
env:
CC: clang-13
CFLAGS: ${{ env.CFLAGS_ALL }}
run: ./configure
- name: Compile with clang
env:
CC: clang-13
CFLAGS: ${{ env.CFLAGS_ALL }}
${{ env.CFLAGS_CLANG_LIBCPERCIVA }}
${{ env.CFLAGS_CLANG_PROJECT }}
# make(1) doesn't automatically override the CFLAGS macro set inside
# Makefile with the environment variable.
run: make CFLAGS="${{ env.CFLAGS }}"
- name: Test clang binaries
env:
USE_VALGRIND: 1
run: make test VERBOSE=1
- name: Clean
run: make clean
- name: Configure with gcc
env:
CC: gcc-10
CFLAGS: ${{ env.CFLAGS_ALL }}
run: ./configure
- name: Compile with gcc
env:
CC: gcc-10
CFLAGS: ${{ env.CFLAGS_ALL }}
${{ env.CFLAGS_GCC_LIBCPERCIVA }}
${{ env.CFLAGS_GCC_PROJECT }}
# make(1) doesn't automatically override the CFLAGS macro set inside
# Makefile with the environment variable.
run: make CFLAGS="${{ env.CFLAGS }}"
- name: Test gcc binaries
env:
USE_VALGRIND: 1
run: make test VERBOSE=1
- name: Check for untracked files
run: test -z "$(git status --porcelain=v1)"
macOS:
name: macOS
runs-on: macOS-14
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install software
run: brew install automake libtool
- name: Run autoreconf
run: autoreconf -i
- name: Configure with clang
env:
CC: clang
CFLAGS: ${{ env.CFLAGS_ALL }}
${{ env.CFLAGS_OSX }}
LDFLAGS: ${{ env.LDFLAGS_OSX }}
run: ./configure
- name: Compile with clang
env:
CC: clang
CFLAGS: ${{ env.CFLAGS_ALL }}
${{ env.CFLAGS_CLANG_LIBCPERCIVA }}
${{ env.CFLAGS_CLANG_PROJECT }}
${{ env.CFLAGS_OSX }}
LDFLAGS: ${{ env.LDFLAGS_OSX }}
# make(1) doesn't automatically override the CFLAGS macro set inside
# Makefile with the environment variable.
run: make CFLAGS="${{ env.CFLAGS }}"
- name: Test clang binaries
run: make test VERBOSE=1
================================================
FILE: .github/workflows/coverity-scan.yml
================================================
name: coverity-scan
# Only trigger on the [coverity-scan] branch.
on:
push:
branches:
- coverity-scan
# Run coverity scan. For now, we're re-using the Travis-CI script, which
# requires us to fake a TRAVIS_BRANCH environment variable.
jobs:
coverity-scan:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run autoreconf
run: autoreconf -i
- name: Configure with the default compiler
run: ./configure
- name: Coverity scan
env:
COVERITY_SCAN_PROJECT_NAME: ${{ github.repository }}
COVERITY_SCAN_BRANCH_PATTERN: coverity-scan
COVERITY_SCAN_NOTIFICATION_EMAIL: cperciva@tarsnap.com
COVERITY_SCAN_BUILD_COMMAND: make all
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
TRAVIS_BRANCH: coverity-scan
run: curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash || true
================================================
FILE: .gitignore
================================================
# Development tools
/devel-tools/
# Result of autoreconf -i
/Makefile.in
/aclocal.m4
/config.aux/
/config.h.in
/config.h.in~
/configure
/configure~
# m4/ directory: only keep certain files
/m4/*
!/m4/check_darwin_paths.m4
!/m4/check_disable_compiler_warnings.m4
!/m4/check_libcperciva_posix.m4
!/m4/check_memlimit_support.m4
!/m4/check_posix_sh.m4
!/m4/check_solaris_c99.m4
# Standard out-of-tree build directory
/build/
# In-tree configure
.deps/
/Makefile
/config.h
/config.log
/config.status
/libtool
/stamp-h1
# In-tree build, only top-level
/apisupport-config.h
/cpusupport-config.h
# In-tree build, all directories
.dirstamp
.libs/
*.la
*.lo
*.o
# In-tree binaries
/scrypt
/tests/libscrypt-kdf/sample-libscrypt-kdf
/tests/valgrind/potential-memleaks
/tests/verify-strings/test_scrypt
# In-tree test output
/tests-output/
/tests-valgrind/
================================================
FILE: BUILDING
================================================
Installing
----------
We strongly recommend that people use the latest official release tarball on
https://www.tarsnap.com/scrypt.html, and build with:
./configure
make
make install
Official scrypt tarball releases should build and run on any IEEE Std 1003.1
(POSIX) compliant system which
1. Includes the Software Development Utilities option,
2. Has OpenSSL available via -lcrypto and #include <openssl/foo>, and
3. Provides /dev/urandom.
libscrypt-kdf
-------------
To install the development library, run:
./configure --enable-libscrypt-kdf
make install
Platform-specific notes
-----------------------
- when cross-compiling, runtime POSIX compatibility checks are disabled.
For more information, see libcperciva/POSIX/README.
- On OS X, the version of OpenSSL included with the operating
system is outdated (0.9.8) and deprecated, and it is recommended
that scrypt be built with an updated version of OpenSSL. On OS X
10.11 "El Capitan" and higher, OpenSSL was removed entirely. After
installing a newer version of OpenSSL, use
CPPFLAGS="-I /path/to/openssl/headers"
LDFLAGS="-L /path/to/openssl/lib"
to build scrypt.
In particular, if you installed OpenSSL using homebrew, you may
pass the relevant directories directly to ./configure:
./configure CPPFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib"
Alternatively, you may wish to add these lines to your $HOME/.profile file:
export CPPFLAGS="-I/usr/local/opt/openssl/include $CPPFLAGS"
export LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS"
and then close & re-open your terminal window.
Building from git
-----------------
For experimental development from git, build with:
autoreconf -i
./configure
make
- You must have automake 1.11.2 or higher, and libtool.
- In order to support the `AX_CFLAGS_WARN_ALL` autoconf directive, you will
need to install the autoconf archive. On Debian systems, use the
`autoconf-archive` package; on FreeBSD, use `devel/autoconf-archive`.
- Ignore this message if it appears:
aclocal: warning: couldn't open directory 'm4': No such file or directory
================================================
FILE: COPYRIGHT
================================================
The included code and documentation ("scrypt") is distributed under the
following terms:
Copyright 2005-2025 Colin Percival. All rights reserved.
Copyright 2011-2025 Tarsnap Backup Inc. All rights reserved.
Copyright 2014 Sean Kelly. 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.
================================================
FILE: FORMAT
================================================
scrypt encrypted data format
----------------------------
offset length
0 6 "scrypt"
6 1 scrypt data file version number (== 0)
7 1 log2(N) (must be between 1 and 63 inclusive)
8 4 r (big-endian integer; must satisfy r * p < 2^30)
12 4 p (big-endian integer; must satisfy r * p < 2^30)
16 32 salt
48 16 first 16 bytes of SHA256(bytes 0 .. 47)
64 32 HMAC-SHA256(bytes 0 .. 63)
96 X data xor AES256-CTR key stream generated with nonce == 0
96+X 32 HMAC-SHA256(bytes 0 .. 96 + (X - 1))
AES256-CTR is computed with a 256-bit AES key key_enc, and HMAC-SHA256 is
computed with a 256-bit key key_hmac, where
scrypt(password, salt, N, r, p, 64) == [key_enc][key_hmac]
================================================
FILE: Makefile.am
================================================
bin_PROGRAMS= scrypt
noinst_PROGRAMS= \
tests/valgrind/potential-memleaks \
tests/verify-strings/test_scrypt
dist_man_MANS=$(scrypt_man_MANS)
ACLOCAL_AMFLAGS= -I m4
# These files fulfill the crypto_scrypt() function, with the exception of
# libcperciva/alg/sha256_shani.c
# lib/crypto/crypto_scrypt_smix_sse2.c
# which require special compiler flags and are thus compiled as separate
# libraries. See test_scrypt for an example.
crypto_scrypt_files= \
lib-platform/crypto/crypto_scrypt.c \
lib-platform/crypto/crypto_scrypt.h \
lib-platform/platform.h \
lib/crypto/crypto_scrypt_smix.c \
lib/crypto/crypto_scrypt_smix.h \
lib/crypto/crypto_scrypt_smix_sse2.h \
libcperciva/alg/sha256.c \
libcperciva/alg/sha256.h \
libcperciva/alg/sha256_arm.h \
libcperciva/alg/sha256_shani.h \
libcperciva/alg/sha256_sse2.h \
libcperciva/cpusupport/cpusupport.h \
libcperciva/util/insecure_memzero.c \
libcperciva/util/insecure_memzero.h \
libcperciva/util/warnp.c \
libcperciva/util/warnp.h
# Don't include crypto_aesctr_shared.c in this list, as it should be included
# directly into other translation unit(s), and not compiled on its own.
scrypt_SOURCES= \
$(crypto_scrypt_files) \
lib-platform/util/memlimit.h \
lib/scryptenc/scryptenc.c \
lib/scryptenc/scryptenc.h \
lib/scryptenc/scryptenc_cpuperf.c \
lib/scryptenc/scryptenc_cpuperf.h \
lib/scryptenc/scryptenc_print_error.c \
lib/scryptenc/scryptenc_print_error.h \
lib/util/passphrase_entry.c \
lib/util/passphrase_entry.h \
libcperciva/crypto/crypto_aes.h \
libcperciva/crypto/crypto_aes_aesni.h \
libcperciva/crypto/crypto_aes_aesni_m128i.h \
libcperciva/crypto/crypto_aes_arm.h \
libcperciva/crypto/crypto_aes_arm_u8.h \
libcperciva/crypto/crypto_aesctr.c \
libcperciva/crypto/crypto_aesctr.h \
libcperciva/crypto/crypto_aesctr_aesni.h \
libcperciva/crypto/crypto_aesctr_arm.h \
libcperciva/crypto/crypto_entropy.c \
libcperciva/crypto/crypto_entropy.h \
libcperciva/crypto/crypto_entropy_rdrand.h \
libcperciva/crypto/crypto_verify_bytes.c \
libcperciva/crypto/crypto_verify_bytes.h \
libcperciva/util/align_ptr.h \
libcperciva/util/asprintf.c \
libcperciva/util/asprintf.h \
libcperciva/util/entropy.c \
libcperciva/util/entropy.h \
libcperciva/util/getopt.c \
libcperciva/util/getopt.h \
libcperciva/util/humansize.c \
libcperciva/util/humansize.h \
libcperciva/util/monoclock.c \
libcperciva/util/monoclock.h \
libcperciva/util/parsenum.h \
libcperciva/util/readpass.c \
libcperciva/util/readpass.h \
libcperciva/util/readpass_file.c \
libcperciva/util/sysendian.h \
main.c
AM_CPPFLAGS= \
-I$(srcdir)/lib \
-I$(srcdir)/lib-platform \
-I$(srcdir)/lib-platform/crypto \
-I$(srcdir)/lib-platform/util \
-I$(srcdir)/lib/crypto \
-I$(srcdir)/lib/scryptenc \
-I$(srcdir)/lib/util \
-I$(srcdir)/libcperciva/alg \
-I$(srcdir)/libcperciva/cpusupport \
-I$(srcdir)/libcperciva/crypto \
-I$(srcdir)/libcperciva/util \
-DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" \
-DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" \
-D_POSIX_C_SOURCE=200809L \
-D_XOPEN_SOURCE=700 \
${CFLAGS_POSIX}
# Each "paragraph" denotes a rank of dependencies. Libraries without
# dependencies go in the bottom paragraph; a library which depends on one of
# those goes in the preceeding paragraph; and so on.
scrypt_LDADD= \
libcperciva_crypto_aes.la \
\
libcperciva_aesni.la \
libcperciva_arm_aes.la \
libcperciva_arm_sha256.la \
libcperciva_cpusupport_detect.la \
libcperciva_rdrand.la \
libcperciva_shani.la \
libscrypt_memlimit.la \
libscrypt_sse2.la \
${LDADD_POSIX}
scrypt_man_MANS= scrypt.1
# apisupport needs to access post-configure info: lib-platform/platform.h,
# config.h, and -DHAVE_CONFIG_H.
apisupport-config.h:
( export CC="${CC}"; export CFLAGS="-I${top_srcdir}/lib-platform -I${builddir} ${DEFS} ${CFLAGS}"; command -p sh $(srcdir)/libcperciva/apisupport/Build/apisupport.sh "$$PATH") > apisupport-config.h.tmp && command -p mv apisupport-config.h.tmp apisupport-config.h
cpusupport-config.h:
( export CC="${CC}"; export CFLAGS="${CFLAGS}"; command -p sh $(srcdir)/libcperciva/cpusupport/Build/cpusupport.sh "$$PATH") > cpusupport-config.h.tmp && command -p mv cpusupport-config.h.tmp cpusupport-config.h
BUILT_SOURCES= \
apisupport-config.h \
cpusupport-config.h
CLEANFILES= \
apisupport-config.h \
apisupport-config.h.tmp \
cpusupport-config.h \
cpusupport-config.h.tmp
# Libraries from libcperciva code.
noinst_LTLIBRARIES= libcperciva_aesni.la
libcperciva_aesni_la_SOURCES= \
libcperciva/crypto/crypto_aes_aesni.c \
libcperciva/crypto/crypto_aesctr_aesni.c
nodist_libcperciva_aesni_la_SOURCES= cpusupport-config.h
libcperciva_aesni_la_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_AESNI}`
noinst_LTLIBRARIES+= libcperciva_arm_aes.la
libcperciva_arm_aes_la_SOURCES= \
libcperciva/crypto/crypto_aes_arm.c \
libcperciva/crypto/crypto_aesctr_arm.c
nodist_libcperciva_arm_aes_la_SOURCES= cpusupport-config.h
libcperciva_arm_aes_la_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_ARM_AES}`
noinst_LTLIBRARIES+= libcperciva_rdrand.la
libcperciva_rdrand_la_SOURCES= libcperciva/crypto/crypto_entropy_rdrand.c
nodist_libcperciva_rdrand_la_SOURCES= cpusupport-config.h
libcperciva_rdrand_la_CFLAGS= \
`. ./cpusupport-config.h; echo $${CFLAGS_X86_RDRAND}`
noinst_LTLIBRARIES+= libcperciva_shani.la
libcperciva_shani_la_SOURCES= libcperciva/alg/sha256_shani.c
nodist_libcperciva_shani_la_SOURCES= cpusupport-config.h
libcperciva_shani_la_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_SHANI} $${CFLAGS_X86_SSSE3}`
noinst_LTLIBRARIES+= libcperciva_arm_sha256.la
libcperciva_arm_sha256_la_SOURCES= libcperciva/alg/sha256_arm.c
nodist_libcperciva_arm_sha256_la_SOURCES= cpusupport-config.h
libcperciva_arm_sha256_la_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_ARM_SHA256}`
noinst_LTLIBRARIES+= libcperciva_crypto_aes.la
libcperciva_crypto_aes_la_SOURCES= libcperciva/crypto/crypto_aes.c
nodist_libcperciva_crypto_aes_la_SOURCES= cpusupport-config.h
libcperciva_crypto_aes_la_CFLAGS=`. ./apisupport-config.h; echo $${CFLAGS_LIBCRYPTO_LOW_LEVEL_AES}`
noinst_LTLIBRARIES+= libcperciva_cpusupport_detect.la
libcperciva_cpusupport_detect_la_SOURCES= \
libcperciva/cpusupport/cpusupport_arm_aes.c \
libcperciva/cpusupport/cpusupport_arm_sha256.c \
libcperciva/cpusupport/cpusupport_x86_aesni.c \
libcperciva/cpusupport/cpusupport_x86_rdrand.c \
libcperciva/cpusupport/cpusupport_x86_shani.c \
libcperciva/cpusupport/cpusupport_x86_sse2.c \
libcperciva/cpusupport/cpusupport_x86_ssse3.c
nodist_libcperciva_cpusupport_detect_la_SOURCES= cpusupport-config.h
# Library from libcperciva and scrypt code.
noinst_LTLIBRARIES+= libscrypt_sse2.la
libscrypt_sse2_la_SOURCES= \
lib/crypto/crypto_scrypt_smix_sse2.c \
libcperciva/alg/sha256_sse2.c
nodist_libscrypt_sse2_la_SOURCES= cpusupport-config.h
libscrypt_sse2_la_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_SSE2}`
# This library uses non-POSIX functionality, so we need to cancel the
# _POSIX_C_SOURCE and _XOPEN_SOURCE defined in AM_CPPFLAGS.
noinst_LTLIBRARIES+= libscrypt_memlimit.la
libscrypt_memlimit_la_SOURCES= \
lib-platform/util/memlimit.c
libscrypt_memlimit_la_CFLAGS=`. ./apisupport-config.h; echo $${CFLAGS_NONPOSIX_MEMLIMIT}`
# Install libscrypt-kdf?
if LIBSCRYPT_KDF
lib_LTLIBRARIES= libscrypt-kdf.la
libscrypt_kdf_la_LDFLAGS= \
-export-symbols-regex 'crypto_scrypt$$' \
-version-info 1
include_HEADERS= libscrypt-kdf/scrypt-kdf.h
noinst_PROGRAMS+= tests/libscrypt-kdf/sample-libscrypt-kdf
else
# Allow the user to get a usable library even if they didn't run configure
# with --enable-libscrypt-kdf. If we didn't include this, they would get
# empty libraries if they ran `make libscrypt-kdf.la`.
EXTRA_LTLIBRARIES= libscrypt-kdf.la
endif
# Shared definitions for libscrypt-kdf.
libscrypt_kdf_la_SOURCES= $(crypto_scrypt_files)
libscrypt_kdf_la_LIBADD= \
libcperciva_arm_sha256.la \
libcperciva_cpusupport_detect.la \
libcperciva_shani.la \
libscrypt_sse2.la
# Workaround for "created with both libtool and without".
libscrypt_kdf_la_CFLAGS= $(AM_CFLAGS)
# Test libscrypt-kdf compile.
tests_libscrypt_kdf_sample_libscrypt_kdf_SOURCES= \
tests/libscrypt-kdf/sample-libscrypt-kdf.c
tests_libscrypt_kdf_sample_libscrypt_kdf_CPPFLAGS= \
-I$(srcdir)/libscrypt-kdf/
tests_libscrypt_kdf_sample_libscrypt_kdf_LDADD= libscrypt-kdf.la
# crypto_aesctr_shared.c is in this list because it can't be included in the
# _SOURCES because it should only be included as part of another translation
# unit.
EXTRA_DIST= \
.autom4te.cfg \
BUILDING \
COPYRIGHT \
FORMAT \
README.md \
STYLE \
get-version.sh \
lib/README \
lib/crypto/crypto_scrypt-ref.c \
libcperciva/POSIX/README \
libcperciva/POSIX/posix-abstract-declarator.c \
libcperciva/POSIX/posix-cflags.sh \
libcperciva/POSIX/posix-clock_gettime.c \
libcperciva/POSIX/posix-clock_realtime.c \
libcperciva/POSIX/posix-inet-addrstrlen.c \
libcperciva/POSIX/posix-inet6-addrstrlen.c \
libcperciva/POSIX/posix-l.sh \
libcperciva/POSIX/posix-msg_nosignal.c \
libcperciva/POSIX/posix-restrict.c \
libcperciva/POSIX/posix-stat-st_mtim.c \
libcperciva/POSIX/posix-trivial.c \
libcperciva/apisupport/Build/apisupport-LIBCRYPTO-LOW_LEVEL_AES.c\
libcperciva/apisupport/Build/apisupport-NONPOSIX-MEMLIMIT.c \
libcperciva/apisupport/Build/apisupport.sh \
libcperciva/cpusupport/Build/cpusupport-ARM-AES.c \
libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c \
libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c \
libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c \
libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c \
libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c \
libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c \
libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c \
libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c \
libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c \
libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c \
libcperciva/cpusupport/Build/cpusupport.sh \
libcperciva/crypto/crypto_aesctr_shared.c \
tests/01-known-values.sh \
tests/02-decrypt-reference-file.sh \
tests/03-encrypt-decrypt-file.sh \
tests/04-force-resources.sh \
tests/05-system-scrypt-encrypt-decrypt.sh \
tests/06-decrypt-fail.sh \
tests/07-passphrase-env.sh \
tests/08-passphrase-file.sh \
tests/09-explicit-params.sh \
tests/shared_test_functions.sh \
tests/shared_valgrind_functions.sh \
tests/test_scrypt.sh \
tests/verify-strings/test_scrypt.good \
tests/verify-strings/test_scrypt_good.enc \
tests/verify-strings/test_scrypt_small.good
# Binary to test the crypto_scrypt() function.
tests_verify_strings_test_scrypt_SOURCES= \
tests/verify-strings/test_scrypt.c \
$(crypto_scrypt_files)
tests_verify_strings_test_scrypt_LDADD= \
libcperciva_arm_sha256.la \
libcperciva_cpusupport_detect.la \
libcperciva_shani.la \
libscrypt_sse2.la \
${LDADD_POSIX}
# Eliminate false positives while memory-checking for the test framework.
tests_valgrind_potential_memleaks_SOURCES= tests/valgrind/potential-memleaks.c
.PHONY: test
# we can't only build "scrypt tests/verify-strings/test_scrypt" because that
# won't build the BUILT_SOURCES.
test: all
$(top_srcdir)/tests/test_scrypt.sh .
================================================
FILE: README.md
================================================
The scrypt key derivation function
----------------------------------
The scrypt key derivation function was originally developed for use in the
[Tarsnap online backup system](https://www.tarsnap.com/index.html) and is
designed to be far more secure against hardware brute-force attacks than
alternative functions such as [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) or
[bcrypt](https://www.openbsd.org/papers/bcrypt-paper.ps).
We estimate that on modern (2009) hardware, if 5 seconds are spent computing a
derived key, the cost of a hardware brute-force attack against `scrypt` is
roughly 4000 times greater than the cost of a similar attack against bcrypt (to
find the same password), and 20000 times greater than a similar attack against
PBKDF2. If the `scrypt` encryption utility is used with default parameters,
the cost of cracking the password on a file encrypted by `scrypt enc` is
approximately 100 billion times more than the cost of cracking the same
password on a file encrypted by `openssl enc`; this means that a five-character
password using `scrypt` is stronger than a ten-character password using
`openssl`.
Details of the `scrypt` key derivation function are given in:
* The Internet Engineering Task Force (IETF)
[RFC 7914: The scrypt Password-Based Key Derivation Function](
https://tools.ietf.org/html/rfc7914).
* The original conference paper: Colin Percival,
[Stronger Key Derivation via Sequential Memory-Hard Functions](
https://www.tarsnap.com/scrypt/scrypt.pdf), presented at
[BSDCan'09](https://www.bsdcan.org/2009/), May 2009.
[Conference presentation slides](
https://www.tarsnap.com/scrypt/scrypt-slides.pdf).
Some additional articles may be of interest:
* Filippo Valsorda presented a very well-written explanation about how
[the scrypt parameters](https://blog.filippo.io/the-scrypt-parameters/)
impact the memory usage and CPU time of the algorithm.
* J. Alwen, B. Chen, K. Pietrzak, L. Reyzin, S. Tessaro,
[Scrypt is Maximally Memory-Hard](https://eprint.iacr.org/2016/989),
Cryptology ePrint Archive: Report 2016/989.
The scrypt encryption utility
-----------------------------
A simple password-based encryption utility is available as a demonstration of
the `scrypt` key derivation function. It can be invoked as:
* `scrypt enc [options] infile [outfile]` to encrypt data,
* `scrypt dec [options] infile [outfile]` to decrypt data, or
* `scrypt info infile` to see the encryption parameters used, and the memory
required to decrypt the encrypted file.
If `[outfile]` is not specified, the output is written to standard output.
`scrypt` also supports a number of command-line `[options]`:
* `-t maxtime` will instruct `scrypt` to spend at most maxtime seconds
computing the derived encryption key from the password; for encryption, this
value will determine how secure the encrypted data is, while for decryption
this value is used as an upper limit (if `scrypt` detects that it would take
too long to decrypt the data, it will exit with an error message).
* `-m maxmemfrac` instructs `scrypt` to use at most the specified fraction of
the available RAM for computing the derived encryption key. For encryption,
increasing this value might increase the security of the encrypted data,
depending on the `maxtime` value; for decryption, this value is used as an
upper limit and may `cause` scrypt to exit with an error.
* `-M maxmem` instructs `scrypt` to use at most the specified number of bytes
of RAM when computing the derived encryption key.
* `--logN value1`, `-r value2`, `-p value3` will set the encryption parameters
explicitly.
* `--passphrase method:arg` allows the user to specify whether to read the
passphrase from stdin, /dev/tty, an environment variable, or a file.
If the encrypted data is corrupt, `scrypt dec` will exit with a non-zero
status. However, **`scrypt dec` may produce output before it determines that
the encrypted data was corrupt**, so for applications which require data to be
authenticated, you must store the output of `scrypt dec` in a temporary
location and check `scrypt`'s exit code before using the decrypted data.
Using scrypt as a KDF
---------------------
To use scrypt as a [key derivation function](
https://en.wikipedia.org/wiki/Key_derivation_function) (KDF) with
`libscrypt-kdf`, include `scrypt-kdf.h` and use:
```
/**
* scrypt_kdf(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 scrypt_kdf(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
uint32_t, uint32_t, uint8_t *, size_t);
```
There is a sample of using this function in `tests/libscrypt-kdf`.
If you installed the library, you can compile that file and run
the binary:
```
$ cd tests/libscrypt-kdf/
$ c99 sample-libscrypt-kdf.c -lscrypt-kdf
$ ./a.out
crypto_scrypt(): success
```
If you would rather copy our source files directly into your
project, then take a look at the `lib/crypto/crypto_scrypt.h`
header, which provides `crypto_scrypt()`.
Official releases
-----------------
The `scrypt` utility has been tested on FreeBSD, NetBSD, OpenBSD, Linux
(Slackware, CentOS, Gentoo, Ubuntu), Solaris, OS X, Cygwin, and GNU Hurd.
* [scrypt version 1.3.3 source tarball](
https://www.tarsnap.com/scrypt/scrypt-1.3.3.tgz)
* [GPG-signed SHA256 for scrypt version 1.3.3](
https://www.tarsnap.com/scrypt/scrypt-sigs-1.3.3.asc) (signature
generated using Tarsnap [code signing key](
https://www.tarsnap.com/tarsnap-signing-key.asc))
This cleartext signature of the SHA256 output can be verified with:
gpg --decrypt scrypt-sigs-1.3.3.asc
You may then compare the displayed hash to the SHA256 hash of
`scrypt-1.3.3.tgz`.
In addition, `scrypt` is available in the OpenBSD and FreeBSD ports trees and
in NetBSD pkgsrc as `security/scrypt`.
Building
--------
:exclamation: We strongly recommend that people use the latest
official release tarball on https://www.tarsnap.com/scrypt.html
To build scrypt, extract the tarball and run `./configure` && `make`. See the
[BUILDING](BUILDING) file for more details (e.g., dealing with OpenSSL on OSX).
Testing
-------
A small test suite can be run with:
make test
On platforms with less than 1 GB of RAM, use:
make test SMALLMEM=1
Memory-testing normal operations with valgrind (takes approximately 4 times as
long as no valgrind tests) can be enabled with:
make test USE_VALGRIND=1
Memory-testing all tests with valgrind (requires over 1 GB memory, and takes
approximately 4 times as long as `USE_VALGRIND=1`) can be enabled with:
make test USE_VALGRIND=2
Mailing list
------------
The scrypt key derivation function and the scrypt encryption utility are
discussed on the <scrypt@tarsnap.com> mailing list.
================================================
FILE: STYLE
================================================
Code style
==========
In general, FreeBSD style(9) should be followed unless it is irrelevant
(e.g., $FreeBSD$ tags).
Functions with external linkage are declared like this:
/**
* module_func(arg1, arg2):
* Description of what the function does, referring to arguments as
* ${arg1} or suchlike.
*/
int module_func(void *, int);
The identical comment appears in the C file where the function is defined.
Static functions may have the above form of comment, or simply a
/* Brief description of what the function does. */
line before the function.
"Unrewrappable" comments starting in the first column should be
/**
* Written like this.
*
* Because (some of) the line-breaks are important.
*/
whereas when such comments are indented, they should be
/*-
* Written like this.
*
* Because (some of) the line-breaks are important.
*/
Line lengths should generally be 78 characters, and not more than 80
characters.
In general, functions should return (int)(-1) or NULL to indicate error.
Errors should be printed via warnp (if errno is relevant) or warn0 (if errno
is not relevant) when they are first detected and also at higher levels where
useful. As an exception to this, malloc failures (i.e., errno = ENOMEM) can
result in failure being passed back up the call chain without being printed
immediately. (Naturally, other errors can be passed back where a function
definition so specifies; e.g., ENOENT in cases where a file not existing is
not erroneous.)
The first statement in main(), after variable declarations, should be
"WARNP_INIT;" in order to set the program name used for printing warnings.
We use %d rather than %i in printf and warn0/warnp strings.
In general, functions should be structured with one return statement per
status, e.g., one return() for success and one return() for failure. Errors
should be handled by using goto to enter the error return path, e.g.,
int
foo(int bar)
{
if (something fails)
goto err0;
/* ... */
if (something else fails)
goto err1;
/* ... */
if (yet another operation fails)
goto err2;
/* Success! */
return (0);
err2:
/* Clean up something. */
err1:
/* Clean up something else. */
err0:
/* Failure! */
return (-1);
}
As an exception to the above, if there is only one way for the function to
fail, the idioms
return (baz(bar));
and
int rc;
rc = baz(bar);
/* ... cleanup code here ... */
return (rc);
are allowed; furthermore, in cases such as foo_free(), the idiom
if (we shouldn't do anything)
return;
is preferred over
if (we shouldn't do anything)
goto done;
at the start of a function.
Headers should be included in the following groups, with a blank line after
each (non-empty) group:
1. <sys/*.h>, with <sys/types.h> first followed by others alphabetically.
2. <net/*.h>, in alphabetical order.
3. <*.h>, in alphabetical order.
4. header files from /lib/, in alphabetical order.
5. header files from the program being built, in alphabetical order.
6. header files (usually just one) defining the interface for this C file.
If ssize_t is needed, <unistd.h> should be included to provide it.
If size_t is needed, <stddef.h> should be included to provide it unless
<stdio.h>, <stdlib.h>, <string.h>, or <unistd.h> is already required.
If the C99 integer types (uint8_t, int64_t, etc.) are required, <stdint.h>
should be included to provide them unless <inttypes.h> is already required.
The type 'char' should only be used to represent human-readable characters
(input from users, output to users, pathnames, et cetera). The type
'char *' should normally be a NUL-terminated string. The types 'signed
char' and 'unsigned char' should never be used; C99 integer types should
be used instead.
When a variable is declared to have a pointer type, there should be a space
between the '*' and the variable name, e.g.,
int
main(int argc, char * argv[])
{
char * opt_p = NULL;
Note that this is inconsistent with FreeBSD style(9). When used as a unary
operator, '*' is not separated from its argument, e.g.,
while (*p != '\0')
p++;
When a struct is referenced, the idiom
/* Opaque types. */
struct foo;
struct bar * bar_from_foo(struct foo *);
is preferable to
#include "foo.h" /* needed for struct foo */
struct bar * bar_from_foo(struct foo *);
unless there is some reason why the internal layout of struct foo is needed
(e.g., if struct bar contains a struct foo rather than a struct foo *). Such
struct declarations should be sorted alphabetically.
The file foo.c should only export symbols of the following forms:
foo_* -- most symbols should be of this form.
FOO_* / BAR_FOO_*
-- allowed in cases where FOO or BAR_FOO is idiomatic (e.g.,
MD5, HMAC_SHA256).
foo() / defoo() / unfoo()
-- where "foo" is a verb and this improves code clarity.
Functions named foo_free should return void, and foo_free(NULL) should have
no effect. The right way to spell a comment about this is
/* Behave consistently with free(NULL). */
If static variables need to be initialized to 0 (or NULL) then they should be
explicitly declared that way; implicit initialization should not be used.
In non-trivial code, comments should be included which describe in English
what is being done by the surrounding code with sufficient detail that if the
code were removed, it could be replaced based on reading the comments without
requiring any significant creativity.
Comments and documentation should be written in en-GB-oed; i.e., with
the 'u' included in words such as "honour", "colour", and "neighbour",
and the ending '-ize' in words such as "organize" and "realize". The
Oxford (aka. serial) comma should be used in lists. Quotation marks
should be placed logically, i.e., not including punctuation marks which
do not form a logical part of the quoted text. Two spaces should be used
after a period which ends a sentence.
The first local variable declaration in cookie-using functions should be
struct foo * bar = cookie;
When versions of functions are written to exploit special CPU features
(using the cpusupport framework), that code should be placed into a
separate file (e.g., crypto_aes_aesni.c) so that it can be compiled with
different compiler flags. Such a file should start with
#include "cpusupport.h"
#ifdef CPUSUPPORT_FOO_BAR
/**
* CPUSUPPORT CFLAGS: FOO_BAR FOO_BAZ
*/
and end with
#endif /* CPUSUPPORT_FOO_BAR */
For example, we could have
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)
/**
* CPUSUPPORT CFLAGS: X86_SHANI X86_SSSE3
*/
Functions for which special CPU-feature-exploiting variants exist should
take the form
{
/* Variable declarations here. */
/* Asserts here, if any. */
#ifdef CPUSUPPORT_FOO_BAR
if (/* We've decided we can use the variant code */) {
/* Call variant code and return. */
}
#endif
/* Normal implementation of the function. */
}
If there are multiple CPU-feature-exploiting variants, the `if` could instead
be a `switch` which invokes the appropriate variant function.
================================================
FILE: configure.ac
================================================
AC_PREREQ([2.69])
AC_INIT([scrypt],[m4_esyscmd([sh get-version.sh])],
[https://github.com/Tarsnap/scrypt],[scrypt],[http://www.tarsnap.com/scrypt/])
# Safety check: make sure that the srcdir contains this file.
AC_CONFIG_SRCDIR([lib/scryptenc/scryptenc.c])
# Use auxiliary subscripts from this subdirectory (cleans up root).
AC_CONFIG_AUX_DIR([config.aux])
# Directory for our additional macros.
AC_CONFIG_MACRO_DIR([m4])
# Compute $target_os and related variables.
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([foreign subdir-objects])
# Checks for programs.
m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_C99])
AM_PROG_AR
LT_INIT
# Don't rebuild the configure script. I'm distributing a perfectly good one.
AM_MAINTAINER_MODE
# Get the POSIX sh early, in case the configure script causes
# `command -p getconf` to fail in a broken environment.
CHECK_POSIX_SH
# Check if we need -std=c99 in LDFLAGS (for gcc on Solaris).
CHECK_SOLARIS_C99
# Check if we need to add extra paths to CPPFLAGS and LDFLAGS for macOS.
CHECK_DARWIN_PATHS
# Checks for AES support in OpenSSL.
AC_SEARCH_LIBS([AES_encrypt], [crypto],,
AC_MSG_ERROR([function AES_ENCRYPT not found]))
AC_CHECK_HEADERS([openssl/aes.h],,
[AC_MSG_ERROR([Unable to find the openssl/aes.h header])])
# Check how we can find out the available memory.
CHECK_MEMLIMIT_SUPPORT
# Check for posix_memalign.
AC_CHECK_FUNCS_ONCE([posix_memalign])
# Check for mmap so we can work around its absence on Minix.
AC_CHECK_FUNCS_ONCE([mmap])
# Use 64-bit file offsets.
AC_SYS_LARGEFILE
# Check whether the user has requested to disable compiler warnings.
CHECK_DISABLE_COMPILER_WARNINGS
# Check libcperciva POSIX compatibility.
CHECK_LIBCPERCIVA_POSIX([${srcdir}/libcperciva])
# Check whether the user wants to install libscrypt-kdf.
AC_ARG_ENABLE(libscrypt-kdf, AS_HELP_STRING([--enable-libscrypt-kdf],
[Install libscrypt-kdf and development headers.]))
AM_CONDITIONAL([LIBSCRYPT_KDF], [test "x${enable_libscrypt_kdf}" = "xyes"])
# Write configure results and the Makefile.
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
================================================
FILE: get-version.sh
================================================
#!/bin/sh
version=1.3.3-head
# This script outputs a version number for this project to stdout.
# - if $SCRYPT_VERSION is given, it is used.
# - otherwise, it uses ${version}.
# - if there is a ".git/" directory, it will attempt to get a version number
# from `git describe` in the form 1.2.0-238-g0a25a7c, where the middle value
# is the number of commits since the 1.2.0 tag.
# Use $SCRYPT_VERSION if it exists.
if [ -n "${SCRYPT_VERSION}" ]; then
# Do not use \n; that confuses autoconf.
printf "%s" "${SCRYPT_VERSION}"
exit 0
fi
# Get a version number from git, if it exists.
if git rev-parse 2>/dev/null; then
# Get a version string from the latest git tag.
if version_git=$( git describe --tags --match '[[:digit:]].*' ) \
2>/dev/null ; then
version_decapitated=$( echo "${version}" | sed "s/-head//" )
# Check that the beginning of this tag matches the version.
case ${version_git} in
"${version_decapitated}"*)
# If so, use that version string.
version=${version_git};;
*)
printf "git tag does not match version\n" 1>&2
exit 1;;
esac
fi
fi
# Output the version to stdout. Do not use \n; that confuses autoconf.
printf "%s" "${version}"
================================================
FILE: lib/README
================================================
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.
================================================
FILE: lib/crypto/crypto_scrypt-ref.c
================================================
/*-
* 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 <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "sha256.h"
#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;
size_t r = _r, p = _p;
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) */
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
/* 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) */
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
/* Free memory. */
free(V);
free(XY);
free(B);
/* Success! */
return (0);
err2:
free(XY);
err1:
free(B);
err0:
/* Failure! */
return (-1);
}
================================================
FILE: lib/crypto/crypto_scrypt_smix.c
================================================
/*-
* 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 <stdint.h>
#include <string.h>
#include "sysendian.h"
#include "crypto_scrypt_smix.h"
static void blkcpy(uint32_t *, const uint32_t *, size_t);
static void blkxor(uint32_t *, const uint32_t *, size_t);
static void salsa20_8(uint32_t[16]);
static void blockmix_salsa8(const uint32_t *, uint32_t *, uint32_t *, size_t);
static uint64_t integerify(const uint32_t *, size_t);
static void
blkcpy(uint32_t * dest, const uint32_t * src, size_t len)
{
memcpy(dest, src, len);
}
static void
blkxor(uint32_t * dest, const uint32_t * src, size_t len)
{
size_t i;
for (i = 0; i < len / 4; i++)
dest[i] ^= src[i];
}
/**
* salsa20_8(B):
* Apply the salsa20/8 core to the provided block.
*/
static void
salsa20_8(uint32_t B[16])
{
uint32_t x[16];
size_t i;
blkcpy(x, B, 64);
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
}
for (i = 0; i < 16; i++)
B[i] += x[i];
}
/**
* 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(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
{
size_t i;
/* 1: X <-- B_{2r - 1} */
blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
/* 2: for i = 0 to 2r - 1 do */
for (i = 0; i < 2 * r; i += 2) {
/* 3: X <-- H(X \xor B_i) */
blkxor(X, &Bin[i * 16], 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 * 8], X, 64);
/* 3: X <-- H(X \xor B_i) */
blkxor(X, &Bin[i * 16 + 16], 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 * 8 + r * 16], X, 64);
}
}
/**
* integerify(B, r):
* Return the result of parsing B_{2r-1} as a little-endian integer.
*/
static uint64_t
integerify(const uint32_t * B, size_t r)
{
const uint32_t * X = B + (2 * r - 1) * 16;
return (((uint64_t)(X[1]) << 32) + X[0]);
}
/**
* crypto_scrypt_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.
*/
void
crypto_scrypt_smix(uint8_t * B, size_t r, uint64_t N, void * _v, void * XY)
{
uint32_t * X = XY;
uint32_t * Y = (void *)((uint8_t *)(XY) + 128 * r);
uint32_t * Z = (void *)((uint8_t *)(XY) + 256 * r);
uint32_t * V = _v;
uint64_t i;
uint64_t j;
size_t k;
/* 1: X <-- B */
for (k = 0; k < 32 * r; k++)
X[k] = le32dec(&B[4 * k]);
/* 2: for i = 0 to N - 1 do */
for (i = 0; i < N; i += 2) {
/* 3: V_i <-- X */
blkcpy(&V[i * (32 * r)], X, 128 * r);
/* 4: X <-- H(X) */
blockmix_salsa8(X, Y, Z, r);
/* 3: V_i <-- X */
blkcpy(&V[(i + 1) * (32 * 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, &V[j * (32 * 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, &V[j * (32 * r)], 128 * r);
blockmix_salsa8(Y, X, Z, r);
}
/* 10: B' <-- X */
for (k = 0; k < 32 * r; k++)
le32enc(&B[4 * k], X[k]);
}
================================================
FILE: lib/crypto/crypto_scrypt_smix.h
================================================
#ifndef CRYPTO_SCRYPT_SMIX_H_
#define CRYPTO_SCRYPT_SMIX_H_
#include <stddef.h>
#include <stdint.h>
/**
* crypto_scrypt_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.
*/
void crypto_scrypt_smix(uint8_t *, size_t, uint64_t, void *, void *);
#endif /* !CRYPTO_SCRYPT_SMIX_H_ */
================================================
FILE: lib/crypto/crypto_scrypt_smix_sse2.c
================================================
/*-
* 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 "cpusupport.h"
#ifdef CPUSUPPORT_X86_SSE2
#include <emmintrin.h>
#include <stdint.h>
#include "sysendian.h"
#include "crypto_scrypt_smix_sse2.h"
static void blkcpy(__m128i *, const __m128i *, size_t);
static void blkxor(__m128i *, const __m128i *, size_t);
static void salsa20_8(__m128i[4]);
static void blockmix_salsa8(const __m128i *, __m128i *, __m128i *, size_t);
static uint64_t integerify(const __m128i *, size_t);
static void
blkcpy(__m128i * dest, const __m128i * src, size_t len)
{
size_t L = len / 16;
size_t i;
for (i = 0; i < L; i++)
dest[i] = src[i];
}
static void
blkxor(__m128i * dest, const __m128i * src, size_t len)
{
size_t L = len / 16;
size_t i;
for (i = 0; i < L; i++)
dest[i] = _mm_xor_si128(dest[i], src[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(const __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.
* Note that B's layout is permuted compared to the generic implementation.
*/
static uint64_t
integerify(const __m128i * B, size_t r)
{
const __m128i * X = B + (2*r - 1) * 4;
uint32_t X0, X13;
/* Get the first 32-bit element in X[0]. */
X0 = (uint32_t)_mm_cvtsi128_si32(X[0]);
/* Get the second 32-bit element in X[3]. */
X13 = (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(X[3], 4));
return (((uint64_t)(X13) << 32) + X0);
}
/**
* crypto_scrypt_smix_sse2(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.
*
* Use SSE2 instructions.
*/
void
crypto_scrypt_smix_sse2(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]);
}
}
}
#endif /* CPUSUPPORT_X86_SSE2 */
================================================
FILE: lib/crypto/crypto_scrypt_smix_sse2.h
================================================
#ifndef CRYPTO_SCRYPT_SMIX_SSE2_H_
#define CRYPTO_SCRYPT_SMIX_SSE2_H_
#include <stddef.h>
#include <stdint.h>
/**
* crypto_scrypt_smix_sse2(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.
*
* Use SSE2 instructions.
*/
void crypto_scrypt_smix_sse2(uint8_t *, size_t, uint64_t, void *, void *);
#endif /* !CRYPTO_SCRYPT_SMIX_SSE2_H_ */
================================================
FILE: lib/scryptenc/scryptenc.c
================================================
/*-
* 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 <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypto_aes.h"
#include "crypto_aesctr.h"
#include "crypto_entropy.h"
#include "crypto_verify_bytes.h"
#include "humansize.h"
#include "insecure_memzero.h"
#include "sha256.h"
#include "sysendian.h"
#include "warnp.h"
#include "crypto_scrypt.h"
#include "memlimit.h"
#include "scryptenc_cpuperf.h"
#include "scryptenc.h"
#define ENCBLOCK 65536
static int pickparams(size_t, double, double,
int *, uint32_t *, uint32_t *, int);
static int checkparams(size_t, double, double, int, uint32_t, uint32_t, int,
int);
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
static int scryptdec_file_load_header(FILE * infile, uint8_t header[static 96]);
#else
static int scryptdec_file_load_header(FILE *, uint8_t[static 96]);
#endif
struct scryptdec_file_cookie {
FILE * infile; /* This is not owned by this cookie. */
uint8_t header[96];
uint8_t dk[64];
};
static void
display_params(int logN, uint32_t r, uint32_t p, size_t memlimit,
double opps, double maxtime)
{
uint64_t N = (uint64_t)(1) << logN;
uint64_t mem_minimum = 128 * r * N;
double expected_seconds = opps > 0 ? (double)(4 * N * r * p) / opps : 0;
char * human_memlimit = humansize(memlimit);
char * human_mem_minimum = humansize(mem_minimum);
/* Parameters */
fprintf(stderr, "Parameters used: N = %" PRIu64 "; r = %" PRIu32
"; p = %" PRIu32 ";\n", N, r, p);
/* Memory */
fprintf(stderr, " Decrypting this file requires at least"
" %s of memory", human_mem_minimum);
if (memlimit > 0)
fprintf(stderr, " (%s available)", human_memlimit);
/* CPU time */
if (opps > 0)
fprintf(stderr, ",\n and will take approximately %.1f "
"seconds (limit: %.1f seconds)", expected_seconds, maxtime);
fprintf(stderr, ".\n");
/* Clean up */
free(human_memlimit);
free(human_mem_minimum);
}
static int
pickparams(size_t maxmem, double maxmemfrac, double maxtime,
int * logN, uint32_t * r, uint32_t * p, int verbose)
{
size_t memlimit;
double opps;
double opslimit;
double maxN, maxrp;
uint64_t checkN;
int rc;
/* Figure out how much memory to use. */
if (memtouse(maxmem, maxmemfrac, &memlimit))
return (SCRYPT_ELIMIT);
/* Figure out how fast the CPU is. */
if ((rc = scryptenc_cpuperf(&opps)) != SCRYPT_OK)
return (rc);
opslimit = opps * maxtime;
/* Allow a minimum of 2^15 salsa20/8 cores. */
if (opslimit < 32768)
opslimit = 32768;
/* Fix r = 8 for now. */
*r = 8;
/*
* The memory limit requires that 128Nr <= memlimit, while the CPU
* limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32,
* opslimit imposes the stronger limit on N.
*/
#ifdef DEBUG
fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n",
memlimit, opslimit);
#endif
if (opslimit < (double)memlimit / 32) {
/* Set p = 1 and choose N based on the CPU limit. */
*p = 1;
maxN = opslimit / (*r * 4);
for (*logN = 1; *logN < 63; *logN += 1) {
checkN = (uint64_t)(1) << *logN;
/*
* Find the largest power of two <= maxN, which is
* also the least power of two > maxN/2.
*/
if ((double)checkN > maxN / 2)
break;
}
} else {
/* Set N based on the memory limit. */
maxN = (double)(memlimit / (*r * 128));
for (*logN = 1; *logN < 63; *logN += 1) {
checkN = (uint64_t)(1) << *logN;
if ((double)checkN > maxN / 2)
break;
}
/* Choose p based on the CPU limit. */
checkN = (uint64_t)(1) << *logN;
maxrp = (opslimit / 4) / (double)checkN;
if (maxrp > 0x3fffffff)
maxrp = 0x3fffffff;
*p = (uint32_t)(maxrp) / *r;
}
if (verbose)
display_params(*logN, *r, *p, memlimit, opps, maxtime);
/* Success! */
return (SCRYPT_OK);
}
static int
checkparams(size_t maxmem, double maxmemfrac, double maxtime,
int logN, uint32_t r, uint32_t p, int verbose, int force)
{
size_t memlimit;
double opps;
double opslimit;
uint64_t N;
int rc;
/* Sanity-check values. */
if ((logN < 1) || (logN > 63))
return (SCRYPT_EINVAL);
if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000)
return (SCRYPT_EINVAL);
if ((r == 0) || (p == 0))
return (SCRYPT_EINVAL);
/* Are we forcing decryption, regardless of resource limits? */
if (!force) {
/* Figure out the maximum amount of memory we can use. */
if (memtouse(maxmem, maxmemfrac, &memlimit))
return (SCRYPT_ELIMIT);
/* Figure out how fast the CPU is. */
if ((rc = scryptenc_cpuperf(&opps)) != SCRYPT_OK)
return (rc);
opslimit = opps * maxtime;
if (verbose)
display_params(logN, r, p, memlimit, opps, maxtime);
/* Check limits. */
N = (uint64_t)(1) << logN;
if (((memlimit / N) / r < 128) &&
(((opslimit / (double)N) / r) / p < 4))
return (SCRYPT_EBIGSLOW);
if ((memlimit / N) / r < 128)
return (SCRYPT_ETOOBIG);
if (((opslimit / (double)N) / r) / p < 4)
return (SCRYPT_ETOOSLOW);
} else {
/* We have no limit. */
memlimit = 0;
opps = 0;
if (verbose)
display_params(logN, r, p, memlimit, opps, maxtime);
}
/* Success! */
return (SCRYPT_OK);
}
/*
* NOTE: The caller is responsible for sanitizing ${dk}, including if this
* function fails.
*/
static int
scryptenc_setup(uint8_t header[96], uint8_t dk[64],
const uint8_t * passwd, size_t passwdlen,
struct scryptenc_params * P, int verbose, int force)
{
uint8_t salt[32];
uint8_t hbuf[32];
uint64_t N;
SHA256_CTX ctx;
uint8_t * key_hmac = &dk[32];
HMAC_SHA256_CTX hctx;
int rc;
/* Determine parameters. */
if (P->logN != 0) {
/* Check logN, r, p. */
if ((rc = checkparams(P->maxmem, P->maxmemfrac, P->maxtime,
P->logN, P->r, P->p, verbose, force)) != 0) {
/* Warn about resource limit, but suppress the error. */
if ((rc == SCRYPT_ETOOBIG) || (rc == SCRYPT_EBIGSLOW))
warn0("Warning: Explicit parameters"
" might exceed memory limit");
if ((rc == SCRYPT_ETOOSLOW) || (rc == SCRYPT_EBIGSLOW))
warn0("Warning: Explicit parameters"
" might exceed time limit");
if ((rc == SCRYPT_ETOOBIG) || (rc == SCRYPT_ETOOSLOW) ||
(rc == SCRYPT_EBIGSLOW))
rc = 0;
/* Provide a more meaningful error message. */
if (rc == SCRYPT_EINVAL)
rc = SCRYPT_EPARAM;
/* Bail if we haven't suppressed the error. */
if (rc != 0)
return (rc);
}
} else {
/* Pick values for N, r, p. */
if ((rc = pickparams(P->maxmem, P->maxmemfrac, P->maxtime,
&P->logN, &P->r, &P->p, verbose)) != 0)
return (rc);
}
/* Sanity check. */
assert((P->logN > 0) && (P->logN < 64));
/* Set N. */
N = (uint64_t)(1) << P->logN;
/* Get some salt. */
if (crypto_entropy_read(salt, 32))
return (SCRYPT_ESALT);
/* Generate the derived keys. */
if (crypto_scrypt(passwd, passwdlen, salt, 32, N, P->r, P->p, dk, 64))
return (SCRYPT_EKEY);
/* Construct the file header. */
memcpy(header, "scrypt", 6);
header[6] = 0;
header[7] = P->logN & 0xff;
be32enc(&header[8], P->r);
be32enc(&header[12], P->p);
memcpy(&header[16], salt, 32);
/* Add header checksum. */
SHA256_Init(&ctx);
SHA256_Update(&ctx, header, 48);
SHA256_Final(hbuf, &ctx);
memcpy(&header[48], hbuf, 16);
/* Add header signature (used for verifying password). */
HMAC_SHA256_Init(&hctx, key_hmac, 32);
HMAC_SHA256_Update(&hctx, header, 64);
HMAC_SHA256_Final(hbuf, &hctx);
memcpy(&header[64], hbuf, 32);
/* Success! */
return (SCRYPT_OK);
}
/**
* scryptdec_file_printparams(infile):
* Print the encryption parameters (N, r, p) used for the encrypted ${infile}.
*/
int
scryptdec_file_printparams(FILE * infile)
{
uint8_t header[96];
int logN;
uint32_t r;
uint32_t p;
int rc;
/* Load the header. */
if ((rc = scryptdec_file_load_header(infile, header)) != 0)
goto err0;
/* Parse N, r, p. */
logN = header[7];
r = be32dec(&header[8]);
p = be32dec(&header[12]);
/* Print parameters. */
display_params(logN, r, p, 0, 0, 0);
/* Success! */
return (SCRYPT_OK);
err0:
/* Failure! */
return (rc);
}
/*
* NOTE: The caller is responsible for sanitizing ${dk}, including if this
* function fails.
*/
static int
scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
const uint8_t * passwd, size_t passwdlen,
struct scryptenc_params * P, int verbose,
int force)
{
uint8_t salt[32];
uint8_t hbuf[32];
uint64_t N;
SHA256_CTX ctx;
uint8_t * key_hmac = &dk[32];
HMAC_SHA256_CTX hctx;
int rc;
/* Parse N, r, p, salt. */
P->logN = header[7];
P->r = be32dec(&header[8]);
P->p = be32dec(&header[12]);
memcpy(salt, &header[16], 32);
/* Verify header checksum. */
SHA256_Init(&ctx);
SHA256_Update(&ctx, header, 48);
SHA256_Final(hbuf, &ctx);
if (crypto_verify_bytes(&header[48], hbuf, 16))
return (SCRYPT_EINVAL);
/*
* Check whether the provided parameters are valid and whether the
* key derivation function can be computed within the allowed memory
* and CPU time, unless the user chose to disable this test.
*/
if ((rc = checkparams(P->maxmem, P->maxmemfrac, P->maxtime, P->logN,
P->r, P->p, verbose, force)) != 0)
return (rc);
/* Compute the derived keys. */
N = (uint64_t)(1) << P->logN;
if (crypto_scrypt(passwd, passwdlen, salt, 32, N, P->r, P->p, dk, 64))
return (SCRYPT_EKEY);
/* Check header signature (i.e., verify password). */
HMAC_SHA256_Init(&hctx, key_hmac, 32);
HMAC_SHA256_Update(&hctx, header, 64);
HMAC_SHA256_Final(hbuf, &hctx);
if (crypto_verify_bytes(hbuf, &header[64], 32))
return (SCRYPT_EPASS);
/* Success! */
return (SCRYPT_OK);
}
/**
* scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
* params, verbose, force):
* Encrypt ${inbuflen} bytes from ${inbuf}, writing the resulting
* ${inbuflen} + 128 bytes to ${outbuf}. If ${force} is 1, do not check
* whether decryption will exceed the estimated available memory or time.
* The explicit parameters within ${params} must be zero or must all be
* non-zero. If explicit parameters are used and the computation is estimated
* to exceed resource limits, print a warning instead of returning an error.
* Return the explicit parameters used via ${params}.
*/
int
scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
const uint8_t * passwd, size_t passwdlen,
struct scryptenc_params * P, int verbose, int force)
{
uint8_t dk[64];
uint8_t hbuf[32];
uint8_t header[96];
uint8_t * key_enc = dk;
uint8_t * key_hmac = &dk[32];
int rc;
HMAC_SHA256_CTX hctx;
struct crypto_aes_key * key_enc_exp;
struct crypto_aesctr * AES;
/* The explicit parameters must be zero, or all non-zero. */
assert(((P->logN == 0) && (P->r == 0) && (P->p == 0)) ||
((P->logN != 0) && (P->r != 0) && (P->p != 0)));
/* Generate the header and derived key. */
if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
P, verbose, force)) != 0)
goto err1;
/* Copy header into output buffer. */
memcpy(outbuf, header, 96);
/* Encrypt data. */
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
rc = SCRYPT_EOPENSSL;
goto err1;
}
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
crypto_aes_key_free(key_enc_exp);
rc = SCRYPT_ENOMEM;
goto err1;
}
crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen);
crypto_aesctr_free(AES);
crypto_aes_key_free(key_enc_exp);
/* Add signature. */
HMAC_SHA256_Init(&hctx, key_hmac, 32);
HMAC_SHA256_Update(&hctx, outbuf, 96 + inbuflen);
HMAC_SHA256_Final(hbuf, &hctx);
memcpy(&outbuf[96 + inbuflen], hbuf, 32);
/* Zero sensitive data. */
insecure_memzero(dk, 64);
/* Success! */
return (SCRYPT_OK);
err1:
insecure_memzero(dk, 64);
/* Failure! */
return (rc);
}
/**
* scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
* params, verbose, force):
* Decrypt ${inbuflen} bytes from ${inbuf}, writing the result into ${outbuf}
* and the decrypted data length to ${outlen}. The allocated length of
* ${outbuf} must be at least ${inbuflen}. If ${force} is 1, do not check
* whether decryption will exceed the estimated available memory or time.
* The explicit parameters within ${params} must be zero. Return the explicit
* parameters used via ${params}.
*/
int
scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
size_t * outlen, const uint8_t * passwd, size_t passwdlen,
struct scryptenc_params * P, int verbose,
int force)
{
uint8_t hbuf[32];
uint8_t dk[64];
uint8_t * key_enc = dk;
uint8_t * key_hmac = &dk[32];
int rc;
HMAC_SHA256_CTX hctx;
struct crypto_aes_key * key_enc_exp;
struct crypto_aesctr * AES;
/* The explicit parameters must be zero. */
assert((P->logN == 0) && (P->r == 0) && (P->p == 0));
/*
* All versions of the scrypt format will start with "scrypt" and
* have at least 7 bytes of header.
*/
if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0)) {
rc = SCRYPT_EINVAL;
goto err0;
}
/* Check the format. */
if (inbuf[6] != 0) {
rc = SCRYPT_EVERSION;
goto err0;
}
/* We must have at least 128 bytes. */
if (inbuflen < 128) {
rc = SCRYPT_EINVAL;
goto err0;
}
/* Parse the header and generate derived keys. */
if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
P, verbose, force)) != 0)
goto err1;
/* Decrypt data. */
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
rc = SCRYPT_EOPENSSL;
goto err1;
}
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
crypto_aes_key_free(key_enc_exp);
rc = SCRYPT_ENOMEM;
goto err1;
}
crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128);
crypto_aesctr_free(AES);
crypto_aes_key_free(key_enc_exp);
*outlen = inbuflen - 128;
/* Verify signature. */
HMAC_SHA256_Init(&hctx, key_hmac, 32);
HMAC_SHA256_Update(&hctx, inbuf, inbuflen - 32);
HMAC_SHA256_Final(hbuf, &hctx);
if (crypto_verify_bytes(hbuf, &inbuf[inbuflen - 32], 32)) {
rc = SCRYPT_EINVAL;
goto err1;
}
/* Zero sensitive data. */
insecure_memzero(dk, 64);
/* Success! */
return (SCRYPT_OK);
err1:
insecure_memzero(dk, 64);
err0:
/* Failure! */
return (rc);
}
/**
* scryptenc_file(infile, outfile, passwd, passwdlen, params, verbose, force):
* Read a stream from ${infile} and encrypt it, writing the resulting stream
* to ${outfile}. If ${force} is 1, do not check whether decryption will
* exceed the estimated available memory or time. The explicit parameters
* within ${params} must be zero or must all be non-zero. If explicit
* parameters are used and the computation is estimated to exceed resource
* limits, print a warning instead of returning an error. Return the explicit
* parameters used via ${params}.
*/
int
scryptenc_file(FILE * infile, FILE * outfile,
const uint8_t * passwd, size_t passwdlen,
struct scryptenc_params * P, int verbose, int force)
{
uint8_t buf[ENCBLOCK];
uint8_t dk[64];
uint8_t hbuf[32];
uint8_t header[96];
uint8_t * key_enc = dk;
uint8_t * key_hmac = &dk[32];
size_t readlen;
HMAC_SHA256_CTX hctx;
struct crypto_aes_key * key_enc_exp;
struct crypto_aesctr * AES;
int rc;
/* The explicit parameters must be zero, or all non-zero. */
assert(((P->logN == 0) && (P->r == 0) && (P->p == 0)) ||
((P->logN != 0) && (P->r != 0) && (P->p != 0)));
/* Generate the header and derived key. */
if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
P, verbose, force)) != 0)
goto err1;
/* Hash and write the header. */
HMAC_SHA256_Init(&hctx, key_hmac, 32);
HMAC_SHA256_Update(&hctx, header, 96);
if (fwrite(header, 96, 1, outfile) != 1) {
rc = SCRYPT_EWRFILE;
goto err1;
}
/*
* Read blocks of data, encrypt them, and write them out; hash the
* data as it is produced.
*/
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
rc = SCRYPT_EOPENSSL;
goto err1;
}
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
crypto_aes_key_free(key_enc_exp);
rc = SCRYPT_ENOMEM;
goto err1;
}
do {
if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0)
break;
crypto_aesctr_stream(AES, buf, buf, readlen);
HMAC_SHA256_Update(&hctx, buf, readlen);
if (fwrite(buf, 1, readlen, outfile) < readlen) {
crypto_aesctr_free(AES);
rc = SCRYPT_EWRFILE;
goto err1;
}
} while (1);
crypto_aesctr_free(AES);
crypto_aes_key_free(key_enc_exp);
/* Did we exit the loop due to a read error? */
if (ferror(infile)) {
rc = SCRYPT_ERDFILE;
goto err1;
}
/* Compute the final HMAC and output it. */
HMAC_SHA256_Final(hbuf, &hctx);
if (fwrite(hbuf, 32, 1, outfile) != 1) {
rc = SCRYPT_EWRFILE;
goto err1;
}
/* Zero sensitive data. */
insecure_memzero(dk, 64);
/* Success! */
return (SCRYPT_OK);
err1:
insecure_memzero(dk, 64);
/* Failure! */
return (rc);
}
/**
* scryptdec_file_cookie_free(cookie):
* Free the ${cookie}.
*/
void
scryptdec_file_cookie_free(struct scryptdec_file_cookie * C)
{
/* Behave consistently with free(NULL). */
if (C == NULL)
return;
/* Zero sensitive data. */
insecure_memzero(C->dk, 64);
/* We do not free C->infile because it is not owned by this cookie. */
/* Free the cookie. */
free(C);
}
/* Load the header and check the magic. */
static int
scryptdec_file_load_header(FILE * infile, uint8_t header[static 96])
{
int rc;
/*
* Read the first 7 bytes of the file; all future versions of scrypt
* are guaranteed to have at least 7 bytes of header.
*/
if (fread(header, 7, 1, infile) < 1) {
if (ferror(infile)) {
rc = SCRYPT_ERDFILE;
goto err0;
} else {
rc = SCRYPT_EINVAL;
goto err0;
}
}
/* Do we have the right magic? */
if (memcmp(header, "scrypt", 6)) {
rc = SCRYPT_EINVAL;
goto err0;
}
if (header[6] != 0) {
rc = SCRYPT_EVERSION;
goto err0;
}
/*
* Read another 89 bytes of the file; version 0 of the scrypt file
* format has a 96-byte header.
*/
if (fread(&header[7], 89, 1, infile) < 1) {
if (ferror(infile)) {
rc = SCRYPT_ERDFILE;
goto err0;
} else {
rc = SCRYPT_EINVAL;
goto err0;
}
}
/* Success! */
return (SCRYPT_OK);
err0:
/* Failure! */
return (rc);
}
/**
* scryptdec_file_prep(infile, passwd, passwdlen, params, verbose, force,
* cookie):
* Prepare to decrypt ${infile}, including checking the passphrase. Allocate
* a cookie at ${cookie}. After calling this function, ${infile} should not
* be modified until the decryption is completed by scryptdec_file_copy().
* If ${force} is 1, do not check whether decryption will exceed the estimated
* available memory or time. The explicit parameters within ${params} must be
* zero. Return the explicit parameters to be used via ${params}.
*/
int
scryptdec_file_prep(FILE * infile, const uint8_t * passwd,
size_t passwdlen, struct scryptenc_params * P,
int verbose, int force, struct scryptdec_file_cookie ** cookie)
{
struct scryptdec_file_cookie * C;
int rc;
/* The explicit parameters must be zero. */
assert((P->logN == 0) && (P->r == 0) && (P->p == 0));
/* Allocate the cookie. */
if ((C = malloc(sizeof(struct scryptdec_file_cookie))) == NULL)
return (SCRYPT_ENOMEM);
C->infile = infile;
/* Load the header. */
if ((rc = scryptdec_file_load_header(infile, C->header)) != 0)
goto err1;
/* Parse the header and generate derived keys. */
if ((rc = scryptdec_setup(C->header, C->dk, passwd, passwdlen,
P, verbose, force)) != 0)
goto err1;
/* Set cookie for calling function. */
*cookie = C;
/* Success! */
return (SCRYPT_OK);
err1:
scryptdec_file_cookie_free(C);
/* Failure! */
return (rc);
}
/**
* scryptdec_file_copy(cookie, outfile):
* Read a stream from the file that was passed into the ${cookie} by
* scryptdec_file_prep(), decrypt it, and write the resulting stream to
* ${outfile}. After this function completes, it is safe to modify/close
* ${outfile} and the ${infile} which was given to scryptdec_file_prep().
*/
int
scryptdec_file_copy(struct scryptdec_file_cookie * C, FILE * outfile)
{
uint8_t buf[ENCBLOCK + 32];
uint8_t hbuf[32];
uint8_t * key_enc;
uint8_t * key_hmac;
size_t buflen = 0;
size_t readlen;
HMAC_SHA256_CTX hctx;
struct crypto_aes_key * key_enc_exp;
struct crypto_aesctr * AES;
int rc;
/* Sanity check. */
assert(C != NULL);
/* Use existing array for these pointers. */
key_enc = C->dk;
key_hmac = &C->dk[32];
/* Start hashing with the header. */
HMAC_SHA256_Init(&hctx, key_hmac, 32);
HMAC_SHA256_Update(&hctx, C->header, 96);
/*
* We don't know how long the encrypted data block is (we can't know,
* since data can be streamed into 'scrypt enc') so we need to read
* data and decrypt all of it except the final 32 bytes, then check
* if that final 32 bytes is the correct signature.
*/
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
rc = SCRYPT_EOPENSSL;
goto err0;
}
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
crypto_aes_key_free(key_enc_exp);
rc = SCRYPT_ENOMEM;
goto err0;
}
do {
/* Read data until we have more than 32 bytes of it. */
if ((readlen = fread(&buf[buflen], 1,
ENCBLOCK + 32 - buflen, C->infile)) == 0)
break;
buflen += readlen;
if (buflen <= 32)
continue;
/*
* Decrypt, hash, and output everything except the last 32
* bytes out of what we have in our buffer.
*/
HMAC_SHA256_Update(&hctx, buf, buflen - 32);
crypto_aesctr_stream(AES, buf, buf, buflen - 32);
if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32) {
crypto_aesctr_free(AES);
rc = SCRYPT_EWRFILE;
goto err0;
}
/* Move the last 32 bytes to the start of the buffer. */
memmove(buf, &buf[buflen - 32], 32);
buflen = 32;
} while (1);
crypto_aesctr_free(AES);
crypto_aes_key_free(key_enc_exp);
/* Did we exit the loop due to a read error? */
if (ferror(C->infile)) {
rc = SCRYPT_ERDFILE;
goto err0;
}
/* Did we read enough data that we *might* have a valid signature? */
if (buflen < 32) {
rc = SCRYPT_EINVAL;
goto err0;
}
/* Verify signature. */
HMAC_SHA256_Final(hbuf, &hctx);
if (crypto_verify_bytes(hbuf, buf, 32)) {
rc = SCRYPT_EINVAL;
goto err0;
}
/* Success! */
return (SCRYPT_OK);
err0:
/* Failure! */
return (rc);
}
/**
* scryptdec_file(infile, outfile, passwd, passwdlen, params, verbose, force):
* Read a stream from ${infile} and decrypt it, writing the resulting stream
* to ${outfile}. If ${force} is 1, do not check whether decryption
* will exceed the estimated available memory or time. The explicit
* parameters within ${params} must be zero. Return the explicit parameters
* used via ${params}.
*/
int
scryptdec_file(FILE * infile, FILE * outfile, const uint8_t * passwd,
size_t passwdlen, struct scryptenc_params * P,
int verbose, int force)
{
struct scryptdec_file_cookie * C;
int rc;
/* The explicit parameters must be zero. */
assert((P->logN == 0) && (P->r == 0) && (P->p == 0));
/* Check header, including passphrase. */
if ((rc = scryptdec_file_prep(infile, passwd, passwdlen, P,
verbose, force, &C)) != 0)
goto err0;
/* Copy unencrypted data to outfile. */
if ((rc = scryptdec_file_copy(C, outfile)) != 0)
goto err1;
/* Clean up cookie, attempting to zero sensitive data. */
scryptdec_file_cookie_free(C);
/* Success! */
return (SCRYPT_OK);
err1:
scryptdec_file_cookie_free(C);
err0:
/* Failure! */
return (rc);
}
================================================
FILE: lib/scryptenc/scryptenc.h
================================================
/*-
* 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 SCRYPTENC_H_
#define SCRYPTENC_H_
#include <stdint.h>
#include <stdio.h>
/**
* NOTE: This file provides prototypes for routines which encrypt/decrypt data
* using a key derived from a password by using the scrypt key derivation
* function. If you are just trying to "hash" a password for user logins,
* this is not the code you are looking for. You want to use the
* crypto_scrypt() function directly.
*/
/**
* The parameters maxmem, maxmemfrac, and maxtime used by all of these
* functions are defined as follows:
* maxmem - maximum number of bytes of storage to use for V array (which is
* by far the largest consumer of memory). If this value is set to 0, no
* maximum will be enforced; any other value less than 1 MiB will be
* treated as 1 MiB.
* maxmemfrac - maximum fraction of available storage to use for the V array,
* where "available storage" is defined as the minimum out of the
* RLIMIT_AS, RLIMIT_DATA. and RLIMIT_RSS resource limits (if any are
* set). This value will never cause a limit of less than 1 MiB to
* be enforced.
* maxtime - maximum amount of CPU time to spend computing the derived keys,
* in seconds. This limit is only approximately enforced; the CPU
* performance is estimated and parameter limits are chosen accordingly.
* For the encryption functions, the parameters to the scrypt key derivation
* function are chosen to make the key as strong as possible subject to the
* specified limits; for the decryption functions, the parameters used are
* compared to the computed limits and an error is returned if decrypting
* the data would take too much memory or CPU time.
*/
struct scryptenc_params {
size_t maxmem;
double maxmemfrac;
double maxtime;
/* Explicit parameters. */
int logN;
uint32_t r;
uint32_t p;
};
/* Return codes from scrypt(enc|dec)_(buf|file|prep). */
#define SCRYPT_OK 0 /* success */
#define SCRYPT_ELIMIT 1 /* getrlimit or sysctrl(hw.usermem) failed */
#define SCRYPT_ECLOCK 2 /* clock_getres or clock_gettime failed */
#define SCRYPT_EKEY 3 /* error computing derived key */
#define SCRYPT_ESALT 4 /* could not read salt */
#define SCRYPT_EOPENSSL 5 /* error in OpenSSL */
#define SCRYPT_ENOMEM 6 /* malloc failed */
#define SCRYPT_EINVAL 7 /* data is not a valid scrypt-encrypted block */
#define SCRYPT_EVERSION 8 /* unrecognized scrypt version number */
#define SCRYPT_ETOOBIG 9 /* decrypting would take too much memory */
#define SCRYPT_ETOOSLOW 10 /* decrypting would take too long */
#define SCRYPT_EPASS 11 /* password is incorrect */
#define SCRYPT_EWRFILE 12 /* error writing output file */
#define SCRYPT_ERDFILE 13 /* error reading input file */
#define SCRYPT_EPARAM 14 /* error in explicit parameters */
#define SCRYPT_EBIGSLOW 15 /* both SCRYPT_ETOOBIG and SCRYPT_ETOOSLOW */
/* Opaque structure. */
struct scryptdec_file_cookie;
/**
* scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
* params, verbose, force):
* Encrypt ${inbuflen} bytes from ${inbuf}, writing the resulting
* ${inbuflen} + 128 bytes to ${outbuf}. If ${force} is 1, do not check
* whether decryption will exceed the estimated available memory or time.
* The explicit parameters within ${params} must be zero or must all be
* non-zero. If explicit parameters are used and the computation is estimated
* to exceed resource limits, print a warning instead of returning an error.
* Return the explicit parameters used via ${params}.
*/
int scryptenc_buf(const uint8_t *, size_t, uint8_t *,
const uint8_t *, size_t, struct scryptenc_params *, int, int);
/**
* scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
* params, verbose, force):
* Decrypt ${inbuflen} bytes from ${inbuf}, writing the result into ${outbuf}
* and the decrypted data length to ${outlen}. The allocated length of
* ${outbuf} must be at least ${inbuflen}. If ${force} is 1, do not check
* whether decryption will exceed the estimated available memory or time.
* The explicit parameters within ${params} must be zero. Return the explicit
* parameters used via ${params}.
*/
int scryptdec_buf(const uint8_t *, size_t, uint8_t *, size_t *,
const uint8_t *, size_t, struct scryptenc_params *, int, int);
/**
* scryptenc_file(infile, outfile, passwd, passwdlen, params, verbose, force):
* Read a stream from ${infile} and encrypt it, writing the resulting stream
* to ${outfile}. If ${force} is 1, do not check whether decryption will
* exceed the estimated available memory or time. The explicit parameters
* within ${params} must be zero or must all be non-zero. If explicit
* parameters are used and the computation is estimated to exceed resource
* limits, print a warning instead of returning an error. Return the explicit
* parameters used via ${params}.
*/
int scryptenc_file(FILE *, FILE *, const uint8_t *, size_t,
struct scryptenc_params *, int, int);
/**
* scryptdec_file_printparams(infile):
* Print the encryption parameters (N, r, p) used for the encrypted ${infile}.
*/
int scryptdec_file_printparams(FILE *);
/**
* scryptdec_file(infile, outfile, passwd, passwdlen, params, verbose, force):
* Read a stream from ${infile} and decrypt it, writing the resulting stream
* to ${outfile}. If ${force} is 1, do not check whether decryption
* will exceed the estimated available memory or time. The explicit
* parameters within ${params} must be zero. Return the explicit parameters
* used via ${params}.
*/
int scryptdec_file(FILE *, FILE *, const uint8_t *, size_t,
struct scryptenc_params *, int, int);
/**
* scryptdec_file_prep(infile, passwd, passwdlen, params, verbose, force,
* cookie):
* Prepare to decrypt ${infile}, including checking the passphrase. Allocate
* a cookie at ${cookie}. After calling this function, ${infile} should not
* be modified until the decryption is completed by scryptdec_file_copy().
* If ${force} is 1, do not check whether decryption will exceed the estimated
* available memory or time. The explicit parameters within ${params} must be
* zero. Return the explicit parameters to be used via ${params}.
*/
int scryptdec_file_prep(FILE *, const uint8_t *, size_t,
struct scryptenc_params *, int, int, struct scryptdec_file_cookie **);
/**
* scryptdec_file_copy(cookie, outfile):
* Read a stream from the file that was passed into the ${cookie} by
* scryptdec_file_prep(), decrypt it, and write the resulting stream to
* ${outfile}. After this function completes, it is safe to modify/close
* ${outfile} and the ${infile} which was given to scryptdec_file_prep().
*/
int scryptdec_file_copy(struct scryptdec_file_cookie *, FILE *);
/**
* scryptdec_file_cookie_free(cookie):
* Free the ${cookie}.
*/
void scryptdec_file_cookie_free(struct scryptdec_file_cookie *);
#endif /* !SCRYPTENC_H_ */
================================================
FILE: lib/scryptenc/scryptenc_cpuperf.c
================================================
/*-
* 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 <sys/time.h>
#include <stdint.h>
#include <stdio.h>
#include "crypto_scrypt.h"
#include "monoclock.h"
#include "scryptenc.h"
#include "scryptenc_cpuperf.h"
static int
getclockdiff(struct timeval * st, double * diffd)
{
struct timeval en;
if (monoclock_get(&en))
return (1);
*diffd = timeval_diff((*st), en);
/* Success! */
return (0);
}
/**
* scryptenc_cpuperf(opps):
* Estimate the number of salsa20/8 cores which can be executed per second,
* and store the value in ${opps}. Return a SCRYPT_* code.
*/
int
scryptenc_cpuperf(double * opps)
{
struct timeval st;
double resd, diffd;
uint64_t i = 0;
/* Get the clock resolution. */
if (monoclock_getres(&resd))
return (SCRYPT_ECLOCK);
#ifdef DEBUG
fprintf(stderr, "Clock resolution is %g\n", resd);
#endif
/* Loop until the clock ticks. */
if (monoclock_get(&st))
return (SCRYPT_ECLOCK);
do {
/* Do an scrypt. */
if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0))
return (SCRYPT_EKEY);
/* Has the clock ticked? */
if (getclockdiff(&st, &diffd))
return (SCRYPT_ECLOCK);
if (diffd > 0)
break;
} while (1);
/* Count how many scrypts we can do before the next tick. */
if (monoclock_get(&st))
return (SCRYPT_ECLOCK);
do {
/* Do an scrypt. */
if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0))
return (SCRYPT_EKEY);
/* We invoked the salsa20/8 core 512 times. */
i += 512;
/* Check if we have looped for long enough. */
if (getclockdiff(&st, &diffd))
return (SCRYPT_ECLOCK);
if (diffd > resd)
break;
} while (1);
#ifdef DEBUG
fprintf(stderr, "%ju salsa20/8 cores performed in %g seconds\n",
(uintmax_t)i, diffd);
#endif
/* We can do approximately i salsa20/8 cores per diffd seconds. */
*opps = (double)i / diffd;
/* Success! */
return (SCRYPT_OK);
}
================================================
FILE: lib/scryptenc/scryptenc_cpuperf.h
================================================
/*-
* 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 SCRYPTENC_CPUPERF_H_
#define SCRYPTENC_CPUPERF_H_
/**
* scryptenc_cpuperf(opps):
* Estimate the number of salsa20/8 cores which can be executed per second,
* and store the value in ${opps}. Return a SCRYPT_* code.
*/
int scryptenc_cpuperf(double *);
#endif /* !SCRYPTENC_CPUPERF_H_ */
================================================
FILE: lib/scryptenc/scryptenc_print_error.c
================================================
#include <assert.h>
#include <stddef.h>
#include "warnp.h"
#include "scryptenc.h"
#include "scryptenc_print_error.h"
/**
* scryptenc_print_error(rc, infilename, outfilename):
* Print the error corresponding to ${rc}. If relevant, use ${infilename}
* or ${outfilename} to display an error about reading or writing; these
* arguments can be NULL to indicate standard input or output.
*/
void
scryptenc_print_error(int rc, const char * infilename,
const char * outfilename)
{
/* Sanity check: this should only be used for errors. */
assert(rc != SCRYPT_OK);
/* Display error. */
switch (rc) {
case SCRYPT_ELIMIT:
warnp("Error determining amount of available memory");
break;
case SCRYPT_ECLOCK:
warnp("Error reading clocks");
break;
case SCRYPT_EKEY:
warnp("Error computing derived key");
break;
case SCRYPT_ESALT:
warnp("Error reading salt");
break;
case SCRYPT_EOPENSSL:
warnp("OpenSSL error");
break;
case SCRYPT_ENOMEM:
warnp("Error allocating memory");
break;
case SCRYPT_EINVAL:
warn0("Input is not valid scrypt-encrypted block");
break;
case SCRYPT_EVERSION:
warn0("Unrecognized scrypt format version");
break;
case SCRYPT_ETOOBIG:
warn0("Decrypting file would require too much memory");
break;
case SCRYPT_ETOOSLOW:
warn0("Decrypting file would take too much CPU time");
break;
case SCRYPT_EBIGSLOW:
warn0("Decrypting file would require too much memory"
" and CPU time");
break;
case SCRYPT_EPASS:
warn0("Passphrase is incorrect");
break;
case SCRYPT_EWRFILE:
warnp("Error writing file: %s",
(outfilename != NULL) ? outfilename : "standard output");
break;
case SCRYPT_ERDFILE:
warnp("Error reading file: %s",
(infilename != NULL) ? infilename : "standard input");
break;
case SCRYPT_EPARAM:
warn0("Error in explicit parameters");
break;
default:
warn0("Programmer error: unrecognized scrypt error");
break;
}
}
================================================
FILE: lib/scryptenc/scryptenc_print_error.h
================================================
#ifndef SCRYPTENC_PRINT_ERROR_H_
#define SCRYPTENC_PRINT_ERROR_H_
/**
* scryptenc_print_error(rc, infilename, outfilename):
* Print the error corresponding to ${rc}. If relevant, use ${infilename}
* or ${outfilename} to display an error about reading or writing; these
* arguments can be NULL to indicate standard input or output.
*/
void scryptenc_print_error(int, const char *, const char *);
#endif /* !SCRYPTENC_PRINT_ERROR_H_ */
================================================
FILE: lib/util/passphrase_entry.c
================================================
#include <stdlib.h>
#include <string.h>
#include "passphrase_entry.h"
#include "readpass.h"
#include "warnp.h"
/**
* passphrase_entry_parse(arg, entry_method_p, entry_arg_p):
* Parse "METHOD:ARG" from ${arg} into an ${*entry_method_p}:${*entry_arg_p}.
*/
int
passphrase_entry_parse(const char * arg,
enum passphrase_entry * passphrase_entry_p, const char ** passphrase_arg_p)
{
const char * p;
/* Find the separator in "method:arg", or fail if there isn't one. */
if ((p = strchr(arg, ':')) == NULL)
goto err1;
/* Extract the "arg" part. */
*passphrase_arg_p = &p[1];
/* Parse the "method". */
if (strncmp(arg, "dev:", 4) == 0) {
if (strcmp(*passphrase_arg_p, "tty-stdin") == 0) {
*passphrase_entry_p = PASSPHRASE_TTY_STDIN;
goto success;
}
else if (strcmp(*passphrase_arg_p, "stdin-once") == 0) {
*passphrase_entry_p = PASSPHRASE_STDIN_ONCE;
goto success;
}
else if (strcmp(*passphrase_arg_p, "tty-once") == 0) {
*passphrase_entry_p = PASSPHRASE_TTY_ONCE;
goto success;
}
}
if (strncmp(arg, "env:", 4) == 0) {
*passphrase_entry_p = PASSPHRASE_ENV;
goto success;
}
if (strncmp(arg, "file:", 5) == 0) {
*passphrase_entry_p = PASSPHRASE_FILE;
goto success;
}
err1:
warn0("Invalid option: --passphrase %s", arg);
/* Failure! */
return (-1);
success:
/* Success! */
return (0);
}
/**
* passphrase_entry_readpass(passwd, entry_method, entry_arg, prompt,
* confirmprompt, once):
* Use ${entry_method} to read a passphrase and return it as a malloced
* NUL-terminated string via ${passwd}. If ${entry_method} is
* PASSPHRASE_TTY_STDIN and ${once} is zero, ask for the passphrase twice;
* otherwise ask for it once. If reading from a terminal, use ${prompt} for
* the first prompt, and ${confirmprompt} for the second prompt (if
* applicable); otherwise do not print any prompts.
*/
int
passphrase_entry_readpass(char ** passwd,
enum passphrase_entry passphrase_entry, const char * passphrase_arg,
const char * prompt, const char * confirmprompt, int once)
{
const char * passwd_env;
switch (passphrase_entry) {
case PASSPHRASE_TTY_STDIN:
/* Read passphrase, prompting only once if decrypting. */
if (readpass(passwd, prompt, (once) ? NULL : confirmprompt, 1))
goto err0;
break;
case PASSPHRASE_STDIN_ONCE:
/* Read passphrase, prompting only once, from stdin only. */
if (readpass(passwd, prompt, NULL, 0))
goto err0;
break;
case PASSPHRASE_TTY_ONCE:
/* Read passphrase, prompting only once, from tty only. */
if (readpass(passwd, prompt, NULL, 2))
goto err0;
break;
case PASSPHRASE_ENV:
/* We're not allowed to modify the output of getenv(). */
if ((passwd_env = getenv(passphrase_arg)) == NULL) {
warn0("Failed to read from ${%s}", passphrase_arg);
goto err0;
}
/* This allows us to use the same insecure_zero() logic. */
if ((*passwd = strdup(passwd_env)) == NULL) {
warnp("Out of memory");
goto err0;
}
break;
case PASSPHRASE_FILE:
if (readpass_file(passwd, passphrase_arg))
goto err0;
break;
case PASSPHRASE_UNSET:
warn0("Programming error: passphrase_entry is not set");
goto err0;
}
/* Success! */
return (0);
err0:
/* Failure! */
return (-1);
}
================================================
FILE: lib/util/passphrase_entry.h
================================================
#ifndef PASSPHRASE_ENTRY_H_
#define PASSPHRASE_ENTRY_H_
/* How should we get the passphrase? */
enum passphrase_entry {
PASSPHRASE_UNSET,
PASSPHRASE_TTY_STDIN,
PASSPHRASE_STDIN_ONCE,
PASSPHRASE_TTY_ONCE,
PASSPHRASE_ENV,
PASSPHRASE_FILE,
};
/**
* passphrase_entry_parse(arg, entry_method_p, entry_arg_p):
* Parse "METHOD:ARG" from ${arg} into an ${*entry_method_p}:${*entry_arg_p}.
*/
int passphrase_entry_parse(const char *, enum passphrase_entry *,
const char **);
/**
* passphrase_entry_readpass(passwd, entry_method, entry_arg, prompt,
* confirmprompt, once):
* Use ${entry_method} to read a passphrase and return it as a malloced
* NUL-terminated string via ${passwd}. If ${entry_method} is
* PASSPHRASE_TTY_STDIN and ${once} is zero, ask for the passphrase twice;
* otherwise ask for it once. If reading from a terminal, use ${prompt} for
* the first prompt, and ${confirmprompt} for the second prompt (if
* applicable); otherwise do not print any prompts.
*/
int passphrase_entry_readpass(char **, enum passphrase_entry, const char *,
const char *, const char *, int);
#endif /* !PASSPHRASE_ENTRY_H_ */
================================================
FILE: lib-platform/crypto/crypto_scrypt.c
================================================
/*-
* 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 "platform.h"
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "cpusupport.h"
#include "sha256.h"
#include "warnp.h"
#include "crypto_scrypt_smix.h"
#include "crypto_scrypt_smix_sse2.h"
#include "crypto_scrypt.h"
static void (* smix_func)(uint8_t *, size_t, uint64_t, void *, void *) = NULL;
/**
* crypto_scrypt_internal(passwd, passwdlen, salt, saltlen, N, r, p, buf,
* buflen, smix):
* Perform the requested scrypt computation, using ${smix} as the smix routine.
*/
static int
crypto_scrypt_internal(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 (* smix)(uint8_t *, size_t, uint64_t, void *, void *))
{
void * B0, * V0, * XY0;
uint8_t * B;
uint32_t * V;
uint32_t * XY;
size_t r = _r, p = _p;
uint32_t i;
/* Sanity-check parameters. */
if ((r == 0) || (p == 0)) {
errno = EINVAL;
goto err0;
}
#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 < 2)) {
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);
#if !defined(MAP_ANON) || !defined(HAVE_MMAP)
if ((errno = posix_memalign(&V0, 64, (size_t)(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));
#if !defined(MAP_ANON) || !defined(HAVE_MMAP)
if ((V0 = malloc(128 * r * N + 63)) == NULL)
goto err2;
V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
#endif
#endif
#if defined(MAP_ANON) && defined(HAVE_MMAP)
if ((V0 = mmap(NULL, (size_t)(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) */
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
/* 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) */
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
/* Free memory. */
#if defined(MAP_ANON) && defined(HAVE_MMAP)
if (munmap(V0, (size_t)(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);
}
#define TESTLEN 64
static struct scrypt_test {
const char * passwd;
const char * salt;
uint64_t N;
uint32_t r;
uint32_t p;
uint8_t result[TESTLEN];
} testcase = {
.passwd = "pleaseletmein",
.salt = "SodiumChloride",
.N = 16,
.r = 8,
.p = 1,
.result = {
0x25, 0xa9, 0xfa, 0x20, 0x7f, 0x87, 0xca, 0x09,
0xa4, 0xef, 0x8b, 0x9f, 0x77, 0x7a, 0xca, 0x16,
0xbe, 0xb7, 0x84, 0xae, 0x18, 0x30, 0xbf, 0xbf,
0xd3, 0x83, 0x25, 0xaa, 0xbb, 0x93, 0x77, 0xdf,
0x1b, 0xa7, 0x84, 0xd7, 0x46, 0xea, 0x27, 0x3b,
0xf5, 0x16, 0xa4, 0x6f, 0xbf, 0xac, 0xf5, 0x11,
0xc5, 0xbe, 0xba, 0x4c, 0x4a, 0xb3, 0xac, 0xc7,
0xfa, 0x6f, 0x46, 0x0b, 0x6c, 0x0f, 0x47, 0x7b,
}
};
static int
testsmix(void (* smix)(uint8_t *, size_t, uint64_t, void *, void *))
{
uint8_t hbuf[TESTLEN];
/* Perform the computation. */
if (crypto_scrypt_internal(
(const uint8_t *)testcase.passwd, strlen(testcase.passwd),
(const uint8_t *)testcase.salt, strlen(testcase.salt),
testcase.N, testcase.r, testcase.p, hbuf, TESTLEN, smix))
return (-1);
/* Does it match? */
return (memcmp(testcase.result, hbuf, TESTLEN));
}
static void
selectsmix(void)
{
#ifdef CPUSUPPORT_X86_SSE2
/* If we're running on an SSE2-capable CPU, try that code. */
if (cpusupport_x86_sse2()) {
/* If SSE2ized smix works, use it. */
if (!testsmix(crypto_scrypt_smix_sse2)) {
smix_func = crypto_scrypt_smix_sse2;
return;
}
warn0("Disabling broken SSE2 scrypt support - please report bug!");
}
#endif
/* If generic smix works, use it. */
if (!testsmix(crypto_scrypt_smix)) {
smix_func = crypto_scrypt_smix;
return;
}
warn0("Generic scrypt code is broken - please report bug!");
/* If we get here, something really bad happened. */
abort();
}
/**
* 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 0 < 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)
{
if (smix_func == NULL)
selectsmix();
return (crypto_scrypt_internal(passwd, passwdlen, salt, saltlen, N,
_r, _p, buf, buflen, smix_func));
}
================================================
FILE: lib-platform/crypto/crypto_scrypt.h
================================================
/*-
* 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 <stddef.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 0 < 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_ */
================================================
FILE: lib-platform/platform.h
================================================
#ifndef PLATFORM_H_
#define PLATFORM_H_
/* Ensure that we have a config file. */
#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 /* !PLATFORM_H_ */
================================================
FILE: lib-platform/util/memlimit.c
================================================
/*-
* 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 "platform.h"
#include <sys/types.h>
#include <sys/resource.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#ifdef HAVE_SYS_SYSINFO_H
#include <sys/sysinfo.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#ifdef DEBUG
#include <stdio.h>
#endif
#include "memlimit.h"
/* If we don't have CTL_HW, we can't use HW_USERMEM. */
#ifndef CTL_HW
#undef HW_USERMEM
#endif
/* Is RLIMIT_DATA relevant on this platform? */
#if !defined(HAVE_MMAP) || defined(__OpenBSD__)
#define USE_RLIMIT_DATA
#endif
#ifdef CTL_HW
static int
memlimit_sysctl_hw(size_t * memlimit, int mibleaf)
{
int mib[2];
uint8_t sysctlbuf[8];
size_t sysctlbuflen = 8;
uint64_t sysctlval;
/* Ask the kernel how much RAM we have. */
mib[0] = CTL_HW;
mib[1] = mibleaf;
if (sysctl(mib, 2, sysctlbuf, &sysctlbuflen, NULL, 0))
return (1);
/*
* If we read 8 bytes out, assume this is a system-endian uint64_t.
* If we only read 4 bytes out, the OS is trying to give us a
* uint32_t answer -- but given how many systems now have 4GB+ of RAM,
* it's probably truncating, and we really can't trust the value we
* have returned to us.
*/
if (sysctlbuflen == sizeof(uint64_t))
memcpy(&sysctlval, sysctlbuf, sizeof(uint64_t));
else if (sysctlbuflen == sizeof(uint32_t))
sysctlval = SIZE_MAX;
else
return (1);
/* Return the sysctl value, but clamp to SIZE_MAX if necessary. */
#if UINT64_MAX > SIZE_MAX
if (sysctlval > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = (size_t)sysctlval;
#else
*memlimit = sysctlval;
#endif
/* Success! */
return (0);
}
#endif
/* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */
#ifndef HAVE_STRUCT_SYSINFO
#undef HAVE_SYSINFO
#endif
/* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */
#ifndef HAVE_STRUCT_SYSINFO_TOTALRAM
#undef HAVE_SYSINFO
#endif
#ifdef HAVE_SYSINFO
static int
memlimit_sysinfo(size_t * memlimit)
{
struct sysinfo info;
uint64_t totalmem;
/* Get information from the kernel. */
if (sysinfo(&info))
return (1);
totalmem = info.totalram;
/* If we're on a modern kernel, adjust based on mem_unit. */
#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT
totalmem = totalmem * info.mem_unit;
#endif
/* Return the value, but clamp to SIZE_MAX if necessary. */
#if UINT64_MAX > SIZE_MAX
if (totalmem > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = (size_t)totalmem;
#else
*memlimit = totalmem;
#endif
/* Success! */
return (0);
}
#endif /* HAVE_SYSINFO */
static int
memlimit_rlimit(size_t * memlimit)
{
struct rlimit rl;
uint64_t memrlimit;
/* Find the least of... */
memrlimit = (uint64_t)(-1);
/* ... RLIMIT_AS... */
#ifdef RLIMIT_AS
if (getrlimit(RLIMIT_AS, &rl))
return (1);
if ((rl.rlim_cur != RLIM_INFINITY) &&
((uint64_t)rl.rlim_cur < memrlimit))
memrlimit = (uint64_t)rl.rlim_cur;
#endif
#ifdef USE_RLIMIT_DATA
/* ... RLIMIT_DATA (if we're not using mmap)... */
if (getrlimit(RLIMIT_DATA, &rl))
return (1);
if ((rl.rlim_cur != RLIM_INFINITY) &&
((uint64_t)rl.rlim_cur < memrlimit))
memrlimit = (uint64_t)rl.rlim_cur;
#endif
/* ... and RLIMIT_RSS. */
#ifdef RLIMIT_RSS
if (getrlimit(RLIMIT_RSS, &rl))
return (1);
if ((rl.rlim_cur != RLIM_INFINITY) &&
((uint64_t)rl.rlim_cur < memrlimit))
memrlimit = (uint64_t)rl.rlim_cur;
#endif
/* Return the value, but clamp to SIZE_MAX if necessary. */
#if UINT64_MAX > SIZE_MAX
if (memrlimit > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = (size_t)memrlimit;
#else
*memlimit = memrlimit;
#endif
/* Success! */
return (0);
}
#ifdef _SC_PHYS_PAGES
/* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */
#ifndef _SC_PAGE_SIZE
#define _SC_PAGE_SIZE _SC_PAGESIZE
#endif
static int
memlimit_sysconf(size_t * memlimit)
{
long pagesize;
long physpages;
uint64_t totalmem;
/* Set errno to 0 in order to distinguish "no limit" from "error". */
errno = 0;
/* Read the two limits. */
if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) ||
((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) {
/*
* Did an error occur? OS X may return EINVAL due to not
* supporting _SC_PHYS_PAGES in spite of defining it.
*/
if (errno != 0 && errno != EINVAL)
return (1);
/* If not, there is no limit. */
totalmem = (uint64_t)(-1);
} else {
/* Compute the limit. */
totalmem = (uint64_t)(pagesize) * (uint64_t)(physpages);
}
/* Return the value, but clamp to SIZE_MAX if necessary. */
#if UINT64_MAX > SIZE_MAX
if (totalmem > SIZE_MAX)
*memlimit = SIZE_MAX;
else
*memlimit = (size_t)totalmem;
#else
*memlimit = totalmem;
#endif
/* Success! */
return (0);
}
#endif
/**
* memtouse(maxmem, maxmemfrac, memlimit):
* Examine the system and return the amount of RAM which should be
* used in ${memlimit}. This value should be the specified
* ${maxmemfrac} fraction of available RAM, but no more than
* ${maxmem} and no less than 1 MiB. ${maxmemfrac} must be larger than 0
* and <= 1.0.
*/
int
memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit)
{
size_t usermem_memlimit, memsize_memlimit;
size_t sysinfo_memlimit, rlimit_memlimit;
size_t sysconf_memlimit;
size_t memlimit_min;
size_t memavail;
/* Check limit. */
assert((maxmemfrac > 0) && (maxmemfrac <= 1.0));
/* Get memory limits. */
#ifdef HW_USERMEM
if (memlimit_sysctl_hw(&usermem_memlimit, HW_USERMEM))
return (1);
#else
usermem_memlimit = SIZE_MAX;
#endif
#ifdef HW_MEMSIZE
if (memlimit_sysctl_hw(&memsize_memlimit, HW_MEMSIZE))
return (1);
#else
memsize_memlimit = SIZE_MAX;
#endif
#ifdef HAVE_SYSINFO
if (memlimit_sysinfo(&sysinfo_memlimit))
return (1);
#else
sysinfo_memlimit = SIZE_MAX;
#endif
if (memlimit_rlimit(&rlimit_memlimit))
return (1);
#ifdef _SC_PHYS_PAGES
if (memlimit_sysconf(&sysconf_memlimit))
return (1);
#else
sysconf_memlimit = SIZE_MAX;
#endif
#ifdef DEBUG
/* rlimit has two '\t' so that they line up. */
fprintf(stderr, "Memory limits are:\n\tusermem:\t%zu\n"
"\tmemsize:\t%zu\n\tsysinfo:\t%zu\n\trlimit:\t\t%zu\n"
"\tsysconf:\t%zu\n", usermem_memlimit, memsize_memlimit,
sysinfo_memlimit, rlimit_memlimit, sysconf_memlimit);
#endif
/*
* Some systems return bogus values for hw.usermem due to ZFS making
* use of wired pages. Assume that at least 50% of physical pages
* are available to userland on demand.
*/
if (sysconf_memlimit != SIZE_MAX) {
if (usermem_memlimit < sysconf_memlimit / 2)
usermem_memlimit = sysconf_memlimit / 2;
}
/* Find the smallest of them. */
memlimit_min = SIZE_MAX;
if (memlimit_min > usermem_memlimit)
memlimit_min = usermem_memlimit;
if (memlimit_min > memsize_memlimit)
memlimit_min = memsize_memlimit;
if (memlimit_min > sysinfo_memlimit)
memlimit_min = sysinfo_memlimit;
if (memlimit_min > rlimit_memlimit)
memlimit_min = rlimit_memlimit;
if (memlimit_min > sysconf_memlimit)
memlimit_min = sysconf_memlimit;
#ifdef DEBUG
/* This line is continued after the maxmemfrac calculation. */
fprintf(stderr, "Minimum is %zu;", memlimit_min);
#endif
/* Only use the specified fraction of the available memory. */
memavail = (size_t)(maxmemfrac * (double)memlimit_min);
#ifdef DEBUG
fprintf(stderr, " will apply maxmemfrac of %g\n", maxmemfrac);
#endif
/* Don't use more than the specified maximum. */
if ((maxmem > 0) && (memavail > maxmem))
memavail = maxmem;
/* But always allow at least 1 MiB. */
if (memavail < 1048576)
memavail = 1048576;
#ifdef DEBUG
fprintf(stderr, "Memory allowed:\t\t%zu\n", memavail);
#endif
/* Return limit via the provided pointer. */
*memlimit = memavail;
return (0);
}
================================================
FILE: lib-platform/util/memlimit.h
================================================
/*-
* 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 MEMLIMIT_H_
#define MEMLIMIT_H_
#include <stddef.h>
/**
* memtouse(maxmem, maxmemfrac, memlimit):
* Examine the system and return the amount of RAM which should be
* used in ${memlimit}. This value should be the specified
* ${maxmemfrac} fraction of available RAM, but no more than
* ${maxmem} and no less than 1 MiB. ${maxmemfrac} must be larger than 0
* and <= 1.0.
*/
int memtouse(size_t, double, size_t *);
#endif /* !MEMLIMIT_H_ */
================================================
FILE: libcperciva/POSIX/README
================================================
POSIX compatibility code
------------------------
This code exists to work around some common POSIX compatibility issues.
POSIX specifies that if the first line of a Makefile is ".POSIX:" then the
Makefile should be processed according to POSIX rules, including with CC=c99;
thus we should see behaviour consistent with a standard-compliant C99
compiler.
One POSIX compatibility check requires a runtime test. This will be
automatically disabled if the build system detects that you are
cross-compiling for another platform, or it can be manually disabled by
setting DISABLE_POSIX_RUNTIME_CHECKS to a non-zero value.
- posix-cflags.sh: Detects if ${CC} supports certain POSIX features, and
outputs a POSIXFAIL_ define if it is not supported so that we can work around
the problem.
The potential command-line flags are:
- DPOSIXFAIL_MSG_NOSIGNAL: <sys/socket.h> not defining MSG_NOSIGNAL.
- DPOSIXFAIL_CLOCK_REALTIME: <time.h> not defining CLOCK_REALTIME.
- DPOSIXFAIL_CLOCK_GETTIME: <time.h> not declaring clock_gettime(), or
clock_gettime() is not linkable. The latter test requires a runtime check.
- DPOSIXFAIL_INET_ADDRSTRLEN: <netinet/in.h> not defining
INET_ADDRSTRLEN.
- DPOSIXFAIL_INET6_ADDRSTRLEN: <netinet/in.h> not defining
INET6_ADDRSTRLEN.
- DPOSIXFAIL_ABSTRACT_DECLARATOR: ${CC} does not accept
qualifiers in an abstract declarator.
- DPOSIXFAIL_STAT_ST_MTIM: struct stat does not contain st_mtim.
- std=c99: ${CC} does not accept the `restrict` keyword by default, but
accepts it when given this flag.
- posix-cflags-filter.sh: Detects if ${CC} supports expected ${CFLAG} value(s).
The potential ${CFLAGS} flags it checks are:
- O2: some compilers only accept -O.
- posix-l.sh: Detects whether the linker supports certain POSIX features.
The potential command-line flags are:
- lrt lxnet: c99 is required to understand these options, and ignore them if
the routines for which they specify linkage are already in the standard C
library
================================================
FILE: libcperciva/POSIX/posix-abstract-declarator.c
================================================
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
static int func(int ARGNAME[static restrict 1]);
#else
static int func(int [static restrict 1]);
#endif
int
func(int arr[static restrict 1])
{
(void)arr; /* UNUSED */
/* Success! */
return (0);
}
int
main(void)
{
(void)func; /* UNUSED */
/* Success! */
return (0);
}
================================================
FILE: libcperciva/POSIX/posix-cflags.sh
================================================
# Should be sourced by
# command -p sh posix-cflags.sh "$PATH"
# from within a Makefile.
# Sanity check environment variables
if [ -z "${CC}" ]; then
echo "\$CC is not defined! Cannot run any compiler tests." 1>&2
exit 1
fi
if ! [ "${PATH}" = "$1" ]; then
echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2
PATH=$1
fi
# Find directory of this script and the source files
D=$(dirname "$0")
# Check if we can compile & run a binary.
if ! ${CC} ${CFLAGS} "${D}/posix-trivial.c" 2>/dev/null; then
echo "WARNING: failed to compile posix-trivial.c" 1>&2
else
# If the user hasn't disabled runtime checks...
if [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -eq "0" ]; then
# ... test if we can run the trivial binary.
if ! ./a.out ; then
echo "WARNING: failed to run a trivial binary; " 1>&2
echo "disabling runtime POSIX compatibility checks" 1>&2
DISABLE_POSIX_RUNTIME_CHECKS=1
fi
fi
fi
FIRST=YES
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-msg_nosignal.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_MSG_NOSIGNAL"
echo "WARNING: POSIX violation: <sys/socket.h> not defining MSG_NOSIGNAL" 1>&2
fi
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-clock_realtime.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_CLOCK_REALTIME"
echo "WARNING: POSIX violation: <time.h> not defining CLOCK_REALTIME" 1>&2
fi
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-inet-addrstrlen.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_INET_ADDRSTRLEN"
echo "WARNING: POSIX violation: <netinet/in.h> not defining INET_ADDRSTRLEN" 1>&2
fi
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-inet6-addrstrlen.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_INET6_ADDRSTRLEN"
echo "WARNING: POSIX violation: <netinet/in.h> not defining INET6_ADDRSTRLEN" 1>&2
fi
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-clock_gettime.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_CLOCK_GETTIME"
echo "WARNING: POSIX violation: <time.h> not declaring clock_gettime()" 1>&2
elif [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -ne "0" ]; then
# Do nothing
true
else
# Even if the compilation succeeds, we still need to run the binary
# because OS X 10.11 with XCode 8 _will_ contain clock_gettime() in the
# header (because it was added in 10.12 and they only use one SDK per
# XCode version), but it will link to the 10.11 library (which doesn't
# include it). Annoyingly, there's two levels of error output on OS X:
# one from the binary itself, and one from the signal it sends to the
# calling process. The "( ./x 2>y ) 2>y" captures both types of error
# message.
if ! ( ./a.out 2>/dev/null ) 2>/dev/null ; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_CLOCK_GETTIME"
echo "WARNING: POSIX violation: clock_gettime() is not linkable" 1>&2
fi
fi
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-stat-st_mtim.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_STAT_ST_MTIM"
echo "WARNING: POSIX violation: struct stat does not contain st_mtim" 1>&2
fi
CFLAGS_C99=""
if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-restrict.c" 2>/dev/null; then
echo "WARNING: POSIX violation: ${CC} does not accept the 'restrict' keyword" 1>&2
if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -std=c99 "${D}/posix-restrict.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-std=c99"
CFLAGS_C99="-std=c99"
fi
fi
if ! ${CC} ${CFLAGS} ${CFLAGS_C99} -D_POSIX_C_SOURCE=200809L -DARGNAME="" "${D}/posix-abstract-declarator.c" 2>/dev/null; then
echo "WARNING: POSIX violation: ${CC} does not accept qualifiers in an abstract declarator" 1>&2
# Test compile with -DPOSIXFAIL_ABSTRACT_DECLARATOR
if ${CC} ${CFLAGS} ${CFLAGS_C99} -D_POSIX_C_SOURCE=200809L -DPOSIXFAIL_ABSTRACT_DECLARATOR "${D}/posix-abstract-declarator.c" 2>/dev/null; then
[ "${FIRST}" = "NO" ] && printf " "; FIRST=NO
printf %s "-DPOSIXFAIL_ABSTRACT_DECLARATOR"
fi
fi
rm -f a.out
================================================
FILE: libcperciva/POSIX/posix-clock_gettime.c
================================================
#include <time.h>
int
main(void)
{
struct timespec ts;
return (clock_gettime(CLOCK_REALTIME, &ts));
}
================================================
FILE: libcperciva/POSIX/posix-clock_realtime.c
================================================
#include <time.h>
int
main(void)
{
return (CLOCK_REALTIME);
}
================================================
FILE: libcperciva/POSIX/posix-inet-addrstrlen.c
================================================
#include <netinet/in.h>
int
main(void)
{
return (INET_ADDRSTRLEN);
}
================================================
FILE: libcperciva/POSIX/posix-inet6-addrstrlen.c
================================================
#include <netinet/in.h>
int
main(void)
{
return (INET6_ADDRSTRLEN);
}
================================================
FILE: libcperciva/POSIX/posix-l.sh
================================================
# Should be sourced by
# command -p sh posix-l.sh "$PATH"
# from within a Makefile.
# Sanity check environment variables
if [ -z "${CC}" ]; then
echo "\$CC is not defined! Cannot run any compiler tests." 1>&2
exit 1
fi
if ! [ "${PATH}" = "$1" ]; then
echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2
PATH=$1
fi
# Find directory of this script and the source files
D=$(dirname "$0")
FIRST=YES
for LIB in rt xnet; do
if ${CC} ${CFLAGS} -l"${LIB}" "${D}/posix-trivial.c" 2>/dev/null; then
if [ "${FIRST}" = "NO" ]; then
printf " ";
fi
printf "%s" "-l${LIB}";
FIRST=NO;
else
echo "WARNING: POSIX violation: ${CC} does not understand -l${LIB}" 1>&2
fi
rm -f a.out
done
================================================
FILE: libcperciva/POSIX/posix-msg_nosignal.c
================================================
#include <sys/socket.h>
int
main(void)
{
return (MSG_NOSIGNAL);
}
================================================
FILE: libcperciva/POSIX/posix-restrict.c
================================================
static int
foo(const char * restrict x, const char * restrict y)
{
return (x == y);
}
int
main(void)
{
char x[10];
char y[10];
return (foo(x, y));
}
================================================
FILE: libcperciva/POSIX/posix-stat-st_mtim.c
================================================
#include <sys/stat.h>
int
main(void)
{
struct stat sb;
/* Can we reference st_mtim? */
(void)sb.st_mtim.tv_sec;
/* Success! */
return (0);
}
================================================
FILE: libcperciva/POSIX/posix-trivial.c
================================================
int
main(void)
{
/* Success! */
return (0);
}
================================================
FILE: libcperciva/alg/sha256.c
================================================
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "cpusupport.h"
#include "insecure_memzero.h"
#include "sha256_arm.h"
#include "sha256_shani.h"
#include "sha256_sse2.h"
#include "sysendian.h"
#include "warnp.h"
#include "sha256.h"
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) || \
defined(CPUSUPPORT_X86_SSE2) || \
defined(CPUSUPPORT_ARM_SHA256)
#define HWACCEL
static enum {
HW_SOFTWARE = 0,
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)
HW_X86_SHANI,
#endif
#if defined(CPUSUPPORT_X86_SSE2)
HW_X86_SSE2,
#endif
#if defined(CPUSUPPORT_ARM_SHA256)
HW_ARM_SHA256,
#endif
HW_UNSET
} hwaccel = HW_UNSET;
#endif
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
static void SHA256_Transform(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64], uint32_t W[static restrict 64],
uint32_t S[static restrict 8]);
#else
static void SHA256_Transform(uint32_t[static restrict 8],
const uint8_t[static restrict 64], uint32_t[static restrict 64],
uint32_t[static restrict 8]);
#endif
/*
* Encode a length len/4 vector of (uint32_t) into a length len vector of
* (uint8_t) in big-endian form. Assumes len is a multiple of 4.
*/
static void
be32enc_vect(uint8_t * dst, const uint32_t * src, size_t len)
{
size_t i;
/* Sanity-check. */
assert(len % 4 == 0);
/* Encode vector, one word at a time. */
for (i = 0; i < len / 4; i++)
be32enc(dst + i * 4, src[i]);
}
/*
* Decode a big-endian length len vector of (uint8_t) into a length
* len/4 vector of (uint32_t). Assumes len is a multiple of 4.
*/
static void
be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len)
{
size_t i;
/* Sanity-check. */
assert(len % 4 == 0);
/* Decode vector, one word at a time. */
for (i = 0; i < len / 4; i++)
dst[i] = be32dec(src + i * 4);
}
/* SHA256 round constants. */
static const uint32_t Krnd[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/* Magic initialization constants. */
static const uint32_t initial_state[8] = {
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};
#ifdef HWACCEL
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)
/* Shim so that we can test SHA256_Transform_shani() in the standard manner. */
static void
SHA256_Transform_shani_with_W_S(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64], uint32_t W[static restrict 64],
uint32_t S[static restrict 8])
{
(void)W; /* UNUSED */
(void)S; /* UNUSED */
SHA256_Transform_shani(state, block);
}
#endif
#if defined(CPUSUPPORT_ARM_SHA256)
/* Shim so that we can test SHA256_Transform_arm() in the standard manner. */
static void
SHA256_Transform_arm_with_W_S(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64], uint32_t W[static restrict 64],
uint32_t S[static restrict 8])
{
(void)W; /* UNUSED */
(void)S; /* UNUSED */
SHA256_Transform_arm(state, block);
}
#endif
/*
* Test whether software and hardware extensions transform code produce the
* same results. Must be called with (hwaccel == HW_SOFTWARE).
*/
static int
hwtest(const uint32_t state[static restrict 8],
const uint8_t block[static restrict 64],
uint32_t W[static restrict 64], uint32_t S[static restrict 8],
void (* func)(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64], uint32_t W[static restrict 64],
uint32_t S[static restrict 8]))
{
uint32_t state_sw[8];
uint32_t state_hw[8];
/* Software transform. */
memcpy(state_sw, state, sizeof(state_sw));
SHA256_Transform(state_sw, block, W, S);
/* Hardware transform. */
memcpy(state_hw, state, sizeof(state_hw));
func(state_hw, block, W, S);
/* Do the results match? */
return (memcmp(state_sw, state_hw, sizeof(state_sw)));
}
/* Which type of hardware acceleration should we use, if any? */
static void
hwaccel_init(void)
{
uint32_t W[64];
uint32_t S[8];
uint8_t block[64];
uint8_t i;
/* If we've already set hwaccel, we're finished. */
if (hwaccel != HW_UNSET)
return;
/* Default to software. */
hwaccel = HW_SOFTWARE;
/* Test case: Hash 0x00 0x01 0x02 ... 0x3f. */
for (i = 0; i < 64; i++)
block[i] = i;
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)
CPUSUPPORT_VALIDATE(hwaccel, HW_X86_SHANI,
cpusupport_x86_shani() && cpusupport_x86_ssse3(),
hwtest(initial_state, block, W, S,
SHA256_Transform_shani_with_W_S));
#endif
#if defined(CPUSUPPORT_X86_SSE2)
CPUSUPPORT_VALIDATE(hwaccel, HW_X86_SSE2, cpusupport_x86_sse2(),
hwtest(initial_state, block, W, S, SHA256_Transform_sse2));
#endif
#if defined(CPUSUPPORT_ARM_SHA256)
CPUSUPPORT_VALIDATE(hwaccel, HW_ARM_SHA256, cpusupport_arm_sha256(),
hwtest(initial_state, block, W, S, SHA256_Transform_arm_with_W_S));
#endif
}
#endif /* HWACCEL */
/* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
/* SHA256 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
h += S1(e) + Ch(e, f, g) + k; \
d += h; \
h += S0(a) + Maj(a, b, c)
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, ii) \
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
S[(66 - i) % 8], S[(67 - i) % 8], \
S[(68 - i) % 8], S[(69 - i) % 8], \
S[(70 - i) % 8], S[(71 - i) % 8], \
W[i + ii] + Krnd[i + ii])
/* Message schedule computation */
#define MSCH(W, ii, i) \
W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
/*
* SHA256 block compression function. The 256-bit state is transformed via
* the 512-bit input block to produce a new state. The arrays W and S may be
* filled with sensitive data, and should be sanitized by the callee.
*/
static void
SHA256_Transform(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64],
uint32_t W[static restrict 64], uint32_t S[static restrict 8])
{
int i;
#ifdef HWACCEL
#if defined(__GNUC__) && defined(__aarch64__)
/*
* We require that SHA256_Init() is called before SHA256_Transform(),
* but the compiler has no way of knowing that. This assert adds a
* significant speed boost for gcc on 64-bit ARM, and a minor penalty
* on other systems & compilers.
*/
assert(hwaccel != HW_UNSET);
#endif
switch (hwaccel) {
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)
case HW_X86_SHANI:
SHA256_Transform_shani(state, block);
return;
#endif
#if defined(CPUSUPPORT_X86_SSE2)
case HW_X86_SSE2:
SHA256_Transform_sse2(state, block, W, S);
return;
#endif
#if defined(CPUSUPPORT_ARM_SHA256)
case HW_ARM_SHA256:
SHA256_Transform_arm(state, block);
return;
#endif
case HW_SOFTWARE:
case HW_UNSET:
break;
}
#endif /* HWACCEL */
/* 1. Prepare the first part of the message schedule W. */
be32dec_vect(W, block, 64);
/* 2. Initialize working variables. */
memcpy(S, state, 32);
/* 3. Mix. */
for (i = 0; i < 64; i += 16) {
RNDr(S, W, 0, i);
RNDr(S, W, 1, i);
RNDr(S, W, 2, i);
RNDr(S, W, 3, i);
RNDr(S, W, 4, i);
RNDr(S, W, 5, i);
RNDr(S, W, 6, i);
RNDr(S, W, 7, i);
RNDr(S, W, 8, i);
RNDr(S, W, 9, i);
RNDr(S, W, 10, i);
RNDr(S, W, 11, i);
RNDr(S, W, 12, i);
RNDr(S, W, 13, i);
RNDr(S, W, 14, i);
RNDr(S, W, 15, i);
if (i == 48)
break;
MSCH(W, 0, i);
MSCH(W, 1, i);
MSCH(W, 2, i);
MSCH(W, 3, i);
MSCH(W, 4, i);
MSCH(W, 5, i);
MSCH(W, 6, i);
MSCH(W, 7, i);
MSCH(W, 8, i);
MSCH(W, 9, i);
MSCH(W, 10, i);
MSCH(W, 11, i);
MSCH(W, 12, i);
MSCH(W, 13, i);
MSCH(W, 14, i);
MSCH(W, 15, i);
}
/* 4. Mix local working variables into global state. */
for (i = 0; i < 8; i++)
state[i] += S[i];
}
static const uint8_t PAD[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
SHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72])
{
size_t r;
/* Figure out how many bytes we have buffered. */
r = (ctx->count >> 3) & 0x3f;
/* Pad to 56 mod 64, transforming if we finish a block en route. */
if (r < 56) {
/* Pad to 56 mod 64. */
memcpy(&ctx->buf[r], PAD, 56 - r);
} else {
/* Finish the current block and mix. */
memcpy(&ctx->buf[r], PAD, 64 - r);
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
/* The start of the final block is all zeroes. */
memset(&ctx->buf[0], 0, 56);
}
/* Add the terminating bit-count. */
be64enc(&ctx->buf[56], ctx->count);
/* Mix in the final block. */
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
}
/**
* SHA256_Init(ctx):
* Initialize the SHA256 context ${ctx}.
*/
void
SHA256_Init(SHA256_CTX * ctx)
{
/* Zero bits processed so far. */
ctx->count = 0;
/* Initialize state. */
memcpy(ctx->state, initial_state, sizeof(initial_state));
#ifdef HWACCEL
/* Ensure that we've chosen the type of hardware acceleration. */
hwaccel_init();
#endif
}
/**
* SHA256_Update(ctx, in, len):
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
*/
static void
SHA256_Update_internal(SHA256_CTX * ctx, const void * in, size_t len,
uint32_t tmp32[static restrict 72])
{
uint32_t r;
const uint8_t * src = in;
/* Return immediately if we have nothing to do. */
if (len == 0)
return;
/* Number of bytes left in the buffer from previous updates. */
r = (ctx->count >> 3) & 0x3f;
/* Update number of bits. */
ctx->count += (uint64_t)(len) << 3;
/* Handle the case where we don't need to perform any transforms. */
if (len < 64 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block. */
memcpy(&ctx->buf[r], src, 64 - r);
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
src += 64 - r;
len -= 64 - r;
/* Perform complete blocks. */
while (len >= 64) {
SHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]);
src += 64;
len -= 64;
}
/* Copy left over data into buffer. */
memcpy(ctx->buf, src, len);
}
/* Wrapper function for intermediate-values sanitization. */
void
SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
{
uint32_t tmp32[72];
/* Call the real function. */
SHA256_Update_internal(ctx, in, len, tmp32);
/* Clean the stack. */
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
}
/**
* SHA256_Final(digest, ctx):
* Output the SHA256 hash of the data input to the context ${ctx} into the
* buffer ${digest}, and clear the context state.
*/
static void
SHA256_Final_internal(uint8_t digest[32], SHA256_CTX * ctx,
uint32_t tmp32[static restrict 72])
{
/* Add padding. */
SHA256_Pad(ctx, tmp32);
/* Write the hash. */
be32enc_vect(digest, ctx->state, 32);
}
/* Wrapper function for intermediate-values sanitization. */
void
SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx)
{
uint32_t tmp32[72];
/* Call the real function. */
SHA256_Final_internal(digest, ctx, tmp32);
/* Clear the context state. */
insecure_memzero(ctx, sizeof(SHA256_CTX));
/* Clean the stack. */
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
}
/**
* SHA256_Buf(in, len, digest):
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
*/
void
SHA256_Buf(const void * in, size_t len, uint8_t digest[32])
{
SHA256_CTX ctx;
uint32_t tmp32[72];
SHA256_Init(&ctx);
SHA256_Update_internal(&ctx, in, len, tmp32);
SHA256_Final_internal(digest, &ctx, tmp32);
/* Clean the stack. */
insecure_memzero(&ctx, sizeof(SHA256_CTX));
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
}
/**
* HMAC_SHA256_Init(ctx, K, Klen):
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
* ${K}.
*/
static void
HMAC_SHA256_Init_internal(HMAC_SHA256_CTX * ctx, const void * _k, size_t Klen,
uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64],
uint8_t khash[static restrict 32])
{
const uint8_t * K = _k;
size_t i;
/* If Klen > 64, the key is really SHA256(K). */
if (Klen > 64) {
SHA256_Init(&ctx->ictx);
SHA256_Update_internal(&ctx->ictx, K, Klen, tmp32);
SHA256_Final_internal(khash, &ctx->ictx, tmp32);
K = khash;
Klen = 32;
}
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
SHA256_Init(&ctx->ictx);
memset(pad, 0x36, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
SHA256_Update_internal(&ctx->ictx, pad, 64, tmp32);
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
SHA256_Init(&ctx->octx);
memset(pad, 0x5c, 64);
for (i = 0; i < Klen; i++)
pad[i] ^= K[i];
SHA256_Update_internal(&ctx->octx, pad, 64, tmp32);
}
/* Wrapper function for intermediate-values sanitization. */
void
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * K, size_t Klen)
{
uint32_t tmp32[72];
uint8_t pad[64];
uint8_t khash[32];
/* Call the real function. */
HMAC_SHA256_Init_internal(ctx, K, Klen, tmp32, pad, khash);
/* Clean the stack. */
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
insecure_memzero(khash, 32);
insecure_memzero(pad, 64);
}
/**
* HMAC_SHA256_Update(ctx, in, len):
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
*/
static void
HMAC_SHA256_Update_internal(HMAC_SHA256_CTX * ctx, const void * in, size_t len,
uint32_t tmp32[static restrict 72])
{
/* Feed data to the inner SHA256 operation. */
SHA256_Update_internal(&ctx->ictx, in, len, tmp32);
}
/* Wrapper function for intermediate-values sanitization. */
void
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)
{
uint32_t tmp32[72];
/* Call the real function. */
HMAC_SHA256_Update_internal(ctx, in, len, tmp32);
/* Clean the stack. */
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
}
/**
* HMAC_SHA256_Final(digest, ctx):
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
* buffer ${digest}, and clear the context state.
*/
static void
HMAC_SHA256_Final_internal(uint8_t digest[32], HMAC_SHA256_CTX * ctx,
uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32])
{
/* Finish the inner SHA256 operation. */
SHA256_Final_internal(ihash, &ctx->ictx, tmp32);
/* Feed the inner hash to the outer SHA256 operation. */
SHA256_Update_internal(&ctx->octx, ihash, 32, tmp32);
/* Finish the outer SHA256 operation. */
SHA256_Final_internal(digest, &ctx->octx, tmp32);
}
/* Wrapper function for intermediate-values sanitization. */
void
HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx)
{
uint32_t tmp32[72];
uint8_t ihash[32];
/* Call the real function. */
HMAC_SHA256_Final_internal(digest, ctx, tmp32, ihash);
/* Clear the context state. */
insecure_memzero(ctx, sizeof(HMAC_SHA256_CTX));
/* Clean the stack. */
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
insecure_memzero(ihash, 32);
}
/**
* HMAC_SHA256_Buf(K, Klen, in, len, digest):
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
* length ${Klen}, and write the result to ${digest}.
*/
void
HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len,
uint8_t digest[32])
{
HMAC_SHA256_CTX ctx;
uint32_t tmp32[72];
uint8_t tmp8[96];
HMAC_SHA256_Init_internal(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]);
HMAC_SHA256_Update_internal(&ctx, in, len, tmp32);
HMAC_SHA256_Final_internal(digest, &ctx, tmp32, &tmp8[0]);
/* Clean the stack. */
insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
insecure_memzero(tmp8, 96);
}
/**
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
*/
void
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
{
HMAC_SHA256_CTX Phctx, PShctx, hctx;
uint32_t tmp32[72];
uint8_t tmp8[96];
size_t i;
uint8_t ivec[4];
uint8_t U[32];
uint8_t T[32];
uint64_t j;
int k;
size_t clen;
#if SIZE_MAX >= (32 * UINT32_MAX)
/* Sanity-check. */
assert(dkLen <= 32 * (size_t)(UINT32_MAX));
#endif
/* Compute HMAC state after processing P. */
HMAC_SHA256_Init_internal(&Phctx, passwd, passwdlen,
tmp32, &tmp8[0], &tmp8[64]);
/* Compute HMAC state after processing P and S. */
memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX));
HMAC_SHA256_Update_internal(&PShctx, salt, saltlen, tmp32);
/* Iterate through the blocks. */
for (i = 0; i * 32 < dkLen; i++) {
/* Generate INT(i + 1). */
be32enc(ivec, (uint32_t)(i + 1));
/* Compute U_1 = PRF(P, S || INT(i)). */
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
HMAC_SHA256_Update_internal(&hctx, ivec, 4, tmp32);
HMAC_SHA256_Final_internal(U, &hctx, tmp32, tmp8);
/* T_i = U_1 ... */
memcpy(T, U, 32);
for (j = 2; j <= c; j++) {
/* Compute U_j. */
memcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX));
HMAC_SHA256_Update_internal(&hctx, U, 32, tmp32);
HMAC_SHA256_Final_internal(U, &hctx, tmp32, tmp8);
/* ... xor U_j ... */
for (k = 0; k < 32; k++)
T[k] ^= U[k];
}
/* Copy as many bytes as necessary into buf. */
clen = dkLen - i * 32;
if (clen > 32)
clen = 32;
memcpy(&buf[i * 32], T, clen);
}
/* Clean the stack. */
insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX));
insecure_memzero(tmp32, sizeof(uint32_t) * 72);
insecure_memzero(tmp8, 96);
insecure_memzero(U, 32);
insecure_memzero(T, 32);
}
================================================
FILE: libcperciva/alg/sha256.h
================================================
#ifndef SHA256_H_
#define SHA256_H_
#include <stddef.h>
#include <stdint.h>
/*
* Use #defines in order to avoid namespace collisions with anyone else's
* SHA256 code (e.g., the code in OpenSSL).
*/
#define SHA256_Init libcperciva_SHA256_Init
#define SHA256_Update libcperciva_SHA256_Update
#define SHA256_Final libcperciva_SHA256_Final
#define SHA256_Buf libcperciva_SHA256_Buf
#define SHA256_CTX libcperciva_SHA256_CTX
#define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init
#define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update
#define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final
#define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf
#define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX
/* Context structure for SHA256 operations. */
typedef struct {
uint32_t state[8];
uint64_t count;
uint8_t buf[64];
} SHA256_CTX;
/**
* SHA256_Init(ctx):
* Initialize the SHA256 context ${ctx}.
*/
void SHA256_Init(SHA256_CTX *);
/**
* SHA256_Update(ctx, in, len):
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
*/
void SHA256_Update(SHA256_CTX *, const void *, size_t);
/**
* SHA256_Final(digest, ctx):
* Output the SHA256 hash of the data input to the context ${ctx} into the
* buffer ${digest}, and clear the context state.
*/
void SHA256_Final(uint8_t[32], SHA256_CTX *);
/**
* SHA256_Buf(in, len, digest):
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
*/
void SHA256_Buf(const void *, size_t, uint8_t[32]);
/* Context structure for HMAC-SHA256 operations. */
typedef struct {
SHA256_CTX ictx;
SHA256_CTX octx;
} HMAC_SHA256_CTX;
/**
* HMAC_SHA256_Init(ctx, K, Klen):
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
* ${K}.
*/
void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);
/**
* HMAC_SHA256_Update(ctx, in, len):
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
*/
void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);
/**
* HMAC_SHA256_Final(digest, ctx):
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
* buffer ${digest}, and clear the context state.
*/
void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *);
/**
* HMAC_SHA256_Buf(K, Klen, in, len, digest):
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
* length ${Klen}, and write the result to ${digest}.
*/
void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]);
/**
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
*/
void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
uint64_t, uint8_t *, size_t);
#endif /* !SHA256_H_ */
================================================
FILE: libcperciva/alg/sha256_arm.c
================================================
#include "cpusupport.h"
#ifdef CPUSUPPORT_ARM_SHA256
/**
* CPUSUPPORT CFLAGS: ARM_SHA256
*/
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __ARM_NEON
#include <arm_neon.h>
#endif
#include "sha256_arm.h"
/* SHA256 round constants. */
static const uint32_t Krnd[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/* Round computation. */
#define RND4(S, M, Kp) do { \
uint32x4_t S0_step; \
uint32x4_t Wk; \
S0_step = S[0]; \
Wk = vaddq_u32(M, vld1q_u32(Kp)); \
S[0] = vsha256hq_u32(S[0], S[1], Wk); \
S[1] = vsha256h2q_u32(S[1], S0_step, Wk); \
} while (0)
/* Message schedule computation */
#define MSG4(X0, X1, X2, X3) \
X0 = vsha256su1q_u32(vsha256su0q_u32(X0, X1), X2, X3)
/**
* SHA256_Transform_arm(state, block):
* Compute the SHA256 block compression function, transforming ${state} using
* the data in ${block}. This implementation uses ARM SHA256 instructions,
* and should only be used if _SHA256 is defined and cpusupport_arm_sha256()
* returns nonzero.
*/
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
void
SHA256_Transform_arm(uint32_t state[8], const uint8_t block[64])
#else
void
SHA256_Transform_arm(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64])
#endif
{
uint32x4_t Y[4];
uint32x4_t S[2];
uint32x4_t _state[2];
int i;
/* 1. Prepare the first part of the message schedule W. */
Y[0] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[0])));
Y[1] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[16])));
Y[2] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[32])));
Y[3] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[48])));
/* 2. Initialize working variables. */
S[0] = _state[0] = vld1q_u32(&state[0]);
S[1] = _state[1] = vld1q_u32(&state[4]);
/* 3. Mix. */
for (i = 0; i < 64; i += 16) {
RND4(S, Y[0], &Krnd[i + 0]);
RND4(S, Y[1], &Krnd[i + 4]);
RND4(S, Y[2], &Krnd[i + 8]);
RND4(S, Y[3], &Krnd[i + 12]);
if (i == 48)
break;
MSG4(Y[0], Y[1], Y[2], Y[3]);
MSG4(Y[1], Y[2], Y[3], Y[0]);
MSG4(Y[2], Y[3], Y[0], Y[1]);
MSG4(Y[3], Y[0], Y[1], Y[2]);
}
/* 4. Mix local working variables into global state. */
vst1q_u32(&state[0], vaddq_u32(_state[0], S[0]));
vst1q_u32(&state[4], vaddq_u32(_state[1], S[1]));
}
#endif /* CPUSUPPORT_ARM_SHA256 */
================================================
FILE: libcperciva/alg/sha256_arm.h
================================================
#ifndef SHA256_ARM_H_
#define SHA256_ARM_H_
#include <stdint.h>
/**
* SHA256_Transform_arm(state, block):
* Compute the SHA256 block compression function, transforming ${state} using
* the data in ${block}. This implementation uses ARM SHA256 instructions,
* and should only be used if _SHA256 is defined and cpusupport_arm_sha256()
* returns nonzero.
*/
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
void SHA256_Transform_arm(uint32_t state[8], const uint8_t block[64]);
#else
void SHA256_Transform_arm(uint32_t[static restrict 8],
const uint8_t[static restrict 64]);
#endif
#endif /* !SHA256_ARM_H_ */
================================================
FILE: libcperciva/alg/sha256_shani.c
================================================
#include "cpusupport.h"
#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)
/**
* CPUSUPPORT CFLAGS: X86_SHANI X86_SSSE3
*/
#include <immintrin.h>
#include <stdint.h>
#include "sha256_shani.h"
/**
* This code uses intrinsics from the following feature sets:
* SHANI: _mm_sha256msg1_epu32, _mm_sha256msg2_epu32, _mm_sha256rnds2_epu32
* SSSE3: _mm_shuffle_epi8, _mm_alignr_epi8
* SSE2: Everything else
*
* The SSSE3 intrinsics could be avoided at a slight cost by using a few SSE2
* instructions in their place; we have not done this since to our knowledge
* there are presently no CPUs which support the SHANI instruction set but do
* not support SSSE3.
*/
/* Load 32-bit big-endian words. */
static __m128i
be32dec_128(const uint8_t * src)
{
const __m128i SHUF = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11,
4, 5, 6, 7, 0, 1, 2, 3);
__m128i x;
/* Load four 32-bit words. */
x = _mm_loadu_si128((const __m128i *)src);
/* Reverse the order of the bytes in each word. */
return (_mm_shuffle_epi8(x, SHUF));
}
/* Convert an unsigned 32-bit immediate into a signed value. */
#define I32(a) ((UINT32_C(a) >= UINT32_C(0x80000000)) ? \
-(int32_t)(UINT32_C(0xffffffff) - UINT32_C(a)) - 1 : (int32_t)INT32_C(a))
/* Load four unsigned 32-bit immediates into a vector register. */
#define IMM4(a, b, c, d) _mm_set_epi32(I32(a), I32(b), I32(c), I32(d))
/* Run four rounds of SHA256. */
#define RND4(S, W, K0, K1, K2, K3) do { \
__m128i M; \
\
/* Add the next four words of message schedule and round constants. */ \
M = _mm_add_epi32(W, IMM4(K3, K2, K1, K0)); \
\
/* Perform two rounds of SHA256, using the low two words in M. */ \
S[1] = _mm_sha256rnds2_epu32(S[1], S[0], M); \
\
/* Shift the two words of M down and perform the next two rounds. */ \
M = _mm_srli_si128(M, 8); \
S[0] = _mm_sha256rnds2_epu32(S[0], S[1], M); \
} while (0)
/* Compute the ith set of four words of message schedule. */
#define MSG4(W, i) do { \
W[(i + 0) % 4] = _mm_sha256msg1_epu32(W[(i + 0) % 4], W[(i + 1) % 4]); \
W[(i + 0) % 4] = _mm_add_epi32(W[(i + 0) % 4], \
_mm_alignr_epi8(W[(i + 3) % 4], W[(i + 2) % 4], 4)); \
W[(i + 0) % 4] = _mm_sha256msg2_epu32(W[(i + 0) % 4], W[(i + 3) % 4]); \
} while (0)
/* Perform 4 rounds of SHA256 and generate more message schedule if needed. */
#define RNDMSG(S, W, i, K0, K1, K2, K3) do { \
RND4(S, W[i % 4], K0, K1, K2, K3); \
if (i < 12) \
MSG4(W, i + 4); \
} while (0)
/**
* SHA256_Transform_shani(state, block):
* Compute the SHA256 block compression function, transforming ${state} using
* the data in ${block}. This implementation uses x86 SHANI and SSSE3
* instructions, and should only be used if CPUSUPPORT_X86_SHANI and _SSSE3
* are defined and cpusupport_x86_shani() and _ssse3() return nonzero.
*/
void
SHA256_Transform_shani(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64])
{
__m128i S3210, S7654;
__m128i S0123, S4567;
__m128i S0145, S2367;
__m128i W[4];
__m128i S[2];
/* Load state. */
S3210 = _mm_loadu_si128((const __m128i *)&state[0]);
S7654 = _mm_loadu_si128((const __m128i *)&state[4]);
/* Shuffle the 8 32-bit values into the order we need them. */
S0123 = _mm_shuffle_epi32(S3210, 0x1B);
S4567 = _mm_shuffle_epi32(S7654, 0x1B);
S0145 = _mm_unpackhi_epi64(S4567, S0123);
S2367 = _mm_unpacklo_epi64(S4567, S0123);
/* Load input block; this is the start of the message schedule. */
W[0] = be32dec_128(&block[0]);
W[1] = be32dec_128(&block[16]);
W[2] = be32dec_128(&block[32]);
W[3] = be32dec_128(&block[48]);
/* Initialize working variables. */
S[0] = S0145;
S[1] = S2367;
/* Perform 64 rounds, 4 at a time. */
RNDMSG(S, W, 0, 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5);
RNDMSG(S, W, 1, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5);
RNDMSG(S, W, 2, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3);
RNDMSG(S, W, 3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174);
RNDMSG(S, W, 4, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc);
RNDMSG(S, W, 5, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da);
RNDMSG(S, W, 6, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7);
RNDMSG(S, W, 7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967);
RNDMSG(S, W, 8, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13);
RNDMSG(S, W, 9, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85);
RNDMSG(S, W, 10, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3);
RNDMSG(S, W, 11, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070);
RNDMSG(S, W, 12, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5);
RNDMSG(S, W, 13, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3);
RNDMSG(S, W, 14, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208);
RNDMSG(S, W, 15, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2);
/* Mix local working variables into global state. */
S0145 = _mm_add_epi32(S0145, S[0]);
S2367 = _mm_add_epi32(S2367, S[1]);
/* Shuffle state back to the original word order and store. */
S0123 = _mm_unpackhi_epi64(S2367, S0145);
S4567 = _mm_unpacklo_epi64(S2367, S0145);
S3210 = _mm_shuffle_epi32(S0123, 0x1B);
S7654 = _mm_shuffle_epi32(S4567, 0x1B);
_mm_storeu_si128((__m128i *)&state[0], S3210);
_mm_storeu_si128((__m128i *)&state[4], S7654);
}
#endif /* CPUSUPPORT_X86_SHANI && CPUSUPPORT_X86_SSSE3 */
================================================
FILE: libcperciva/alg/sha256_shani.h
================================================
#ifndef SHA256_SHANI_H_
#define SHA256_SHANI_H_
#include <stdint.h>
/**
* SHA256_Transform_shani(state, block):
* Compute the SHA256 block compression function, transforming ${state} using
* the data in ${block}. This implementation uses x86 SHANI and SSSE3
* instructions, and should only be used if CPUSUPPORT_X86_SHANI and _SSSE3
* are defined and cpusupport_x86_shani() and _ssse3() return nonzero.
*/
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
void SHA256_Transform_shani(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64]);
#else
void SHA256_Transform_shani(uint32_t[static restrict 8],
const uint8_t[static restrict 64]);
#endif
#endif /* !SHA256_SHANI_H_ */
================================================
FILE: libcperciva/alg/sha256_sse2.c
================================================
#include "cpusupport.h"
#ifdef CPUSUPPORT_X86_SSE2
/**
* CPUSUPPORT CFLAGS: X86_SSE2
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <emmintrin.h>
#include "sha256_sse2.h"
/**
* mm_bswap_epi32(a):
* Byte-swap each 32-bit word.
*/
static inline __m128i
mm_bswap_epi32(__m128i a)
{
/* Swap bytes in each 16-bit word. */
a = _mm_or_si128(_mm_slli_epi16(a, 8), _mm_srli_epi16(a, 8));
/* Swap all 16-bit words. */
a = _mm_shufflelo_epi16(a, _MM_SHUFFLE(2, 3, 0, 1));
a = _mm_shufflehi_epi16(a, _MM_SHUFFLE(2, 3, 0, 1));
return (a);
}
/* SHA256 round constants. */
static const uint32_t Krnd[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/* Elementary functions used by SHA256 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
/* SHA256 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
h += S1(e) + Ch(e, f, g) + k; \
d += h; \
h += S0(a) + Maj(a, b, c)
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, ii) \
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
S[(66 - i) % 8], S[(67 - i) % 8], \
S[(68 - i) % 8], S[(69 - i) % 8], \
S[(70 - i) % 8], S[(71 - i) % 8], \
W[i + ii] + Krnd[i + ii])
/* Message schedule computation */
#define SHR32(x, n) (_mm_srli_epi32(x, n))
#define ROTR32(x, n) (_mm_or_si128(SHR32(x, n), _mm_slli_epi32(x, (32-n))))
#define s0_128(x) _mm_xor_si128(_mm_xor_si128( \
ROTR32(x, 7), ROTR32(x, 18)), SHR32(x, 3))
static inline __m128i
s1_128_high(__m128i a)
{
__m128i b;
__m128i c;
/* ROTR, loading data as {B, B, A, A}; lanes 1 & 3 will be junk. */
b = _mm_shuffle_epi32(a, _MM_SHUFFLE(1, 1, 0, 0));
c = _mm_xor_si128(_mm_srli_epi64(b, 17), _mm_srli_epi64(b, 19));
/* Shift and XOR with rotated data; lanes 1 & 3 will be junk. */
c = _mm_xor_si128(c, _mm_srli_epi32(b, 10));
/* Shuffle good data back and zero unwanted lanes. */
c = _mm_shuffle_epi32(c, _MM_SHUFFLE(2, 0, 2, 0));
c = _mm_slli_si128(c, 8);
return (c);
}
static inline __m128i
s1_128_low(__m128i a)
{
__m128i b;
__m128i c;
/* ROTR, loading data as {B, B, A, A}; lanes 1 & 3 will be junk. */
b = _mm_shuffle_epi32(a, _MM_SHUFFLE(3, 3, 2, 2));
c = _mm_xor_si128(_mm_srli_epi64(b, 17), _mm_srli_epi64(b, 19));
/* Shift and XOR with rotated data; lanes 1 & 3 will be junk. */
c = _mm_xor_si128(c, _mm_srli_epi32(b, 10));
/* Shuffle good data back and zero unwanted lanes. */
c = _mm_shuffle_epi32(c, _MM_SHUFFLE(2, 0, 2, 0));
c = _mm_srli_si128(c, 8);
return (c);
}
/**
* SPAN_ONE_THREE(a, b):
* Combine the upper three words of ${a} with the lowest word of ${b}. This
* could also be thought of returning bits [159:32] of the 256-bit value
* consisting of (b[127:0] a[127:0]). In other words, set:
* dst[31:0] := a[63:32]
* dst[63:32] := a[95:64]
* dst[95:64] := a[127:96]
* dst[127:96] := b[31:0]
*/
#define SPAN_ONE_THREE(a, b) (_mm_shuffle_epi32(_mm_castps_si128( \
_mm_move_ss(_mm_castsi128_ps(a), _mm_castsi128_ps(b))), \
_MM_SHUFFLE(0, 3, 2, 1)))
/**
* MSG4(X0, X1, X2, X3):
* Calculate the next four values of the message schedule. If we define
* ${W[j]} as the first unknown value in the message schedule, then the input
* arguments are:
* X0 = W[j - 16] : W[j - 13]
* X1 = W[j - 12] : W[j - 9]
* X2 = W[j - 8] : W[j - 5]
* X3 = W[j - 4] : W[j - 1]
* This function therefore calculates:
* X4 = W[j + 0] : W[j + 3]
*/
static inline __m128i
MSG4(__m128i X0, __m128i X1, __m128i X2, __m128i X3)
{
__m128i X4;
__m128i Xj_minus_seven, Xj_minus_fifteen;
/* Set up variables which span X values. */
Xj_minus_seven = SPAN_ONE_THREE(X2, X3);
Xj_minus_fifteen = SPAN_ONE_THREE(X0, X1);
/* Begin computing X4. */
X4 = _mm_add_epi32(X0, Xj_minus_seven);
X4 = _mm_add_epi32(X4, s0_128(Xj_minus_fifteen));
/* First half of s1. */
X4 = _mm_add_epi32(X4, s1_128_low(X3));
/* Second half of s1; this depends on the above value of X4. */
X4 = _mm_add_epi32(X4, s1_128_high(X4));
return (X4);
}
/**
* SHA256_Transform_sse2(state, block, W, S):
* Compute the SHA256 block compression function, transforming ${state} using
* the data in ${block}. This implementation uses x86 SSE2 instructions, and
* should only be used if _SSE2 is defined and cpusupport_x86_sse2() returns
* nonzero. The arrays W and S may be filled with sensitive data, and should
* be cleared by the callee.
*/
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
void
SHA256_Transform_sse2(uint32_t state[8], const uint8_t block[64],
uint32_t W[64], uint32_t S[8])
#else
void
SHA256_Transform_sse2(uint32_t state[static restrict 8],
const uint8_t block[static restrict 64], uint32_t W[static restrict 64],
uint32_t S[static restrict 8])
#endif
{
__m128i Y[4];
int i;
/* 1. Prepare the first part of the message schedule W. */
Y[0] = mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[0]));
_mm_storeu_si128((__m128i *)&W[0], Y[0]);
Y[1] = mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[16]));
_mm_storeu_si128((__m128i *)&W[4], Y[1]);
Y[2] = mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[32]));
_mm_storeu_si128((__m128i *)&W[8], Y[2]);
Y[3] = mm_bswap_epi32(_mm_loadu_si128((const __m128i *)&block[48]));
_mm_storeu_si128((__m128i *)&W[12], Y[3]);
/* 2. Initialize working variables. */
memcpy(S, state, 32);
/* 3. Mix. */
for (i = 0; i < 64; i += 16) {
RNDr(S, W, 0, i);
RNDr(S, W, 1, i);
RNDr(S, W, 2, i);
RNDr(S, W, 3, i);
RNDr(S, W, 4, i);
RNDr(S, W, 5, i);
RNDr(S, W, 6, i);
RNDr(S, W, 7, i);
RNDr(S, W, 8, i);
RNDr(S, W, 9, i);
RNDr(S, W, 10, i);
RNDr(S, W, 11, i);
RNDr(S, W, 12, i);
RNDr(S, W, 13, i);
RNDr(S, W, 14, i);
RNDr(S, W, 15, i);
if (i == 48)
break;
Y[0] = MSG4(Y[0], Y[1], Y[2], Y[3]);
_mm_storeu_si128((__m128i *)&W[16 + i + 0], Y[0]);
Y[1] = MSG4(Y[1], Y[2], Y[3], Y[0]);
_mm_storeu_si128((__m128i *)&W[16 + i + 4], Y[1]);
Y[2] = MSG4(Y[2], Y[3], Y[0], Y[1]);
_mm_storeu_si128((__m128i *)&W[16 + i + 8], Y[2]);
Y[3] = MSG4(Y[3], Y[0], Y[1], Y[2]);
_mm_storeu_si128((__m128i *)&W[16 + i + 12], Y[3]);
}
/* 4. Mix local working variables into global state. */
for (i = 0; i < 8; i++)
state[i] += S[i];
}
#endif /* CPUSUPPORT_X86_SSE2 */
================================================
FILE: libcperciva/alg/sha256_sse2.h
================================================
#ifndef SHA256_SSE2_H_
#define SHA256_SSE2_H_
#include <stdint.h>
/**
* SHA256_Transform_sse2(state, block, W, S):
* Compute the SHA256 block compression function, transforming ${state} using
* the data in ${block}. This implementation uses x86 SSE2 instructions, and
* should only be used if _SSE2 is defined and cpusupport_x86_sse2() returns
* nonzero. The arrays W and S may be filled with sensitive data, and should
* be cleared by the callee.
*/
#ifdef POSIXFAIL_ABSTRACT_DECLARATOR
void SHA256_Transform_sse2(uint32_t state[8],
const uint8_t block[64], uint32_t W[64], uint32_t S[8]);
#else
void SHA256_Transform_sse2(uint32_t[static restrict 8],
const uint8_t[static restrict 64], uint32_t W[static restrict 64],
uint32_t S[static restrict 8]);
#endif
#endif /* !SHA256_SSE2_H_ */
================================================
FILE: libcperciva/apisupport/Build/apisupport-LIBCRYPTO-LOW_LEVEL_AES.c
================================================
#include <stdint.h>
#include <openssl/aes.h>
int
main(void)
{
AES_KEY kexp_actual;
const uint8_t key_unexpanded[16] = { 0 };
AES_set_encrypt_key(key_unexpanded, 128, &kexp_actual);
/* Success! */
return (0);
}
================================================
FILE: libcperciva/apisupport/Build/apisupport-NONPOSIX-MEMLIMIT.c
================================================
#include "platform.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#ifdef HAVE_SYS_SYSINFO_H
#include <sys/sysinfo.h>
#endif
int
main(void)
{
/* Success! */
return (0);
}
================================================
FILE: libcperciva/apisupport/Build/apisupport.sh
================================================
# Should be sourced by `command -p sh path/to/apisupport.sh "$PATH"` from
# within a Makefile.
if ! [ "${PATH}" = "$1" ]; then
echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2
PATH=$1
fi
# Standard output should be written to apisupport-config.h, which is both a
# C header file defining APISUPPORT_PLATFORM_FEATURE macros and sourceable sh
# code which sets CFLAGS_PLATFORM_FEATURE environment variables.
SRCDIR=$(command -p dirname "$0")
CFLAGS_HARDCODED="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
# Do we want to record stderr to a file?
if [ "${DEBUG:-0}" -eq "0" ]; then
outcc="/dev/null"
else
outcc="apisupport-stderr.log"
rm -f "${outcc}"
fi
feature() {
PLATFORM=$1
FEATURE=$2
EXTRALIB=$3
shift 3;
# Bail if we didn't include this feature in this source tree.
feature_filename="${SRCDIR}/apisupport-${PLATFORM}-${FEATURE}.c"
if ! [ -f "${feature_filename}" ]; then
return
fi
# Check if we can compile this feature (and any required arguments).
printf "Checking if compiler supports %s %s feature..." \
"${PLATFORM}" "${FEATURE}" 1>&2
for API_CFLAGS in "$@"; do
if ${CC} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_HARDCODED} \
${API_CFLAGS} "${feature_filename}" ${LDADD_EXTRA} \
${EXTRALIB} 2>>"${outcc}"; then
rm -f a.out
break;
fi
API_CFLAGS=NOTSUPPORTED;
done
case ${API_CFLAGS} in
NOTSUPPORTED)
echo " no" 1>&2
;;
"")
echo " yes" 1>&2
echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1"
;;
*)
echo " yes, via ${API_CFLAGS}" 1>&2
echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1"
echo "#ifdef apisupport_dummy"
echo "export CFLAGS_${PLATFORM}_${FEATURE}=\"${API_CFLAGS}\""
echo "#endif"
;;
esac
}
if [ "$2" = "--all" ]; then
feature() {
PLATFORM=$1
FEATURE=$2
echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1"
}
fi
# Detect how to compile non-POSIX code.
feature NONPOSIX SETGROUPS "" "" \
"-U_POSIX_C_SOURCE -U_XOPEN_SOURCE" \
"-U_POSIX_C_SOURCE -U_XOPEN_SOURCE -Wno-reserved-id-macro"
feature NONPOSIX MEMLIMIT "" "" \
"-U_POSIX_C_SOURCE -U_XOPEN_SOURCE" \
"-U_POSIX_C_SOURCE -U_XOPEN_SOURCE -Wno-reserved-id-macro"
# Detect how to compile libssl and libcrypto code.
feature LIBSSL HOST_NAME "-lssl" "" \
"-Wno-cast-qual"
feature LIBCRYPTO LOW_LEVEL_AES "-lcrypto" "" \
"-Wno-deprecated-declarations"
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-ARM-AES.c
================================================
#include <stdint.h>
#ifdef __ARM_NEON
#include <arm_neon.h>
#endif
int
main(void)
{
uint8x16_t data;
uint8x16_t key = {0};
uint8x16_t output;
uint32x4_t lanes = {0};
uint8_t arr[16] = {0};
/* Check AES. */
data = vld1q_u8(arr);
output = vaeseq_u8(data, key);
(void)output; /* UNUSED */
/* Check _u32: some compilers only support the _u8 variant. */
lanes = vdupq_laneq_u32(lanes, 0);
/* Success! */
return (0);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c
================================================
#ifdef __ARM_NEON
#include <arm_neon.h>
#endif
int
main(void)
{
uint32x4_t w0 = {0};
uint32x4_t w4 = {0};
uint32x4_t output;
output = vsha256su0q_u32(w0, w4);
(void)output; /* UNUSED */
/* Success! */
return (0);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c
================================================
#include <sys/auxv.h>
int
main(void)
{
int res;
unsigned long val;
res = elf_aux_info(AT_HWCAP, &val, sizeof(unsigned long));
(void)res;
return (val != 0);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c
================================================
#include <sys/auxv.h>
int
main(void)
{
unsigned long val;
val = getauxval(AT_HWCAP);
return (val != 0);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c
================================================
#include <stdint.h>
#include <wmmintrin.h>
/*
* Use a separate function for this, because that means that the alignment of
* the _mm_loadu_si128() will move to function level, which may require
* -Wno-cast-align.
*/
static __m128i
load_128(const uint8_t * src)
{
__m128i x;
x = _mm_loadu_si128((const __m128i *)src);
return (x);
}
int
main(void)
{
__m128i x, y;
uint8_t a[16] = {0};
x = load_128(a);
#ifdef BROKEN_MM_LOADU_SI64
y = _mm_loadu_si128((const __m128i *)a);
#else
y = _mm_loadu_si64(a);
#endif
y = _mm_aesenc_si128(x, y);
_mm_storeu_si128((__m128i *)&a[0], y);
return (a[0]);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c
================================================
#include <cpuid.h>
int
main(void)
{
unsigned int a, b, c, d;
return (__get_cpuid(0, &a, &b, &c, &d));
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c
================================================
#include <cpuid.h>
int
main(void)
{
unsigned int a, b, c, d;
__cpuid_count(7, 0, a, b, c, d);
return ((int)a);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c
================================================
#include <immintrin.h>
int
main(void)
{
unsigned int x;
return (!_rdrand32_step(&x));
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c
================================================
#include <immintrin.h>
#include <stdint.h>
/*
* Use a separate function for this, because that means that the alignment of
* the _mm_loadu_si128() will move to function level, which may require
* -Wno-cast-align.
*/
static __m128i
load_128(const uint8_t * src)
{
__m128i x;
x = _mm_loadu_si128((const __m128i *)src);
return (x);
}
int
main(void)
{
__m128i x;
uint8_t a[16] = {0};
x = load_128(a);
x = _mm_sha256msg1_epu32(x, x);
_mm_storeu_si128((__m128i *)a, x);
return (a[0]);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c
================================================
#include <emmintrin.h>
static char a[16];
/*
* Use a separate function for this, because that means that the alignment of
* the _mm_loadu_si128() will move to function level, which may require
* -Wno-cast-align.
*/
static __m128i
load_128(const char * src)
{
__m128i x;
x = _mm_loadu_si128((const __m128i *)src);
return (x);
}
int
main(void)
{
__m128i x;
x = load_128(a);
_mm_storeu_si128((__m128i *)a, x);
return (a[0]);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c
================================================
#include <emmintrin.h>
#include <tmmintrin.h>
static char a[16];
/*
* Use a separate function for this, because that means that the alignment of
* the _mm_loadu_si128() will move to function level, which may require
* -Wno-cast-align.
*/
static __m128i
load_128(const char * src)
{
__m128i x;
x = _mm_loadu_si128((const __m128i *)src);
return (x);
}
int
main(void)
{
__m128i x;
x = load_128(a);
x = _mm_alignr_epi8(x, x, 8);
_mm_storeu_si128((__m128i *)a, x);
return (a[0]);
}
================================================
FILE: libcperciva/cpusupport/Build/cpusupport.sh
================================================
# Should be sourced by `command -p sh path/to/cpusupport.sh "$PATH"` from
# within a Makefile.
if ! [ "${PATH}" = "$1" ]; then
echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2
PATH=$1
fi
# Standard output should be written to cpusupport-config.h, which is both a
# C header file defining CPUSUPPORT_ARCH_FEATURE macros and sourceable sh
# code which sets CFLAGS_ARCH_FEATURE environment variables.
SRCDIR=$(command -p dirname "$0")
CFLAGS_HARDCODED="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700"
# Do we want to record stderr to a file?
if [ "${DEBUG:-0}" -eq "0" ]; then
outcc="/dev/null"
else
outcc="cpusupport-stderr.log"
rm -f "${outcc}"
fi
feature() {
ARCH=$1
FEATURE=$2
shift 2;
# Bail if we didn't include this feature in this source tree.
feature_filename="${SRCDIR}/cpusupport-${ARCH}-${FEATURE}.c"
if ! [ -f "${feature_filename}" ]; then
return
fi
# Check if we can compile this feature (and any required arguments).
printf "Checking if compiler supports %s %s feature..." \
"${ARCH}" "${FEATURE}" 1>&2
for CPU_CFLAGS in "$@"; do
if ${CC} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_HARDCODED} \
${CPU_CFLAGS} "${feature_filename}" 2>>"${outcc}"; then
rm -f a.out
break;
fi
CPU_CFLAGS=NOTSUPPORTED;
done
case ${CPU_CFLAGS} in
NOTSUPPORTED)
echo " no" 1>&2
;;
"")
echo " yes" 1>&2
echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1"
;;
*)
echo " yes, via ${CPU_CFLAGS}" 1>&2
echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1"
echo "#ifdef cpusupport_dummy"
echo "export CFLAGS_${ARCH}_${FEATURE}=\"${CPU_CFLAGS}\""
echo "#endif"
;;
esac
}
if [ "$2" = "--all" ]; then
feature() {
ARCH=$1
FEATURE=$2
echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1"
}
fi
# Detect CPU-detection features
feature HWCAP ELF_AUX_INFO ""
feature HWCAP GETAUXVAL ""
feature X86 CPUID ""
feature X86 CPUID_COUNT ""
# Detect specific features
feature X86 AESNI "" "-maes" \
"-maes -Wno-cast-align" \
"-maes -Wno-missing-prototypes -Wno-cast-qual" \
"-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align" \
"-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align \
-DBROKEN_MM_LOADU_SI64"
feature X86 RDRAND "" "-mrdrnd"
feature X86 SHANI "" "-msse2 -msha" \
"-msse2 -msha -Wno-cast-align"
feature X86 SSE2 "" \
"-Wno-cast-align" \
"-msse2" \
"-msse2 -Wno-cast-align"
feature X86 SSE42 "" "-msse4.2" \
"-msse4.2 -Wno-cast-align" \
"-msse4.2 -Wno-cast-align -fno-strict-aliasing" \
"-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual"
feature X86 SSE42_64 "" "-msse4.2" \
"-msse4.2 -Wno-cast-align" \
"-msse4.2 -Wno-cast-align -fno-strict-aliasing" \
"-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual"
feature X86 SSSE3 "" "-mssse3" \
"-mssse3 -Wno-cast-align"
# Detect specific ARM features
feature ARM AES "-march=armv8.1-a+crypto" \
"-march=armv8.1-a+crypto -D__ARM_ACLE=200"
feature ARM CRC32_64 "-march=armv8.1-a" \
"-march=armv8.1-a+crc" \
"-march=armv8.1-a+crc -Wno-cast-align" \
"-march=armv8.1-a -D__ARM_ACLE=200"
feature ARM SHA256 "-march=armv8.1-a+crypto" \
"-march=armv8.1-a+crypto -Wno-cast-align" \
"-march=armv8.1-a+crypto -D__ARM_ACLE=200"
================================================
FILE: libcperciva/cpusupport/cpusupport.h
================================================
#ifndef CPUSUPPORT_H_
#define CPUSUPPORT_H_
/*
* To enable support for non-portable CPU features at compile time, one or
* more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done
* directly on the compiler command line via -D CPUSUPPORT_ARCH_FEATURE or
* -D CPUSUPPORT_ARCH_FEATURE=1; or a file can be created with the
* necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h
* (or similar) can be provided to include that file here.
*/
#ifdef CPUSUPPORT_CONFIG_FILE
#include CPUSUPPORT_CONFIG_FILE
#endif
/**
* The CPUSUPPORT_FEATURE macro declares the necessary variables and
* functions for detecting CPU feature support at run time. The function
* defined in the macro acts to cache the result of the ..._detect function
* using the ..._present and ..._init variables. The _detect function and the
* _present and _init variables are turn defined by CPUSUPPORT_FEATURE_DECL in
* appropriate cpusupport_foo_bar.c file.
*
* In order to allow CPUSUPPORT_FEATURE to be used for features which do not
* have corresponding CPUSUPPORT_FEATURE_DECL blocks in another source file,
* we abuse the C preprocessor: If CPUSUPPORT_${enabler} is defined to 1, then
* we access _present_1, _init_1, and _detect_1; but if it is not defined, we
* access _present_CPUSUPPORT_${enabler} etc., which we define as static, thus
* preventing the compiler from emitting a reference to an external symbol.
*
* In this way, it becomes possible to issue CPUSUPPORT_FEATURE invocations
* for nonexistent features without running afoul of the requirement that
* "If an identifier declared with external linkage is used... in the entire
* program there shall be exactly one external definition" (C99 standard, 6.9
* paragraph 5). In practice, this means that users of the cpusupport code
* can omit build and runtime detection files without changing the framework
* code.
*/
#define CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) \
static int cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \
static int cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \
static inline int cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler(void) { return (0); } \
extern int cpusupport_ ## arch_feature ## _present_ ## enabled; \
extern int cpusupport_ ## arch_feature ## _init_ ## enabled; \
int cpusupport_ ## arch_feature ## _detect_ ## enabled(void); \
\
static inline int \
cpusupport_ ## arch_feature(void) \
{ \
\
if (cpusupport_ ## arch_feature ## _present_ ## enabled) \
return (1); \
else if (cpusupport_ ## arch_feature ## _init_ ## enabled) \
return (0); \
cpusupport_ ## arch_feature ## _present_ ## enabled = \
cpusupport_ ## arch_feature ## _detect_ ## enabled(); \
cpusupport_ ## arch_feature ## _init_ ## enabled = 1; \
return (cpusupport_ ## arch_feature ## _present_ ## enabled); \
} \
static void (* cpusupport_ ## arch_feature ## _dummyptr)(void); \
static inline void \
cpusupport_ ## arch_feature ## _dummyfunc(void) \
{ \
\
(void)cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \
(void)cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \
(void)cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler; \
(void)cpusupport_ ## arch_feature ## _present_ ## enabled; \
(void)cpusupport_ ## arch_feature ## _init_ ## enabled; \
(void)cpusupport_ ## arch_feature ## _detect_ ## enabled; \
(void)cpusupport_ ## arch_feature ## _dummyptr; \
} \
static void (* cpusupport_ ## arch_feature ## _dummyptr)(void) = cpusupport_ ## arch_feature ## _dummyfunc; \
struct cpusupport_ ## arch_feature ## _dummy
#define CPUSUPPORT_FEATURE_(arch_feature, enabler, enabled) \
CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled)
#define CPUSUPPORT_FEATURE(arch, feature, enabler) \
CPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler)
/**
* CPUSUPPORT_FEATURE_DECL(arch, feature):
* Macro which defines variables and provides a function declaration for
* detecting the presence of "feature" on the "arch" architecture. The
* function body following this macro expansion must return nonzero if the
* feature is present, or zero if the feature is not present or the detection
* fails for any reason.
*/
#define CPUSUPPORT_FEATURE_DECL(arch, feature) \
extern int cpusupport_ ## arch ## _ ## feature ## _present_1; \
extern int cpusupport_ ## arch ## _ ## feature ## _init_1; \
int cpusupport_ ## arch ## _ ## feature ## _present_1 = 0; \
int cpusupport_ ## arch ## _ ## feature ## _init_1 = 0; \
int cpusupport_ ## arch ## _ ## feature ## _detect_1(void); \
int \
cpusupport_ ## arch ## _ ## feature ## _detect_1(void)
/**
* CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, check):
* Check if we can enable ${success_value}, given the ${cpusupport_checks} and
* ${check}; if so, write to ${hwvar}. If the ${cpusupport_checks} pass but
* the ${check} is non-zero, produce a warning which includes a stringified
* ${success_value}, then fallthrough.
*/
#define CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, \
check) do { \
if ((cpusupport_checks)) { \
if ((check) == 0) { \
(hwvar) = (success_value); \
return; \
} else { \
warn0("Disabling " #success_value \
" due to failed self-test"); \
} \
} \
} while (0)
/**
* List of features. If a feature here is not enabled by the appropriate
* CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the
* relevant macro may be defined (e.g., by Build/cpusupport.sh successfully
* compiling Build/cpusupport-ARCH-FEATURE.c) then the C file containing the
* corresponding run-time detection code (cpusupport_arch_feature.c) must be
* compiled and linked in.
*
* There are a few features for which we do not have run-time checks:
* - X86_CPUID: compile-time is enough; if __get_cpuid() fails, then all the
* x86 detection features will fail, but there's nothing we can
* do about that.
* - X86_CPUID_COUNT: ditto.
* - X86_SSE42_64: the cpuid check tells us if the CPU supports SSE4.2, but
* that says nothing about whether it's in 64-bit mode.
*/
CPUSUPPORT_FEATURE(x86, aesni, X86_AESNI);
CPUSUPPORT_FEATURE(x86, rdrand, X86_RDRAND);
CPUSUPPORT_FEATURE(x86, shani, X86_SHANI);
CPUSUPPORT_FEATURE(x86, sse2, X86_SSE2);
CPUSUPPORT_FEATURE(x86, sse42, X86_SSE42);
CPUSUPPORT_FEATURE(x86, ssse3, X86_SSSE3);
CPUSUPPORT_FEATURE(arm, aes, ARM_AES);
CPUSUPPORT_FEATURE(arm, crc32_64, ARM_CRC32_64);
CPUSUPPORT_FEATURE(arm, sha256, ARM_SHA256);
#endif /* !CPUSUPPORT_H_ */
================================================
FILE: libcperciva/cpusupport/cpusupport_arm_aes.c
================================================
gitextract_hxdnsnbb/
├── .autom4te.cfg
├── .github/
│ └── workflows/
│ ├── compile.yml
│ └── coverity-scan.yml
├── .gitignore
├── BUILDING
├── COPYRIGHT
├── FORMAT
├── Makefile.am
├── README.md
├── STYLE
├── configure.ac
├── get-version.sh
├── lib/
│ ├── README
│ ├── crypto/
│ │ ├── crypto_scrypt-ref.c
│ │ ├── crypto_scrypt_smix.c
│ │ ├── crypto_scrypt_smix.h
│ │ ├── crypto_scrypt_smix_sse2.c
│ │ └── crypto_scrypt_smix_sse2.h
│ ├── scryptenc/
│ │ ├── scryptenc.c
│ │ ├── scryptenc.h
│ │ ├── scryptenc_cpuperf.c
│ │ ├── scryptenc_cpuperf.h
│ │ ├── scryptenc_print_error.c
│ │ └── scryptenc_print_error.h
│ └── util/
│ ├── passphrase_entry.c
│ └── passphrase_entry.h
├── lib-platform/
│ ├── crypto/
│ │ ├── crypto_scrypt.c
│ │ └── crypto_scrypt.h
│ ├── platform.h
│ └── util/
│ ├── memlimit.c
│ └── memlimit.h
├── libcperciva/
│ ├── POSIX/
│ │ ├── README
│ │ ├── posix-abstract-declarator.c
│ │ ├── posix-cflags.sh
│ │ ├── posix-clock_gettime.c
│ │ ├── posix-clock_realtime.c
│ │ ├── posix-inet-addrstrlen.c
│ │ ├── posix-inet6-addrstrlen.c
│ │ ├── posix-l.sh
│ │ ├── posix-msg_nosignal.c
│ │ ├── posix-restrict.c
│ │ ├── posix-stat-st_mtim.c
│ │ └── posix-trivial.c
│ ├── alg/
│ │ ├── sha256.c
│ │ ├── sha256.h
│ │ ├── sha256_arm.c
│ │ ├── sha256_arm.h
│ │ ├── sha256_shani.c
│ │ ├── sha256_shani.h
│ │ ├── sha256_sse2.c
│ │ └── sha256_sse2.h
│ ├── apisupport/
│ │ └── Build/
│ │ ├── apisupport-LIBCRYPTO-LOW_LEVEL_AES.c
│ │ ├── apisupport-NONPOSIX-MEMLIMIT.c
│ │ └── apisupport.sh
│ ├── cpusupport/
│ │ ├── Build/
│ │ │ ├── cpusupport-ARM-AES.c
│ │ │ ├── cpusupport-ARM-SHA256.c
│ │ │ ├── cpusupport-HWCAP-ELF_AUX_INFO.c
│ │ │ ├── cpusupport-HWCAP-GETAUXVAL.c
│ │ │ ├── cpusupport-X86-AESNI.c
│ │ │ ├── cpusupport-X86-CPUID.c
│ │ │ ├── cpusupport-X86-CPUID_COUNT.c
│ │ │ ├── cpusupport-X86-RDRAND.c
│ │ │ ├── cpusupport-X86-SHANI.c
│ │ │ ├── cpusupport-X86-SSE2.c
│ │ │ ├── cpusupport-X86-SSSE3.c
│ │ │ └── cpusupport.sh
│ │ ├── cpusupport.h
│ │ ├── cpusupport_arm_aes.c
│ │ ├── cpusupport_arm_sha256.c
│ │ ├── cpusupport_x86_aesni.c
│ │ ├── cpusupport_x86_rdrand.c
│ │ ├── cpusupport_x86_shani.c
│ │ ├── cpusupport_x86_sse2.c
│ │ └── cpusupport_x86_ssse3.c
│ ├── crypto/
│ │ ├── crypto_aes.c
│ │ ├── crypto_aes.h
│ │ ├── crypto_aes_aesni.c
│ │ ├── crypto_aes_aesni.h
│ │ ├── crypto_aes_aesni_m128i.h
│ │ ├── crypto_aes_arm.c
│ │ ├── crypto_aes_arm.h
│ │ ├── crypto_aes_arm_u8.h
│ │ ├── crypto_aesctr.c
│ │ ├── crypto_aesctr.h
│ │ ├── crypto_aesctr_aesni.c
│ │ ├── crypto_aesctr_aesni.h
│ │ ├── crypto_aesctr_arm.c
│ │ ├── crypto_aesctr_arm.h
│ │ ├── crypto_aesctr_shared.c
│ │ ├── crypto_entropy.c
│ │ ├── crypto_entropy.h
│ │ ├── crypto_entropy_rdrand.c
│ │ ├── crypto_entropy_rdrand.h
│ │ ├── crypto_verify_bytes.c
│ │ └── crypto_verify_bytes.h
│ └── util/
│ ├── align_ptr.h
│ ├── asprintf.c
│ ├── asprintf.h
│ ├── entropy.c
│ ├── entropy.h
│ ├── getopt.c
│ ├── getopt.h
│ ├── humansize.c
│ ├── humansize.h
│ ├── insecure_memzero.c
│ ├── insecure_memzero.h
│ ├── monoclock.c
│ ├── monoclock.h
│ ├── parsenum.h
│ ├── readpass.c
│ ├── readpass.h
│ ├── readpass_file.c
│ ├── sysendian.h
│ ├── warnp.c
│ └── warnp.h
├── libscrypt-kdf/
│ └── scrypt-kdf.h
├── m4/
│ ├── check_darwin_paths.m4
│ ├── check_disable_compiler_warnings.m4
│ ├── check_libcperciva_posix.m4
│ ├── check_memlimit_support.m4
│ ├── check_posix_sh.m4
│ └── check_solaris_c99.m4
├── main.c
├── release-tools/
│ ├── create-sign-tarball.sh
│ └── mktarball.sh
├── scrypt.1
└── tests/
├── 01-known-values.sh
├── 02-decrypt-reference-file.sh
├── 03-encrypt-decrypt-file.sh
├── 04-force-resources.sh
├── 05-system-scrypt-encrypt-decrypt.sh
├── 06-decrypt-fail.sh
├── 07-passphrase-env.sh
├── 08-passphrase-file.sh
├── 09-explicit-params.sh
├── libscrypt-kdf/
│ └── sample-libscrypt-kdf.c
├── shared_test_functions.sh
├── shared_valgrind_functions.sh
├── test_scrypt.sh
├── valgrind/
│ └── potential-memleaks.c
└── verify-strings/
├── test_scrypt.c
├── test_scrypt.good
├── test_scrypt_good.enc
└── test_scrypt_small.good
SYMBOL INDEX (264 symbols across 70 files)
FILE: lib-platform/crypto/crypto_scrypt.c
function crypto_scrypt_internal (line 55) | static int
type scrypt_test (line 169) | struct scrypt_test {
function testsmix (line 194) | static int
function selectsmix (line 210) | static void
function crypto_scrypt (line 246) | int
FILE: lib-platform/util/memlimit.c
function memlimit_sysctl_hw (line 69) | static int
function memlimit_sysinfo (line 123) | static int
function memlimit_rlimit (line 154) | static int
function memlimit_sysconf (line 211) | static int
function memtouse (line 261) | int
FILE: lib/crypto/crypto_scrypt-ref.c
function blkcpy (line 46) | static void
function blkxor (line 55) | static void
function salsa20_8 (line 68) | static void
function blockmix_salsa8 (line 126) | static void
function integerify (line 156) | static uint64_t
function smix (line 170) | static void
function crypto_scrypt (line 213) | int
FILE: lib/crypto/crypto_scrypt_smix.c
function blkcpy (line 42) | static void
function blkxor (line 49) | static void
function salsa20_8 (line 62) | static void
function blockmix_salsa8 (line 108) | static void
function integerify (line 140) | static uint64_t
function crypto_scrypt_smix (line 156) | void
FILE: lib/crypto/crypto_scrypt_smix_sse2.c
function blkcpy (line 45) | static void
function blkxor (line 55) | static void
function salsa20_8 (line 69) | static void
function blockmix_salsa8 (line 133) | static void
function integerify (line 166) | static uint64_t
function crypto_scrypt_smix_sse2 (line 191) | void
FILE: lib/scryptenc/scryptenc.c
type scryptdec_file_cookie (line 64) | struct scryptdec_file_cookie {
function display_params (line 70) | static void
function pickparams (line 101) | static int
function checkparams (line 175) | static int
function scryptenc_setup (line 233) | static int
function scryptdec_file_printparams (line 319) | int
function scryptdec_setup (line 352) | static int
function scryptenc_buf (line 415) | int
function scryptdec_buf (line 485) | int
function scryptenc_file (line 576) | int
function scryptdec_file_cookie_free (line 667) | void
function scryptdec_file_load_header (line 685) | static int
function scryptdec_file_prep (line 746) | int
function scryptdec_file_copy (line 791) | int
function scryptdec_file (line 894) | int
FILE: lib/scryptenc/scryptenc.h
type scryptenc_params (line 64) | struct scryptenc_params {
type scryptdec_file_cookie (line 94) | struct scryptdec_file_cookie
type scryptenc_params (line 108) | struct scryptenc_params
type scryptenc_params (line 121) | struct scryptenc_params
type scryptenc_params (line 134) | struct scryptenc_params
type scryptenc_params (line 151) | struct scryptenc_params
type scryptenc_params (line 164) | struct scryptenc_params
type scryptdec_file_cookie (line 164) | struct scryptdec_file_cookie
type scryptdec_file_cookie (line 173) | struct scryptdec_file_cookie
type scryptdec_file_cookie (line 179) | struct scryptdec_file_cookie
FILE: lib/scryptenc/scryptenc_cpuperf.c
function getclockdiff (line 40) | static int
function scryptenc_cpuperf (line 58) | int
FILE: lib/scryptenc/scryptenc_print_error.c
function scryptenc_print_error (line 15) | void
FILE: lib/util/passphrase_entry.c
function passphrase_entry_parse (line 12) | int
function passphrase_entry_readpass (line 70) | int
FILE: lib/util/passphrase_entry.h
type passphrase_entry (line 5) | enum passphrase_entry {
type passphrase_entry (line 18) | enum passphrase_entry
type passphrase_entry (line 31) | enum passphrase_entry
FILE: libcperciva/POSIX/posix-abstract-declarator.c
function func (line 7) | int
function main (line 17) | int
FILE: libcperciva/POSIX/posix-clock_gettime.c
function main (line 3) | int
FILE: libcperciva/POSIX/posix-clock_realtime.c
function main (line 3) | int
FILE: libcperciva/POSIX/posix-inet-addrstrlen.c
function main (line 3) | int
FILE: libcperciva/POSIX/posix-inet6-addrstrlen.c
function main (line 3) | int
FILE: libcperciva/POSIX/posix-msg_nosignal.c
function main (line 3) | int
FILE: libcperciva/POSIX/posix-restrict.c
function foo (line 1) | static int
function main (line 8) | int
FILE: libcperciva/POSIX/posix-stat-st_mtim.c
function main (line 3) | int
FILE: libcperciva/POSIX/posix-trivial.c
function main (line 1) | int
FILE: libcperciva/alg/sha256.c
function be32enc_vect (line 49) | static void
function be32dec_vect (line 66) | static void
function SHA256_Transform_shani_with_W_S (line 108) | static void
function SHA256_Transform_arm_with_W_S (line 122) | static void
function hwtest (line 139) | static int
function hwaccel_init (line 163) | static void
function SHA256_Transform (line 232) | static void
function SHA256_Pad (line 331) | static void
function SHA256_Init (line 363) | void
function SHA256_Update_internal (line 383) | static void
function SHA256_Update (line 424) | void
function SHA256_Final_internal (line 441) | static void
function SHA256_Final (line 454) | void
function SHA256_Buf (line 473) | void
function HMAC_SHA256_Init_internal (line 493) | static void
function HMAC_SHA256_Init (line 526) | void
function HMAC_SHA256_Update_internal (line 546) | static void
function HMAC_SHA256_Update (line 556) | void
function HMAC_SHA256_Final_internal (line 573) | static void
function HMAC_SHA256_Final (line 589) | void
function HMAC_SHA256_Buf (line 611) | void
function PBKDF2_SHA256 (line 634) | void
FILE: libcperciva/alg/sha256.h
type SHA256_CTX (line 23) | typedef struct {
type HMAC_SHA256_CTX (line 55) | typedef struct {
FILE: libcperciva/alg/sha256_arm.c
function SHA256_Transform_arm (line 62) | void
FILE: libcperciva/alg/sha256_shani.c
function __m128i (line 25) | static __m128i
function SHA256_Transform_shani (line 83) | void
FILE: libcperciva/alg/sha256_sse2.c
function __m128i (line 19) | static inline __m128i
function __m128i (line 80) | static inline __m128i
function __m128i (line 100) | static inline __m128i
function __m128i (line 146) | static inline __m128i
function SHA256_Transform_sse2 (line 182) | void
FILE: libcperciva/apisupport/Build/apisupport-LIBCRYPTO-LOW_LEVEL_AES.c
function main (line 5) | int
FILE: libcperciva/apisupport/Build/apisupport-NONPOSIX-MEMLIMIT.c
function main (line 13) | int
FILE: libcperciva/cpusupport/Build/cpusupport-ARM-AES.c
function main (line 7) | int
FILE: libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c
function main (line 5) | int
FILE: libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c
function main (line 3) | int
FILE: libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c
function main (line 3) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c
function __m128i (line 10) | static __m128i
function main (line 19) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c
function main (line 3) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c
function main (line 3) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c
function main (line 3) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c
function __m128i (line 9) | static __m128i
function main (line 18) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c
function __m128i (line 10) | static __m128i
function main (line 19) | int
FILE: libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c
function __m128i (line 11) | static __m128i
function main (line 20) | int
FILE: libcperciva/crypto/crypto_aes.c
type crypto_aes_key (line 41) | struct crypto_aes_key
type aes_test (line 44) | struct aes_test {
function functest (line 73) | static int
function x86_aesni_oneshot (line 105) | static int
function arm_aes_oneshot (line 128) | static int
function openssl_oneshot (line 148) | static int
function hwaccel_init (line 170) | static void
function crypto_aes_can_use_intrinsics (line 207) | int
type crypto_aes_key (line 235) | struct crypto_aes_key
function crypto_aes_encrypt_block (line 280) | void
function crypto_aes_key_free (line 308) | void
FILE: libcperciva/crypto/crypto_aes.h
type crypto_aes_key (line 8) | struct crypto_aes_key
type crypto_aes_key (line 24) | struct crypto_aes_key
type crypto_aes_key (line 32) | struct crypto_aes_key
type crypto_aes_key (line 38) | struct crypto_aes_key
FILE: libcperciva/crypto/crypto_aes_aesni.c
type crypto_aes_key_aesni (line 19) | struct crypto_aes_key_aesni {
function crypto_aes_key_expand_128_aesni (line 42) | static void
function crypto_aes_key_expand_256_aesni (line 98) | static void
type crypto_aes_key_aesni (line 154) | struct crypto_aes_key_aesni
type crypto_aes_key_aesni (line 157) | struct crypto_aes_key_aesni
function __m128i (line 192) | __m128i
function crypto_aes_encrypt_block_aesni (line 228) | void
function crypto_aes_key_free_aesni (line 243) | void
FILE: libcperciva/crypto/crypto_aes_arm.c
type crypto_aes_key_arm (line 22) | struct crypto_aes_key_arm {
function uint8x16_t (line 55) | static inline uint8x16_t
function uint8x16_t (line 78) | static inline uint8x16_t
function crypto_aes_key_expand_128_arm (line 119) | static void
function crypto_aes_key_expand_256_arm (line 164) | static void
type crypto_aes_key_arm (line 205) | struct crypto_aes_key_arm
type crypto_aes_key_arm (line 208) | struct crypto_aes_key_arm
function uint8x16_t (line 243) | uint8x16_t
function crypto_aes_encrypt_block_arm (line 281) | void
function crypto_aes_key_free_arm (line 296) | void
FILE: libcperciva/crypto/crypto_aesctr.c
function hwaccel_init (line 45) | static void
type crypto_aesctr (line 82) | struct crypto_aesctr
type crypto_aesctr (line 85) | struct crypto_aesctr
type crypto_aesctr (line 88) | struct crypto_aesctr
function crypto_aesctr_init2 (line 104) | void
type crypto_aesctr (line 138) | struct crypto_aesctr
type crypto_aes_key (line 139) | struct crypto_aes_key
type crypto_aesctr (line 141) | struct crypto_aesctr
function crypto_aesctr_stream (line 167) | void
function crypto_aesctr_free (line 210) | void
function crypto_aesctr_buf (line 229) | void
FILE: libcperciva/crypto/crypto_aesctr.h
type crypto_aes_key (line 8) | struct crypto_aes_key
type crypto_aesctr (line 9) | struct crypto_aesctr
type crypto_aesctr (line 18) | struct crypto_aesctr
type crypto_aes_key (line 18) | struct crypto_aes_key
type crypto_aesctr (line 26) | struct crypto_aesctr
type crypto_aesctr (line 33) | struct crypto_aesctr
type crypto_aes_key (line 33) | struct crypto_aes_key
type crypto_aesctr (line 42) | struct crypto_aesctr
type crypto_aesctr (line 49) | struct crypto_aesctr
type crypto_aes_key (line 55) | struct crypto_aes_key
FILE: libcperciva/crypto/crypto_aesctr_aesni.c
function __m128i (line 43) | static inline __m128i
function crypto_aesctr_aesni_stream_wholeblocks (line 55) | static void
function crypto_aesctr_aesni_stream (line 117) | void
FILE: libcperciva/crypto/crypto_aesctr_aesni.h
type crypto_aesctr (line 8) | struct crypto_aesctr
type crypto_aesctr (line 16) | struct crypto_aesctr
FILE: libcperciva/crypto/crypto_aesctr_arm.c
function crypto_aesctr_arm_stream_wholeblocks (line 36) | static void
function crypto_aesctr_arm_stream (line 98) | void
FILE: libcperciva/crypto/crypto_aesctr_arm.h
type crypto_aesctr (line 8) | struct crypto_aesctr
type crypto_aesctr (line 16) | struct crypto_aesctr
FILE: libcperciva/crypto/crypto_aesctr_shared.c
type crypto_aesctr (line 8) | struct crypto_aesctr {
function crypto_aesctr_stream_cipherblock_generate (line 16) | static inline void
function crypto_aesctr_stream_cipherblock_use (line 38) | static inline void
function crypto_aesctr_stream_pre_wholeblock (line 62) | static inline int
function crypto_aesctr_stream_post_wholeblock (line 89) | static inline void
FILE: libcperciva/crypto/crypto_entropy.c
function update_from_rdrand (line 43) | static void
function instantiate (line 62) | static int
function update (line 96) | static void
function reseed (line 143) | static int
function generate (line 178) | static void
function crypto_entropy_read (line 206) | int
FILE: libcperciva/crypto/crypto_entropy_rdrand.c
function generate_seed_rdrand (line 18) | int
FILE: libcperciva/crypto/crypto_verify_bytes.c
function crypto_verify_bytes (line 11) | uint8_t
FILE: libcperciva/util/asprintf.c
function asprintf (line 11) | int
FILE: libcperciva/util/entropy.c
type entropy_read_cookie (line 26) | struct entropy_read_cookie {
type entropy_read_cookie (line 35) | struct entropy_read_cookie
type entropy_read_cookie (line 38) | struct entropy_read_cookie
type entropy_read_cookie (line 41) | struct entropy_read_cookie
function entropy_read_fill (line 67) | int
function entropy_read_done (line 107) | int
function entropy_read (line 139) | int
FILE: libcperciva/util/entropy.h
type entropy_read_cookie (line 8) | struct entropy_read_cookie
type entropy_read_cookie (line 15) | struct entropy_read_cookie
type entropy_read_cookie (line 22) | struct entropy_read_cookie
type entropy_read_cookie (line 28) | struct entropy_read_cookie
FILE: libcperciva/util/getopt.c
type opt (line 27) | struct opt {
function getopt_atexit (line 64) | static void
function reset (line 73) | static void
function searchopt (line 114) | static size_t
function getopt_lookup (line 259) | size_t
function getopt_register_opt (line 291) | void
function getopt_register_missing (line 324) | void
function getopt_setrange (line 340) | void
FILE: libcperciva/util/humansize.c
function humansize_parse (line 64) | int
FILE: libcperciva/util/insecure_memzero.c
function insecure_memzero_func (line 7) | static void
FILE: libcperciva/util/insecure_memzero.h
function insecure_memzero (line 30) | static inline void
FILE: libcperciva/util/monoclock.c
function monoclock_get (line 26) | int
function monoclock_get_cputime (line 71) | int
function monoclock_getres (line 106) | int
FILE: libcperciva/util/monoclock.h
type timeval (line 16) | struct timeval
type timeval (line 24) | struct timeval
FILE: libcperciva/util/parsenum.h
function parsenum_float (line 142) | static inline double
function intmax_t (line 159) | static inline intmax_t
function uintmax_t (line 179) | static inline uintmax_t
FILE: libcperciva/util/readpass.c
function handle (line 33) | static void
function resetsigs (line 41) | static void
function readpass (line 68) | int
FILE: libcperciva/util/readpass_file.c
function readpass_file (line 20) | int
FILE: libcperciva/util/sysendian.h
function be16dec (line 20) | static inline uint16_t
function be16enc (line 28) | static inline void
function be32dec (line 37) | static inline uint32_t
function be32enc (line 46) | static inline void
function be64dec (line 57) | static inline uint64_t
function be64enc (line 68) | static inline void
function le16dec (line 83) | static inline uint16_t
function le16enc (line 91) | static inline void
function le32dec (line 100) | static inline uint32_t
function le32enc (line 109) | static inline void
function le64dec (line 120) | static inline uint64_t
function le64enc (line 131) | static inline void
FILE: libcperciva/util/warnp.c
function warnp_atexit (line 16) | static void
function warnp_setprogname (line 32) | void
function warn (line 56) | void
function warnx (line 98) | void
function warnp_syslog (line 143) | void
function warnp_syslog_priority (line 159) | void
FILE: main.c
function usage (line 44) | static void
function scrypt_mode_info (line 62) | static int
function scrypt_mode_enc_dec (line 110) | static int
function main (line 220) | int
FILE: tests/libscrypt-kdf/sample-libscrypt-kdf.c
function main (line 15) | int
FILE: tests/valgrind/potential-memleaks.c
function pl_freebsd_fgets (line 8) | static void
function pl_freebsd_printf_space (line 18) | static void
function pl_freebsd_printf_space_newline (line 26) | static void
function pl_freebsd_strerror (line 34) | static void
type memleaktest (line 43) | struct memleaktest {
function main (line 54) | int
FILE: tests/verify-strings/test_scrypt.c
type scrypt_test (line 8) | struct scrypt_test {
function main (line 22) | int
Condensed preview — 144 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (422K chars).
[
{
"path": ".autom4te.cfg",
"chars": 183,
"preview": "## ------------------ ##\n## User Preferences. ##\n## ------------------ ##\n\nbegin-language: \"Autoconf-without-aclocal-m4"
},
{
"path": ".github/workflows/compile.yml",
"chars": 3684,
"preview": "name: Compile & test\n\n# Run whenever we push to any branch without a \"/\", other than [coverity-scan].\non:\n push:\n br"
},
{
"path": ".github/workflows/coverity-scan.yml",
"chars": 978,
"preview": "name: coverity-scan\n\n# Only trigger on the [coverity-scan] branch.\non:\n push:\n branches:\n - coverity-scan\n\n# Ru"
},
{
"path": ".gitignore",
"chars": 844,
"preview": "# Development tools\n/devel-tools/\n# Result of autoreconf -i\n/Makefile.in\n/aclocal.m4\n/config.aux/\n/config.h.in\n/config.h"
},
{
"path": "BUILDING",
"chars": 2187,
"preview": "Installing\n----------\n\nWe strongly recommend that people use the latest official release tarball on\nhttps://www.tarsnap."
},
{
"path": "COPYRIGHT",
"chars": 1485,
"preview": "The included code and documentation (\"scrypt\") is distributed under the\nfollowing terms:\n\nCopyright 2005-2025 Colin Perc"
},
{
"path": "FORMAT",
"chars": 664,
"preview": "scrypt encrypted data format\n----------------------------\n\noffset\tlength\n0\t6\t\"scrypt\"\n6\t1\tscrypt data file version numbe"
},
{
"path": "Makefile.am",
"chars": 11876,
"preview": "bin_PROGRAMS=\tscrypt\nnoinst_PROGRAMS=\t\t\t\t\t\t\t\\\n\ttests/valgrind/potential-memleaks\t\t\t\t\\\n\ttests/verify-strings/test_scrypt\n"
},
{
"path": "README.md",
"chars": 7061,
"preview": "The scrypt key derivation function\n----------------------------------\n\n\nThe scrypt key derivation function was originall"
},
{
"path": "STYLE",
"chars": 7037,
"preview": "Code style\n==========\n\nIn general, FreeBSD style(9) should be followed unless it is irrelevant\n(e.g., $FreeBSD$ tags).\n\n"
},
{
"path": "configure.ac",
"chars": 2106,
"preview": "AC_PREREQ([2.69])\nAC_INIT([scrypt],[m4_esyscmd([sh get-version.sh])],\n [https://github.com/Tarsnap/scrypt],[scrypt],[ht"
},
{
"path": "get-version.sh",
"chars": 1189,
"preview": "#!/bin/sh\n\nversion=1.3.3-head\n\n# This script outputs a version number for this project to stdout.\n# - if $SCRYPT_VERSION"
},
{
"path": "lib/README",
"chars": 369,
"preview": "The source code under this directory is taken from the client for the\nTarsnap online backup system (and released under t"
},
{
"path": "lib/crypto/crypto_scrypt-ref.c",
"chars": 7480,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/crypto/crypto_scrypt_smix.c",
"chars": 6026,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/crypto/crypto_scrypt_smix.h",
"chars": 573,
"preview": "#ifndef CRYPTO_SCRYPT_SMIX_H_\n#define CRYPTO_SCRYPT_SMIX_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * crypto_scry"
},
{
"path": "lib/crypto/crypto_scrypt_smix_sse2.c",
"chars": 7151,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/crypto/crypto_scrypt_smix_sse2.h",
"chars": 627,
"preview": "#ifndef CRYPTO_SCRYPT_SMIX_SSE2_H_\n#define CRYPTO_SCRYPT_SMIX_SSE2_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * c"
},
{
"path": "lib/scryptenc/scryptenc.c",
"chars": 24628,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/scryptenc/scryptenc.h",
"chars": 8317,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/scryptenc/scryptenc_cpuperf.c",
"chars": 3272,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/scryptenc/scryptenc_cpuperf.h",
"chars": 1757,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib/scryptenc/scryptenc_print_error.c",
"chars": 1935,
"preview": "#include <assert.h>\n#include <stddef.h>\n\n#include \"warnp.h\"\n\n#include \"scryptenc.h\"\n#include \"scryptenc_print_error.h\"\n\n"
},
{
"path": "lib/scryptenc/scryptenc_print_error.h",
"chars": 442,
"preview": "#ifndef SCRYPTENC_PRINT_ERROR_H_\n#define SCRYPTENC_PRINT_ERROR_H_\n\n/**\n * scryptenc_print_error(rc, infilename, outfilen"
},
{
"path": "lib/util/passphrase_entry.c",
"chars": 3222,
"preview": "#include <stdlib.h>\n#include <string.h>\n\n#include \"passphrase_entry.h\"\n#include \"readpass.h\"\n#include \"warnp.h\"\n\n/**\n * "
},
{
"path": "lib/util/passphrase_entry.h",
"chars": 1145,
"preview": "#ifndef PASSPHRASE_ENTRY_H_\n#define PASSPHRASE_ENTRY_H_\n\n/* How should we get the passphrase? */\nenum passphrase_entry {"
},
{
"path": "lib-platform/crypto/crypto_scrypt.c",
"chars": 7173,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib-platform/crypto/crypto_scrypt.h",
"chars": 2103,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib-platform/platform.h",
"chars": 280,
"preview": "#ifndef PLATFORM_H_\n#define PLATFORM_H_\n\n/* Ensure that we have a config file. */\n#if defined(CONFIG_H_FILE)\n#include CO"
},
{
"path": "lib-platform/util/memlimit.c",
"chars": 9155,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "lib-platform/util/memlimit.h",
"chars": 1914,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "libcperciva/POSIX/README",
"chars": 2018,
"preview": "POSIX compatibility code\n------------------------\n\nThis code exists to work around some common POSIX compatibility issue"
},
{
"path": "libcperciva/POSIX/posix-abstract-declarator.c",
"chars": 316,
"preview": "#ifdef POSIXFAIL_ABSTRACT_DECLARATOR\nstatic int func(int ARGNAME[static restrict 1]);\n#else\nstatic int func(int [static "
},
{
"path": "libcperciva/POSIX/posix-cflags.sh",
"chars": 4316,
"preview": "# Should be sourced by\n# command -p sh posix-cflags.sh \"$PATH\"\n# from within a Makefile.\n\n# Sanity check environment"
},
{
"path": "libcperciva/POSIX/posix-clock_gettime.c",
"chars": 106,
"preview": "#include <time.h>\n\nint\nmain(void)\n{\n\tstruct timespec ts;\n\n\treturn (clock_gettime(CLOCK_REALTIME, &ts));\n}\n"
},
{
"path": "libcperciva/POSIX/posix-clock_realtime.c",
"chars": 65,
"preview": "#include <time.h>\n\nint\nmain(void)\n{\n\n\treturn (CLOCK_REALTIME);\n}\n"
},
{
"path": "libcperciva/POSIX/posix-inet-addrstrlen.c",
"chars": 72,
"preview": "#include <netinet/in.h>\n\nint\nmain(void)\n{\n\n\treturn (INET_ADDRSTRLEN);\n}\n"
},
{
"path": "libcperciva/POSIX/posix-inet6-addrstrlen.c",
"chars": 73,
"preview": "#include <netinet/in.h>\n\nint\nmain(void)\n{\n\n\treturn (INET6_ADDRSTRLEN);\n}\n"
},
{
"path": "libcperciva/POSIX/posix-l.sh",
"chars": 718,
"preview": "# Should be sourced by\n# command -p sh posix-l.sh \"$PATH\"\n# from within a Makefile.\n\n# Sanity check environment vari"
},
{
"path": "libcperciva/POSIX/posix-msg_nosignal.c",
"chars": 69,
"preview": "#include <sys/socket.h>\n\nint\nmain(void)\n{\n\n\treturn (MSG_NOSIGNAL);\n}\n"
},
{
"path": "libcperciva/POSIX/posix-restrict.c",
"chars": 156,
"preview": "static int\nfoo(const char * restrict x, const char * restrict y)\n{\n\n\treturn (x == y);\n}\n\nint\nmain(void)\n{\n\tchar x[10];\n\t"
},
{
"path": "libcperciva/POSIX/posix-stat-st_mtim.c",
"chars": 149,
"preview": "#include <sys/stat.h>\n\nint\nmain(void)\n{\n\tstruct stat sb;\n\n\t/* Can we reference st_mtim? */\n\t(void)sb.st_mtim.tv_sec;\n\n\t/"
},
{
"path": "libcperciva/POSIX/posix-trivial.c",
"chars": 49,
"preview": "int\nmain(void)\n{\n\n\t/* Success! */\n\treturn (0);\n}\n"
},
{
"path": "libcperciva/alg/sha256.c",
"chars": 18695,
"preview": "#include <assert.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"cpusupport.h\"\n#include \"insecure_memzero.h\"\n#incl"
},
{
"path": "libcperciva/alg/sha256.h",
"chars": 2827,
"preview": "#ifndef SHA256_H_\n#define SHA256_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/*\n * Use #defines in order to avoid names"
},
{
"path": "libcperciva/alg/sha256_arm.c",
"chars": 3042,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_ARM_SHA256\n/**\n * CPUSUPPORT CFLAGS: ARM_SHA256\n */\n\n#include <assert.h>\n#incl"
},
{
"path": "libcperciva/alg/sha256_arm.h",
"chars": 609,
"preview": "#ifndef SHA256_ARM_H_\n#define SHA256_ARM_H_\n\n#include <stdint.h>\n\n/**\n * SHA256_Transform_arm(state, block):\n * Compute "
},
{
"path": "libcperciva/alg/sha256_shani.c",
"chars": 5339,
"preview": "#include \"cpusupport.h\"\n#if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3)\n/**\n * CPUSUPPORT CFLAGS: X86"
},
{
"path": "libcperciva/alg/sha256_shani.h",
"chars": 702,
"preview": "#ifndef SHA256_SHANI_H_\n#define SHA256_SHANI_H_\n\n#include <stdint.h>\n\n/**\n * SHA256_Transform_shani(state, block):\n * Co"
},
{
"path": "libcperciva/alg/sha256_sse2.c",
"chars": 7173,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_X86_SSE2\n/**\n * CPUSUPPORT CFLAGS: X86_SSE2\n */\n\n#include <assert.h>\n#include "
},
{
"path": "libcperciva/alg/sha256_sse2.h",
"chars": 812,
"preview": "#ifndef SHA256_SSE2_H_\n#define SHA256_SSE2_H_\n\n#include <stdint.h>\n\n/**\n * SHA256_Transform_sse2(state, block, W, S):\n *"
},
{
"path": "libcperciva/apisupport/Build/apisupport-LIBCRYPTO-LOW_LEVEL_AES.c",
"chars": 219,
"preview": "#include <stdint.h>\n\n#include <openssl/aes.h>\n\nint\nmain(void)\n{\n\tAES_KEY kexp_actual;\n\tconst uint8_t key_unexpanded[16] "
},
{
"path": "libcperciva/apisupport/Build/apisupport-NONPOSIX-MEMLIMIT.c",
"chars": 241,
"preview": "#include \"platform.h\"\n\n#ifdef HAVE_SYS_PARAM_H\n#include <sys/param.h>\n#endif\n#ifdef HAVE_SYS_SYSCTL_H\n#include <sys/sysc"
},
{
"path": "libcperciva/apisupport/Build/apisupport.sh",
"chars": 2341,
"preview": "# Should be sourced by `command -p sh path/to/apisupport.sh \"$PATH\"` from\n# within a Makefile.\nif ! [ \"${PATH}\" = \"$1\" ]"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-ARM-AES.c",
"chars": 431,
"preview": "#include <stdint.h>\n\n#ifdef __ARM_NEON\n#include <arm_neon.h>\n#endif\n\nint\nmain(void)\n{\n\tuint8x16_t data;\n\tuint8x16_t key "
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c",
"chars": 225,
"preview": "#ifdef __ARM_NEON\n#include <arm_neon.h>\n#endif\n\nint\nmain(void)\n{\n\tuint32x4_t w0 = {0};\n\tuint32x4_t w4 = {0};\n\tuint32x4_t"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c",
"chars": 166,
"preview": "#include <sys/auxv.h>\n\nint\nmain(void)\n{\n\tint res;\n\tunsigned long val;\n\n\tres = elf_aux_info(AT_HWCAP, &val, sizeof(unsign"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c",
"chars": 112,
"preview": "#include <sys/auxv.h>\n\nint\nmain(void)\n{\n\tunsigned long val;\n\n\tval = getauxval(AT_HWCAP);\n\n\treturn (val != 0);\n}\n"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c",
"chars": 609,
"preview": "#include <stdint.h>\n\n#include <wmmintrin.h>\n\n/*\n * Use a separate function for this, because that means that the alignme"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c",
"chars": 108,
"preview": "#include <cpuid.h>\n\nint\nmain(void)\n{\n\tunsigned int a, b, c, d;\n\n\treturn (__get_cpuid(0, &a, &b, &c, &d));\n}\n"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c",
"chars": 118,
"preview": "#include <cpuid.h>\n\nint\nmain(void)\n{\n\tunsigned int a, b, c, d;\n\n\t__cpuid_count(7, 0, a, b, c, d);\n\treturn ((int)a);\n}\n"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c",
"chars": 92,
"preview": "#include <immintrin.h>\n\nint\nmain(void)\n{\n\tunsigned int x;\n\n\treturn (!_rdrand32_step(&x));\n}\n"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c",
"chars": 498,
"preview": "#include <immintrin.h>\n#include <stdint.h>\n\n/*\n * Use a separate function for this, because that means that the alignmen"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c",
"chars": 440,
"preview": "#include <emmintrin.h>\n\nstatic char a[16];\n\n/*\n * Use a separate function for this, because that means that the alignmen"
},
{
"path": "libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c",
"chars": 494,
"preview": "#include <emmintrin.h>\n#include <tmmintrin.h>\n\nstatic char a[16];\n\n/*\n * Use a separate function for this, because that "
},
{
"path": "libcperciva/cpusupport/Build/cpusupport.sh",
"chars": 3334,
"preview": "# Should be sourced by `command -p sh path/to/cpusupport.sh \"$PATH\"` from\n# within a Makefile.\nif ! [ \"${PATH}\" = \"$1\" ]"
},
{
"path": "libcperciva/cpusupport/cpusupport.h",
"chars": 6878,
"preview": "#ifndef CPUSUPPORT_H_\n#define CPUSUPPORT_H_\n\n/*\n * To enable support for non-portable CPU features at compile time, one "
},
{
"path": "libcperciva/cpusupport/cpusupport_arm_aes.c",
"chars": 1481,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_HWCAP_GETAUXVAL\n#include <sys/auxv.h>\n\n#if defined(__arm__)\n/**\n * Workaround"
},
{
"path": "libcperciva/cpusupport/cpusupport_arm_sha256.c",
"chars": 1496,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_HWCAP_GETAUXVAL\n#include <sys/auxv.h>\n\n#if defined(__arm__)\n/**\n * Workaround"
},
{
"path": "libcperciva/cpusupport/cpusupport_x86_aesni.c",
"chars": 607,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_X86_CPUID\n#include <cpuid.h>\n\n#define CPUID_AESNI_BIT (1 << 25)\n#endif\n\nCPUSU"
},
{
"path": "libcperciva/cpusupport/cpusupport_x86_rdrand.c",
"chars": 610,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_X86_CPUID\n#include <cpuid.h>\n\n#define CPUID_RDRAND_BIT (1 << 30)\n#endif\n\nCPUS"
},
{
"path": "libcperciva/cpusupport/cpusupport_x86_shani.c",
"chars": 859,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_X86_CPUID_COUNT\n#include <cpuid.h>\n\n#define CPUID_SHANI_BIT (1 << 29)\n#endif\n"
},
{
"path": "libcperciva/cpusupport/cpusupport_x86_sse2.c",
"chars": 604,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_X86_CPUID\n#include <cpuid.h>\n\n#define CPUID_SSE2_BIT (1 << 26)\n#endif\n\nCPUSUP"
},
{
"path": "libcperciva/cpusupport/cpusupport_x86_ssse3.c",
"chars": 606,
"preview": "#include \"cpusupport.h\"\n\n#ifdef CPUSUPPORT_X86_CPUID\n#include <cpuid.h>\n\n#define CPUID_SSSE3_BIT (1 << 9)\n#endif\n\nCPUSUP"
},
{
"path": "libcperciva/crypto/crypto_aes.c",
"chars": 7787,
"preview": "/**\n * APISUPPORT CFLAGS: LIBCRYPTO_LOW_LEVEL_AES\n */\n\n#include <assert.h>\n#include <stdint.h>\n#include <stdlib.h>\n#incl"
},
{
"path": "libcperciva/crypto/crypto_aes.h",
"chars": 1140,
"preview": "#ifndef CRYPTO_AES_H_\n#define CRYPTO_AES_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* Opaque structure. */\nstruct cry"
},
{
"path": "libcperciva/crypto/crypto_aes_aesni.c",
"chars": 8541,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_X86_AESNI\n/**\n * CPUSUPPORT CFLAGS: X86_AESNI\n */\n\n#include <stdint.h>\n#includ"
},
{
"path": "libcperciva/crypto/crypto_aes_aesni.h",
"chars": 1154,
"preview": "#ifndef CRYPTO_AES_AESNI_H_\n#define CRYPTO_AES_AESNI_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * crypto_aes_key_"
},
{
"path": "libcperciva/crypto/crypto_aes_aesni_m128i.h",
"chars": 522,
"preview": "#ifndef CRYPTO_AES_AESNI_M128I_H_\n#define CRYPTO_AES_AESNI_M128I_H_\n\n#include <emmintrin.h>\n\n/**\n * crypto_aes_encrypt_b"
},
{
"path": "libcperciva/crypto/crypto_aes_arm.c",
"chars": 9330,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_ARM_AES\n/**\n * CPUSUPPORT CFLAGS: ARM_AES\n */\n\n#include <stdint.h>\n#include <s"
},
{
"path": "libcperciva/crypto/crypto_aes_arm.h",
"chars": 1122,
"preview": "#ifndef CRYPTO_AES_ARM_H_\n#define CRYPTO_AES_ARM_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * crypto_aes_key_expa"
},
{
"path": "libcperciva/crypto/crypto_aes_arm_u8.h",
"chars": 521,
"preview": "#ifndef CRYPTO_AES_ARM_U8_H_\n#define CRYPTO_AES_ARM_U8_H_\n\n#ifdef __ARM_NEON\n#include <arm_neon.h>\n#endif\n\n/**\n * crypto"
},
{
"path": "libcperciva/crypto/crypto_aesctr.c",
"chars": 5978,
"preview": "#include <assert.h>\n#include <stdint.h>\n#include <stdlib.h>\n\n#include \"cpusupport.h\"\n#include \"crypto_aes.h\"\n#include \"c"
},
{
"path": "libcperciva/crypto/crypto_aesctr.h",
"chars": 1776,
"preview": "#ifndef CRYPTO_AESCTR_H_\n#define CRYPTO_AESCTR_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* Opaque types. */\nstruct c"
},
{
"path": "libcperciva/crypto/crypto_aesctr_aesni.c",
"chars": 3909,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_X86_AESNI\n/**\n * CPUSUPPORT CFLAGS: X86_AESNI\n */\n\n#include <assert.h>\n#includ"
},
{
"path": "libcperciva/crypto/crypto_aesctr_aesni.h",
"chars": 572,
"preview": "#ifndef CRYPTO_AESCTR_AESNI_H_\n#define CRYPTO_AESCTR_AESNI_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* Opaque type. "
},
{
"path": "libcperciva/crypto/crypto_aesctr_arm.c",
"chars": 3383,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_ARM_AES\n/**\n * CPUSUPPORT CFLAGS: ARM_AES\n */\n\n#include <assert.h>\n#include <s"
},
{
"path": "libcperciva/crypto/crypto_aesctr_arm.h",
"chars": 562,
"preview": "#ifndef CRYPTO_AESCTR_ARM_H_\n#define CRYPTO_AESCTR_ARM_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* Opaque type. */\ns"
},
{
"path": "libcperciva/crypto/crypto_aesctr_shared.c",
"chars": 2858,
"preview": "/*\n * This code is shared between crypto_aesctr*.c files, and should not be\n * compiled as a separate translation unit. "
},
{
"path": "libcperciva/crypto/crypto_entropy.c",
"chars": 5484,
"preview": "#include <assert.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"cpusupport.h\"\n#include \"crypto_entropy_rdrand.h\"\n"
},
{
"path": "libcperciva/crypto/crypto_entropy.h",
"chars": 260,
"preview": "#ifndef CRYPTO_ENTROPY_H_\n#define CRYPTO_ENTROPY_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * crypto_entropy_read"
},
{
"path": "libcperciva/crypto/crypto_entropy_rdrand.c",
"chars": 702,
"preview": "#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_X86_RDRAND\n/**\n * CPUSUPPORT CFLAGS: X86_RDRAND\n */\n\n#include <immintrin.h>\n#i"
},
{
"path": "libcperciva/crypto/crypto_entropy_rdrand.h",
"chars": 433,
"preview": "#ifndef CRYPTO_ENTROPY_RDRAND_H_\n#define CRYPTO_ENTROPY_RDRAND_H_\n\n#include <stddef.h>\n\n/**\n * generate_seed_rdrand(buf,"
},
{
"path": "libcperciva/crypto/crypto_verify_bytes.c",
"chars": 467,
"preview": "#include <stddef.h>\n#include <stdint.h>\n\n#include \"crypto_verify_bytes.h\"\n\n/**\n * crypto_verify_bytes(buf0, buf1, len):\n"
},
{
"path": "libcperciva/crypto/crypto_verify_bytes.h",
"chars": 413,
"preview": "#ifndef CRYPTO_VERIFY_BYTES_H_\n#define CRYPTO_VERIFY_BYTES_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * crypto_ve"
},
{
"path": "libcperciva/util/align_ptr.h",
"chars": 1697,
"preview": "#ifndef ALIGN_PTR_H_\n#define ALIGN_PTR_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * ALIGN_PTR_DECL(type, name, nu"
},
{
"path": "libcperciva/util/asprintf.c",
"chars": 790,
"preview": "#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"asprintf.h\"\n\n/**\n * asprintf(ret, format, ...):\n *"
},
{
"path": "libcperciva/util/asprintf.h",
"chars": 322,
"preview": "#ifndef ASPRINTF_H_\n#define ASPRINTF_H_\n\n/* Avoid namespace collisions with BSD/GNU asprintf. */\n#ifdef asprintf\n#undef "
},
{
"path": "libcperciva/util/entropy.c",
"chars": 3222,
"preview": "#include <assert.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stdint.h>\n#include <stdlib.h>\n#i"
},
{
"path": "libcperciva/util/entropy.h",
"chars": 855,
"preview": "#ifndef ENTROPY_H_\n#define ENTROPY_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* Opaque type. */\nstruct entropy_read_c"
},
{
"path": "libcperciva/util/getopt.c",
"chars": 8608,
"preview": "#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"getopt.h\"\n\n/*\n * Standard geto"
},
{
"path": "libcperciva/util/getopt.h",
"chars": 7009,
"preview": "#ifndef GETOPT_H_\n#define GETOPT_H_\n\n#include <assert.h>\n#include <setjmp.h>\n#include <stddef.h>\n\n/**\n * This getopt imp"
},
{
"path": "libcperciva/util/humansize.c",
"chars": 3279,
"preview": "#include <stdio.h>\n\n#include \"asprintf.h\"\n#include \"warnp.h\"\n\n#include \"humansize.h\"\n\n/**\n * humansize(size):\n * Given a"
},
{
"path": "libcperciva/util/humansize.h",
"chars": 613,
"preview": "#ifndef HUMANSIZE_H_\n#define HUMANSIZE_H_\n\n#include <stdint.h>\n\n/**\n * humansize(size):\n * Given a size ${size} in bytes"
},
{
"path": "libcperciva/util/insecure_memzero.c",
"chars": 404,
"preview": "#include <stddef.h>\n#include <stdint.h>\n\n#include \"insecure_memzero.h\"\n\n/* Function which does the zeroing. */\nstatic vo"
},
{
"path": "libcperciva/util/insecure_memzero.h",
"chars": 1489,
"preview": "#ifndef INSECURE_MEMZERO_H_\n#define INSECURE_MEMZERO_H_\n\n#include <stddef.h>\n\n/* Pointer to memory-zeroing function. */\n"
},
{
"path": "libcperciva/util/monoclock.c",
"chars": 3611,
"preview": "#include <sys/time.h>\n\n#include <errno.h>\n#include <time.h>\n\n#include \"warnp.h\"\n\n#include \"monoclock.h\"\n\n/* Determine wh"
},
{
"path": "libcperciva/util/monoclock.h",
"chars": 1111,
"preview": "#ifndef MONOCLOCK_H_\n#define MONOCLOCK_H_\n\n#include <sys/time.h>\n\n/* Macro to simplify benchmarks. */\n#define timeval_di"
},
{
"path": "libcperciva/util/parsenum.h",
"chars": 6494,
"preview": "#ifndef PARSENUM_H_\n#define PARSENUM_H_\n\n#include <assert.h>\n#include <errno.h>\n#include <inttypes.h>\n#include <math.h>\n"
},
{
"path": "libcperciva/util/readpass.c",
"chars": 6089,
"preview": "#include <signal.h>\n#include <stdio.h>\n#include <string.h>\n#include <termios.h>\n#include <unistd.h>\n\n#include \"insecure_"
},
{
"path": "libcperciva/util/readpass.h",
"chars": 1336,
"preview": "#ifndef READPASS_H_\n#define READPASS_H_\n\n/* Avoid namespace collisions with other \"readpass\" functions. */\n#ifdef readpa"
},
{
"path": "libcperciva/util/readpass_file.c",
"chars": 1714,
"preview": "#include <stdio.h>\n#include <string.h>\n\n#include \"insecure_memzero.h\"\n#include \"warnp.h\"\n\n#include \"readpass.h\"\n\n/* Maxi"
},
{
"path": "libcperciva/util/sysendian.h",
"chars": 3164,
"preview": "#ifndef SYSENDIAN_H_\n#define SYSENDIAN_H_\n\n#include <stdint.h>\n\n/* Avoid namespace collisions with BSD <sys/endian.h>. *"
},
{
"path": "libcperciva/util/warnp.c",
"chars": 3566,
"preview": "#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <syslog.h>\n\n#"
},
{
"path": "libcperciva/util/warnp.h",
"chars": 1907,
"preview": "#ifndef WARNP_H_\n#define WARNP_H_\n\n#include <errno.h>\n#include <stddef.h>\n\n/* Avoid namespace collisions with BSD <err.h"
},
{
"path": "libscrypt-kdf/scrypt-kdf.h",
"chars": 2279,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "m4/check_darwin_paths.m4",
"chars": 518,
"preview": "# CHECK_DARWIN_PATHS\n# -------------------\nAC_DEFUN([CHECK_DARWIN_PATHS],\n[AC_REQUIRE([AC_CANONICAL_TARGET])\n\ncase $targ"
},
{
"path": "m4/check_disable_compiler_warnings.m4",
"chars": 528,
"preview": "# CHECK_DISABLE_COMPILER_WARNINGS\n# -------------------------------\nAC_DEFUN([CHECK_DISABLE_COMPILER_WARNINGS], [\n\tAC_MS"
},
{
"path": "m4/check_libcperciva_posix.m4",
"chars": 551,
"preview": "# CHECK_LIBCPERCIVA_POSIX([LIBCPERCIVA_DIR])\n# ------------------------------------------\nAC_DEFUN([CHECK_LIBCPERCIVA_PO"
},
{
"path": "m4/check_memlimit_support.m4",
"chars": 864,
"preview": "# CHECK_MEMLIMIT_SUPPORT\n# ----------------------\nAC_DEFUN([CHECK_MEMLIMIT_SUPPORT], [\n\t# Check for a linuxy sysinfo sys"
},
{
"path": "m4/check_posix_sh.m4",
"chars": 673,
"preview": "# CHECK_POSIX_SH\n# --------------\nAC_DEFUN([CHECK_POSIX_SH], [\n\t# Allow users to manually specify the path to a POSIX sh"
},
{
"path": "m4/check_solaris_c99.m4",
"chars": 1232,
"preview": "# CHECK_SOLARIS_C99\n# -----------------\n# On Solaris, the default standard library is c89-compatible. Some linkers\n# re"
},
{
"path": "main.c",
"chars": 10830,
"preview": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, wi"
},
{
"path": "release-tools/create-sign-tarball.sh",
"chars": 823,
"preview": "#!/bin/sh\n\n# Process command-line arguments\nSCRYPTVERSION=$1\nGNUPG_SIGNING_HOME=$2\n\n# Check for required arguments\nif [ "
},
{
"path": "release-tools/mktarball.sh",
"chars": 889,
"preview": "#!/bin/sh\n\nVERSION=$1\nif [ -z \"${VERSION}\" ]; then\n\techo \"Please specify the version number\"\n\texit 1\nfi\nDESTDIR=scrypt-$"
},
{
"path": "scrypt.1",
"chars": 6583,
"preview": ".\\\" Copyright 2009 Colin Percival\n.\\\" All rights reserved.\n.\\\"\n.\\\" Redistribution and use in source and binary forms, wi"
},
{
"path": "tests/01-known-values.sh",
"chars": 850,
"preview": "#!/bin/sh\n\n### Constants\n# The scenario command requires a lot of memory, so valgrind is only enabled\n# if $USE_VALGRIND"
},
{
"path": "tests/02-decrypt-reference-file.sh",
"chars": 1896,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\nencrypted_refere"
},
{
"path": "tests/03-encrypt-decrypt-file.sh",
"chars": 1286,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\nencrypted_file=\""
},
{
"path": "tests/04-force-resources.sh",
"chars": 1588,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\nlongwait_encrypt"
},
{
"path": "tests/05-system-scrypt-encrypt-decrypt.sh",
"chars": 1856,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\nencrypted_file_1"
},
{
"path": "tests/06-decrypt-fail.sh",
"chars": 952,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nnon_encoded_file=\"${scriptdir}/06-decrypt-fail.sh\"\nnon_encoded_file_stderr=\"${"
},
{
"path": "tests/07-passphrase-env.sh",
"chars": 2470,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\nencrypted_refere"
},
{
"path": "tests/08-passphrase-file.sh",
"chars": 2628,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\npassphrase_file="
},
{
"path": "tests/09-explicit-params.sh",
"chars": 2170,
"preview": "#!/bin/sh\n\n### Constants\nc_valgrind_min=1\nreference_file=\"${scriptdir}/verify-strings/test_scrypt.good\"\nencrypted_file=\""
},
{
"path": "tests/libscrypt-kdf/sample-libscrypt-kdf.c",
"chars": 758,
"preview": "#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"scrypt-kdf.h\"\n\n/* Parameters controlling memory us"
},
{
"path": "tests/shared_test_functions.sh",
"chars": 11346,
"preview": "#!/bin/sh\n\n### Definitions\n#\n# This test suite uses the following terminology:\n# - scenario: a series of commands to tes"
},
{
"path": "tests/shared_valgrind_functions.sh",
"chars": 15813,
"preview": "#!/bin/sh\n\nset -o noclobber -o nounset\n\n### Design\n#\n# This file contains functions related to checking with valgrind. "
},
{
"path": "tests/test_scrypt.sh",
"chars": 516,
"preview": "#!/bin/sh\n\n### Find script directory and load helper functions.\nscriptdir=$(CDPATH='' cd -- \"$(dirname -- \"$0\")\" && pwd "
},
{
"path": "tests/valgrind/potential-memleaks.c",
"chars": 1468,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define FGETS_BUFSIZE 64\n\n/* Problem with FreeBSD 10.3 fgets"
},
{
"path": "tests/verify-strings/test_scrypt.c",
"chars": 1571,
"preview": "#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"crypto_scrypt.h\"\n#include \"warnp.h\"\n\nstatic struct"
},
{
"path": "tests/verify-strings/test_scrypt.good",
"chars": 969,
"preview": "scrypt(\"\", \"\", 16, 1, 1, 64) =\n77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97\nf1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2"
},
{
"path": "tests/verify-strings/test_scrypt_small.good",
"chars": 714,
"preview": "scrypt(\"\", \"\", 16, 1, 1, 64) =\n77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97\nf1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the Tarsnap/scrypt GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 144 files (376.5 KB), approximately 125.5k tokens, and a symbol index with 264 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.