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 , 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 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. , with first followed by others alphabetically. 2. , 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, should be included to provide it. If size_t is needed, should be included to provide it unless , , , or is already required. If the C99 integer types (uint8_t, int64_t, etc.) are required, should be included to provide them unless 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 #include #include #include #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 #include #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 #include /** * 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 #include #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 #include /** * 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 #include #include #include #include #include #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 #include /** * 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 #include #include #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 #include #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 #include #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 #include #include #include #include #include #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 #include /** * 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 #include #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_SYSCTL_H #include #endif #ifdef HAVE_SYS_SYSINFO_H #include #endif #include #include #include #include #include #include #ifdef DEBUG #include #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 /** * 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: not defining MSG_NOSIGNAL. - DPOSIXFAIL_CLOCK_REALTIME: not defining CLOCK_REALTIME. - DPOSIXFAIL_CLOCK_GETTIME: not declaring clock_gettime(), or clock_gettime() is not linkable. The latter test requires a runtime check. - DPOSIXFAIL_INET_ADDRSTRLEN: not defining INET_ADDRSTRLEN. - DPOSIXFAIL_INET6_ADDRSTRLEN: 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: 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: 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: 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: 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: 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 int main(void) { struct timespec ts; return (clock_gettime(CLOCK_REALTIME, &ts)); } ================================================ FILE: libcperciva/POSIX/posix-clock_realtime.c ================================================ #include int main(void) { return (CLOCK_REALTIME); } ================================================ FILE: libcperciva/POSIX/posix-inet-addrstrlen.c ================================================ #include int main(void) { return (INET_ADDRSTRLEN); } ================================================ FILE: libcperciva/POSIX/posix-inet6-addrstrlen.c ================================================ #include 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 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 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 #include #include #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 #include /* * 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 #include #include #ifdef __ARM_NEON #include #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 /** * 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 #include #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 /** * 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 #include #include #include #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 /** * 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 #include 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 #endif #ifdef HAVE_SYS_SYSCTL_H #include #endif #ifdef HAVE_SYS_SYSINFO_H #include #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 #ifdef __ARM_NEON #include #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 #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 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 int main(void) { unsigned long val; val = getauxval(AT_HWCAP); return (val != 0); } ================================================ FILE: libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c ================================================ #include #include /* * 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 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 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 int main(void) { unsigned int x; return (!_rdrand32_step(&x)); } ================================================ FILE: libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c ================================================ #include #include /* * 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 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 #include 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 ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_HWCAP_GETAUXVAL #include #if defined(__arm__) /** * Workaround for a glibc bug: contains a comment saying: * The following must match the kernel's . * However, it does not contain any of the HWCAP2_* entries from . */ #ifndef HWCAP2_AES #include #endif #endif /* __arm__ */ #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) #include #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ CPUSUPPORT_FEATURE_DECL(arm, aes) { int supported = 0; #if defined(CPUSUPPORT_ARM_AES) #if defined(CPUSUPPORT_HWCAP_GETAUXVAL) unsigned long capabilities; #if defined(__aarch64__) capabilities = getauxval(AT_HWCAP); supported = (capabilities & HWCAP_AES) ? 1 : 0; #elif defined(__arm__) capabilities = getauxval(AT_HWCAP2); supported = (capabilities & HWCAP2_AES) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) unsigned long capabilities; #if defined(__aarch64__) if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP_AES) ? 1 : 0; #else if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP2_AES) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ #endif /* CPUSUPPORT_ARM_AES */ /* Return the supported status. */ return (supported); } ================================================ FILE: libcperciva/cpusupport/cpusupport_arm_sha256.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_HWCAP_GETAUXVAL #include #if defined(__arm__) /** * Workaround for a glibc bug: contains a comment saying: * The following must match the kernel's . * However, it does not contain any of the HWCAP2_* entries from . */ #ifndef HWCAP2_CRC32 #include #endif #endif /* __arm__ */ #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) #include #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ CPUSUPPORT_FEATURE_DECL(arm, sha256) { int supported = 0; #if defined(CPUSUPPORT_ARM_SHA256) #if defined(CPUSUPPORT_HWCAP_GETAUXVAL) unsigned long capabilities; #if defined(__aarch64__) capabilities = getauxval(AT_HWCAP); supported = (capabilities & HWCAP_SHA2) ? 1 : 0; #elif defined(__arm__) capabilities = getauxval(AT_HWCAP2); supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) unsigned long capabilities; #if defined(__aarch64__) if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP_SHA2) ? 1 : 0; #else if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ #endif /* CPUSUPPORT_ARM_SHA256 */ /* Return the supported status. */ return (supported); } ================================================ FILE: libcperciva/cpusupport/cpusupport_x86_aesni.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_AESNI_BIT (1 << 25) #endif CPUSUPPORT_FEATURE_DECL(x86, aesni) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((ecx & CPUID_AESNI_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } ================================================ FILE: libcperciva/cpusupport/cpusupport_x86_rdrand.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_RDRAND_BIT (1 << 30) #endif CPUSUPPORT_FEATURE_DECL(x86, rdrand) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((ecx & CPUID_RDRAND_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } ================================================ FILE: libcperciva/cpusupport/cpusupport_x86_shani.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID_COUNT #include #define CPUID_SHANI_BIT (1 << 29) #endif CPUSUPPORT_FEATURE_DECL(x86, shani) { #ifdef CPUSUPPORT_X86_CPUID_COUNT unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 7) goto unsupported; /* * Ask about extended CPU features. Note that this macro violates * the principle of being "function-like" by taking the variables * used for holding output registers as named parameters rather than * as pointers (which would be necessary if __cpuid_count were a * function). */ __cpuid_count(7, 0, eax, ebx, ecx, edx); /* Return the relevant feature bit. */ return ((ebx & CPUID_SHANI_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } ================================================ FILE: libcperciva/cpusupport/cpusupport_x86_sse2.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_SSE2_BIT (1 << 26) #endif CPUSUPPORT_FEATURE_DECL(x86, sse2) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((edx & CPUID_SSE2_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } ================================================ FILE: libcperciva/cpusupport/cpusupport_x86_ssse3.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_SSSE3_BIT (1 << 9) #endif CPUSUPPORT_FEATURE_DECL(x86, ssse3) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((ecx & CPUID_SSSE3_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } ================================================ FILE: libcperciva/crypto/crypto_aes.c ================================================ /** * APISUPPORT CFLAGS: LIBCRYPTO_LOW_LEVEL_AES */ #include #include #include #include #include #include "cpusupport.h" #include "crypto_aes_aesni.h" #include "crypto_aes_arm.h" #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes.h" #if defined(CPUSUPPORT_X86_AESNI) || defined(CPUSUPPORT_ARM_AES) #define HWACCEL static enum { HW_SOFTWARE = 0, #if defined(CPUSUPPORT_X86_AESNI) HW_X86_AESNI, #endif #if defined(CPUSUPPORT_ARM_AES) HW_ARM_AES, #endif HW_UNSET } hwaccel = HW_UNSET; #endif /** * This represents either an AES_KEY or a struct crypto_aes_key_aesni; we * know which it is based on whether we're using AESNI code or not. As such, * it's just an opaque pointer; but declaring it as a named structure type * prevents type-mismatch bugs in upstream code. */ struct crypto_aes_key; #ifdef HWACCEL static struct aes_test { const uint8_t key[32]; const size_t len; const uint8_t ptext[16]; const uint8_t ctext[16]; } testcases[] = { { /* NIST FIPS 179, Appendix C - Example Vectors, AES-128, p. 35. */ .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, .len = 16, .ptext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, .ctext = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } }, { /* NIST FIPS 179, Appendix C - Example Vectors, AES-256, p. 42. */ .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, }, .len = 32, .ptext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, .ctext = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } } }; /* Test a function against test vectors. */ static int functest(int (* func)(const uint8_t *, size_t, const uint8_t[16], uint8_t[16])) { struct aes_test * knowngood; uint8_t ctext[16]; size_t i; for (i = 0; i < sizeof(testcases) / sizeof(testcases[0]); i++) { knowngood = &testcases[i]; /* Sanity-check. */ assert((knowngood->len == 16) || (knowngood->len == 32)); /* Expand the key and encrypt with the provided function. */ if (func(knowngood->key, knowngood->len, knowngood->ptext, ctext)) goto err0; /* Does the output match the known good value? */ if (memcmp(knowngood->ctext, ctext, 16)) goto err0; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } #if defined(CPUSUPPORT_X86_AESNI) static int x86_aesni_oneshot(const uint8_t * key_unexpanded, size_t len, const uint8_t ptext[16], uint8_t ctext[16]) { void * kexp_hw; /* Expand the key and encrypt with hardware intrinsics. */ if ((kexp_hw = crypto_aes_key_expand_aesni(key_unexpanded, len)) == NULL) goto err0; crypto_aes_encrypt_block_aesni(ptext, ctext, kexp_hw); crypto_aes_key_free_aesni(kexp_hw); /* Success! */ return (0); err0: /* Failure! */ return (-1); } #endif #if defined(CPUSUPPORT_ARM_AES) static int arm_aes_oneshot(const uint8_t * key_unexpanded, size_t len, const uint8_t ptext[16], uint8_t * ctext) { void * kexp_hw; if ((kexp_hw = crypto_aes_key_expand_arm(key_unexpanded, len)) == NULL) goto err0; crypto_aes_encrypt_block_arm(ptext, ctext, kexp_hw); crypto_aes_key_free_arm(kexp_hw); /* Success! */ return (0); err0: /* Failure! */ return (-1); } #endif static int openssl_oneshot(const uint8_t * key_unexpanded, size_t len, const uint8_t ptext[16], uint8_t * ctext) { AES_KEY kexp_actual; AES_KEY * kexp = &kexp_actual; /* Expand the key, encrypt, and clean up. */ if (AES_set_encrypt_key(key_unexpanded, (int)(len * 8), kexp) != 0) goto err0; AES_encrypt(ptext, ctext, kexp); insecure_memzero(kexp, sizeof(AES_KEY)); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Which type of hardware acceleration should we use, if any? */ static void hwaccel_init(void) { /* If we've already set hwaccel, we're finished. */ if (hwaccel != HW_UNSET) return; /* Default to software. */ hwaccel = HW_SOFTWARE; #if defined(CPUSUPPORT_X86_AESNI) CPUSUPPORT_VALIDATE(hwaccel, HW_X86_AESNI, cpusupport_x86_aesni(), functest(x86_aesni_oneshot)); #endif #if defined(CPUSUPPORT_ARM_AES) CPUSUPPORT_VALIDATE(hwaccel, HW_ARM_AES, cpusupport_arm_aes(), functest(arm_aes_oneshot)); #endif /* * If we're here, we're not using any intrinsics. Test OpenSSL; if * there's an error, print a warning and abort. */ if (functest(openssl_oneshot)) { warn0("OpenSSL gives incorrect AES values."); abort(); } } #endif /* HWACCEL */ /** * crypto_aes_can_use_intrinsics(void): * Test whether hardware intrinsics are safe to use. Return 1 if x86 AESNI * operations are available, 2 if ARM-AES operations are available, or 0 if * none are available. */ int crypto_aes_can_use_intrinsics(void) { #ifdef HWACCEL /* Ensure that we've chosen the type of hardware acceleration. */ hwaccel_init(); #if defined(CPUSUPPORT_X86_AESNI) if (hwaccel == HW_X86_AESNI) return (1); #endif #if defined(CPUSUPPORT_ARM_AES) if (hwaccel == HW_ARM_AES) return (2); #endif #endif /* HWACCEL */ /* Software only. */ return (0); } /** * crypto_aes_key_expand(key_unexpanded, len): * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a * structure which can be passed to crypto_aes_encrypt_block(). The length * must be 16 or 32. */ struct crypto_aes_key * crypto_aes_key_expand(const uint8_t * key_unexpanded, size_t len) { AES_KEY * kexp; /* Sanity-check. */ assert((len == 16) || (len == 32)); #ifdef HWACCEL /* Ensure that we've chosen the type of hardware acceleration. */ hwaccel_init(); #ifdef CPUSUPPORT_X86_AESNI if (hwaccel == HW_X86_AESNI) return (crypto_aes_key_expand_aesni(key_unexpanded, len)); #endif #ifdef CPUSUPPORT_ARM_AES if (hwaccel == HW_ARM_AES) return (crypto_aes_key_expand_arm(key_unexpanded, len)); #endif #endif /* HWACCEL */ /* Allocate structure. */ if ((kexp = malloc(sizeof(AES_KEY))) == NULL) goto err0; /* Expand the key. */ if (AES_set_encrypt_key(key_unexpanded, (int)(len * 8), kexp) != 0) goto err1; /* Success! */ return ((void *)kexp); err1: free(kexp); err0: /* Failure! */ return (NULL); } /** * crypto_aes_encrypt_block(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. ${in} and ${out} can overlap. */ void crypto_aes_encrypt_block(const uint8_t in[16], uint8_t out[16], const struct crypto_aes_key * key) { #ifdef HWACCEL #ifdef CPUSUPPORT_X86_AESNI if (hwaccel == HW_X86_AESNI) { crypto_aes_encrypt_block_aesni(in, out, (const void *)key); return; } #endif #ifdef CPUSUPPORT_ARM_AES if (hwaccel == HW_ARM_AES) { crypto_aes_encrypt_block_arm(in, out, (const void *)key); return; } #endif #endif /* HWACCEL */ /* Get AES to do the work. */ AES_encrypt(in, out, (const void *)key); } /** * crypto_aes_key_free(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free(struct crypto_aes_key * key) { #ifdef HWACCEL #ifdef CPUSUPPORT_X86_AESNI if (hwaccel == HW_X86_AESNI) { crypto_aes_key_free_aesni((void *)key); return; } #endif #ifdef CPUSUPPORT_ARM_AES if (hwaccel == HW_ARM_AES) { crypto_aes_key_free_arm((void *)key); return; } #endif #endif /* HWACCEL */ /* Behave consistently with free(NULL). */ if (key == NULL) return; /* Attempt to zero the expanded key. */ insecure_memzero(key, sizeof(AES_KEY)); /* Free the key. */ free(key); } ================================================ FILE: libcperciva/crypto/crypto_aes.h ================================================ #ifndef CRYPTO_AES_H_ #define CRYPTO_AES_H_ #include #include /* Opaque structure. */ struct crypto_aes_key; /** * crypto_aes_can_use_intrinsics(void): * Test whether hardware intrinsics are safe to use. Return 1 if x86 AESNI * operations are available, 2 if ARM-AES operations are available, or 0 if * none are available. */ int crypto_aes_can_use_intrinsics(void); /** * crypto_aes_key_expand(key_unexpanded, len): * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a * structure which can be passed to crypto_aes_encrypt_block(). The length * must be 16 or 32. */ struct crypto_aes_key * crypto_aes_key_expand(const uint8_t *, size_t); /** * crypto_aes_encrypt_block(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. ${in} and ${out} can overlap. */ void crypto_aes_encrypt_block(const uint8_t[16], uint8_t[16], const struct crypto_aes_key *); /** * crypto_aes_key_free(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free(struct crypto_aes_key *); #endif /* !CRYPTO_AES_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aes_aesni.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_AESNI /** * CPUSUPPORT CFLAGS: X86_AESNI */ #include #include #include #include "align_ptr.h" #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes_aesni.h" #include "crypto_aes_aesni_m128i.h" /* Expanded-key structure. */ struct crypto_aes_key_aesni { ALIGN_PTR_DECL(__m128i, rkeys, 15, sizeof(__m128i)); size_t nr; }; /* Compute an AES-128 round key. */ #define MKRKEY128(rkeys, i, rcon) do { \ __m128i _s = rkeys[i - 1]; \ __m128i _t = rkeys[i - 1]; \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 4)); \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 8)); \ _t = _mm_aeskeygenassist_si128(_t, rcon); \ _t = _mm_shuffle_epi32(_t, 0xff); \ rkeys[i] = _mm_xor_si128(_s, _t); \ } while (0) /** * crypto_aes_key_expand_128_aesni(key_unexpanded, rkeys): * Expand the 128-bit AES unexpanded key ${key_unexpanded} into the 11 round * keys ${rkeys}. This implementation uses x86 AESNI instructions, and should * only be used if CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() * returns nonzero. */ static void crypto_aes_key_expand_128_aesni(const uint8_t key_unexpanded[16], __m128i rkeys[11]) { /* The first round key is just the key. */ /*- * XXX Compiler breakage: * The intrinsic defined by Intel for _mm_loadu_si128 defines it as * taking a (const __m128i *) parameter. This forces us to write a * bug: The cast to (const __m128i *) is invalid since it increases * the alignment requirement of the pointer. Alas, until compilers * get fixed intrinsics, all we can do is code the bug and require * that alignment-requirement-increasing compiler warnings get * disabled. */ rkeys[0] = _mm_loadu_si128((const __m128i *)&key_unexpanded[0]); /* * Each of the remaining round keys are computed from the preceding * round key: rotword+subword+rcon (provided as aeskeygenassist) to * compute the 'temp' value, then xor with 1, 2, 3, or all 4 of the * 32-bit words from the preceding round key. Unfortunately, 'rcon' * is encoded as an immediate value, so we need to write the loop out * ourselves rather than allowing the compiler to expand it. */ MKRKEY128(rkeys, 1, 0x01); MKRKEY128(rkeys, 2, 0x02); MKRKEY128(rkeys, 3, 0x04); MKRKEY128(rkeys, 4, 0x08); MKRKEY128(rkeys, 5, 0x10); MKRKEY128(rkeys, 6, 0x20); MKRKEY128(rkeys, 7, 0x40); MKRKEY128(rkeys, 8, 0x80); MKRKEY128(rkeys, 9, 0x1b); MKRKEY128(rkeys, 10, 0x36); } /* Compute an AES-256 round key. */ #define MKRKEY256(rkeys, i, shuffle, rcon) do { \ __m128i _s = rkeys[i - 2]; \ __m128i _t = rkeys[i - 1]; \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 4)); \ _s = _mm_xor_si128(_s, _mm_slli_si128(_s, 8)); \ _t = _mm_aeskeygenassist_si128(_t, rcon); \ _t = _mm_shuffle_epi32(_t, shuffle); \ rkeys[i] = _mm_xor_si128(_s, _t); \ } while (0) /** * crypto_aes_key_expand_256_aesni(key_unexpanded, rkeys): * Expand the 256-bit unexpanded AES key ${key_unexpanded} into the 15 round * keys ${rkeys}. This implementation uses x86 AESNI instructions, and should * only be used if CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() * returns nonzero. */ static void crypto_aes_key_expand_256_aesni(const uint8_t key_unexpanded[32], __m128i rkeys[15]) { /* The first two round keys are just the key. */ /*- * XXX Compiler breakage: * The intrinsic defined by Intel for _mm_loadu_si128 defines it as * taking a (const __m128i *) parameter. This forces us to write a * bug: The cast to (const __m128i *) is invalid since it increases * the alignment requirement of the pointer. Alas, until compilers * get fixed intrinsics, all we can do is code the bug and require * that alignment-requirement-increasing compiler warnings get * disabled. */ rkeys[0] = _mm_loadu_si128((const __m128i *)&key_unexpanded[0]); rkeys[1] = _mm_loadu_si128((const __m128i *)&key_unexpanded[16]); /* * Each of the remaining round keys are computed from the preceding * pair of keys. Even rounds use rotword+subword+rcon, while odd * rounds just use subword; the aeskeygenassist instruction computes * both, and we use 0xff or 0xaa to select the one we need. The rcon * value used is irrelevant for odd rounds since we ignore the value * which it feeds into. Unfortunately, the 'shuffle' and 'rcon' * values are encoded into the instructions as immediates, so we need * to write the loop out ourselves rather than allowing the compiler * to expand it. */ MKRKEY256(rkeys, 2, 0xff, 0x01); MKRKEY256(rkeys, 3, 0xaa, 0x00); MKRKEY256(rkeys, 4, 0xff, 0x02); MKRKEY256(rkeys, 5, 0xaa, 0x00); MKRKEY256(rkeys, 6, 0xff, 0x04); MKRKEY256(rkeys, 7, 0xaa, 0x00); MKRKEY256(rkeys, 8, 0xff, 0x08); MKRKEY256(rkeys, 9, 0xaa, 0x00); MKRKEY256(rkeys, 10, 0xff, 0x10); MKRKEY256(rkeys, 11, 0xaa, 0x00); MKRKEY256(rkeys, 12, 0xff, 0x20); MKRKEY256(rkeys, 13, 0xaa, 0x00); MKRKEY256(rkeys, 14, 0xff, 0x40); } /** * crypto_aes_key_expand_aesni(key_unexpanded, len): * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a * structure which can be passed to crypto_aes_encrypt_block_aesni(). The * length must be 16 or 32. This implementation uses x86 AESNI instructions, * and should only be used if CPUSUPPORT_X86_AESNI is defined and * cpusupport_x86_aesni() returns nonzero. */ void * crypto_aes_key_expand_aesni(const uint8_t * key_unexpanded, size_t len) { struct crypto_aes_key_aesni * kexp; /* Allocate structure. */ if ((kexp = malloc(sizeof(struct crypto_aes_key_aesni))) == NULL) goto err0; /* Figure out where to put the round keys. */ ALIGN_PTR_INIT(kexp->rkeys, sizeof(__m128i)); /* Compute round keys. */ if (len == 16) { kexp->nr = 10; crypto_aes_key_expand_128_aesni(key_unexpanded, kexp->rkeys); } else if (len == 32) { kexp->nr = 14; crypto_aes_key_expand_256_aesni(key_unexpanded, kexp->rkeys); } else { warn0("Unsupported AES key length: %zu bytes", len); goto err1; } /* Success! */ return (kexp); err1: free(kexp); err0: /* Failure! */ return (NULL); } /** * crypto_aes_encrypt_block_aesni_m128i(in, key): * Using the expanded AES key ${key}, encrypt the block ${in} and return the * resulting ciphertext. This implementation uses x86 AESNI instructions, * and should only be used if CPUSUPPORT_X86_AESNI is defined and * cpusupport_x86_aesni() returns nonzero. */ __m128i crypto_aes_encrypt_block_aesni_m128i(__m128i in, const void * key) { const struct crypto_aes_key_aesni * _key = key; const __m128i * aes_key = _key->rkeys; __m128i aes_state = in; size_t nr = _key->nr; aes_state = _mm_xor_si128(aes_state, aes_key[0]); aes_state = _mm_aesenc_si128(aes_state, aes_key[1]); aes_state = _mm_aesenc_si128(aes_state, aes_key[2]); aes_state = _mm_aesenc_si128(aes_state, aes_key[3]); aes_state = _mm_aesenc_si128(aes_state, aes_key[4]); aes_state = _mm_aesenc_si128(aes_state, aes_key[5]); aes_state = _mm_aesenc_si128(aes_state, aes_key[6]); aes_state = _mm_aesenc_si128(aes_state, aes_key[7]); aes_state = _mm_aesenc_si128(aes_state, aes_key[8]); aes_state = _mm_aesenc_si128(aes_state, aes_key[9]); if (nr > 10) { aes_state = _mm_aesenc_si128(aes_state, aes_key[10]); aes_state = _mm_aesenc_si128(aes_state, aes_key[11]); aes_state = _mm_aesenc_si128(aes_state, aes_key[12]); aes_state = _mm_aesenc_si128(aes_state, aes_key[13]); } aes_state = _mm_aesenclast_si128(aes_state, aes_key[nr]); return (aes_state); } /** * crypto_aes_encrypt_block_aesni(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This * implementation uses x86 AESNI instructions, and should only be used if * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ void crypto_aes_encrypt_block_aesni(const uint8_t in[16], uint8_t out[16], const void * key) { __m128i aes_state; aes_state = _mm_loadu_si128((const __m128i *)in); aes_state = crypto_aes_encrypt_block_aesni_m128i(aes_state, key); _mm_storeu_si128((__m128i *)out, aes_state); } /** * crypto_aes_key_free_aesni(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free_aesni(void * key) { /* Behave consistently with free(NULL). */ if (key == NULL) return; /* Attempt to zero the expanded key. */ insecure_memzero(key, sizeof(struct crypto_aes_key_aesni)); /* Free the key. */ free(key); } #endif /* CPUSUPPORT_X86_AESNI */ ================================================ FILE: libcperciva/crypto/crypto_aes_aesni.h ================================================ #ifndef CRYPTO_AES_AESNI_H_ #define CRYPTO_AES_AESNI_H_ #include #include /** * crypto_aes_key_expand_aesni(key_unexpanded, len): * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a * structure which can be passed to crypto_aes_encrypt_block_aesni(). The * length must be 16 or 32. This implementation uses x86 AESNI instructions, * and should only be used if CPUSUPPORT_X86_AESNI is defined and * cpusupport_x86_aesni() returns nonzero. */ void * crypto_aes_key_expand_aesni(const uint8_t *, size_t); /** * crypto_aes_encrypt_block_aesni(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This * implementation uses x86 AESNI instructions, and should only be used if * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. */ void crypto_aes_encrypt_block_aesni(const uint8_t[16], uint8_t[16], const void *); /** * crypto_aes_key_free_aesni(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free_aesni(void *); #endif /* !CRYPTO_AES_AESNI_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aes_aesni_m128i.h ================================================ #ifndef CRYPTO_AES_AESNI_M128I_H_ #define CRYPTO_AES_AESNI_M128I_H_ #include /** * crypto_aes_encrypt_block_aesni_m128i(in, key): * Using the expanded AES key ${key}, encrypt the block ${in} and return the * resulting ciphertext. This implementation uses x86 AESNI instructions, * and should only be used if CPUSUPPORT_X86_AESNI is defined and * cpusupport_x86_aesni() returns nonzero. */ __m128i crypto_aes_encrypt_block_aesni_m128i(__m128i, const void *); #endif /* !CRYPTO_AES_AESNI_M128I_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aes_arm.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_ARM_AES /** * CPUSUPPORT CFLAGS: ARM_AES */ #include #include #ifdef __ARM_NEON #include #endif #include "align_ptr.h" #include "insecure_memzero.h" #include "warnp.h" #include "crypto_aes_arm.h" #include "crypto_aes_arm_u8.h" /* Expanded-key structure. */ struct crypto_aes_key_arm { ALIGN_PTR_DECL(uint8x16_t, rkeys, 15, sizeof(uint8x16_t)); size_t nr; }; /** * vdupq_laneq_u32_u8(a, lane): * Set all 32-bit vector lanes to the same value. Exactly the same as * vdupq_laneq_u32(), except that accepts (and returns) uint8x16_t. */ #define vdupq_laneq_u32_u8(a, lane) \ vreinterpretq_u8_u32(vdupq_laneq_u32(vreinterpretq_u32_u8(a), lane)) /** * vshlq_n_u128(a, n): * Shift left (immediate), applied to the whole vector at once. * * Implementation note: this concatenates ${a} with a vector containing zeros, * then extracts a new vector from the pair (similar to a sliding window). * For example, vshlq_n_u128(a, 3) would do: * 0xaaaaaaaaaaaaaaaa0000000000000000 * return: ~~~~~~~~~~~~~~~~ * This is the recommended method of shifting an entire vector with Neon * intrinsics; all of the built-in shift instructions operate on multiple * values (such as a pair of 64-bit values). */ #define vshlq_n_u128(a, n) vextq_u8(vdupq_n_u8(0), a, 16 - n) /** * SubWord_duplicate(a): * Perform the AES SubWord operation on the final 32-bit word (bits 96..127) * of ${a}, and return a vector consisting of that value copied to all lanes. */ static inline uint8x16_t SubWord_duplicate(uint8x16_t a) { /* * Duplicate the final 32-bit word in all other lanes. By having four * copies of the same uint32_t, we cause the ShiftRows in the upcoming * AESE to have no effect. */ a = vdupq_laneq_u32_u8(a, 3); /* AESE does AddRoundKey (nop), ShiftRows (nop), and SubBytes. */ a = vaeseq_u8(a, vdupq_n_u8(0)); return (a); } /** * SubWord_RotWord_XOR_duplicate(a, rcon): * Perform the AES key schedule operations of SubWord, RotWord, and XOR with * ${rcon}, acting on the final 32-bit word (bits 96..127) of ${a}, and return * a vector consisting of that value copied to all lanes. */ static inline uint8x16_t SubWord_RotWord_XOR_duplicate(uint8x16_t a, const uint32_t rcon) { uint32_t x3; /* Perform SubWord on the final 32-bit word and copy it to all lanes. */ a = SubWord_duplicate(a); /* We'll use non-neon for the rest. */ x3 = vgetq_lane_u32(vreinterpretq_u32_u8(a), 0); /*- * x3 gets RotWord. Note that * RotWord(SubWord(a)) == SubWord(RotWord(a)) */ x3 = (x3 >> 8) | (x3 << (32 - 8)); /* x3 gets XOR'd with rcon. */ x3 = x3 ^ rcon; /* Copy x3 to all 128 bits, and convert it to a uint8x16_t. */ return (vreinterpretq_u8_u32(vdupq_n_u32(x3))); } /* Compute an AES-128 round key. */ #define MKRKEY128(rkeys, i, rcon) do { \ uint8x16_t _s = rkeys[i - 1]; \ uint8x16_t _t = rkeys[i - 1]; \ _s = veorq_u8(_s, vshlq_n_u128(_s, 4)); \ _s = veorq_u8(_s, vshlq_n_u128(_s, 8)); \ _t = SubWord_RotWord_XOR_duplicate(_t, rcon); \ rkeys[i] = veorq_u8(_s, _t); \ } while (0) /** * crypto_aes_key_expand_128_arm(key_unexpanded, rkeys): * Expand the 128-bit unexpanded AES key ${key_unexpanded} into the 11 round * keys ${rkeys}. This implementation uses ARM AES instructions, and should * only be used if CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() * returns nonzero. */ static void crypto_aes_key_expand_128_arm(const uint8_t key_unexpanded[16], uint8x16_t rkeys[11]) { /* The first round key is just the key. */ rkeys[0] = vld1q_u8(&key_unexpanded[0]); /* * Each of the remaining round keys are computed from the preceding * round key: rotword+subword+rcon (provided as aeskeygenassist) to * compute the 'temp' value, then xor with 1, 2, 3, or all 4 of the * 32-bit words from the preceding round key. */ MKRKEY128(rkeys, 1, 0x01); MKRKEY128(rkeys, 2, 0x02); MKRKEY128(rkeys, 3, 0x04); MKRKEY128(rkeys, 4, 0x08); MKRKEY128(rkeys, 5, 0x10); MKRKEY128(rkeys, 6, 0x20); MKRKEY128(rkeys, 7, 0x40); MKRKEY128(rkeys, 8, 0x80); MKRKEY128(rkeys, 9, 0x1b); MKRKEY128(rkeys, 10, 0x36); } /* Compute an AES-256 round key. */ #define MKRKEY256(rkeys, i, rcon) do { \ uint8x16_t _s = rkeys[i - 2]; \ uint8x16_t _t = rkeys[i - 1]; \ _s = veorq_u8(_s, vshlq_n_u128(_s, 4)); \ _s = veorq_u8(_s, vshlq_n_u128(_s, 8)); \ _t = (i % 2 == 1) ? \ SubWord_duplicate(_t) : \ SubWord_RotWord_XOR_duplicate(_t, rcon); \ rkeys[i] = veorq_u8(_s, _t); \ } while (0) /** * crypto_aes_key_expand_256_arm(key_unexpanded, rkeys): * Expand the 256-bit unexpanded AES key ${key_unexpanded} into the 15 round * keys ${rkeys}. This implementation uses ARM AES instructions, and should * only be used if CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() * returns nonzero. */ static void crypto_aes_key_expand_256_arm(const uint8_t key_unexpanded[32], uint8x16_t rkeys[15]) { /* The first two round keys are just the key. */ rkeys[0] = vld1q_u8(&key_unexpanded[0]); rkeys[1] = vld1q_u8(&key_unexpanded[16]); /* * Each of the remaining round keys are computed from the preceding * pair of keys. Even rounds use rotword+subword+rcon, while odd * rounds just use subword. The rcon value used is irrelevant for odd * rounds since we ignore the value which it feeds into. */ MKRKEY256(rkeys, 2, 0x01); MKRKEY256(rkeys, 3, 0x00); MKRKEY256(rkeys, 4, 0x02); MKRKEY256(rkeys, 5, 0x00); MKRKEY256(rkeys, 6, 0x04); MKRKEY256(rkeys, 7, 0x00); MKRKEY256(rkeys, 8, 0x08); MKRKEY256(rkeys, 9, 0x00); MKRKEY256(rkeys, 10, 0x10); MKRKEY256(rkeys, 11, 0x00); MKRKEY256(rkeys, 12, 0x20); MKRKEY256(rkeys, 13, 0x00); MKRKEY256(rkeys, 14, 0x40); } /** * crypto_aes_key_expand_arm(key_unexpanded, len): * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a * structure which can be passed to crypto_aes_encrypt_block_arm(). The * length must be 16 or 32. This implementation uses ARM AES instructions, * and should only be used if CPUSUPPORT_ARM_AES is defined and * cpusupport_arm_aes() returns nonzero. */ void * crypto_aes_key_expand_arm(const uint8_t * key_unexpanded, size_t len) { struct crypto_aes_key_arm * kexp; /* Allocate structure. */ if ((kexp = malloc(sizeof(struct crypto_aes_key_arm))) == NULL) goto err0; /* Figure out where to put the round keys. */ ALIGN_PTR_INIT(kexp->rkeys, sizeof(uint8x16_t)); /* Compute round keys. */ if (len == 16) { kexp->nr = 10; crypto_aes_key_expand_128_arm(key_unexpanded, kexp->rkeys); } else if (len == 32) { kexp->nr = 14; crypto_aes_key_expand_256_arm(key_unexpanded, kexp->rkeys); } else { warn0("Unsupported AES key length: %zu bytes", len); goto err1; } /* Success! */ return (kexp); err1: free(kexp); err0: /* Failure! */ return (NULL); } /** * crypto_aes_encrypt_block_arm_u8(in, key): * Using the expanded AES key ${key}, encrypt the block ${in} and return the * resulting ciphertext. This implementation uses ARM AES instructions, * and should only be used if CPUSUPPORT_ARM_AES is defined and * cpusupport_arm_aes() returns nonzero. */ uint8x16_t crypto_aes_encrypt_block_arm_u8(uint8x16_t in, const void * key) { const struct crypto_aes_key_arm * _key = key; const uint8x16_t * aes_key = _key->rkeys; uint8x16_t aes_state = in; size_t nr = _key->nr; aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[0])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[1])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[2])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[3])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[4])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[5])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[6])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[7])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[8])); if (nr > 10) { aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[9])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[10])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[11])); aes_state = vaesmcq_u8(vaeseq_u8(aes_state, aes_key[12])); } /* Last round. */ aes_state = vaeseq_u8(aes_state, aes_key[nr - 1]); aes_state = veorq_u8(aes_state, aes_key[nr]); return (aes_state); } /** * crypto_aes_encrypt_block_arm(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This * implementation uses ARM AES instructions, and should only be used if * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. */ void crypto_aes_encrypt_block_arm(const uint8_t in[16], uint8_t out[16], const void * key) { uint8x16_t aes_state; aes_state = vld1q_u8(in); aes_state = crypto_aes_encrypt_block_arm_u8(aes_state, key); vst1q_u8(out, aes_state); } /** * crypto_aes_key_free_arm(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free_arm(void * key) { /* Behave consistently with free(NULL). */ if (key == NULL) return; /* Attempt to zero the expanded key. */ insecure_memzero(key, sizeof(struct crypto_aes_key_arm)); /* Free the key. */ free(key); } #endif /* CPUSUPPORT_ARM_AES */ ================================================ FILE: libcperciva/crypto/crypto_aes_arm.h ================================================ #ifndef CRYPTO_AES_ARM_H_ #define CRYPTO_AES_ARM_H_ #include #include /** * crypto_aes_key_expand_arm(key_unexpanded, len): * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a * structure which can be passed to crypto_aes_encrypt_block_arm(). The * length must be 16 or 32. This implementation uses ARM AES instructions, * and should only be used if CPUSUPPORT_ARM_AES is defined and * cpusupport_arm_aes() returns nonzero. */ void * crypto_aes_key_expand_arm(const uint8_t *, size_t); /** * crypto_aes_encrypt_block_arm(in, out, key): * Using the expanded AES key ${key}, encrypt the block ${in} and write the * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This * implementation uses ARM AES instructions, and should only be used if * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. */ void crypto_aes_encrypt_block_arm(const uint8_t[16], uint8_t[16], const void *); /** * crypto_aes_key_free_arm(key): * Free the expanded AES key ${key}. */ void crypto_aes_key_free_arm(void *); #endif /* !CRYPTO_AES_ARM_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aes_arm_u8.h ================================================ #ifndef CRYPTO_AES_ARM_U8_H_ #define CRYPTO_AES_ARM_U8_H_ #ifdef __ARM_NEON #include #endif /** * crypto_aes_encrypt_block_arm_u8(in, key): * Using the expanded AES key ${key}, encrypt the block ${in} and return the * resulting ciphertext. This implementation uses ARM AES instructions, * and should only be used if CPUSUPPORT_ARM_AES is defined and * cpusupport_arm_aes() returns nonzero. */ uint8x16_t crypto_aes_encrypt_block_arm_u8(uint8x16_t, const void *); #endif /* !CRYPTO_AES_ARM_U8_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aesctr.c ================================================ #include #include #include #include "cpusupport.h" #include "crypto_aes.h" #include "crypto_aesctr_aesni.h" #include "crypto_aesctr_arm.h" #include "insecure_memzero.h" #include "sysendian.h" #include "crypto_aesctr.h" /** * In order to optimize AES-CTR, it is desirable to separate out the handling * of individual bytes of data vs. the handling of complete (16 byte) blocks. * The handling of blocks in turn can be optimized further using CPU * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code * remains the same across platforms it should be inlined into the same (CPU * feature specific) routines for performance reasons. * * In order to allow those generic functions to be inlined into multiple * functions in separate translation units, we place them into a "shared" C * file which is included in each of the platform-specific variants. */ #include "crypto_aesctr_shared.c" #if defined(CPUSUPPORT_X86_AESNI) || defined(CPUSUPPORT_ARM_AES) #define HWACCEL static enum { HW_SOFTWARE = 0, #if defined(CPUSUPPORT_X86_AESNI) HW_X86_AESNI, #endif #if defined(CPUSUPPORT_ARM_AES) HW_ARM_AES, #endif HW_UNSET } hwaccel = HW_UNSET; #endif #ifdef HWACCEL /* Which type of hardware acceleration should we use, if any? */ static void hwaccel_init(void) { /* If we've already set hwaccel, we're finished. */ if (hwaccel != HW_UNSET) return; /* Default to software. */ hwaccel = HW_SOFTWARE; /* Can we use AESNI? */ switch (crypto_aes_can_use_intrinsics()) { #ifdef CPUSUPPORT_X86_AESNI case 1: hwaccel = HW_X86_AESNI; break; #endif #ifdef CPUSUPPORT_ARM_AES case 2: hwaccel = HW_ARM_AES; break; #endif case 0: break; default: /* Should never happen. */ assert(0); } } #endif /* HWACCEL */ /** * crypto_aesctr_alloc(void): * Allocate an object for performing AES in CTR code. This must be followed * by calling _init2(). */ struct crypto_aesctr * crypto_aesctr_alloc(void) { struct crypto_aesctr * stream; /* Allocate memory. */ if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) goto err0; /* Success! */ return (stream); err0: /* Failure! */ return (NULL); } /** * crypto_aesctr_init2(stream, key, nonce): * Reset the AES-CTR stream ${stream}, using the ${key} and ${nonce}. If ${key} * is NULL, retain the previous AES key. */ void crypto_aesctr_init2(struct crypto_aesctr * stream, const struct crypto_aes_key * key, uint64_t nonce) { /* If the key is NULL, retain the previous AES key. */ if (key != NULL) stream->key = key; /* Set nonce as provided and reset bytectr. */ be64enc(stream->pblk, nonce); stream->bytectr = 0; /* * Set the counter such that the least significant byte will wrap once * incremented. */ stream->pblk[15] = 0xff; #ifdef HWACCEL hwaccel_init(); #endif /* Sanity check. */ assert(stream->key != NULL); } /** * crypto_aesctr_init(key, nonce): * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided * expanded ${key} and ${nonce}. The key provided must remain valid for the * lifetime of the stream. This is the same as calling _alloc() followed by * _init2(). */ struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key * key, uint64_t nonce) { struct crypto_aesctr * stream; /* Sanity check. */ assert(key != NULL); /* Allocate memory. */ if ((stream = crypto_aesctr_alloc()) == NULL) goto err0; /* Initialize values. */ crypto_aesctr_init2(stream, key, nonce); /* Success! */ return (stream); err0: /* Failure! */ return (NULL); } /** * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the * buffers ${inbuf} and ${outbuf} overlap, they must be identical. */ void crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) { #if defined(HWACCEL) #if defined(CPUSUPPORT_X86_AESNI) if ((buflen >= 16) && (hwaccel == HW_X86_AESNI)) { crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen); return; } #endif #if defined(CPUSUPPORT_ARM_AES) if ((buflen >= 16) && (hwaccel == HW_ARM_AES)) { crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen); return; } #endif #endif /* HWACCEL */ /* Process any bytes before we can process a whole block. */ if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, &buflen)) return; /* Process whole blocks of 16 bytes. */ while (buflen >= 16) { /* Generate a block of cipherstream. */ crypto_aesctr_stream_cipherblock_generate(stream); /* Encrypt the bytes and update the positions. */ crypto_aesctr_stream_cipherblock_use(stream, &inbuf, &outbuf, &buflen, 16, 0); } /* Process any final bytes after finishing all whole blocks. */ crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); } /** * crypto_aesctr_free(stream): * Free the AES-CTR stream ${stream}. */ void crypto_aesctr_free(struct crypto_aesctr * stream) { /* Behave consistently with free(NULL). */ if (stream == NULL) return; /* Zero potentially sensitive information. */ insecure_memzero(stream, sizeof(struct crypto_aesctr)); /* Free the stream. */ free(stream); } /** * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): * Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free(). */ void crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce, const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) { struct crypto_aesctr stream_rec; struct crypto_aesctr * stream = &stream_rec; /* Sanity check. */ assert(key != NULL); /* Initialize values. */ crypto_aesctr_init2(stream, key, nonce); /* Perform the encryption. */ crypto_aesctr_stream(stream, inbuf, outbuf, buflen); /* Zero potentially sensitive information. */ insecure_memzero(stream, sizeof(struct crypto_aesctr)); } ================================================ FILE: libcperciva/crypto/crypto_aesctr.h ================================================ #ifndef CRYPTO_AESCTR_H_ #define CRYPTO_AESCTR_H_ #include #include /* Opaque types. */ struct crypto_aes_key; struct crypto_aesctr; /** * crypto_aesctr_init(key, nonce): * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided * expanded ${key} and ${nonce}. The key provided must remain valid for the * lifetime of the stream. This is the same as calling _alloc() followed by * _init2(). */ struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key *, uint64_t); /** * crypto_aesctr_alloc(void): * Allocate an object for performing AES in CTR code. This must be followed * by calling _init2(). */ struct crypto_aesctr * crypto_aesctr_alloc(void); /** * crypto_aesctr_init2(stream, key, nonce): * Reset the AES-CTR stream ${stream}, using the ${key} and ${nonce}. If ${key} * is NULL, retain the previous AES key. */ void crypto_aesctr_init2(struct crypto_aesctr *, const struct crypto_aes_key *, uint64_t); /** * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the * buffers ${inbuf} and ${outbuf} overlap, they must be identical. */ void crypto_aesctr_stream(struct crypto_aesctr *, const uint8_t *, uint8_t *, size_t); /** * crypto_aesctr_free(stream): * Free the AES-CTR stream ${stream}. */ void crypto_aesctr_free(struct crypto_aesctr *); /** * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): * Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free(). */ void crypto_aesctr_buf(const struct crypto_aes_key *, uint64_t, const uint8_t *, uint8_t *, size_t); #endif /* !CRYPTO_AESCTR_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aesctr_aesni.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_AESNI /** * CPUSUPPORT CFLAGS: X86_AESNI */ #include #include #include #include #include "crypto_aes.h" #include "crypto_aes_aesni_m128i.h" #include "sysendian.h" #include "crypto_aesctr_aesni.h" /** * In order to optimize AES-CTR, it is desirable to separate out the handling * of individual bytes of data vs. the handling of complete (16 byte) blocks. * The handling of blocks in turn can be optimized further using CPU * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code * remains the same across platforms it should be inlined into the same (CPU * feature specific) routines for performance reasons. * * In order to allow those generic functions to be inlined into multiple * functions in separate translation units, we place them into a "shared" C * file which is included in each of the platform-specific variants. */ #include "crypto_aesctr_shared.c" #ifdef BROKEN_MM_LOADU_SI64 #warning Working around compiler bug: _mm_loadu_si64 is missing #warning Updating to a newer compiler may improve performance #endif /** * load_si64(mem): * Load an unaligned 64-bit integer from memory into the lowest 64 bits of the * returned value. The contents of the upper 64 bits is not defined. */ static inline __m128i load_si64(const void * mem) { #ifdef BROKEN_MM_LOADU_SI64 return (_mm_castpd_si128(_mm_load_sd(mem))); #else return (_mm_loadu_si64(mem)); #endif } /* Process multiple whole blocks by generating & using a cipherblock. */ static void crypto_aesctr_aesni_stream_wholeblocks(struct crypto_aesctr * stream, const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen) { __m128i bufsse; __m128i inbufsse; __m128i nonce_be; uint8_t block_counter_be_arr[8]; uint64_t block_counter; size_t num_blocks; size_t i; /* Load local variables from stream. */ nonce_be = load_si64(stream->pblk); block_counter = stream->bytectr / 16; /* How many blocks should we process? */ num_blocks = (*buflen) / 16; /* * This is 'for (i = num_blocks; i > 0; i--)', but ensuring that the * compiler knows that we will execute the loop at least once. */ i = num_blocks; do { /* Prepare counter. */ be64enc(block_counter_be_arr, block_counter); /* Encrypt the cipherblock. */ bufsse = load_si64(block_counter_be_arr); bufsse = _mm_unpacklo_epi64(nonce_be, bufsse); bufsse = crypto_aes_encrypt_block_aesni_m128i(bufsse, stream->key); /* Encrypt the byte(s). */ inbufsse = _mm_loadu_si128((const __m128i *)(*inbuf)); bufsse = _mm_xor_si128(inbufsse, bufsse); _mm_storeu_si128((__m128i *)(*outbuf), bufsse); /* Update the positions. */ block_counter++; *inbuf += 16; *outbuf += 16; /* Update the counter. */ i--; } while (i > 0); /* Update the overall buffer length. */ *buflen -= 16 * num_blocks; /* Update variables in stream. */ memcpy(stream->pblk + 8, block_counter_be_arr, 8); stream->bytectr += 16 * num_blocks; } /** * crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the * buffers ${inbuf} and ${outbuf} overlap, they must be identical. */ void crypto_aesctr_aesni_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) { /* Process any bytes before we can process a whole block. */ if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, &buflen)) return; /* Process whole blocks of 16 bytes. */ if (buflen >= 16) crypto_aesctr_aesni_stream_wholeblocks(stream, &inbuf, &outbuf, &buflen); /* Process any final bytes after finishing all whole blocks. */ crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); } #endif /* CPUSUPPORT_X86_AESNI */ ================================================ FILE: libcperciva/crypto/crypto_aesctr_aesni.h ================================================ #ifndef CRYPTO_AESCTR_AESNI_H_ #define CRYPTO_AESCTR_AESNI_H_ #include #include /* Opaque type. */ struct crypto_aesctr; /** * crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the * buffers ${inbuf} and ${outbuf} overlap, they must be identical. */ void crypto_aesctr_aesni_stream(struct crypto_aesctr *, const uint8_t *, uint8_t *, size_t); #endif /* !CRYPTO_AESCTR_AESNI_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aesctr_arm.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_ARM_AES /** * CPUSUPPORT CFLAGS: ARM_AES */ #include #include #include #ifdef __ARM_NEON #include #endif #include "crypto_aes.h" #include "crypto_aes_arm_u8.h" #include "sysendian.h" #include "crypto_aesctr_arm.h" /** * In order to optimize AES-CTR, it is desirable to separate out the handling * of individual bytes of data vs. the handling of complete (16 byte) blocks. * The handling of blocks in turn can be optimized further using CPU * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code * remains the same across platforms it should be inlined into the same (CPU * feature specific) routines for performance reasons. * * In order to allow those generic functions to be inlined into multiple * functions in separate translation units, we place them into a "shared" C * file which is included in each of the platform-specific variants. */ #include "crypto_aesctr_shared.c" /* Process multiple whole blocks by generating & using a cipherblock. */ static void crypto_aesctr_arm_stream_wholeblocks(struct crypto_aesctr * stream, const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen) { uint8x16_t bufarm; uint8x16_t inbufarm; uint8x8_t nonce_be; uint8x8_t block_counter_be; uint8_t block_counter_be_arr[8]; uint64_t block_counter; size_t num_blocks; size_t i; /* Load local variables from stream. */ nonce_be = vld1_u8(stream->pblk); block_counter = stream->bytectr / 16; /* How many blocks should we process? */ num_blocks = (*buflen) / 16; /* * This is 'for (i = num_blocks; i > 0; i--)', but ensuring that the * compiler knows that we will execute the loop at least once. */ i = num_blocks; do { /* Prepare counter. */ be64enc(block_counter_be_arr, block_counter); /* Encrypt the cipherblock. */ block_counter_be = vld1_u8(block_counter_be_arr); bufarm = vcombine_u8(nonce_be, block_counter_be); bufarm = crypto_aes_encrypt_block_arm_u8(bufarm, stream->key); /* Encrypt the byte(s). */ inbufarm = vld1q_u8(*inbuf); bufarm = veorq_u8(inbufarm, bufarm); vst1q_u8(*outbuf, bufarm); /* Update the positions. */ block_counter++; *inbuf += 16; *outbuf += 16; /* Update the counter. */ i--; } while (i > 0); /* Update the overall buffer length. */ *buflen -= 16 * num_blocks; /* Update variables in stream. */ memcpy(stream->pblk + 8, block_counter_be_arr, 8); stream->bytectr += 16 * num_blocks; } /** * crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the * buffers ${inbuf} and ${outbuf} overlap, they must be identical. */ void crypto_aesctr_arm_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) { /* Process any bytes before we can process a whole block. */ if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, &buflen)) return; /* Process whole blocks of 16 bytes. */ if (buflen >= 16) crypto_aesctr_arm_stream_wholeblocks(stream, &inbuf, &outbuf, &buflen); /* Process any final bytes after finishing all whole blocks. */ crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); } #endif /* CPUSUPPORT_ARM_AES */ ================================================ FILE: libcperciva/crypto/crypto_aesctr_arm.h ================================================ #ifndef CRYPTO_AESCTR_ARM_H_ #define CRYPTO_AESCTR_ARM_H_ #include #include /* Opaque type. */ struct crypto_aesctr; /** * crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen): * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the * buffers ${inbuf} and ${outbuf} overlap, they must be identical. */ void crypto_aesctr_arm_stream(struct crypto_aesctr *, const uint8_t *, uint8_t *, size_t); #endif /* !CRYPTO_AESCTR_ARM_H_ */ ================================================ FILE: libcperciva/crypto/crypto_aesctr_shared.c ================================================ /* * This code is shared between crypto_aesctr*.c files, and should not be * compiled as a separate translation unit. For details, see the comments in * those files. */ /* AES-CTR state. */ struct crypto_aesctr { const struct crypto_aes_key * key; uint64_t bytectr; uint8_t buf[16]; uint8_t pblk[16]; }; /* Generate a block of cipherstream. */ static inline void crypto_aesctr_stream_cipherblock_generate(struct crypto_aesctr * stream) { /* Sanity check. */ assert(stream->bytectr % 16 == 0); /* Prepare counter. */ stream->pblk[15]++; if (stream->pblk[15] == 0) { /* * If incrementing the least significant byte resulted in it * wrapping, re-encode the complete 64-bit value. */ be64enc(stream->pblk + 8, stream->bytectr / 16); } /* Encrypt the cipherblock. */ crypto_aes_encrypt_block(stream->pblk, stream->buf, stream->key); } /* Encrypt ${nbytes} bytes, then update ${inbuf}, ${outbuf}, and ${buflen}. */ static inline void crypto_aesctr_stream_cipherblock_use(struct crypto_aesctr * stream, const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen, size_t nbytes, size_t bytemod) { size_t i; /* Encrypt the byte(s). */ for (i = 0; i < nbytes; i++) (*outbuf)[i] = (*inbuf)[i] ^ stream->buf[bytemod + i]; /* Move to the next byte(s) of cipherstream. */ stream->bytectr += nbytes; /* Update the positions. */ *inbuf += nbytes; *outbuf += nbytes; *buflen -= nbytes; } /* * Process any bytes before we can process a whole block. Return 1 if there * are no bytes left to process after calling this function. */ static inline int crypto_aesctr_stream_pre_wholeblock(struct crypto_aesctr * stream, const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p) { size_t bytemod; /* Do we have any bytes left in the current cipherblock? */ bytemod = stream->bytectr % 16; if (bytemod != 0) { /* Do we have enough to complete the request? */ if (bytemod + *buflen_p <= 16) { /* Process only buflen bytes, then return. */ crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, buflen_p, *buflen_p, bytemod); return (1); } /* Encrypt the byte(s) and update the positions. */ crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, buflen_p, 16 - bytemod, bytemod); } /* Success! */ return (0); } /* Process any final bytes after finishing all whole blocks. */ static inline void crypto_aesctr_stream_post_wholeblock(struct crypto_aesctr * stream, const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p) { /* Process any final bytes; we need a new cipherblock. */ if (*buflen_p > 0) { /* Generate a block of cipherstream. */ crypto_aesctr_stream_cipherblock_generate(stream); /* Encrypt the byte(s) and update the positions. */ crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, buflen_p, *buflen_p, 0); } } ================================================ FILE: libcperciva/crypto/crypto_entropy.c ================================================ #include #include #include #include "cpusupport.h" #include "crypto_entropy_rdrand.h" #include "entropy.h" #include "insecure_memzero.h" #include "sha256.h" #include "crypto_entropy.h" /** * This system implements the HMAC_DRBG pseudo-random number generator as * specified in section 10.1.2 of the NIST SP 800-90 standard. In this * implementation, the optional personalization_string and additional_input * specified in the standard are not implemented. */ /* Internal HMAC_DRBG state. */ static struct { uint8_t Key[32]; uint8_t V[32]; uint32_t reseed_counter; } drbg; /* Set to non-zero once the PRNG has been instantiated. */ static int instantiated = 0; /* Could be as high as 2^48 if we wanted... */ #define RESEED_INTERVAL 256 /* Limited to 2^16 by specification. */ #define GENERATE_MAXLEN 65536 static int instantiate(void); static void update(const uint8_t *, size_t); static int reseed(void); static void generate(uint8_t *, size_t); #ifdef CPUSUPPORT_X86_RDRAND static void update_from_rdrand(void) { unsigned int buf[8]; /* This is only *extra* entropy, so it's ok if it fails. */ if (generate_seed_rdrand(buf, 8)) return; update((uint8_t *)buf, sizeof(buf)); /* Clean up. */ insecure_memzero(buf, sizeof(buf)); } #endif /** * instantiate(void): * Initialize the DRBG state. (Section 10.1.2.3) */ static int instantiate(void) { uint8_t seed_material[48]; /* Obtain random seed_material = (entropy_input || nonce). */ if (entropy_read(seed_material, 48)) return (-1); /* Initialize Key, V, and reseed_counter. */ memset(drbg.Key, 0x00, 32); memset(drbg.V, 0x01, 32); drbg.reseed_counter = 1; /* Mix the random seed into the state. */ update(seed_material, 48); #ifdef CPUSUPPORT_X86_RDRAND /* Add output of RDRAND into the state. */ if (cpusupport_x86_rdrand()) update_from_rdrand(); #endif /* Clean the stack. */ insecure_memzero(seed_material, 48); /* Success! */ return (0); } /** * update(data, datalen): * Update the DRBG state using the provided data. (Section 10.1.2.2) */ static void update(const uint8_t * data, size_t datalen) { HMAC_SHA256_CTX ctx; uint8_t K[32]; uint8_t Vx[33]; /* Load (Key, V) into (K, Vx). */ memcpy(K, drbg.Key, 32); memcpy(Vx, drbg.V, 32); /* K <- HMAC(K, V || 0x00 || data). */ Vx[32] = 0x00; HMAC_SHA256_Init(&ctx, K, 32); HMAC_SHA256_Update(&ctx, Vx, 33); HMAC_SHA256_Update(&ctx, data, datalen); HMAC_SHA256_Final(K, &ctx); /* V <- HMAC(K, V). */ HMAC_SHA256_Buf(K, 32, Vx, 32, Vx); /* If the provided data is non-Null, perform another mixing stage. */ if (datalen != 0) { /* K <- HMAC(K, V || 0x01 || data). */ Vx[32] = 0x01; HMAC_SHA256_Init(&ctx, K, 32); HMAC_SHA256_Update(&ctx, Vx, 33); HMAC_SHA256_Update(&ctx, data, datalen); HMAC_SHA256_Final(K, &ctx); /* V <- HMAC(K, V). */ HMAC_SHA256_Buf(K, 32, Vx, 32, Vx); } /* Copy (K, Vx) back to (Key, V). */ memcpy(drbg.Key, K, 32); memcpy(drbg.V, Vx, 32); /* Clean the stack. */ insecure_memzero(K, 32); insecure_memzero(Vx, 33); } /** * reseed(void): * Reseed the DRBG state (mix in new entropy). (Section 10.1.2.4) */ static int reseed(void) { uint8_t seed_material[32]; /* Obtain random seed_material = entropy_input. */ if (entropy_read(seed_material, 32)) return (-1); /* Mix the random seed into the state. */ update(seed_material, 32); #ifdef CPUSUPPORT_X86_RDRAND /* Add output of RDRAND into the state. */ if (cpusupport_x86_rdrand()) update_from_rdrand(); #endif /* Reset the reseed_counter. */ drbg.reseed_counter = 1; /* Clean the stack. */ insecure_memzero(seed_material, 32); /* Success! */ return (0); } /** * generate(buf, buflen): * Fill the provided buffer with random bits, assuming that reseed_counter * is less than RESEED_INTERVAL (the caller is responsible for calling * reseed() as needed) and ${buflen} is less than 2^16 (the caller is * responsible for splitting up larger requests). (Section 10.1.2.5) */ static void generate(uint8_t * buf, size_t buflen) { size_t bufpos; assert(buflen <= GENERATE_MAXLEN); assert(drbg.reseed_counter <= RESEED_INTERVAL); /* Iterate until we've filled the buffer. */ for (bufpos = 0; bufpos < buflen; bufpos += 32) { HMAC_SHA256_Buf(drbg.Key, 32, drbg.V, 32, drbg.V); if (buflen - bufpos >= 32) memcpy(&buf[bufpos], drbg.V, 32); else memcpy(&buf[bufpos], drbg.V, buflen - bufpos); } /* Mix up state. */ update(NULL, 0); /* We're one data-generation step closer to needing a reseed. */ drbg.reseed_counter += 1; } /** * crypto_entropy_read(buf, buflen): * Fill the buffer with unpredictable bits. */ int crypto_entropy_read(uint8_t * buf, size_t buflen) { size_t bytes_to_provide; /* Instantiate if needed. */ if (instantiated == 0) { /* Try to instantiate the PRNG. */ if (instantiate()) return (-1); /* We have instantiated the PRNG. */ instantiated = 1; } /* Loop until we've filled the buffer. */ while (buflen > 0) { /* Do we need to reseed? */ if (drbg.reseed_counter > RESEED_INTERVAL) { if (reseed()) return (-1); } /* How much data are we generating in this step? */ if (buflen > GENERATE_MAXLEN) bytes_to_provide = GENERATE_MAXLEN; else bytes_to_provide = buflen; /* Generate bytes. */ generate(buf, bytes_to_provide); /* We've done part of the buffer. */ buf += bytes_to_provide; buflen -= bytes_to_provide; } /* Success! */ return (0); } ================================================ FILE: libcperciva/crypto/crypto_entropy.h ================================================ #ifndef CRYPTO_ENTROPY_H_ #define CRYPTO_ENTROPY_H_ #include #include /** * crypto_entropy_read(buf, buflen): * Fill the buffer with unpredictable bits. */ int crypto_entropy_read(uint8_t *, size_t); #endif /* !CRYPTO_ENTROPY_H_ */ ================================================ FILE: libcperciva/crypto/crypto_entropy_rdrand.c ================================================ #include "cpusupport.h" #ifdef CPUSUPPORT_X86_RDRAND /** * CPUSUPPORT CFLAGS: X86_RDRAND */ #include #include #include "crypto_entropy_rdrand.h" /** * generate_seed_rdrand(buf, len): * Fill the ${buf} buffer with values from RDRAND. This implementation uses * the RDRAND instruction, and should only be used if CPUSUPPORT_X86_RDRAND is * defined and cpusupport_x86_rdrand() returns nonzero. */ int generate_seed_rdrand(unsigned int * buf, size_t len) { size_t i; /* Fill buffer. */ for (i = 0; i < len; i++) { if (!_rdrand32_step(&buf[i])) goto err0; } /* Success! */ return (0); err0: /* Failure! */ return (1); } #endif /* CPUSUPPORT_X86_RDRAND */ ================================================ FILE: libcperciva/crypto/crypto_entropy_rdrand.h ================================================ #ifndef CRYPTO_ENTROPY_RDRAND_H_ #define CRYPTO_ENTROPY_RDRAND_H_ #include /** * generate_seed_rdrand(buf, len): * Fill the ${buf} buffer with values from RDRAND. This implementation uses * the RDRAND instruction, and should only be used if CPUSUPPORT_X86_RDRAND is * defined and cpusupport_x86_rdrand() returns nonzero. */ int generate_seed_rdrand(unsigned int *, size_t); #endif /* !CRYPTO_ENTROPY_RDRAND_H_ */ ================================================ FILE: libcperciva/crypto/crypto_verify_bytes.c ================================================ #include #include #include "crypto_verify_bytes.h" /** * crypto_verify_bytes(buf0, buf1, len): * Return zero if and only if ${buf0[0 .. len - 1]} and ${buf1[0 .. len - 1]} * are identical. Do not leak any information via timing side channels. */ uint8_t crypto_verify_bytes(const uint8_t * buf0, const uint8_t * buf1, size_t len) { uint8_t rc = 0; size_t i; for (i = 0; i < len; i++) rc = rc | (buf0[i] ^ buf1[i]); return (rc); } ================================================ FILE: libcperciva/crypto/crypto_verify_bytes.h ================================================ #ifndef CRYPTO_VERIFY_BYTES_H_ #define CRYPTO_VERIFY_BYTES_H_ #include #include /** * crypto_verify_bytes(buf0, buf1, len): * Return zero if and only if ${buf0[0 .. len - 1]} and ${buf1[0 .. len - 1]} * are identical. Do not leak any information via timing side channels. */ uint8_t crypto_verify_bytes(const uint8_t *, const uint8_t *, size_t); #endif /* !CRYPTO_VERIFY_BYTES_H_ */ ================================================ FILE: libcperciva/util/align_ptr.h ================================================ #ifndef ALIGN_PTR_H_ #define ALIGN_PTR_H_ #include #include /** * ALIGN_PTR_DECL(type, name, num, alignsize): * Declare a pointer called ${name}, which points to an array large enough to * contain ${num} values of ${type} and is aligned to ${alignsize} bytes. The * pointer must not be used until ALIGN_PTR_INIT(${name}, ${alignsize}) has * been called. This macro may also create an additional variable called * "${name}_buf". */ #define ALIGN_PTR_DECL(type, name, num, alignsize) \ uint8_t name##_buf[num * sizeof(type) + (alignsize - 1)]; \ type * name /** * ALIGN_PTR_INIT(name, alignsize): * Initialize the variable called ${name} to point to an array which is * aligned to ${alignsize} bytes. They must have previously been declared * with ALIGN_PTR_DECL(${name}, ${alignsize}). This macro assumes that * casting a pointer to uintptr_t behaves naturally, i.e. yields a byte offset * relative to aligned memory. */ #define ALIGN_PTR_INIT(name, alignsize) \ name = align_ptr(name##_buf, alignsize) /** * align_ptr(arr, alignment): * Return a pointer to the first memory location within ${arr} which is * aligned to ${alignsize} bytes. (It is expected that this function will * only be called via the ALIGN_PTR_INIT macro). */ static inline void * align_ptr(uint8_t * arr, size_t alignment) { size_t offset; /* * This assumes that casting a pointer to uintptr_t behaves naturally, * i.e. yields a byte offset relative to aligned memory. */ offset = (uintptr_t)(&arr[0]) % alignment; offset = (alignment - offset) % alignment; /* Return the aligned pointer. */ return ((void *)&arr[offset]); } #endif /* !ALIGN_PTR_H_ */ ================================================ FILE: libcperciva/util/asprintf.c ================================================ #include #include #include #include "asprintf.h" /** * asprintf(ret, format, ...): * Do asprintf(3) like GNU and BSD do. */ int asprintf(char ** ret, const char * format, ...) { va_list ap; int len; size_t buflen; /* Figure out how long the string needs to be. */ va_start(ap, format); len = vsnprintf(NULL, 0, format, ap); va_end(ap); /* Did we fail? */ if (len < 0) goto err0; buflen = (size_t)(len) + 1; /* Allocate memory. */ if ((*ret = malloc(buflen)) == NULL) goto err0; /* Actually generate the string. */ va_start(ap, format); len = vsnprintf(*ret, buflen, format, ap); va_end(ap); /* Did we fail? */ if (len < 0) goto err1; /* Success! */ return (len); err1: free(*ret); err0: /* Failure! */ return (-1); } ================================================ FILE: libcperciva/util/asprintf.h ================================================ #ifndef ASPRINTF_H_ #define ASPRINTF_H_ /* Avoid namespace collisions with BSD/GNU asprintf. */ #ifdef asprintf #undef asprintf #endif #define asprintf libcperciva_asprintf /** * asprintf(ret, format, ...): * Do asprintf(3) like GNU and BSD do. */ int asprintf(char **, const char *, ...); #endif /* !ASPRINTF_H_ */ ================================================ FILE: libcperciva/util/entropy.c ================================================ #include #include #include #include #include #include #include #include "warnp.h" #include "entropy.h" /** * XXX Portability * XXX We obtain random bytes from the operating system by opening * XXX /dev/urandom and reading them from that device; this works on * XXX modern UNIX-like operating systems but not on systems like * XXX win32 where there is no concept of /dev/urandom. */ /** * Entropy reader state. At present it holds a file descriptor for * /dev/urandom, but in the future this structure may gain other OS-dependent * state, e.g. a Windows Handle. */ struct entropy_read_cookie { int fd; }; /** * entropy_read_init(void): * Initialize the ability to produce random bytes from the operating system, * and return a cookie. */ struct entropy_read_cookie * entropy_read_init(void) { struct entropy_read_cookie * er; /* Allocate cookie. */ if ((er = malloc(sizeof(struct entropy_read_cookie))) == NULL) { warnp("malloc"); goto err0; } /* Open /dev/urandom. */ if ((er->fd = open("/dev/urandom", O_RDONLY)) == -1) { warnp("open(/dev/urandom)"); goto err1; } /* Success! */ return (er); err1: free(er); err0: /* Failure! */ return (NULL); } /** * entropy_read_fill(er, buf, buflen): * Fill the given buffer with random bytes provided by the operating system * using the resources in ${er}. */ int entropy_read_fill(struct entropy_read_cookie * er, uint8_t * buf, size_t buflen) { ssize_t lenread; /* Sanity checks. */ assert(er != NULL); assert(buflen <= SSIZE_MAX); /* Read bytes until we have filled the buffer. */ while (buflen > 0) { if ((lenread = read(er->fd, buf, buflen)) == -1) { warnp("read(/dev/urandom)"); goto err0; } /* The random device should never EOF. */ if (lenread == 0) { warn0("EOF on /dev/urandom?"); goto err0; } /* We've filled a portion of the buffer. */ buf += (size_t)lenread; buflen -= (size_t)lenread; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * entropy_read_done(er): * Release any resources used by ${er}. */ int entropy_read_done(struct entropy_read_cookie * er) { /* Sanity check. */ assert(er != NULL); /* Close the device. */ while (close(er->fd) == -1) { if (errno != EINTR) { warnp("close(/dev/urandom)"); goto err1; } } /* Clean up. */ free(er); /* Success! */ return (0); err1: free(er); /* Failure! */ return (-1); } /** * entropy_read(buf, buflen): * Fill the given buffer with random bytes provided by the operating system. */ int entropy_read(uint8_t * buf, size_t buflen) { struct entropy_read_cookie * er; /* Sanity-check the buffer size. */ assert(buflen <= SSIZE_MAX); /* Open /dev/urandom. */ if ((er = entropy_read_init()) == NULL) { warn0("entropy_read_init"); goto err0; } /* Read bytes until we have filled the buffer. */ if (entropy_read_fill(er, buf, buflen)) { warn0("entropy_read_fill"); goto err1; } /* Close the device. */ if (entropy_read_done(er)) { warn0("entropy_read_done"); goto err0; } /* Success! */ return (0); err1: entropy_read_done(er); err0: /* Failure! */ return (-1); } ================================================ FILE: libcperciva/util/entropy.h ================================================ #ifndef ENTROPY_H_ #define ENTROPY_H_ #include #include /* Opaque type. */ struct entropy_read_cookie; /** * entropy_read_init(void): * Initialize the ability to produce random bytes from the operating system, * and return a cookie. */ struct entropy_read_cookie * entropy_read_init(void); /** * entropy_read_fill(er, buf, buflen): * Fill the given buffer with random bytes provided by the operating system * using the resources in ${er}. */ int entropy_read_fill(struct entropy_read_cookie *, uint8_t *, size_t); /** * entropy_read_done(er): * Release any resources used by ${er}. */ int entropy_read_done(struct entropy_read_cookie *); /** * entropy_read(buf, buflen): * Fill the given buffer with random bytes provided by the operating system. */ int entropy_read(uint8_t *, size_t); #endif /* !ENTROPY_H_ */ ================================================ FILE: libcperciva/util/getopt.c ================================================ #include #include #include #include #include "getopt.h" /* * Standard getopt global variables. optreset starts as non-zero in order to * trigger initialization behaviour. */ const char * optarg = NULL; int optind = 1; int opterr = 1; int optreset = 1; /* * Quasi-internal global variables -- these are used via GETOPT macros. */ const char * getopt_dummy = "(dummy)"; int getopt_initialized = 0; /* * Internal variables. */ static const char * cmdname = NULL; static struct opt { const char * os; size_t olen; int hasarg; } * opts = NULL; /* Probably a sparse array: some values, some NULLs. */ static size_t nopts; /* Maximum number of options. */ static size_t opt_missing; static size_t opt_default; static size_t opt_found; static const char * packedopts; static char popt[3]; static int atexit_registered = 0; /* Print a message. */ #define PRINTMSG(...) do { \ if (cmdname != NULL) \ fprintf(stderr, "%s: ", cmdname); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } while (0) /* Print an error message and die. */ #define DIE(...) do { \ PRINTMSG(__VA_ARGS__); \ abort(); \ } while (0) /* Print a warning, if warnings are enabled. */ #define WARN(...) do { \ if (opterr == 0) \ break; \ if (opt_missing != opt_default) \ break; \ PRINTMSG(__VA_ARGS__); \ } while (0) /* Free allocated options array. */ static void getopt_atexit(void) { free(opts); opts = NULL; } /* Reset internal state. */ static void reset(int argc, char * const argv[]) { const char * p; /* If we have arguments, stash argv[0] for error messages. */ if (argc > 0) { /* Find the basename, without leading directories. */ for (p = cmdname = argv[0]; *p != '\0'; p++) { if (*p == '/') cmdname = p + 1; } } /* Discard any registered command-line options. */ free(opts); opts = NULL; /* Register atexit handler if we haven't done so already. */ if (!atexit_registered) { atexit(getopt_atexit); atexit_registered = 1; } /* We will start scanning from the first option. */ optind = 1; /* We're not in the middle of any packed options. */ packedopts = NULL; /* We haven't found any option yet. */ opt_found = (size_t)(-1); /* We're not initialized yet. */ getopt_initialized = 0; /* Finished resetting state. */ optreset = 0; } /* Search for an option string. */ static size_t searchopt(const char * os) { size_t i; /* Scan the array of options. */ for (i = 0; i < nopts; i++) { /* Is there an option in this slot? */ if (opts[i].os == NULL) continue; /* Does this match up to the length of the option string? */ if (strncmp(opts[i].os, os, opts[i].olen)) continue; /* Do we have