├── .autom4te.cfg ├── .github └── workflows │ ├── compile.yml │ └── coverity-scan.yml ├── .gitignore ├── BUILDING ├── COPYRIGHT ├── FORMAT ├── Makefile.am ├── README.md ├── STYLE ├── configure.ac ├── get-version.sh ├── lib-platform ├── crypto │ ├── crypto_scrypt.c │ └── crypto_scrypt.h ├── platform.h └── util │ ├── memlimit.c │ └── memlimit.h ├── 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 ├── 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 /.autom4te.cfg: -------------------------------------------------------------------------------- 1 | ## ------------------ ## 2 | ## User Preferences. ## 3 | ## ------------------ ## 4 | 5 | begin-language: "Autoconf-without-aclocal-m4" 6 | args: --no-cache 7 | end-language: "Autoconf-without-aclocal-m4" 8 | -------------------------------------------------------------------------------- /.github/workflows/compile.yml: -------------------------------------------------------------------------------- 1 | name: Compile & test 2 | 3 | # Run whenever we push to any branch without a "/", other than [coverity-scan]. 4 | on: 5 | push: 6 | branches: 7 | - '*' 8 | - '!coverity-scan' 9 | 10 | env: 11 | # Shared variables amongst all projects / platforms / compilers. 12 | CFLAGS_ALL: -std=c99 -O2 13 | CFLAGS_CLANG_LIBCPERCIVA: -Wall -Wextra -Werror -Weverything 14 | -Wno-#warnings -Wno-pedantic -Wno-padded 15 | -Wno-format-nonliteral 16 | -Wno-disabled-macro-expansion 17 | -Wno-missing-noreturn 18 | -Wno-unused-macros 19 | -Wno-documentation-unknown-command 20 | -Wno-implicit-fallthrough 21 | CFLAGS_GCC_LIBCPERCIVA: -Wall -Wextra -Werror -Wpedantic 22 | -pedantic-errors -Wno-clobbered 23 | # Variables for specific projects / platforms / compilers. 24 | CFLAGS_CLANG_PROJECT: -Wno-reserved-id-macro 25 | CFLAGS_GCC_PROJECT: -Wno-cpp 26 | CFLAGS_OSX: -Wno-poison-system-directories 27 | -Wno-deprecated-declarations 28 | LDFLAGS_OSX: 29 | 30 | jobs: 31 | Ubuntu: 32 | name: Ubuntu 33 | runs-on: ubuntu-22.04 34 | steps: 35 | - name: Update apt-get 36 | run: sudo apt-get update 37 | - name: Install software 38 | run: sudo apt-get install --no-install-recommends 39 | valgrind autoconf-archive 40 | - name: Checkout code 41 | uses: actions/checkout@v4 42 | - name: Run autoreconf 43 | run: 44 | autoreconf -i 45 | - name: Configure with clang 46 | env: 47 | CC: clang-13 48 | CFLAGS: ${{ env.CFLAGS_ALL }} 49 | run: ./configure 50 | - name: Compile with clang 51 | env: 52 | CC: clang-13 53 | CFLAGS: ${{ env.CFLAGS_ALL }} 54 | ${{ env.CFLAGS_CLANG_LIBCPERCIVA }} 55 | ${{ env.CFLAGS_CLANG_PROJECT }} 56 | # make(1) doesn't automatically override the CFLAGS macro set inside 57 | # Makefile with the environment variable. 58 | run: make CFLAGS="${{ env.CFLAGS }}" 59 | - name: Test clang binaries 60 | env: 61 | USE_VALGRIND: 1 62 | run: make test VERBOSE=1 63 | - name: Clean 64 | run: make clean 65 | - name: Configure with gcc 66 | env: 67 | CC: gcc-10 68 | CFLAGS: ${{ env.CFLAGS_ALL }} 69 | run: ./configure 70 | - name: Compile with gcc 71 | env: 72 | CC: gcc-10 73 | CFLAGS: ${{ env.CFLAGS_ALL }} 74 | ${{ env.CFLAGS_GCC_LIBCPERCIVA }} 75 | ${{ env.CFLAGS_GCC_PROJECT }} 76 | # make(1) doesn't automatically override the CFLAGS macro set inside 77 | # Makefile with the environment variable. 78 | run: make CFLAGS="${{ env.CFLAGS }}" 79 | - name: Test gcc binaries 80 | env: 81 | USE_VALGRIND: 1 82 | run: make test VERBOSE=1 83 | - name: Check for untracked files 84 | run: test -z "$(git status --porcelain=v1)" 85 | macOS: 86 | name: macOS 87 | runs-on: macOS-13 88 | steps: 89 | - name: Checkout code 90 | uses: actions/checkout@v4 91 | - name: Install software 92 | run: brew install automake 93 | - name: Run autoreconf 94 | run: autoreconf -i 95 | - name: Configure with clang 96 | env: 97 | CC: clang 98 | CFLAGS: ${{ env.CFLAGS_ALL }} 99 | ${{ env.CFLAGS_OSX }} 100 | LDFLAGS: ${{ env.LDFLAGS_OSX }} 101 | run: ./configure 102 | - name: Compile with clang 103 | env: 104 | CC: clang 105 | CFLAGS: ${{ env.CFLAGS_ALL }} 106 | ${{ env.CFLAGS_CLANG_LIBCPERCIVA }} 107 | ${{ env.CFLAGS_CLANG_PROJECT }} 108 | ${{ env.CFLAGS_OSX }} 109 | LDFLAGS: ${{ env.LDFLAGS_OSX }} 110 | # make(1) doesn't automatically override the CFLAGS macro set inside 111 | # Makefile with the environment variable. 112 | run: make CFLAGS="${{ env.CFLAGS }}" 113 | - name: Test clang binaries 114 | run: make test VERBOSE=1 115 | -------------------------------------------------------------------------------- /.github/workflows/coverity-scan.yml: -------------------------------------------------------------------------------- 1 | name: coverity-scan 2 | 3 | # Only trigger on the [coverity-scan] branch. 4 | on: 5 | push: 6 | branches: 7 | - coverity-scan 8 | 9 | # Run coverity scan. For now, we're re-using the Travis-CI script, which 10 | # requires us to fake a TRAVIS_BRANCH environment variable. 11 | jobs: 12 | coverity-scan: 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | - name: Run autoreconf 18 | run: autoreconf -i 19 | - name: Configure with the default compiler 20 | run: ./configure 21 | - name: Coverity scan 22 | env: 23 | COVERITY_SCAN_PROJECT_NAME: ${{ github.repository }} 24 | COVERITY_SCAN_BRANCH_PATTERN: coverity-scan 25 | COVERITY_SCAN_NOTIFICATION_EMAIL: cperciva@tarsnap.com 26 | COVERITY_SCAN_BUILD_COMMAND: make all 27 | COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 28 | TRAVIS_BRANCH: coverity-scan 29 | run: curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash || true 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Development tools 2 | /devel-tools/ 3 | # Result of autoreconf -i 4 | /Makefile.in 5 | /aclocal.m4 6 | /config.aux/ 7 | /config.h.in 8 | /config.h.in~ 9 | /configure 10 | /configure~ 11 | # m4/ directory: only keep certain files 12 | /m4/* 13 | !/m4/check_darwin_paths.m4 14 | !/m4/check_disable_compiler_warnings.m4 15 | !/m4/check_libcperciva_posix.m4 16 | !/m4/check_memlimit_support.m4 17 | !/m4/check_posix_sh.m4 18 | !/m4/check_solaris_c99.m4 19 | # Standard out-of-tree build directory 20 | /build/ 21 | # In-tree configure 22 | .deps/ 23 | /Makefile 24 | /config.h 25 | /config.log 26 | /config.status 27 | /libtool 28 | /stamp-h1 29 | # In-tree build, only top-level 30 | /apisupport-config.h 31 | /cpusupport-config.h 32 | # In-tree build, all directories 33 | .dirstamp 34 | .libs/ 35 | *.la 36 | *.lo 37 | *.o 38 | # In-tree binaries 39 | /scrypt 40 | /tests/libscrypt-kdf/sample-libscrypt-kdf 41 | /tests/valgrind/potential-memleaks 42 | /tests/verify-strings/test_scrypt 43 | # In-tree test output 44 | /tests-output/ 45 | /tests-valgrind/ 46 | -------------------------------------------------------------------------------- /BUILDING: -------------------------------------------------------------------------------- 1 | Installing 2 | ---------- 3 | 4 | We strongly recommend that people use the latest official release tarball on 5 | https://www.tarsnap.com/scrypt.html, and build with: 6 | 7 | ./configure 8 | make 9 | make install 10 | 11 | Official scrypt tarball releases should build and run on any IEEE Std 1003.1 12 | (POSIX) compliant system which 13 | 1. Includes the Software Development Utilities option, 14 | 2. Has OpenSSL available via -lcrypto and #include , and 15 | 3. Provides /dev/urandom. 16 | 17 | 18 | libscrypt-kdf 19 | ------------- 20 | 21 | To install the development library, run: 22 | 23 | ./configure --enable-libscrypt-kdf 24 | make install 25 | 26 | 27 | Platform-specific notes 28 | ----------------------- 29 | 30 | - when cross-compiling, runtime POSIX compatibility checks are disabled. 31 | For more information, see libcperciva/POSIX/README. 32 | 33 | - On OS X, the version of OpenSSL included with the operating 34 | system is outdated (0.9.8) and deprecated, and it is recommended 35 | that scrypt be built with an updated version of OpenSSL. On OS X 36 | 10.11 "El Capitan" and higher, OpenSSL was removed entirely. After 37 | installing a newer version of OpenSSL, use 38 | CPPFLAGS="-I /path/to/openssl/headers" 39 | LDFLAGS="-L /path/to/openssl/lib" 40 | to build scrypt. 41 | 42 | In particular, if you installed OpenSSL using homebrew, you may 43 | pass the relevant directories directly to ./configure: 44 | ./configure CPPFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib" 45 | 46 | Alternatively, you may wish to add these lines to your $HOME/.profile file: 47 | export CPPFLAGS="-I/usr/local/opt/openssl/include $CPPFLAGS" 48 | export LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS" 49 | and then close & re-open your terminal window. 50 | 51 | 52 | Building from git 53 | ----------------- 54 | 55 | For experimental development from git, build with: 56 | 57 | autoreconf -i 58 | ./configure 59 | make 60 | 61 | - You must have automake 1.11.2 or higher, and libtool. 62 | - In order to support the `AX_CFLAGS_WARN_ALL` autoconf directive, you will 63 | need to install the autoconf archive. On Debian systems, use the 64 | `autoconf-archive` package; on FreeBSD, use `devel/autoconf-archive`. 65 | - Ignore this message if it appears: 66 | aclocal: warning: couldn't open directory 'm4': No such file or directory 67 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | The included code and documentation ("scrypt") is distributed under the 2 | following terms: 3 | 4 | Copyright 2005-2025 Colin Percival. All rights reserved. 5 | Copyright 2011-2025 Tarsnap Backup Inc. All rights reserved. 6 | Copyright 2014 Sean Kelly. All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /FORMAT: -------------------------------------------------------------------------------- 1 | scrypt encrypted data format 2 | ---------------------------- 3 | 4 | offset length 5 | 0 6 "scrypt" 6 | 6 1 scrypt data file version number (== 0) 7 | 7 1 log2(N) (must be between 1 and 63 inclusive) 8 | 8 4 r (big-endian integer; must satisfy r * p < 2^30) 9 | 12 4 p (big-endian integer; must satisfy r * p < 2^30) 10 | 16 32 salt 11 | 48 16 first 16 bytes of SHA256(bytes 0 .. 47) 12 | 64 32 HMAC-SHA256(bytes 0 .. 63) 13 | 96 X data xor AES256-CTR key stream generated with nonce == 0 14 | 96+X 32 HMAC-SHA256(bytes 0 .. 96 + (X - 1)) 15 | 16 | AES256-CTR is computed with a 256-bit AES key key_enc, and HMAC-SHA256 is 17 | computed with a 256-bit key key_hmac, where 18 | scrypt(password, salt, N, r, p, 64) == [key_enc][key_hmac] 19 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.69]) 2 | AC_INIT([scrypt],[m4_esyscmd([sh get-version.sh])], 3 | [https://github.com/Tarsnap/scrypt],[scrypt],[http://www.tarsnap.com/scrypt/]) 4 | 5 | # Safety check: make sure that the srcdir contains this file. 6 | AC_CONFIG_SRCDIR([lib/scryptenc/scryptenc.c]) 7 | # Use auxiliary subscripts from this subdirectory (cleans up root). 8 | AC_CONFIG_AUX_DIR([config.aux]) 9 | # Directory for our additional macros. 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | # Compute $target_os and related variables. 12 | AC_CANONICAL_TARGET 13 | AM_INIT_AUTOMAKE([foreign subdir-objects]) 14 | 15 | # Checks for programs. 16 | m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_C99]) 17 | AM_PROG_AR 18 | LT_INIT 19 | 20 | # Don't rebuild the configure script. I'm distributing a perfectly good one. 21 | AM_MAINTAINER_MODE 22 | 23 | # Get the POSIX sh early, in case the configure script causes 24 | # `command -p getconf` to fail in a broken environment. 25 | CHECK_POSIX_SH 26 | 27 | # Check if we need -std=c99 in LDFLAGS (for gcc on Solaris). 28 | CHECK_SOLARIS_C99 29 | 30 | # Check if we need to add extra paths to CPPFLAGS and LDFLAGS for macOS. 31 | CHECK_DARWIN_PATHS 32 | 33 | # Checks for AES support in OpenSSL. 34 | AC_SEARCH_LIBS([AES_encrypt], [crypto],, 35 | AC_MSG_ERROR([function AES_ENCRYPT not found])) 36 | AC_CHECK_HEADERS([openssl/aes.h],, 37 | [AC_MSG_ERROR([Unable to find the openssl/aes.h header])]) 38 | 39 | # Check how we can find out the available memory. 40 | CHECK_MEMLIMIT_SUPPORT 41 | 42 | # Check for posix_memalign. 43 | AC_CHECK_FUNCS_ONCE([posix_memalign]) 44 | 45 | # Check for mmap so we can work around its absence on Minix. 46 | AC_CHECK_FUNCS_ONCE([mmap]) 47 | 48 | # Use 64-bit file offsets. 49 | AC_SYS_LARGEFILE 50 | 51 | # Check whether the user has requested to disable compiler warnings. 52 | CHECK_DISABLE_COMPILER_WARNINGS 53 | 54 | # Check libcperciva POSIX compatibility. 55 | CHECK_LIBCPERCIVA_POSIX([${srcdir}/libcperciva]) 56 | 57 | # Check whether the user wants to install libscrypt-kdf. 58 | AC_ARG_ENABLE(libscrypt-kdf, AS_HELP_STRING([--enable-libscrypt-kdf], 59 | [Install libscrypt-kdf and development headers.])) 60 | AM_CONDITIONAL([LIBSCRYPT_KDF], [test "x${enable_libscrypt_kdf}" = "xyes"]) 61 | 62 | # Write configure results and the Makefile. 63 | AC_CONFIG_HEADERS([config.h]) 64 | AC_CONFIG_FILES([Makefile]) 65 | AC_OUTPUT 66 | -------------------------------------------------------------------------------- /get-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | version=1.3.3-head 4 | 5 | # This script outputs a version number for this project to stdout. 6 | # - if $SCRYPT_VERSION is given, it is used. 7 | # - otherwise, it uses ${version}. 8 | # - if there is a ".git/" directory, it will attempt to get a version number 9 | # from `git describe` in the form 1.2.0-238-g0a25a7c, where the middle value 10 | # is the number of commits since the 1.2.0 tag. 11 | 12 | # Use $SCRYPT_VERSION if it exists. 13 | if [ -n "${SCRYPT_VERSION}" ]; then 14 | # Do not use \n; that confuses autoconf. 15 | printf "%s" "${SCRYPT_VERSION}" 16 | exit 0 17 | fi 18 | 19 | # Get a version number from git, if it exists. 20 | if git rev-parse 2>/dev/null; then 21 | # Get a version string from the latest git tag. 22 | if version_git=$( git describe --tags --match '[[:digit:]].*' ) \ 23 | 2>/dev/null ; then 24 | version_decapitated=$( echo "${version}" | sed "s/-head//" ) 25 | # Check that the beginning of this tag matches the version. 26 | case ${version_git} in 27 | "${version_decapitated}"*) 28 | # If so, use that version string. 29 | version=${version_git};; 30 | *) 31 | printf "git tag does not match version\n" 1>&2 32 | exit 1;; 33 | esac 34 | fi 35 | fi 36 | 37 | # Output the version to stdout. Do not use \n; that confuses autoconf. 38 | printf "%s" "${version}" 39 | -------------------------------------------------------------------------------- /lib-platform/crypto/crypto_scrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef CRYPTO_SCRYPT_H_ 30 | #define CRYPTO_SCRYPT_H_ 31 | 32 | #include 33 | #include 34 | 35 | /** 36 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 37 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 38 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 39 | * must satisfy 0 < r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter 40 | * N must be a power of 2 greater than 1. 41 | * 42 | * Return 0 on success; or -1 on error. 43 | */ 44 | int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 45 | uint32_t, uint32_t, uint8_t *, size_t); 46 | 47 | #endif /* !CRYPTO_SCRYPT_H_ */ 48 | -------------------------------------------------------------------------------- /lib-platform/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_H_ 2 | #define PLATFORM_H_ 3 | 4 | /* Ensure that we have a config file. */ 5 | #if defined(CONFIG_H_FILE) 6 | #include CONFIG_H_FILE 7 | #elif defined(HAVE_CONFIG_H) 8 | #include "config.h" 9 | #else 10 | #error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined. 11 | #endif 12 | 13 | #endif /* !PLATFORM_H_ */ 14 | -------------------------------------------------------------------------------- /lib-platform/util/memlimit.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef MEMLIMIT_H_ 30 | #define MEMLIMIT_H_ 31 | 32 | #include 33 | 34 | /** 35 | * memtouse(maxmem, maxmemfrac, memlimit): 36 | * Examine the system and return the amount of RAM which should be 37 | * used in ${memlimit}. This value should be the specified 38 | * ${maxmemfrac} fraction of available RAM, but no more than 39 | * ${maxmem} and no less than 1 MiB. ${maxmemfrac} must be larger than 0 40 | * and <= 1.0. 41 | */ 42 | int memtouse(size_t, double, size_t *); 43 | 44 | #endif /* !MEMLIMIT_H_ */ 45 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | The source code under this directory is taken from the client for the 2 | Tarsnap online backup system (and released under the 2-clause BSD license 3 | with permission of the author); keeping this code in sync with the Tarsnap 4 | code is highly desirable and explains why there is some functionality 5 | included here which is not actually used by the scrypt file encryption 6 | utility. 7 | -------------------------------------------------------------------------------- /lib/crypto/crypto_scrypt_smix.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #include 30 | #include 31 | 32 | #include "sysendian.h" 33 | 34 | #include "crypto_scrypt_smix.h" 35 | 36 | static void blkcpy(uint32_t *, const uint32_t *, size_t); 37 | static void blkxor(uint32_t *, const uint32_t *, size_t); 38 | static void salsa20_8(uint32_t[16]); 39 | static void blockmix_salsa8(const uint32_t *, uint32_t *, uint32_t *, size_t); 40 | static uint64_t integerify(const uint32_t *, size_t); 41 | 42 | static void 43 | blkcpy(uint32_t * dest, const uint32_t * src, size_t len) 44 | { 45 | 46 | memcpy(dest, src, len); 47 | } 48 | 49 | static void 50 | blkxor(uint32_t * dest, const uint32_t * src, size_t len) 51 | { 52 | size_t i; 53 | 54 | for (i = 0; i < len / 4; i++) 55 | dest[i] ^= src[i]; 56 | } 57 | 58 | /** 59 | * salsa20_8(B): 60 | * Apply the salsa20/8 core to the provided block. 61 | */ 62 | static void 63 | salsa20_8(uint32_t B[16]) 64 | { 65 | uint32_t x[16]; 66 | size_t i; 67 | 68 | blkcpy(x, B, 64); 69 | for (i = 0; i < 8; i += 2) { 70 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) 71 | /* Operate on columns. */ 72 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); 73 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); 74 | 75 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); 76 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); 77 | 78 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); 79 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); 80 | 81 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); 82 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); 83 | 84 | /* Operate on rows. */ 85 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); 86 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); 87 | 88 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); 89 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); 90 | 91 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); 92 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); 93 | 94 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); 95 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); 96 | #undef R 97 | } 98 | for (i = 0; i < 16; i++) 99 | B[i] += x[i]; 100 | } 101 | 102 | /** 103 | * blockmix_salsa8(Bin, Bout, X, r): 104 | * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r 105 | * bytes in length; the output Bout must also be the same size. The 106 | * temporary space X must be 64 bytes. 107 | */ 108 | static void 109 | blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) 110 | { 111 | size_t i; 112 | 113 | /* 1: X <-- B_{2r - 1} */ 114 | blkcpy(X, &Bin[(2 * r - 1) * 16], 64); 115 | 116 | /* 2: for i = 0 to 2r - 1 do */ 117 | for (i = 0; i < 2 * r; i += 2) { 118 | /* 3: X <-- H(X \xor B_i) */ 119 | blkxor(X, &Bin[i * 16], 64); 120 | salsa20_8(X); 121 | 122 | /* 4: Y_i <-- X */ 123 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 124 | blkcpy(&Bout[i * 8], X, 64); 125 | 126 | /* 3: X <-- H(X \xor B_i) */ 127 | blkxor(X, &Bin[i * 16 + 16], 64); 128 | salsa20_8(X); 129 | 130 | /* 4: Y_i <-- X */ 131 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 132 | blkcpy(&Bout[i * 8 + r * 16], X, 64); 133 | } 134 | } 135 | 136 | /** 137 | * integerify(B, r): 138 | * Return the result of parsing B_{2r-1} as a little-endian integer. 139 | */ 140 | static uint64_t 141 | integerify(const uint32_t * B, size_t r) 142 | { 143 | const uint32_t * X = B + (2 * r - 1) * 16; 144 | 145 | return (((uint64_t)(X[1]) << 32) + X[0]); 146 | } 147 | 148 | /** 149 | * crypto_scrypt_smix(B, r, N, V, XY): 150 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; 151 | * the temporary storage V must be 128rN bytes in length; the temporary 152 | * storage XY must be 256r + 64 bytes in length. The value N must be a 153 | * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a 154 | * multiple of 64 bytes. 155 | */ 156 | void 157 | crypto_scrypt_smix(uint8_t * B, size_t r, uint64_t N, void * _v, void * XY) 158 | { 159 | uint32_t * X = XY; 160 | uint32_t * Y = (void *)((uint8_t *)(XY) + 128 * r); 161 | uint32_t * Z = (void *)((uint8_t *)(XY) + 256 * r); 162 | uint32_t * V = _v; 163 | uint64_t i; 164 | uint64_t j; 165 | size_t k; 166 | 167 | /* 1: X <-- B */ 168 | for (k = 0; k < 32 * r; k++) 169 | X[k] = le32dec(&B[4 * k]); 170 | 171 | /* 2: for i = 0 to N - 1 do */ 172 | for (i = 0; i < N; i += 2) { 173 | /* 3: V_i <-- X */ 174 | blkcpy(&V[i * (32 * r)], X, 128 * r); 175 | 176 | /* 4: X <-- H(X) */ 177 | blockmix_salsa8(X, Y, Z, r); 178 | 179 | /* 3: V_i <-- X */ 180 | blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); 181 | 182 | /* 4: X <-- H(X) */ 183 | blockmix_salsa8(Y, X, Z, r); 184 | } 185 | 186 | /* 6: for i = 0 to N - 1 do */ 187 | for (i = 0; i < N; i += 2) { 188 | /* 7: j <-- Integerify(X) mod N */ 189 | j = integerify(X, r) & (N - 1); 190 | 191 | /* 8: X <-- H(X \xor V_j) */ 192 | blkxor(X, &V[j * (32 * r)], 128 * r); 193 | blockmix_salsa8(X, Y, Z, r); 194 | 195 | /* 7: j <-- Integerify(X) mod N */ 196 | j = integerify(Y, r) & (N - 1); 197 | 198 | /* 8: X <-- H(X \xor V_j) */ 199 | blkxor(Y, &V[j * (32 * r)], 128 * r); 200 | blockmix_salsa8(Y, X, Z, r); 201 | } 202 | 203 | /* 10: B' <-- X */ 204 | for (k = 0; k < 32 * r; k++) 205 | le32enc(&B[4 * k], X[k]); 206 | } 207 | -------------------------------------------------------------------------------- /lib/crypto/crypto_scrypt_smix.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_SCRYPT_SMIX_H_ 2 | #define CRYPTO_SCRYPT_SMIX_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * crypto_scrypt_smix(B, r, N, V, XY): 9 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; 10 | * the temporary storage V must be 128rN bytes in length; the temporary 11 | * storage XY must be 256r + 64 bytes in length. The value N must be a 12 | * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a 13 | * multiple of 64 bytes. 14 | */ 15 | void crypto_scrypt_smix(uint8_t *, size_t, uint64_t, void *, void *); 16 | 17 | #endif /* !CRYPTO_SCRYPT_SMIX_H_ */ 18 | -------------------------------------------------------------------------------- /lib/crypto/crypto_scrypt_smix_sse2.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_SCRYPT_SMIX_SSE2_H_ 2 | #define CRYPTO_SCRYPT_SMIX_SSE2_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * crypto_scrypt_smix_sse2(B, r, N, V, XY): 9 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; 10 | * the temporary storage V must be 128rN bytes in length; the temporary 11 | * storage XY must be 256r + 64 bytes in length. The value N must be a 12 | * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a 13 | * multiple of 64 bytes. 14 | * 15 | * Use SSE2 instructions. 16 | */ 17 | void crypto_scrypt_smix_sse2(uint8_t *, size_t, uint64_t, void *, void *); 18 | 19 | #endif /* !CRYPTO_SCRYPT_SMIX_SSE2_H_ */ 20 | -------------------------------------------------------------------------------- /lib/scryptenc/scryptenc_cpuperf.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include "crypto_scrypt.h" 35 | #include "monoclock.h" 36 | 37 | #include "scryptenc.h" 38 | #include "scryptenc_cpuperf.h" 39 | 40 | static int 41 | getclockdiff(struct timeval * st, double * diffd) 42 | { 43 | struct timeval en; 44 | 45 | if (monoclock_get(&en)) 46 | return (1); 47 | *diffd = timeval_diff((*st), en); 48 | 49 | /* Success! */ 50 | return (0); 51 | } 52 | 53 | /** 54 | * scryptenc_cpuperf(opps): 55 | * Estimate the number of salsa20/8 cores which can be executed per second, 56 | * and store the value in ${opps}. Return a SCRYPT_* code. 57 | */ 58 | int 59 | scryptenc_cpuperf(double * opps) 60 | { 61 | struct timeval st; 62 | double resd, diffd; 63 | uint64_t i = 0; 64 | 65 | /* Get the clock resolution. */ 66 | if (monoclock_getres(&resd)) 67 | return (SCRYPT_ECLOCK); 68 | 69 | #ifdef DEBUG 70 | fprintf(stderr, "Clock resolution is %g\n", resd); 71 | #endif 72 | 73 | /* Loop until the clock ticks. */ 74 | if (monoclock_get(&st)) 75 | return (SCRYPT_ECLOCK); 76 | do { 77 | /* Do an scrypt. */ 78 | if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0)) 79 | return (SCRYPT_EKEY); 80 | 81 | /* Has the clock ticked? */ 82 | if (getclockdiff(&st, &diffd)) 83 | return (SCRYPT_ECLOCK); 84 | if (diffd > 0) 85 | break; 86 | } while (1); 87 | 88 | /* Count how many scrypts we can do before the next tick. */ 89 | if (monoclock_get(&st)) 90 | return (SCRYPT_ECLOCK); 91 | do { 92 | /* Do an scrypt. */ 93 | if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0)) 94 | return (SCRYPT_EKEY); 95 | 96 | /* We invoked the salsa20/8 core 512 times. */ 97 | i += 512; 98 | 99 | /* Check if we have looped for long enough. */ 100 | if (getclockdiff(&st, &diffd)) 101 | return (SCRYPT_ECLOCK); 102 | if (diffd > resd) 103 | break; 104 | } while (1); 105 | 106 | #ifdef DEBUG 107 | fprintf(stderr, "%ju salsa20/8 cores performed in %g seconds\n", 108 | (uintmax_t)i, diffd); 109 | #endif 110 | 111 | /* We can do approximately i salsa20/8 cores per diffd seconds. */ 112 | *opps = (double)i / diffd; 113 | 114 | /* Success! */ 115 | return (SCRYPT_OK); 116 | } 117 | -------------------------------------------------------------------------------- /lib/scryptenc/scryptenc_cpuperf.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef SCRYPTENC_CPUPERF_H_ 30 | #define SCRYPTENC_CPUPERF_H_ 31 | 32 | /** 33 | * scryptenc_cpuperf(opps): 34 | * Estimate the number of salsa20/8 cores which can be executed per second, 35 | * and store the value in ${opps}. Return a SCRYPT_* code. 36 | */ 37 | int scryptenc_cpuperf(double *); 38 | 39 | #endif /* !SCRYPTENC_CPUPERF_H_ */ 40 | -------------------------------------------------------------------------------- /lib/scryptenc/scryptenc_print_error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "warnp.h" 5 | 6 | #include "scryptenc.h" 7 | #include "scryptenc_print_error.h" 8 | 9 | /** 10 | * scryptenc_print_error(rc, infilename, outfilename): 11 | * Print the error corresponding to ${rc}. If relevant, use ${infilename} 12 | * or ${outfilename} to display an error about reading or writing; these 13 | * arguments can be NULL to indicate standard input or output. 14 | */ 15 | void 16 | scryptenc_print_error(int rc, const char * infilename, 17 | const char * outfilename) 18 | { 19 | 20 | /* Sanity check: this should only be used for errors. */ 21 | assert(rc != SCRYPT_OK); 22 | 23 | /* Display error. */ 24 | switch (rc) { 25 | case SCRYPT_ELIMIT: 26 | warnp("Error determining amount of available memory"); 27 | break; 28 | case SCRYPT_ECLOCK: 29 | warnp("Error reading clocks"); 30 | break; 31 | case SCRYPT_EKEY: 32 | warnp("Error computing derived key"); 33 | break; 34 | case SCRYPT_ESALT: 35 | warnp("Error reading salt"); 36 | break; 37 | case SCRYPT_EOPENSSL: 38 | warnp("OpenSSL error"); 39 | break; 40 | case SCRYPT_ENOMEM: 41 | warnp("Error allocating memory"); 42 | break; 43 | case SCRYPT_EINVAL: 44 | warn0("Input is not valid scrypt-encrypted block"); 45 | break; 46 | case SCRYPT_EVERSION: 47 | warn0("Unrecognized scrypt format version"); 48 | break; 49 | case SCRYPT_ETOOBIG: 50 | warn0("Decrypting file would require too much memory"); 51 | break; 52 | case SCRYPT_ETOOSLOW: 53 | warn0("Decrypting file would take too much CPU time"); 54 | break; 55 | case SCRYPT_EBIGSLOW: 56 | warn0("Decrypting file would require too much memory" 57 | " and CPU time"); 58 | break; 59 | case SCRYPT_EPASS: 60 | warn0("Passphrase is incorrect"); 61 | break; 62 | case SCRYPT_EWRFILE: 63 | warnp("Error writing file: %s", 64 | (outfilename != NULL) ? outfilename : "standard output"); 65 | break; 66 | case SCRYPT_ERDFILE: 67 | warnp("Error reading file: %s", 68 | (infilename != NULL) ? infilename : "standard input"); 69 | break; 70 | case SCRYPT_EPARAM: 71 | warn0("Error in explicit parameters"); 72 | break; 73 | default: 74 | warn0("Programmer error: unrecognized scrypt error"); 75 | break; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/scryptenc/scryptenc_print_error.h: -------------------------------------------------------------------------------- 1 | #ifndef SCRYPTENC_PRINT_ERROR_H_ 2 | #define SCRYPTENC_PRINT_ERROR_H_ 3 | 4 | /** 5 | * scryptenc_print_error(rc, infilename, outfilename): 6 | * Print the error corresponding to ${rc}. If relevant, use ${infilename} 7 | * or ${outfilename} to display an error about reading or writing; these 8 | * arguments can be NULL to indicate standard input or output. 9 | */ 10 | void scryptenc_print_error(int, const char *, const char *); 11 | 12 | #endif /* !SCRYPTENC_PRINT_ERROR_H_ */ 13 | -------------------------------------------------------------------------------- /lib/util/passphrase_entry.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "passphrase_entry.h" 5 | #include "readpass.h" 6 | #include "warnp.h" 7 | 8 | /** 9 | * passphrase_entry_parse(arg, entry_method_p, entry_arg_p): 10 | * Parse "METHOD:ARG" from ${arg} into an ${*entry_method_p}:${*entry_arg_p}. 11 | */ 12 | int 13 | passphrase_entry_parse(const char * arg, 14 | enum passphrase_entry * passphrase_entry_p, const char ** passphrase_arg_p) 15 | { 16 | const char * p; 17 | 18 | /* Find the separator in "method:arg", or fail if there isn't one. */ 19 | if ((p = strchr(arg, ':')) == NULL) 20 | goto err1; 21 | 22 | /* Extract the "arg" part. */ 23 | *passphrase_arg_p = &p[1]; 24 | 25 | /* Parse the "method". */ 26 | if (strncmp(arg, "dev:", 4) == 0) { 27 | if (strcmp(*passphrase_arg_p, "tty-stdin") == 0) { 28 | *passphrase_entry_p = PASSPHRASE_TTY_STDIN; 29 | goto success; 30 | } 31 | else if (strcmp(*passphrase_arg_p, "stdin-once") == 0) { 32 | *passphrase_entry_p = PASSPHRASE_STDIN_ONCE; 33 | goto success; 34 | } 35 | else if (strcmp(*passphrase_arg_p, "tty-once") == 0) { 36 | *passphrase_entry_p = PASSPHRASE_TTY_ONCE; 37 | goto success; 38 | } 39 | } 40 | if (strncmp(arg, "env:", 4) == 0) { 41 | *passphrase_entry_p = PASSPHRASE_ENV; 42 | goto success; 43 | } 44 | if (strncmp(arg, "file:", 5) == 0) { 45 | *passphrase_entry_p = PASSPHRASE_FILE; 46 | goto success; 47 | } 48 | 49 | err1: 50 | warn0("Invalid option: --passphrase %s", arg); 51 | 52 | /* Failure! */ 53 | return (-1); 54 | 55 | success: 56 | /* Success! */ 57 | return (0); 58 | } 59 | 60 | /** 61 | * passphrase_entry_readpass(passwd, entry_method, entry_arg, prompt, 62 | * confirmprompt, once): 63 | * Use ${entry_method} to read a passphrase and return it as a malloced 64 | * NUL-terminated string via ${passwd}. If ${entry_method} is 65 | * PASSPHRASE_TTY_STDIN and ${once} is zero, ask for the passphrase twice; 66 | * otherwise ask for it once. If reading from a terminal, use ${prompt} for 67 | * the first prompt, and ${confirmprompt} for the second prompt (if 68 | * applicable); otherwise do not print any prompts. 69 | */ 70 | int 71 | passphrase_entry_readpass(char ** passwd, 72 | enum passphrase_entry passphrase_entry, const char * passphrase_arg, 73 | const char * prompt, const char * confirmprompt, int once) 74 | { 75 | const char * passwd_env; 76 | 77 | switch (passphrase_entry) { 78 | case PASSPHRASE_TTY_STDIN: 79 | /* Read passphrase, prompting only once if decrypting. */ 80 | if (readpass(passwd, prompt, (once) ? NULL : confirmprompt, 1)) 81 | goto err0; 82 | break; 83 | case PASSPHRASE_STDIN_ONCE: 84 | /* Read passphrase, prompting only once, from stdin only. */ 85 | if (readpass(passwd, prompt, NULL, 0)) 86 | goto err0; 87 | break; 88 | case PASSPHRASE_TTY_ONCE: 89 | /* Read passphrase, prompting only once, from tty only. */ 90 | if (readpass(passwd, prompt, NULL, 2)) 91 | goto err0; 92 | break; 93 | case PASSPHRASE_ENV: 94 | /* We're not allowed to modify the output of getenv(). */ 95 | if ((passwd_env = getenv(passphrase_arg)) == NULL) { 96 | warn0("Failed to read from ${%s}", passphrase_arg); 97 | goto err0; 98 | } 99 | 100 | /* This allows us to use the same insecure_zero() logic. */ 101 | if ((*passwd = strdup(passwd_env)) == NULL) { 102 | warnp("Out of memory"); 103 | goto err0; 104 | } 105 | break; 106 | case PASSPHRASE_FILE: 107 | if (readpass_file(passwd, passphrase_arg)) 108 | goto err0; 109 | break; 110 | case PASSPHRASE_UNSET: 111 | warn0("Programming error: passphrase_entry is not set"); 112 | goto err0; 113 | } 114 | 115 | /* Success! */ 116 | return (0); 117 | 118 | err0: 119 | /* Failure! */ 120 | return (-1); 121 | } 122 | -------------------------------------------------------------------------------- /lib/util/passphrase_entry.h: -------------------------------------------------------------------------------- 1 | #ifndef PASSPHRASE_ENTRY_H_ 2 | #define PASSPHRASE_ENTRY_H_ 3 | 4 | /* How should we get the passphrase? */ 5 | enum passphrase_entry { 6 | PASSPHRASE_UNSET, 7 | PASSPHRASE_TTY_STDIN, 8 | PASSPHRASE_STDIN_ONCE, 9 | PASSPHRASE_TTY_ONCE, 10 | PASSPHRASE_ENV, 11 | PASSPHRASE_FILE, 12 | }; 13 | 14 | /** 15 | * passphrase_entry_parse(arg, entry_method_p, entry_arg_p): 16 | * Parse "METHOD:ARG" from ${arg} into an ${*entry_method_p}:${*entry_arg_p}. 17 | */ 18 | int passphrase_entry_parse(const char *, enum passphrase_entry *, 19 | const char **); 20 | 21 | /** 22 | * passphrase_entry_readpass(passwd, entry_method, entry_arg, prompt, 23 | * confirmprompt, once): 24 | * Use ${entry_method} to read a passphrase and return it as a malloced 25 | * NUL-terminated string via ${passwd}. If ${entry_method} is 26 | * PASSPHRASE_TTY_STDIN and ${once} is zero, ask for the passphrase twice; 27 | * otherwise ask for it once. If reading from a terminal, use ${prompt} for 28 | * the first prompt, and ${confirmprompt} for the second prompt (if 29 | * applicable); otherwise do not print any prompts. 30 | */ 31 | int passphrase_entry_readpass(char **, enum passphrase_entry, const char *, 32 | const char *, const char *, int); 33 | 34 | #endif /* !PASSPHRASE_ENTRY_H_ */ 35 | -------------------------------------------------------------------------------- /libcperciva/POSIX/README: -------------------------------------------------------------------------------- 1 | POSIX compatibility code 2 | ------------------------ 3 | 4 | This code exists to work around some common POSIX compatibility issues. 5 | POSIX specifies that if the first line of a Makefile is ".POSIX:" then the 6 | Makefile should be processed according to POSIX rules, including with CC=c99; 7 | thus we should see behaviour consistent with a standard-compliant C99 8 | compiler. 9 | 10 | One POSIX compatibility check requires a runtime test. This will be 11 | automatically disabled if the build system detects that you are 12 | cross-compiling for another platform, or it can be manually disabled by 13 | setting DISABLE_POSIX_RUNTIME_CHECKS to a non-zero value. 14 | 15 | - posix-cflags.sh: Detects if ${CC} supports certain POSIX features, and 16 | outputs a POSIXFAIL_ define if it is not supported so that we can work around 17 | the problem. 18 | 19 | The potential command-line flags are: 20 | - DPOSIXFAIL_MSG_NOSIGNAL: not defining MSG_NOSIGNAL. 21 | - DPOSIXFAIL_CLOCK_REALTIME: not defining CLOCK_REALTIME. 22 | - DPOSIXFAIL_CLOCK_GETTIME: not declaring clock_gettime(), or 23 | clock_gettime() is not linkable. The latter test requires a runtime check. 24 | - DPOSIXFAIL_INET_ADDRSTRLEN: not defining 25 | INET_ADDRSTRLEN. 26 | - DPOSIXFAIL_INET6_ADDRSTRLEN: not defining 27 | INET6_ADDRSTRLEN. 28 | - DPOSIXFAIL_ABSTRACT_DECLARATOR: ${CC} does not accept 29 | qualifiers in an abstract declarator. 30 | - DPOSIXFAIL_STAT_ST_MTIM: struct stat does not contain st_mtim. 31 | - std=c99: ${CC} does not accept the `restrict` keyword by default, but 32 | accepts it when given this flag. 33 | 34 | - posix-cflags-filter.sh: Detects if ${CC} supports expected ${CFLAG} value(s). 35 | 36 | The potential ${CFLAGS} flags it checks are: 37 | - O2: some compilers only accept -O. 38 | 39 | - posix-l.sh: Detects whether the linker supports certain POSIX features. 40 | 41 | The potential command-line flags are: 42 | - lrt lxnet: c99 is required to understand these options, and ignore them if 43 | the routines for which they specify linkage are already in the standard C 44 | library 45 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-abstract-declarator.c: -------------------------------------------------------------------------------- 1 | #ifdef POSIXFAIL_ABSTRACT_DECLARATOR 2 | static int func(int ARGNAME[static restrict 1]); 3 | #else 4 | static int func(int [static restrict 1]); 5 | #endif 6 | 7 | int 8 | func(int arr[static restrict 1]) 9 | { 10 | 11 | (void)arr; /* UNUSED */ 12 | 13 | /* Success! */ 14 | return (0); 15 | } 16 | 17 | int 18 | main(void) 19 | { 20 | 21 | (void)func; /* UNUSED */ 22 | 23 | /* Success! */ 24 | return (0); 25 | } 26 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-cflags.sh: -------------------------------------------------------------------------------- 1 | # Should be sourced by 2 | # command -p sh posix-cflags.sh "$PATH" 3 | # from within a Makefile. 4 | 5 | # Sanity check environment variables 6 | if [ -z "${CC}" ]; then 7 | echo "\$CC is not defined! Cannot run any compiler tests." 1>&2 8 | exit 1 9 | fi 10 | if ! [ "${PATH}" = "$1" ]; then 11 | echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 12 | PATH=$1 13 | fi 14 | 15 | # Find directory of this script and the source files 16 | D=$(dirname "$0") 17 | 18 | # Check if we can compile & run a binary. 19 | if ! ${CC} ${CFLAGS} "${D}/posix-trivial.c" 2>/dev/null; then 20 | echo "WARNING: failed to compile posix-trivial.c" 1>&2 21 | else 22 | # If the user hasn't disabled runtime checks... 23 | if [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -eq "0" ]; then 24 | # ... test if we can run the trivial binary. 25 | if ! ./a.out ; then 26 | echo "WARNING: failed to run a trivial binary; " 1>&2 27 | echo "disabling runtime POSIX compatibility checks" 1>&2 28 | DISABLE_POSIX_RUNTIME_CHECKS=1 29 | fi 30 | fi 31 | fi 32 | 33 | FIRST=YES 34 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-msg_nosignal.c" 2>/dev/null; then 35 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 36 | printf %s "-DPOSIXFAIL_MSG_NOSIGNAL" 37 | echo "WARNING: POSIX violation: not defining MSG_NOSIGNAL" 1>&2 38 | fi 39 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-clock_realtime.c" 2>/dev/null; then 40 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 41 | printf %s "-DPOSIXFAIL_CLOCK_REALTIME" 42 | echo "WARNING: POSIX violation: not defining CLOCK_REALTIME" 1>&2 43 | fi 44 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-inet-addrstrlen.c" 2>/dev/null; then 45 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 46 | printf %s "-DPOSIXFAIL_INET_ADDRSTRLEN" 47 | echo "WARNING: POSIX violation: not defining INET_ADDRSTRLEN" 1>&2 48 | fi 49 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-inet6-addrstrlen.c" 2>/dev/null; then 50 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 51 | printf %s "-DPOSIXFAIL_INET6_ADDRSTRLEN" 52 | echo "WARNING: POSIX violation: not defining INET6_ADDRSTRLEN" 1>&2 53 | fi 54 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-clock_gettime.c" 2>/dev/null; then 55 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 56 | printf %s "-DPOSIXFAIL_CLOCK_GETTIME" 57 | echo "WARNING: POSIX violation: not declaring clock_gettime()" 1>&2 58 | elif [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -ne "0" ]; then 59 | # Do nothing 60 | true 61 | else 62 | # Even if the compilation succeeds, we still need to run the binary 63 | # because OS X 10.11 with XCode 8 _will_ contain clock_gettime() in the 64 | # header (because it was added in 10.12 and they only use one SDK per 65 | # XCode version), but it will link to the 10.11 library (which doesn't 66 | # include it). Annoyingly, there's two levels of error output on OS X: 67 | # one from the binary itself, and one from the signal it sends to the 68 | # calling process. The "( ./x 2>y ) 2>y" captures both types of error 69 | # message. 70 | if ! ( ./a.out 2>/dev/null ) 2>/dev/null ; then 71 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 72 | printf %s "-DPOSIXFAIL_CLOCK_GETTIME" 73 | echo "WARNING: POSIX violation: clock_gettime() is not linkable" 1>&2 74 | fi 75 | fi 76 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-stat-st_mtim.c" 2>/dev/null; then 77 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 78 | printf %s "-DPOSIXFAIL_STAT_ST_MTIM" 79 | echo "WARNING: POSIX violation: struct stat does not contain st_mtim" 1>&2 80 | fi 81 | CFLAGS_C99="" 82 | if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-restrict.c" 2>/dev/null; then 83 | echo "WARNING: POSIX violation: ${CC} does not accept the 'restrict' keyword" 1>&2 84 | if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -std=c99 "${D}/posix-restrict.c" 2>/dev/null; then 85 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 86 | printf %s "-std=c99" 87 | CFLAGS_C99="-std=c99" 88 | fi 89 | fi 90 | if ! ${CC} ${CFLAGS} ${CFLAGS_C99} -D_POSIX_C_SOURCE=200809L -DARGNAME="" "${D}/posix-abstract-declarator.c" 2>/dev/null; then 91 | echo "WARNING: POSIX violation: ${CC} does not accept qualifiers in an abstract declarator" 1>&2 92 | # Test compile with -DPOSIXFAIL_ABSTRACT_DECLARATOR 93 | if ${CC} ${CFLAGS} ${CFLAGS_C99} -D_POSIX_C_SOURCE=200809L -DPOSIXFAIL_ABSTRACT_DECLARATOR "${D}/posix-abstract-declarator.c" 2>/dev/null; then 94 | [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO 95 | printf %s "-DPOSIXFAIL_ABSTRACT_DECLARATOR" 96 | fi 97 | fi 98 | rm -f a.out 99 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-clock_gettime.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | struct timespec ts; 7 | 8 | return (clock_gettime(CLOCK_REALTIME, &ts)); 9 | } 10 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-clock_realtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | 7 | return (CLOCK_REALTIME); 8 | } 9 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-inet-addrstrlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | 7 | return (INET_ADDRSTRLEN); 8 | } 9 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-inet6-addrstrlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | 7 | return (INET6_ADDRSTRLEN); 8 | } 9 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-l.sh: -------------------------------------------------------------------------------- 1 | # Should be sourced by 2 | # command -p sh posix-l.sh "$PATH" 3 | # from within a Makefile. 4 | 5 | # Sanity check environment variables 6 | if [ -z "${CC}" ]; then 7 | echo "\$CC is not defined! Cannot run any compiler tests." 1>&2 8 | exit 1 9 | fi 10 | if ! [ "${PATH}" = "$1" ]; then 11 | echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 12 | PATH=$1 13 | fi 14 | 15 | # Find directory of this script and the source files 16 | D=$(dirname "$0") 17 | 18 | FIRST=YES 19 | for LIB in rt xnet; do 20 | if ${CC} ${CFLAGS} -l"${LIB}" "${D}/posix-trivial.c" 2>/dev/null; then 21 | if [ "${FIRST}" = "NO" ]; then 22 | printf " "; 23 | fi 24 | printf "%s" "-l${LIB}"; 25 | FIRST=NO; 26 | else 27 | echo "WARNING: POSIX violation: ${CC} does not understand -l${LIB}" 1>&2 28 | fi 29 | rm -f a.out 30 | done 31 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-msg_nosignal.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | 7 | return (MSG_NOSIGNAL); 8 | } 9 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-restrict.c: -------------------------------------------------------------------------------- 1 | static int 2 | foo(const char * restrict x, const char * restrict y) 3 | { 4 | 5 | return (x == y); 6 | } 7 | 8 | int 9 | main(void) 10 | { 11 | char x[10]; 12 | char y[10]; 13 | 14 | return (foo(x, y)); 15 | } 16 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-stat-st_mtim.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | struct stat sb; 7 | 8 | /* Can we reference st_mtim? */ 9 | (void)sb.st_mtim.tv_sec; 10 | 11 | /* Success! */ 12 | return (0); 13 | } 14 | -------------------------------------------------------------------------------- /libcperciva/POSIX/posix-trivial.c: -------------------------------------------------------------------------------- 1 | int 2 | main(void) 3 | { 4 | 5 | /* Success! */ 6 | return (0); 7 | } 8 | -------------------------------------------------------------------------------- /libcperciva/alg/sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_H_ 2 | #define SHA256_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* 8 | * Use #defines in order to avoid namespace collisions with anyone else's 9 | * SHA256 code (e.g., the code in OpenSSL). 10 | */ 11 | #define SHA256_Init libcperciva_SHA256_Init 12 | #define SHA256_Update libcperciva_SHA256_Update 13 | #define SHA256_Final libcperciva_SHA256_Final 14 | #define SHA256_Buf libcperciva_SHA256_Buf 15 | #define SHA256_CTX libcperciva_SHA256_CTX 16 | #define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init 17 | #define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update 18 | #define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final 19 | #define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf 20 | #define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX 21 | 22 | /* Context structure for SHA256 operations. */ 23 | typedef struct { 24 | uint32_t state[8]; 25 | uint64_t count; 26 | uint8_t buf[64]; 27 | } SHA256_CTX; 28 | 29 | /** 30 | * SHA256_Init(ctx): 31 | * Initialize the SHA256 context ${ctx}. 32 | */ 33 | void SHA256_Init(SHA256_CTX *); 34 | 35 | /** 36 | * SHA256_Update(ctx, in, len): 37 | * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. 38 | */ 39 | void SHA256_Update(SHA256_CTX *, const void *, size_t); 40 | 41 | /** 42 | * SHA256_Final(digest, ctx): 43 | * Output the SHA256 hash of the data input to the context ${ctx} into the 44 | * buffer ${digest}, and clear the context state. 45 | */ 46 | void SHA256_Final(uint8_t[32], SHA256_CTX *); 47 | 48 | /** 49 | * SHA256_Buf(in, len, digest): 50 | * Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}. 51 | */ 52 | void SHA256_Buf(const void *, size_t, uint8_t[32]); 53 | 54 | /* Context structure for HMAC-SHA256 operations. */ 55 | typedef struct { 56 | SHA256_CTX ictx; 57 | SHA256_CTX octx; 58 | } HMAC_SHA256_CTX; 59 | 60 | /** 61 | * HMAC_SHA256_Init(ctx, K, Klen): 62 | * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from 63 | * ${K}. 64 | */ 65 | void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); 66 | 67 | /** 68 | * HMAC_SHA256_Update(ctx, in, len): 69 | * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. 70 | */ 71 | void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); 72 | 73 | /** 74 | * HMAC_SHA256_Final(digest, ctx): 75 | * Output the HMAC-SHA256 of the data input to the context ${ctx} into the 76 | * buffer ${digest}, and clear the context state. 77 | */ 78 | void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *); 79 | 80 | /** 81 | * HMAC_SHA256_Buf(K, Klen, in, len, digest): 82 | * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of 83 | * length ${Klen}, and write the result to ${digest}. 84 | */ 85 | void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]); 86 | 87 | /** 88 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 89 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 90 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 91 | */ 92 | void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, 93 | uint64_t, uint8_t *, size_t); 94 | 95 | #endif /* !SHA256_H_ */ 96 | -------------------------------------------------------------------------------- /libcperciva/alg/sha256_arm.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | #ifdef CPUSUPPORT_ARM_SHA256 3 | /** 4 | * CPUSUPPORT CFLAGS: ARM_SHA256 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef __ARM_NEON 12 | #include 13 | #endif 14 | 15 | #include "sha256_arm.h" 16 | 17 | /* SHA256 round constants. */ 18 | static const uint32_t Krnd[64] = { 19 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 20 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 21 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 22 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 23 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 24 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 25 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 26 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 27 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 28 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 29 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 30 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 31 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 32 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 33 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 34 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 35 | }; 36 | 37 | /* Round computation. */ 38 | #define RND4(S, M, Kp) do { \ 39 | uint32x4_t S0_step; \ 40 | uint32x4_t Wk; \ 41 | S0_step = S[0]; \ 42 | Wk = vaddq_u32(M, vld1q_u32(Kp)); \ 43 | S[0] = vsha256hq_u32(S[0], S[1], Wk); \ 44 | S[1] = vsha256h2q_u32(S[1], S0_step, Wk); \ 45 | } while (0) 46 | 47 | /* Message schedule computation */ 48 | #define MSG4(X0, X1, X2, X3) \ 49 | X0 = vsha256su1q_u32(vsha256su0q_u32(X0, X1), X2, X3) 50 | 51 | /** 52 | * SHA256_Transform_arm(state, block): 53 | * Compute the SHA256 block compression function, transforming ${state} using 54 | * the data in ${block}. This implementation uses ARM SHA256 instructions, 55 | * and should only be used if _SHA256 is defined and cpusupport_arm_sha256() 56 | * returns nonzero. 57 | */ 58 | #ifdef POSIXFAIL_ABSTRACT_DECLARATOR 59 | void 60 | SHA256_Transform_arm(uint32_t state[8], const uint8_t block[64]) 61 | #else 62 | void 63 | SHA256_Transform_arm(uint32_t state[static restrict 8], 64 | const uint8_t block[static restrict 64]) 65 | #endif 66 | { 67 | uint32x4_t Y[4]; 68 | uint32x4_t S[2]; 69 | uint32x4_t _state[2]; 70 | int i; 71 | 72 | /* 1. Prepare the first part of the message schedule W. */ 73 | Y[0] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[0]))); 74 | Y[1] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[16]))); 75 | Y[2] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[32]))); 76 | Y[3] = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(&block[48]))); 77 | 78 | /* 2. Initialize working variables. */ 79 | S[0] = _state[0] = vld1q_u32(&state[0]); 80 | S[1] = _state[1] = vld1q_u32(&state[4]); 81 | 82 | /* 3. Mix. */ 83 | for (i = 0; i < 64; i += 16) { 84 | RND4(S, Y[0], &Krnd[i + 0]); 85 | RND4(S, Y[1], &Krnd[i + 4]); 86 | RND4(S, Y[2], &Krnd[i + 8]); 87 | RND4(S, Y[3], &Krnd[i + 12]); 88 | 89 | if (i == 48) 90 | break; 91 | MSG4(Y[0], Y[1], Y[2], Y[3]); 92 | MSG4(Y[1], Y[2], Y[3], Y[0]); 93 | MSG4(Y[2], Y[3], Y[0], Y[1]); 94 | MSG4(Y[3], Y[0], Y[1], Y[2]); 95 | } 96 | 97 | /* 4. Mix local working variables into global state. */ 98 | vst1q_u32(&state[0], vaddq_u32(_state[0], S[0])); 99 | vst1q_u32(&state[4], vaddq_u32(_state[1], S[1])); 100 | } 101 | #endif /* CPUSUPPORT_ARM_SHA256 */ 102 | -------------------------------------------------------------------------------- /libcperciva/alg/sha256_arm.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_ARM_H_ 2 | #define SHA256_ARM_H_ 3 | 4 | #include 5 | 6 | /** 7 | * SHA256_Transform_arm(state, block): 8 | * Compute the SHA256 block compression function, transforming ${state} using 9 | * the data in ${block}. This implementation uses ARM SHA256 instructions, 10 | * and should only be used if _SHA256 is defined and cpusupport_arm_sha256() 11 | * returns nonzero. 12 | */ 13 | #ifdef POSIXFAIL_ABSTRACT_DECLARATOR 14 | void SHA256_Transform_arm(uint32_t state[8], const uint8_t block[64]); 15 | #else 16 | void SHA256_Transform_arm(uint32_t[static restrict 8], 17 | const uint8_t[static restrict 64]); 18 | #endif 19 | 20 | #endif /* !SHA256_ARM_H_ */ 21 | -------------------------------------------------------------------------------- /libcperciva/alg/sha256_shani.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | #if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) 3 | /** 4 | * CPUSUPPORT CFLAGS: X86_SHANI X86_SSSE3 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "sha256_shani.h" 11 | 12 | /** 13 | * This code uses intrinsics from the following feature sets: 14 | * SHANI: _mm_sha256msg1_epu32, _mm_sha256msg2_epu32, _mm_sha256rnds2_epu32 15 | * SSSE3: _mm_shuffle_epi8, _mm_alignr_epi8 16 | * SSE2: Everything else 17 | * 18 | * The SSSE3 intrinsics could be avoided at a slight cost by using a few SSE2 19 | * instructions in their place; we have not done this since to our knowledge 20 | * there are presently no CPUs which support the SHANI instruction set but do 21 | * not support SSSE3. 22 | */ 23 | 24 | /* Load 32-bit big-endian words. */ 25 | static __m128i 26 | be32dec_128(const uint8_t * src) 27 | { 28 | const __m128i SHUF = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 29 | 4, 5, 6, 7, 0, 1, 2, 3); 30 | __m128i x; 31 | 32 | /* Load four 32-bit words. */ 33 | x = _mm_loadu_si128((const __m128i *)src); 34 | 35 | /* Reverse the order of the bytes in each word. */ 36 | return (_mm_shuffle_epi8(x, SHUF)); 37 | } 38 | 39 | /* Convert an unsigned 32-bit immediate into a signed value. */ 40 | #define I32(a) ((UINT32_C(a) >= UINT32_C(0x80000000)) ? \ 41 | -(int32_t)(UINT32_C(0xffffffff) - UINT32_C(a)) - 1 : (int32_t)INT32_C(a)) 42 | 43 | /* Load four unsigned 32-bit immediates into a vector register. */ 44 | #define IMM4(a, b, c, d) _mm_set_epi32(I32(a), I32(b), I32(c), I32(d)) 45 | 46 | /* Run four rounds of SHA256. */ 47 | #define RND4(S, W, K0, K1, K2, K3) do { \ 48 | __m128i M; \ 49 | \ 50 | /* Add the next four words of message schedule and round constants. */ \ 51 | M = _mm_add_epi32(W, IMM4(K3, K2, K1, K0)); \ 52 | \ 53 | /* Perform two rounds of SHA256, using the low two words in M. */ \ 54 | S[1] = _mm_sha256rnds2_epu32(S[1], S[0], M); \ 55 | \ 56 | /* Shift the two words of M down and perform the next two rounds. */ \ 57 | M = _mm_srli_si128(M, 8); \ 58 | S[0] = _mm_sha256rnds2_epu32(S[0], S[1], M); \ 59 | } while (0) 60 | 61 | /* Compute the ith set of four words of message schedule. */ 62 | #define MSG4(W, i) do { \ 63 | W[(i + 0) % 4] = _mm_sha256msg1_epu32(W[(i + 0) % 4], W[(i + 1) % 4]); \ 64 | W[(i + 0) % 4] = _mm_add_epi32(W[(i + 0) % 4], \ 65 | _mm_alignr_epi8(W[(i + 3) % 4], W[(i + 2) % 4], 4)); \ 66 | W[(i + 0) % 4] = _mm_sha256msg2_epu32(W[(i + 0) % 4], W[(i + 3) % 4]); \ 67 | } while (0) 68 | 69 | /* Perform 4 rounds of SHA256 and generate more message schedule if needed. */ 70 | #define RNDMSG(S, W, i, K0, K1, K2, K3) do { \ 71 | RND4(S, W[i % 4], K0, K1, K2, K3); \ 72 | if (i < 12) \ 73 | MSG4(W, i + 4); \ 74 | } while (0) 75 | 76 | /** 77 | * SHA256_Transform_shani(state, block): 78 | * Compute the SHA256 block compression function, transforming ${state} using 79 | * the data in ${block}. This implementation uses x86 SHANI and SSSE3 80 | * instructions, and should only be used if CPUSUPPORT_X86_SHANI and _SSSE3 81 | * are defined and cpusupport_x86_shani() and _ssse3() return nonzero. 82 | */ 83 | void 84 | SHA256_Transform_shani(uint32_t state[static restrict 8], 85 | const uint8_t block[static restrict 64]) 86 | { 87 | __m128i S3210, S7654; 88 | __m128i S0123, S4567; 89 | __m128i S0145, S2367; 90 | __m128i W[4]; 91 | __m128i S[2]; 92 | 93 | /* Load state. */ 94 | S3210 = _mm_loadu_si128((const __m128i *)&state[0]); 95 | S7654 = _mm_loadu_si128((const __m128i *)&state[4]); 96 | 97 | /* Shuffle the 8 32-bit values into the order we need them. */ 98 | S0123 = _mm_shuffle_epi32(S3210, 0x1B); 99 | S4567 = _mm_shuffle_epi32(S7654, 0x1B); 100 | S0145 = _mm_unpackhi_epi64(S4567, S0123); 101 | S2367 = _mm_unpacklo_epi64(S4567, S0123); 102 | 103 | /* Load input block; this is the start of the message schedule. */ 104 | W[0] = be32dec_128(&block[0]); 105 | W[1] = be32dec_128(&block[16]); 106 | W[2] = be32dec_128(&block[32]); 107 | W[3] = be32dec_128(&block[48]); 108 | 109 | /* Initialize working variables. */ 110 | S[0] = S0145; 111 | S[1] = S2367; 112 | 113 | /* Perform 64 rounds, 4 at a time. */ 114 | RNDMSG(S, W, 0, 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5); 115 | RNDMSG(S, W, 1, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5); 116 | RNDMSG(S, W, 2, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3); 117 | RNDMSG(S, W, 3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174); 118 | RNDMSG(S, W, 4, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc); 119 | RNDMSG(S, W, 5, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da); 120 | RNDMSG(S, W, 6, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7); 121 | RNDMSG(S, W, 7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967); 122 | RNDMSG(S, W, 8, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13); 123 | RNDMSG(S, W, 9, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85); 124 | RNDMSG(S, W, 10, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3); 125 | RNDMSG(S, W, 11, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070); 126 | RNDMSG(S, W, 12, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5); 127 | RNDMSG(S, W, 13, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3); 128 | RNDMSG(S, W, 14, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208); 129 | RNDMSG(S, W, 15, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2); 130 | 131 | /* Mix local working variables into global state. */ 132 | S0145 = _mm_add_epi32(S0145, S[0]); 133 | S2367 = _mm_add_epi32(S2367, S[1]); 134 | 135 | /* Shuffle state back to the original word order and store. */ 136 | S0123 = _mm_unpackhi_epi64(S2367, S0145); 137 | S4567 = _mm_unpacklo_epi64(S2367, S0145); 138 | S3210 = _mm_shuffle_epi32(S0123, 0x1B); 139 | S7654 = _mm_shuffle_epi32(S4567, 0x1B); 140 | _mm_storeu_si128((__m128i *)&state[0], S3210); 141 | _mm_storeu_si128((__m128i *)&state[4], S7654); 142 | } 143 | #endif /* CPUSUPPORT_X86_SHANI && CPUSUPPORT_X86_SSSE3 */ 144 | -------------------------------------------------------------------------------- /libcperciva/alg/sha256_shani.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_SHANI_H_ 2 | #define SHA256_SHANI_H_ 3 | 4 | #include 5 | 6 | /** 7 | * SHA256_Transform_shani(state, block): 8 | * Compute the SHA256 block compression function, transforming ${state} using 9 | * the data in ${block}. This implementation uses x86 SHANI and SSSE3 10 | * instructions, and should only be used if CPUSUPPORT_X86_SHANI and _SSSE3 11 | * are defined and cpusupport_x86_shani() and _ssse3() return nonzero. 12 | */ 13 | #ifdef POSIXFAIL_ABSTRACT_DECLARATOR 14 | void SHA256_Transform_shani(uint32_t state[static restrict 8], 15 | const uint8_t block[static restrict 64]); 16 | #else 17 | void SHA256_Transform_shani(uint32_t[static restrict 8], 18 | const uint8_t[static restrict 64]); 19 | #endif 20 | 21 | #endif /* !SHA256_SHANI_H_ */ 22 | -------------------------------------------------------------------------------- /libcperciva/alg/sha256_sse2.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_SSE2_H_ 2 | #define SHA256_SSE2_H_ 3 | 4 | #include 5 | 6 | /** 7 | * SHA256_Transform_sse2(state, block, W, S): 8 | * Compute the SHA256 block compression function, transforming ${state} using 9 | * the data in ${block}. This implementation uses x86 SSE2 instructions, and 10 | * should only be used if _SSE2 is defined and cpusupport_x86_sse2() returns 11 | * nonzero. The arrays W and S may be filled with sensitive data, and should 12 | * be cleared by the callee. 13 | */ 14 | #ifdef POSIXFAIL_ABSTRACT_DECLARATOR 15 | void SHA256_Transform_sse2(uint32_t state[8], 16 | const uint8_t block[64], uint32_t W[64], uint32_t S[8]); 17 | #else 18 | void SHA256_Transform_sse2(uint32_t[static restrict 8], 19 | const uint8_t[static restrict 64], uint32_t W[static restrict 64], 20 | uint32_t S[static restrict 8]); 21 | #endif 22 | 23 | #endif /* !SHA256_SSE2_H_ */ 24 | -------------------------------------------------------------------------------- /libcperciva/apisupport/Build/apisupport-LIBCRYPTO-LOW_LEVEL_AES.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int 6 | main(void) 7 | { 8 | AES_KEY kexp_actual; 9 | const uint8_t key_unexpanded[16] = { 0 }; 10 | 11 | AES_set_encrypt_key(key_unexpanded, 128, &kexp_actual); 12 | 13 | /* Success! */ 14 | return (0); 15 | } 16 | -------------------------------------------------------------------------------- /libcperciva/apisupport/Build/apisupport-NONPOSIX-MEMLIMIT.c: -------------------------------------------------------------------------------- 1 | #include "platform.h" 2 | 3 | #ifdef HAVE_SYS_PARAM_H 4 | #include 5 | #endif 6 | #ifdef HAVE_SYS_SYSCTL_H 7 | #include 8 | #endif 9 | #ifdef HAVE_SYS_SYSINFO_H 10 | #include 11 | #endif 12 | 13 | int 14 | main(void) 15 | { 16 | 17 | /* Success! */ 18 | return (0); 19 | } 20 | -------------------------------------------------------------------------------- /libcperciva/apisupport/Build/apisupport.sh: -------------------------------------------------------------------------------- 1 | # Should be sourced by `command -p sh path/to/apisupport.sh "$PATH"` from 2 | # within a Makefile. 3 | if ! [ "${PATH}" = "$1" ]; then 4 | echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 5 | PATH=$1 6 | fi 7 | 8 | # Standard output should be written to apisupport-config.h, which is both a 9 | # C header file defining APISUPPORT_PLATFORM_FEATURE macros and sourceable sh 10 | # code which sets CFLAGS_PLATFORM_FEATURE environment variables. 11 | SRCDIR=$(command -p dirname "$0") 12 | 13 | CFLAGS_HARDCODED="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700" 14 | 15 | # Do we want to record stderr to a file? 16 | if [ "${DEBUG:-0}" -eq "0" ]; then 17 | outcc="/dev/null" 18 | else 19 | outcc="apisupport-stderr.log" 20 | rm -f "${outcc}" 21 | fi 22 | 23 | feature() { 24 | PLATFORM=$1 25 | FEATURE=$2 26 | EXTRALIB=$3 27 | shift 3; 28 | 29 | # Bail if we didn't include this feature in this source tree. 30 | feature_filename="${SRCDIR}/apisupport-${PLATFORM}-${FEATURE}.c" 31 | if ! [ -f "${feature_filename}" ]; then 32 | return 33 | fi 34 | 35 | # Check if we can compile this feature (and any required arguments). 36 | printf "Checking if compiler supports %s %s feature..." \ 37 | "${PLATFORM}" "${FEATURE}" 1>&2 38 | for API_CFLAGS in "$@"; do 39 | if ${CC} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_HARDCODED} \ 40 | ${API_CFLAGS} "${feature_filename}" ${LDADD_EXTRA} \ 41 | ${EXTRALIB} 2>>"${outcc}"; then 42 | rm -f a.out 43 | break; 44 | fi 45 | API_CFLAGS=NOTSUPPORTED; 46 | done 47 | case ${API_CFLAGS} in 48 | NOTSUPPORTED) 49 | echo " no" 1>&2 50 | ;; 51 | "") 52 | echo " yes" 1>&2 53 | echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1" 54 | ;; 55 | *) 56 | echo " yes, via ${API_CFLAGS}" 1>&2 57 | echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1" 58 | echo "#ifdef apisupport_dummy" 59 | echo "export CFLAGS_${PLATFORM}_${FEATURE}=\"${API_CFLAGS}\"" 60 | echo "#endif" 61 | ;; 62 | esac 63 | } 64 | 65 | if [ "$2" = "--all" ]; then 66 | feature() { 67 | PLATFORM=$1 68 | FEATURE=$2 69 | echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1" 70 | } 71 | fi 72 | 73 | # Detect how to compile non-POSIX code. 74 | feature NONPOSIX SETGROUPS "" "" \ 75 | "-U_POSIX_C_SOURCE -U_XOPEN_SOURCE" \ 76 | "-U_POSIX_C_SOURCE -U_XOPEN_SOURCE -Wno-reserved-id-macro" 77 | feature NONPOSIX MEMLIMIT "" "" \ 78 | "-U_POSIX_C_SOURCE -U_XOPEN_SOURCE" \ 79 | "-U_POSIX_C_SOURCE -U_XOPEN_SOURCE -Wno-reserved-id-macro" 80 | 81 | # Detect how to compile libssl and libcrypto code. 82 | feature LIBSSL HOST_NAME "-lssl" "" \ 83 | "-Wno-cast-qual" 84 | feature LIBCRYPTO LOW_LEVEL_AES "-lcrypto" "" \ 85 | "-Wno-deprecated-declarations" 86 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-ARM-AES.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __ARM_NEON 4 | #include 5 | #endif 6 | 7 | int 8 | main(void) 9 | { 10 | uint8x16_t data; 11 | uint8x16_t key = {0}; 12 | uint8x16_t output; 13 | uint32x4_t lanes = {0}; 14 | uint8_t arr[16] = {0}; 15 | 16 | /* Check AES. */ 17 | data = vld1q_u8(arr); 18 | output = vaeseq_u8(data, key); 19 | (void)output; /* UNUSED */ 20 | 21 | /* Check _u32: some compilers only support the _u8 variant. */ 22 | lanes = vdupq_laneq_u32(lanes, 0); 23 | 24 | /* Success! */ 25 | return (0); 26 | } 27 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c: -------------------------------------------------------------------------------- 1 | #ifdef __ARM_NEON 2 | #include 3 | #endif 4 | 5 | int 6 | main(void) 7 | { 8 | uint32x4_t w0 = {0}; 9 | uint32x4_t w4 = {0}; 10 | uint32x4_t output; 11 | 12 | output = vsha256su0q_u32(w0, w4); 13 | (void)output; /* UNUSED */ 14 | 15 | /* Success! */ 16 | return (0); 17 | } 18 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | int res; 7 | unsigned long val; 8 | 9 | res = elf_aux_info(AT_HWCAP, &val, sizeof(unsigned long)); 10 | (void)res; 11 | 12 | return (val != 0); 13 | } 14 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | unsigned long val; 7 | 8 | val = getauxval(AT_HWCAP); 9 | 10 | return (val != 0); 11 | } 12 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | /* 6 | * Use a separate function for this, because that means that the alignment of 7 | * the _mm_loadu_si128() will move to function level, which may require 8 | * -Wno-cast-align. 9 | */ 10 | static __m128i 11 | load_128(const uint8_t * src) 12 | { 13 | __m128i x; 14 | 15 | x = _mm_loadu_si128((const __m128i *)src); 16 | return (x); 17 | } 18 | 19 | int 20 | main(void) 21 | { 22 | __m128i x, y; 23 | uint8_t a[16] = {0}; 24 | 25 | x = load_128(a); 26 | #ifdef BROKEN_MM_LOADU_SI64 27 | y = _mm_loadu_si128((const __m128i *)a); 28 | #else 29 | y = _mm_loadu_si64(a); 30 | #endif 31 | y = _mm_aesenc_si128(x, y); 32 | _mm_storeu_si128((__m128i *)&a[0], y); 33 | return (a[0]); 34 | } 35 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | unsigned int a, b, c, d; 7 | 8 | return (__get_cpuid(0, &a, &b, &c, &d)); 9 | } 10 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | unsigned int a, b, c, d; 7 | 8 | __cpuid_count(7, 0, a, b, c, d); 9 | return ((int)a); 10 | } 11 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | unsigned int x; 7 | 8 | return (!_rdrand32_step(&x)); 9 | } 10 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * Use a separate function for this, because that means that the alignment of 6 | * the _mm_loadu_si128() will move to function level, which may require 7 | * -Wno-cast-align. 8 | */ 9 | static __m128i 10 | load_128(const uint8_t * src) 11 | { 12 | __m128i x; 13 | 14 | x = _mm_loadu_si128((const __m128i *)src); 15 | return (x); 16 | } 17 | 18 | int 19 | main(void) 20 | { 21 | __m128i x; 22 | uint8_t a[16] = {0}; 23 | 24 | x = load_128(a); 25 | x = _mm_sha256msg1_epu32(x, x); 26 | _mm_storeu_si128((__m128i *)a, x); 27 | return (a[0]); 28 | } 29 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char a[16]; 4 | 5 | /* 6 | * Use a separate function for this, because that means that the alignment of 7 | * the _mm_loadu_si128() will move to function level, which may require 8 | * -Wno-cast-align. 9 | */ 10 | static __m128i 11 | load_128(const char * src) 12 | { 13 | __m128i x; 14 | 15 | x = _mm_loadu_si128((const __m128i *)src); 16 | return (x); 17 | } 18 | 19 | int 20 | main(void) 21 | { 22 | __m128i x; 23 | 24 | x = load_128(a); 25 | _mm_storeu_si128((__m128i *)a, x); 26 | return (a[0]); 27 | } 28 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static char a[16]; 5 | 6 | /* 7 | * Use a separate function for this, because that means that the alignment of 8 | * the _mm_loadu_si128() will move to function level, which may require 9 | * -Wno-cast-align. 10 | */ 11 | static __m128i 12 | load_128(const char * src) 13 | { 14 | __m128i x; 15 | 16 | x = _mm_loadu_si128((const __m128i *)src); 17 | return (x); 18 | } 19 | 20 | int 21 | main(void) 22 | { 23 | __m128i x; 24 | 25 | x = load_128(a); 26 | x = _mm_alignr_epi8(x, x, 8); 27 | _mm_storeu_si128((__m128i *)a, x); 28 | return (a[0]); 29 | } 30 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/Build/cpusupport.sh: -------------------------------------------------------------------------------- 1 | # Should be sourced by `command -p sh path/to/cpusupport.sh "$PATH"` from 2 | # within a Makefile. 3 | if ! [ "${PATH}" = "$1" ]; then 4 | echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 5 | PATH=$1 6 | fi 7 | 8 | # Standard output should be written to cpusupport-config.h, which is both a 9 | # C header file defining CPUSUPPORT_ARCH_FEATURE macros and sourceable sh 10 | # code which sets CFLAGS_ARCH_FEATURE environment variables. 11 | SRCDIR=$(command -p dirname "$0") 12 | 13 | CFLAGS_HARDCODED="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700" 14 | 15 | # Do we want to record stderr to a file? 16 | if [ "${DEBUG:-0}" -eq "0" ]; then 17 | outcc="/dev/null" 18 | else 19 | outcc="cpusupport-stderr.log" 20 | rm -f "${outcc}" 21 | fi 22 | 23 | feature() { 24 | ARCH=$1 25 | FEATURE=$2 26 | shift 2; 27 | 28 | # Bail if we didn't include this feature in this source tree. 29 | feature_filename="${SRCDIR}/cpusupport-${ARCH}-${FEATURE}.c" 30 | if ! [ -f "${feature_filename}" ]; then 31 | return 32 | fi 33 | 34 | # Check if we can compile this feature (and any required arguments). 35 | printf "Checking if compiler supports %s %s feature..." \ 36 | "${ARCH}" "${FEATURE}" 1>&2 37 | for CPU_CFLAGS in "$@"; do 38 | if ${CC} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_HARDCODED} \ 39 | ${CPU_CFLAGS} "${feature_filename}" 2>>"${outcc}"; then 40 | rm -f a.out 41 | break; 42 | fi 43 | CPU_CFLAGS=NOTSUPPORTED; 44 | done 45 | case ${CPU_CFLAGS} in 46 | NOTSUPPORTED) 47 | echo " no" 1>&2 48 | ;; 49 | "") 50 | echo " yes" 1>&2 51 | echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" 52 | ;; 53 | *) 54 | echo " yes, via ${CPU_CFLAGS}" 1>&2 55 | echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" 56 | echo "#ifdef cpusupport_dummy" 57 | echo "export CFLAGS_${ARCH}_${FEATURE}=\"${CPU_CFLAGS}\"" 58 | echo "#endif" 59 | ;; 60 | esac 61 | } 62 | 63 | if [ "$2" = "--all" ]; then 64 | feature() { 65 | ARCH=$1 66 | FEATURE=$2 67 | echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" 68 | } 69 | fi 70 | 71 | # Detect CPU-detection features 72 | feature HWCAP ELF_AUX_INFO "" 73 | feature HWCAP GETAUXVAL "" 74 | feature X86 CPUID "" 75 | feature X86 CPUID_COUNT "" 76 | 77 | # Detect specific features 78 | feature X86 AESNI "" "-maes" \ 79 | "-maes -Wno-cast-align" \ 80 | "-maes -Wno-missing-prototypes -Wno-cast-qual" \ 81 | "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align" \ 82 | "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align \ 83 | -DBROKEN_MM_LOADU_SI64" 84 | feature X86 RDRAND "" "-mrdrnd" 85 | feature X86 SHANI "" "-msse2 -msha" \ 86 | "-msse2 -msha -Wno-cast-align" 87 | feature X86 SSE2 "" \ 88 | "-Wno-cast-align" \ 89 | "-msse2" \ 90 | "-msse2 -Wno-cast-align" 91 | feature X86 SSE42 "" "-msse4.2" \ 92 | "-msse4.2 -Wno-cast-align" \ 93 | "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ 94 | "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" 95 | feature X86 SSE42_64 "" "-msse4.2" \ 96 | "-msse4.2 -Wno-cast-align" \ 97 | "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ 98 | "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" 99 | feature X86 SSSE3 "" "-mssse3" \ 100 | "-mssse3 -Wno-cast-align" 101 | 102 | # Detect specific ARM features 103 | feature ARM AES "-march=armv8.1-a+crypto" \ 104 | "-march=armv8.1-a+crypto -D__ARM_ACLE=200" 105 | feature ARM CRC32_64 "-march=armv8.1-a" \ 106 | "-march=armv8.1-a+crc" \ 107 | "-march=armv8.1-a+crc -Wno-cast-align" \ 108 | "-march=armv8.1-a -D__ARM_ACLE=200" 109 | feature ARM SHA256 "-march=armv8.1-a+crypto" \ 110 | "-march=armv8.1-a+crypto -Wno-cast-align" \ 111 | "-march=armv8.1-a+crypto -D__ARM_ACLE=200" 112 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUSUPPORT_H_ 2 | #define CPUSUPPORT_H_ 3 | 4 | /* 5 | * To enable support for non-portable CPU features at compile time, one or 6 | * more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done 7 | * directly on the compiler command line via -D CPUSUPPORT_ARCH_FEATURE or 8 | * -D CPUSUPPORT_ARCH_FEATURE=1; or a file can be created with the 9 | * necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h 10 | * (or similar) can be provided to include that file here. 11 | */ 12 | #ifdef CPUSUPPORT_CONFIG_FILE 13 | #include CPUSUPPORT_CONFIG_FILE 14 | #endif 15 | 16 | /** 17 | * The CPUSUPPORT_FEATURE macro declares the necessary variables and 18 | * functions for detecting CPU feature support at run time. The function 19 | * defined in the macro acts to cache the result of the ..._detect function 20 | * using the ..._present and ..._init variables. The _detect function and the 21 | * _present and _init variables are turn defined by CPUSUPPORT_FEATURE_DECL in 22 | * appropriate cpusupport_foo_bar.c file. 23 | * 24 | * In order to allow CPUSUPPORT_FEATURE to be used for features which do not 25 | * have corresponding CPUSUPPORT_FEATURE_DECL blocks in another source file, 26 | * we abuse the C preprocessor: If CPUSUPPORT_${enabler} is defined to 1, then 27 | * we access _present_1, _init_1, and _detect_1; but if it is not defined, we 28 | * access _present_CPUSUPPORT_${enabler} etc., which we define as static, thus 29 | * preventing the compiler from emitting a reference to an external symbol. 30 | * 31 | * In this way, it becomes possible to issue CPUSUPPORT_FEATURE invocations 32 | * for nonexistent features without running afoul of the requirement that 33 | * "If an identifier declared with external linkage is used... in the entire 34 | * program there shall be exactly one external definition" (C99 standard, 6.9 35 | * paragraph 5). In practice, this means that users of the cpusupport code 36 | * can omit build and runtime detection files without changing the framework 37 | * code. 38 | */ 39 | #define CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) \ 40 | static int cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \ 41 | static int cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \ 42 | static inline int cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler(void) { return (0); } \ 43 | extern int cpusupport_ ## arch_feature ## _present_ ## enabled; \ 44 | extern int cpusupport_ ## arch_feature ## _init_ ## enabled; \ 45 | int cpusupport_ ## arch_feature ## _detect_ ## enabled(void); \ 46 | \ 47 | static inline int \ 48 | cpusupport_ ## arch_feature(void) \ 49 | { \ 50 | \ 51 | if (cpusupport_ ## arch_feature ## _present_ ## enabled) \ 52 | return (1); \ 53 | else if (cpusupport_ ## arch_feature ## _init_ ## enabled) \ 54 | return (0); \ 55 | cpusupport_ ## arch_feature ## _present_ ## enabled = \ 56 | cpusupport_ ## arch_feature ## _detect_ ## enabled(); \ 57 | cpusupport_ ## arch_feature ## _init_ ## enabled = 1; \ 58 | return (cpusupport_ ## arch_feature ## _present_ ## enabled); \ 59 | } \ 60 | static void (* cpusupport_ ## arch_feature ## _dummyptr)(void); \ 61 | static inline void \ 62 | cpusupport_ ## arch_feature ## _dummyfunc(void) \ 63 | { \ 64 | \ 65 | (void)cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \ 66 | (void)cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \ 67 | (void)cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler; \ 68 | (void)cpusupport_ ## arch_feature ## _present_ ## enabled; \ 69 | (void)cpusupport_ ## arch_feature ## _init_ ## enabled; \ 70 | (void)cpusupport_ ## arch_feature ## _detect_ ## enabled; \ 71 | (void)cpusupport_ ## arch_feature ## _dummyptr; \ 72 | } \ 73 | static void (* cpusupport_ ## arch_feature ## _dummyptr)(void) = cpusupport_ ## arch_feature ## _dummyfunc; \ 74 | struct cpusupport_ ## arch_feature ## _dummy 75 | #define CPUSUPPORT_FEATURE_(arch_feature, enabler, enabled) \ 76 | CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) 77 | #define CPUSUPPORT_FEATURE(arch, feature, enabler) \ 78 | CPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler) 79 | 80 | /** 81 | * CPUSUPPORT_FEATURE_DECL(arch, feature): 82 | * Macro which defines variables and provides a function declaration for 83 | * detecting the presence of "feature" on the "arch" architecture. The 84 | * function body following this macro expansion must return nonzero if the 85 | * feature is present, or zero if the feature is not present or the detection 86 | * fails for any reason. 87 | */ 88 | #define CPUSUPPORT_FEATURE_DECL(arch, feature) \ 89 | extern int cpusupport_ ## arch ## _ ## feature ## _present_1; \ 90 | extern int cpusupport_ ## arch ## _ ## feature ## _init_1; \ 91 | int cpusupport_ ## arch ## _ ## feature ## _present_1 = 0; \ 92 | int cpusupport_ ## arch ## _ ## feature ## _init_1 = 0; \ 93 | int cpusupport_ ## arch ## _ ## feature ## _detect_1(void); \ 94 | int \ 95 | cpusupport_ ## arch ## _ ## feature ## _detect_1(void) 96 | 97 | /** 98 | * CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, check): 99 | * Check if we can enable ${success_value}, given the ${cpusupport_checks} and 100 | * ${check}; if so, write to ${hwvar}. If the ${cpusupport_checks} pass but 101 | * the ${check} is non-zero, produce a warning which includes a stringified 102 | * ${success_value}, then fallthrough. 103 | */ 104 | #define CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, \ 105 | check) do { \ 106 | if ((cpusupport_checks)) { \ 107 | if ((check) == 0) { \ 108 | (hwvar) = (success_value); \ 109 | return; \ 110 | } else { \ 111 | warn0("Disabling " #success_value \ 112 | " due to failed self-test"); \ 113 | } \ 114 | } \ 115 | } while (0) 116 | 117 | /** 118 | * List of features. If a feature here is not enabled by the appropriate 119 | * CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the 120 | * relevant macro may be defined (e.g., by Build/cpusupport.sh successfully 121 | * compiling Build/cpusupport-ARCH-FEATURE.c) then the C file containing the 122 | * corresponding run-time detection code (cpusupport_arch_feature.c) must be 123 | * compiled and linked in. 124 | * 125 | * There are a few features for which we do not have run-time checks: 126 | * - X86_CPUID: compile-time is enough; if __get_cpuid() fails, then all the 127 | * x86 detection features will fail, but there's nothing we can 128 | * do about that. 129 | * - X86_CPUID_COUNT: ditto. 130 | * - X86_SSE42_64: the cpuid check tells us if the CPU supports SSE4.2, but 131 | * that says nothing about whether it's in 64-bit mode. 132 | */ 133 | CPUSUPPORT_FEATURE(x86, aesni, X86_AESNI); 134 | CPUSUPPORT_FEATURE(x86, rdrand, X86_RDRAND); 135 | CPUSUPPORT_FEATURE(x86, shani, X86_SHANI); 136 | CPUSUPPORT_FEATURE(x86, sse2, X86_SSE2); 137 | CPUSUPPORT_FEATURE(x86, sse42, X86_SSE42); 138 | CPUSUPPORT_FEATURE(x86, ssse3, X86_SSSE3); 139 | CPUSUPPORT_FEATURE(arm, aes, ARM_AES); 140 | CPUSUPPORT_FEATURE(arm, crc32_64, ARM_CRC32_64); 141 | CPUSUPPORT_FEATURE(arm, sha256, ARM_SHA256); 142 | 143 | #endif /* !CPUSUPPORT_H_ */ 144 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_arm_aes.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_HWCAP_GETAUXVAL 4 | #include 5 | 6 | #if defined(__arm__) 7 | /** 8 | * Workaround for a glibc bug: contains a comment saying: 9 | * The following must match the kernel's . 10 | * However, it does not contain any of the HWCAP2_* entries from . 11 | */ 12 | #ifndef HWCAP2_AES 13 | #include 14 | #endif 15 | #endif /* __arm__ */ 16 | #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ 17 | 18 | #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) 19 | #include 20 | #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ 21 | 22 | CPUSUPPORT_FEATURE_DECL(arm, aes) 23 | { 24 | int supported = 0; 25 | 26 | #if defined(CPUSUPPORT_ARM_AES) 27 | #if defined(CPUSUPPORT_HWCAP_GETAUXVAL) 28 | unsigned long capabilities; 29 | 30 | #if defined(__aarch64__) 31 | capabilities = getauxval(AT_HWCAP); 32 | supported = (capabilities & HWCAP_AES) ? 1 : 0; 33 | #elif defined(__arm__) 34 | capabilities = getauxval(AT_HWCAP2); 35 | supported = (capabilities & HWCAP2_AES) ? 1 : 0; 36 | #endif 37 | #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ 38 | 39 | #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) 40 | unsigned long capabilities; 41 | 42 | #if defined(__aarch64__) 43 | if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) 44 | return (0); 45 | supported = (capabilities & HWCAP_AES) ? 1 : 0; 46 | #else 47 | if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) 48 | return (0); 49 | supported = (capabilities & HWCAP2_AES) ? 1 : 0; 50 | #endif 51 | #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ 52 | #endif /* CPUSUPPORT_ARM_AES */ 53 | 54 | /* Return the supported status. */ 55 | return (supported); 56 | } 57 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_arm_sha256.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_HWCAP_GETAUXVAL 4 | #include 5 | 6 | #if defined(__arm__) 7 | /** 8 | * Workaround for a glibc bug: contains a comment saying: 9 | * The following must match the kernel's . 10 | * However, it does not contain any of the HWCAP2_* entries from . 11 | */ 12 | #ifndef HWCAP2_CRC32 13 | #include 14 | #endif 15 | #endif /* __arm__ */ 16 | #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ 17 | 18 | #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) 19 | #include 20 | #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ 21 | 22 | CPUSUPPORT_FEATURE_DECL(arm, sha256) 23 | { 24 | int supported = 0; 25 | 26 | #if defined(CPUSUPPORT_ARM_SHA256) 27 | #if defined(CPUSUPPORT_HWCAP_GETAUXVAL) 28 | unsigned long capabilities; 29 | 30 | #if defined(__aarch64__) 31 | capabilities = getauxval(AT_HWCAP); 32 | supported = (capabilities & HWCAP_SHA2) ? 1 : 0; 33 | #elif defined(__arm__) 34 | capabilities = getauxval(AT_HWCAP2); 35 | supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; 36 | #endif 37 | #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ 38 | 39 | #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) 40 | unsigned long capabilities; 41 | 42 | #if defined(__aarch64__) 43 | if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) 44 | return (0); 45 | supported = (capabilities & HWCAP_SHA2) ? 1 : 0; 46 | #else 47 | if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) 48 | return (0); 49 | supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; 50 | #endif 51 | #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ 52 | #endif /* CPUSUPPORT_ARM_SHA256 */ 53 | 54 | /* Return the supported status. */ 55 | return (supported); 56 | } 57 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_x86_aesni.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_X86_CPUID 4 | #include 5 | 6 | #define CPUID_AESNI_BIT (1 << 25) 7 | #endif 8 | 9 | CPUSUPPORT_FEATURE_DECL(x86, aesni) 10 | { 11 | #ifdef CPUSUPPORT_X86_CPUID 12 | unsigned int eax, ebx, ecx, edx; 13 | 14 | /* Check if CPUID supports the level we need. */ 15 | if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) 16 | goto unsupported; 17 | if (eax < 1) 18 | goto unsupported; 19 | 20 | /* Ask about CPU features. */ 21 | if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 22 | goto unsupported; 23 | 24 | /* Return the relevant feature bit. */ 25 | return ((ecx & CPUID_AESNI_BIT) ? 1 : 0); 26 | 27 | unsupported: 28 | #endif 29 | 30 | /* Not supported. */ 31 | return (0); 32 | } 33 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_x86_rdrand.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_X86_CPUID 4 | #include 5 | 6 | #define CPUID_RDRAND_BIT (1 << 30) 7 | #endif 8 | 9 | CPUSUPPORT_FEATURE_DECL(x86, rdrand) 10 | { 11 | #ifdef CPUSUPPORT_X86_CPUID 12 | unsigned int eax, ebx, ecx, edx; 13 | 14 | /* Check if CPUID supports the level we need. */ 15 | if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) 16 | goto unsupported; 17 | if (eax < 1) 18 | goto unsupported; 19 | 20 | /* Ask about CPU features. */ 21 | if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 22 | goto unsupported; 23 | 24 | /* Return the relevant feature bit. */ 25 | return ((ecx & CPUID_RDRAND_BIT) ? 1 : 0); 26 | 27 | unsupported: 28 | #endif 29 | 30 | /* Not supported. */ 31 | return (0); 32 | } 33 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_x86_shani.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_X86_CPUID_COUNT 4 | #include 5 | 6 | #define CPUID_SHANI_BIT (1 << 29) 7 | #endif 8 | 9 | CPUSUPPORT_FEATURE_DECL(x86, shani) 10 | { 11 | #ifdef CPUSUPPORT_X86_CPUID_COUNT 12 | unsigned int eax, ebx, ecx, edx; 13 | 14 | /* Check if CPUID supports the level we need. */ 15 | if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) 16 | goto unsupported; 17 | if (eax < 7) 18 | goto unsupported; 19 | 20 | /* 21 | * Ask about extended CPU features. Note that this macro violates 22 | * the principle of being "function-like" by taking the variables 23 | * used for holding output registers as named parameters rather than 24 | * as pointers (which would be necessary if __cpuid_count were a 25 | * function). 26 | */ 27 | __cpuid_count(7, 0, eax, ebx, ecx, edx); 28 | 29 | /* Return the relevant feature bit. */ 30 | return ((ebx & CPUID_SHANI_BIT) ? 1 : 0); 31 | 32 | unsupported: 33 | #endif 34 | 35 | /* Not supported. */ 36 | return (0); 37 | } 38 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_x86_sse2.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_X86_CPUID 4 | #include 5 | 6 | #define CPUID_SSE2_BIT (1 << 26) 7 | #endif 8 | 9 | CPUSUPPORT_FEATURE_DECL(x86, sse2) 10 | { 11 | #ifdef CPUSUPPORT_X86_CPUID 12 | unsigned int eax, ebx, ecx, edx; 13 | 14 | /* Check if CPUID supports the level we need. */ 15 | if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) 16 | goto unsupported; 17 | if (eax < 1) 18 | goto unsupported; 19 | 20 | /* Ask about CPU features. */ 21 | if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 22 | goto unsupported; 23 | 24 | /* Return the relevant feature bit. */ 25 | return ((edx & CPUID_SSE2_BIT) ? 1 : 0); 26 | 27 | unsupported: 28 | #endif 29 | 30 | /* Not supported. */ 31 | return (0); 32 | } 33 | -------------------------------------------------------------------------------- /libcperciva/cpusupport/cpusupport_x86_ssse3.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | 3 | #ifdef CPUSUPPORT_X86_CPUID 4 | #include 5 | 6 | #define CPUID_SSSE3_BIT (1 << 9) 7 | #endif 8 | 9 | CPUSUPPORT_FEATURE_DECL(x86, ssse3) 10 | { 11 | #ifdef CPUSUPPORT_X86_CPUID 12 | unsigned int eax, ebx, ecx, edx; 13 | 14 | /* Check if CPUID supports the level we need. */ 15 | if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) 16 | goto unsupported; 17 | if (eax < 1) 18 | goto unsupported; 19 | 20 | /* Ask about CPU features. */ 21 | if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 22 | goto unsupported; 23 | 24 | /* Return the relevant feature bit. */ 25 | return ((ecx & CPUID_SSSE3_BIT) ? 1 : 0); 26 | 27 | unsupported: 28 | #endif 29 | 30 | /* Not supported. */ 31 | return (0); 32 | } 33 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aes.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AES_H_ 2 | #define CRYPTO_AES_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Opaque structure. */ 8 | struct crypto_aes_key; 9 | 10 | /** 11 | * crypto_aes_can_use_intrinsics(void): 12 | * Test whether hardware intrinsics are safe to use. Return 1 if x86 AESNI 13 | * operations are available, 2 if ARM-AES operations are available, or 0 if 14 | * none are available. 15 | */ 16 | int crypto_aes_can_use_intrinsics(void); 17 | 18 | /** 19 | * crypto_aes_key_expand(key_unexpanded, len): 20 | * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a 21 | * structure which can be passed to crypto_aes_encrypt_block(). The length 22 | * must be 16 or 32. 23 | */ 24 | struct crypto_aes_key * crypto_aes_key_expand(const uint8_t *, size_t); 25 | 26 | /** 27 | * crypto_aes_encrypt_block(in, out, key): 28 | * Using the expanded AES key ${key}, encrypt the block ${in} and write the 29 | * resulting ciphertext to ${out}. ${in} and ${out} can overlap. 30 | */ 31 | void crypto_aes_encrypt_block(const uint8_t[16], uint8_t[16], 32 | const struct crypto_aes_key *); 33 | 34 | /** 35 | * crypto_aes_key_free(key): 36 | * Free the expanded AES key ${key}. 37 | */ 38 | void crypto_aes_key_free(struct crypto_aes_key *); 39 | 40 | #endif /* !CRYPTO_AES_H_ */ 41 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aes_aesni.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AES_AESNI_H_ 2 | #define CRYPTO_AES_AESNI_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * crypto_aes_key_expand_aesni(key_unexpanded, len): 9 | * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a 10 | * structure which can be passed to crypto_aes_encrypt_block_aesni(). The 11 | * length must be 16 or 32. This implementation uses x86 AESNI instructions, 12 | * and should only be used if CPUSUPPORT_X86_AESNI is defined and 13 | * cpusupport_x86_aesni() returns nonzero. 14 | */ 15 | void * crypto_aes_key_expand_aesni(const uint8_t *, size_t); 16 | 17 | /** 18 | * crypto_aes_encrypt_block_aesni(in, out, key): 19 | * Using the expanded AES key ${key}, encrypt the block ${in} and write the 20 | * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This 21 | * implementation uses x86 AESNI instructions, and should only be used if 22 | * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero. 23 | */ 24 | void crypto_aes_encrypt_block_aesni(const uint8_t[16], uint8_t[16], 25 | const void *); 26 | 27 | /** 28 | * crypto_aes_key_free_aesni(key): 29 | * Free the expanded AES key ${key}. 30 | */ 31 | void crypto_aes_key_free_aesni(void *); 32 | 33 | #endif /* !CRYPTO_AES_AESNI_H_ */ 34 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aes_aesni_m128i.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AES_AESNI_M128I_H_ 2 | #define CRYPTO_AES_AESNI_M128I_H_ 3 | 4 | #include 5 | 6 | /** 7 | * crypto_aes_encrypt_block_aesni_m128i(in, key): 8 | * Using the expanded AES key ${key}, encrypt the block ${in} and return the 9 | * resulting ciphertext. This implementation uses x86 AESNI instructions, 10 | * and should only be used if CPUSUPPORT_X86_AESNI is defined and 11 | * cpusupport_x86_aesni() returns nonzero. 12 | */ 13 | __m128i crypto_aes_encrypt_block_aesni_m128i(__m128i, const void *); 14 | 15 | #endif /* !CRYPTO_AES_AESNI_M128I_H_ */ 16 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aes_arm.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AES_ARM_H_ 2 | #define CRYPTO_AES_ARM_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * crypto_aes_key_expand_arm(key_unexpanded, len): 9 | * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a 10 | * structure which can be passed to crypto_aes_encrypt_block_arm(). The 11 | * length must be 16 or 32. This implementation uses ARM AES instructions, 12 | * and should only be used if CPUSUPPORT_ARM_AES is defined and 13 | * cpusupport_arm_aes() returns nonzero. 14 | */ 15 | void * crypto_aes_key_expand_arm(const uint8_t *, size_t); 16 | 17 | /** 18 | * crypto_aes_encrypt_block_arm(in, out, key): 19 | * Using the expanded AES key ${key}, encrypt the block ${in} and write the 20 | * resulting ciphertext to ${out}. ${in} and ${out} can overlap. This 21 | * implementation uses ARM AES instructions, and should only be used if 22 | * CPUSUPPORT_ARM_AES is defined and cpusupport_arm_aes() returns nonzero. 23 | */ 24 | void crypto_aes_encrypt_block_arm(const uint8_t[16], uint8_t[16], 25 | const void *); 26 | 27 | /** 28 | * crypto_aes_key_free_arm(key): 29 | * Free the expanded AES key ${key}. 30 | */ 31 | void crypto_aes_key_free_arm(void *); 32 | 33 | #endif /* !CRYPTO_AES_ARM_H_ */ 34 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aes_arm_u8.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AES_ARM_U8_H_ 2 | #define CRYPTO_AES_ARM_U8_H_ 3 | 4 | #ifdef __ARM_NEON 5 | #include 6 | #endif 7 | 8 | /** 9 | * crypto_aes_encrypt_block_arm_u8(in, key): 10 | * Using the expanded AES key ${key}, encrypt the block ${in} and return the 11 | * resulting ciphertext. This implementation uses ARM AES instructions, 12 | * and should only be used if CPUSUPPORT_ARM_AES is defined and 13 | * cpusupport_arm_aes() returns nonzero. 14 | */ 15 | uint8x16_t crypto_aes_encrypt_block_arm_u8(uint8x16_t, const void *); 16 | 17 | #endif /* !CRYPTO_AES_ARM_U8_H_ */ 18 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "cpusupport.h" 6 | #include "crypto_aes.h" 7 | #include "crypto_aesctr_aesni.h" 8 | #include "crypto_aesctr_arm.h" 9 | #include "insecure_memzero.h" 10 | #include "sysendian.h" 11 | 12 | #include "crypto_aesctr.h" 13 | 14 | /** 15 | * In order to optimize AES-CTR, it is desirable to separate out the handling 16 | * of individual bytes of data vs. the handling of complete (16 byte) blocks. 17 | * The handling of blocks in turn can be optimized further using CPU 18 | * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code 19 | * remains the same across platforms it should be inlined into the same (CPU 20 | * feature specific) routines for performance reasons. 21 | * 22 | * In order to allow those generic functions to be inlined into multiple 23 | * functions in separate translation units, we place them into a "shared" C 24 | * file which is included in each of the platform-specific variants. 25 | */ 26 | #include "crypto_aesctr_shared.c" 27 | 28 | #if defined(CPUSUPPORT_X86_AESNI) || defined(CPUSUPPORT_ARM_AES) 29 | #define HWACCEL 30 | 31 | static enum { 32 | HW_SOFTWARE = 0, 33 | #if defined(CPUSUPPORT_X86_AESNI) 34 | HW_X86_AESNI, 35 | #endif 36 | #if defined(CPUSUPPORT_ARM_AES) 37 | HW_ARM_AES, 38 | #endif 39 | HW_UNSET 40 | } hwaccel = HW_UNSET; 41 | #endif 42 | 43 | #ifdef HWACCEL 44 | /* Which type of hardware acceleration should we use, if any? */ 45 | static void 46 | hwaccel_init(void) 47 | { 48 | 49 | /* If we've already set hwaccel, we're finished. */ 50 | if (hwaccel != HW_UNSET) 51 | return; 52 | 53 | /* Default to software. */ 54 | hwaccel = HW_SOFTWARE; 55 | 56 | /* Can we use AESNI? */ 57 | switch (crypto_aes_can_use_intrinsics()) { 58 | #ifdef CPUSUPPORT_X86_AESNI 59 | case 1: 60 | hwaccel = HW_X86_AESNI; 61 | break; 62 | #endif 63 | #ifdef CPUSUPPORT_ARM_AES 64 | case 2: 65 | hwaccel = HW_ARM_AES; 66 | break; 67 | #endif 68 | case 0: 69 | break; 70 | default: 71 | /* Should never happen. */ 72 | assert(0); 73 | } 74 | } 75 | #endif /* HWACCEL */ 76 | 77 | /** 78 | * crypto_aesctr_alloc(void): 79 | * Allocate an object for performing AES in CTR code. This must be followed 80 | * by calling _init2(). 81 | */ 82 | struct crypto_aesctr * 83 | crypto_aesctr_alloc(void) 84 | { 85 | struct crypto_aesctr * stream; 86 | 87 | /* Allocate memory. */ 88 | if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) 89 | goto err0; 90 | 91 | /* Success! */ 92 | return (stream); 93 | 94 | err0: 95 | /* Failure! */ 96 | return (NULL); 97 | } 98 | 99 | /** 100 | * crypto_aesctr_init2(stream, key, nonce): 101 | * Reset the AES-CTR stream ${stream}, using the ${key} and ${nonce}. If ${key} 102 | * is NULL, retain the previous AES key. 103 | */ 104 | void 105 | crypto_aesctr_init2(struct crypto_aesctr * stream, 106 | const struct crypto_aes_key * key, uint64_t nonce) 107 | { 108 | 109 | /* If the key is NULL, retain the previous AES key. */ 110 | if (key != NULL) 111 | stream->key = key; 112 | 113 | /* Set nonce as provided and reset bytectr. */ 114 | be64enc(stream->pblk, nonce); 115 | stream->bytectr = 0; 116 | 117 | /* 118 | * Set the counter such that the least significant byte will wrap once 119 | * incremented. 120 | */ 121 | stream->pblk[15] = 0xff; 122 | 123 | #ifdef HWACCEL 124 | hwaccel_init(); 125 | #endif 126 | 127 | /* Sanity check. */ 128 | assert(stream->key != NULL); 129 | } 130 | 131 | /** 132 | * crypto_aesctr_init(key, nonce): 133 | * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided 134 | * expanded ${key} and ${nonce}. The key provided must remain valid for the 135 | * lifetime of the stream. This is the same as calling _alloc() followed by 136 | * _init2(). 137 | */ 138 | struct crypto_aesctr * 139 | crypto_aesctr_init(const struct crypto_aes_key * key, uint64_t nonce) 140 | { 141 | struct crypto_aesctr * stream; 142 | 143 | /* Sanity check. */ 144 | assert(key != NULL); 145 | 146 | /* Allocate memory. */ 147 | if ((stream = crypto_aesctr_alloc()) == NULL) 148 | goto err0; 149 | 150 | /* Initialize values. */ 151 | crypto_aesctr_init2(stream, key, nonce); 152 | 153 | /* Success! */ 154 | return (stream); 155 | 156 | err0: 157 | /* Failure! */ 158 | return (NULL); 159 | } 160 | 161 | /** 162 | * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): 163 | * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor 164 | * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the 165 | * buffers ${inbuf} and ${outbuf} overlap, they must be identical. 166 | */ 167 | void 168 | crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, 169 | uint8_t * outbuf, size_t buflen) 170 | { 171 | 172 | #if defined(HWACCEL) 173 | #if defined(CPUSUPPORT_X86_AESNI) 174 | if ((buflen >= 16) && (hwaccel == HW_X86_AESNI)) { 175 | crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen); 176 | return; 177 | } 178 | #endif 179 | #if defined(CPUSUPPORT_ARM_AES) 180 | if ((buflen >= 16) && (hwaccel == HW_ARM_AES)) { 181 | crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen); 182 | return; 183 | } 184 | #endif 185 | #endif /* HWACCEL */ 186 | 187 | /* Process any bytes before we can process a whole block. */ 188 | if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, 189 | &buflen)) 190 | return; 191 | 192 | /* Process whole blocks of 16 bytes. */ 193 | while (buflen >= 16) { 194 | /* Generate a block of cipherstream. */ 195 | crypto_aesctr_stream_cipherblock_generate(stream); 196 | 197 | /* Encrypt the bytes and update the positions. */ 198 | crypto_aesctr_stream_cipherblock_use(stream, &inbuf, &outbuf, 199 | &buflen, 16, 0); 200 | } 201 | 202 | /* Process any final bytes after finishing all whole blocks. */ 203 | crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); 204 | } 205 | 206 | /** 207 | * crypto_aesctr_free(stream): 208 | * Free the AES-CTR stream ${stream}. 209 | */ 210 | void 211 | crypto_aesctr_free(struct crypto_aesctr * stream) 212 | { 213 | 214 | /* Behave consistently with free(NULL). */ 215 | if (stream == NULL) 216 | return; 217 | 218 | /* Zero potentially sensitive information. */ 219 | insecure_memzero(stream, sizeof(struct crypto_aesctr)); 220 | 221 | /* Free the stream. */ 222 | free(stream); 223 | } 224 | 225 | /** 226 | * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): 227 | * Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free(). 228 | */ 229 | void 230 | crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce, 231 | const uint8_t * inbuf, uint8_t * outbuf, size_t buflen) 232 | { 233 | struct crypto_aesctr stream_rec; 234 | struct crypto_aesctr * stream = &stream_rec; 235 | 236 | /* Sanity check. */ 237 | assert(key != NULL); 238 | 239 | /* Initialize values. */ 240 | crypto_aesctr_init2(stream, key, nonce); 241 | 242 | /* Perform the encryption. */ 243 | crypto_aesctr_stream(stream, inbuf, outbuf, buflen); 244 | 245 | /* Zero potentially sensitive information. */ 246 | insecure_memzero(stream, sizeof(struct crypto_aesctr)); 247 | } 248 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AESCTR_H_ 2 | #define CRYPTO_AESCTR_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Opaque types. */ 8 | struct crypto_aes_key; 9 | struct crypto_aesctr; 10 | 11 | /** 12 | * crypto_aesctr_init(key, nonce): 13 | * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided 14 | * expanded ${key} and ${nonce}. The key provided must remain valid for the 15 | * lifetime of the stream. This is the same as calling _alloc() followed by 16 | * _init2(). 17 | */ 18 | struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key *, 19 | uint64_t); 20 | 21 | /** 22 | * crypto_aesctr_alloc(void): 23 | * Allocate an object for performing AES in CTR code. This must be followed 24 | * by calling _init2(). 25 | */ 26 | struct crypto_aesctr * crypto_aesctr_alloc(void); 27 | 28 | /** 29 | * crypto_aesctr_init2(stream, key, nonce): 30 | * Reset the AES-CTR stream ${stream}, using the ${key} and ${nonce}. If ${key} 31 | * is NULL, retain the previous AES key. 32 | */ 33 | void crypto_aesctr_init2(struct crypto_aesctr *, const struct crypto_aes_key *, 34 | uint64_t); 35 | 36 | /** 37 | * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): 38 | * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor 39 | * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the 40 | * buffers ${inbuf} and ${outbuf} overlap, they must be identical. 41 | */ 42 | void crypto_aesctr_stream(struct crypto_aesctr *, const uint8_t *, 43 | uint8_t *, size_t); 44 | 45 | /** 46 | * crypto_aesctr_free(stream): 47 | * Free the AES-CTR stream ${stream}. 48 | */ 49 | void crypto_aesctr_free(struct crypto_aesctr *); 50 | 51 | /** 52 | * crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen): 53 | * Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free(). 54 | */ 55 | void crypto_aesctr_buf(const struct crypto_aes_key *, uint64_t, 56 | const uint8_t *, uint8_t *, size_t); 57 | 58 | #endif /* !CRYPTO_AESCTR_H_ */ 59 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr_aesni.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | #ifdef CPUSUPPORT_X86_AESNI 3 | /** 4 | * CPUSUPPORT CFLAGS: X86_AESNI 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "crypto_aes.h" 14 | #include "crypto_aes_aesni_m128i.h" 15 | #include "sysendian.h" 16 | 17 | #include "crypto_aesctr_aesni.h" 18 | 19 | /** 20 | * In order to optimize AES-CTR, it is desirable to separate out the handling 21 | * of individual bytes of data vs. the handling of complete (16 byte) blocks. 22 | * The handling of blocks in turn can be optimized further using CPU 23 | * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code 24 | * remains the same across platforms it should be inlined into the same (CPU 25 | * feature specific) routines for performance reasons. 26 | * 27 | * In order to allow those generic functions to be inlined into multiple 28 | * functions in separate translation units, we place them into a "shared" C 29 | * file which is included in each of the platform-specific variants. 30 | */ 31 | #include "crypto_aesctr_shared.c" 32 | 33 | #ifdef BROKEN_MM_LOADU_SI64 34 | #warning Working around compiler bug: _mm_loadu_si64 is missing 35 | #warning Updating to a newer compiler may improve performance 36 | #endif 37 | 38 | /** 39 | * load_si64(mem): 40 | * Load an unaligned 64-bit integer from memory into the lowest 64 bits of the 41 | * returned value. The contents of the upper 64 bits is not defined. 42 | */ 43 | static inline __m128i 44 | load_si64(const void * mem) 45 | { 46 | 47 | #ifdef BROKEN_MM_LOADU_SI64 48 | return (_mm_castpd_si128(_mm_load_sd(mem))); 49 | #else 50 | return (_mm_loadu_si64(mem)); 51 | #endif 52 | } 53 | 54 | /* Process multiple whole blocks by generating & using a cipherblock. */ 55 | static void 56 | crypto_aesctr_aesni_stream_wholeblocks(struct crypto_aesctr * stream, 57 | const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen) 58 | { 59 | __m128i bufsse; 60 | __m128i inbufsse; 61 | __m128i nonce_be; 62 | uint8_t block_counter_be_arr[8]; 63 | uint64_t block_counter; 64 | size_t num_blocks; 65 | size_t i; 66 | 67 | /* Load local variables from stream. */ 68 | nonce_be = load_si64(stream->pblk); 69 | block_counter = stream->bytectr / 16; 70 | 71 | /* How many blocks should we process? */ 72 | num_blocks = (*buflen) / 16; 73 | 74 | /* 75 | * This is 'for (i = num_blocks; i > 0; i--)', but ensuring that the 76 | * compiler knows that we will execute the loop at least once. 77 | */ 78 | i = num_blocks; 79 | do { 80 | /* Prepare counter. */ 81 | be64enc(block_counter_be_arr, block_counter); 82 | 83 | /* Encrypt the cipherblock. */ 84 | bufsse = load_si64(block_counter_be_arr); 85 | bufsse = _mm_unpacklo_epi64(nonce_be, bufsse); 86 | bufsse = crypto_aes_encrypt_block_aesni_m128i(bufsse, 87 | stream->key); 88 | 89 | /* Encrypt the byte(s). */ 90 | inbufsse = _mm_loadu_si128((const __m128i *)(*inbuf)); 91 | bufsse = _mm_xor_si128(inbufsse, bufsse); 92 | _mm_storeu_si128((__m128i *)(*outbuf), bufsse); 93 | 94 | /* Update the positions. */ 95 | block_counter++; 96 | *inbuf += 16; 97 | *outbuf += 16; 98 | 99 | /* Update the counter. */ 100 | i--; 101 | } while (i > 0); 102 | 103 | /* Update the overall buffer length. */ 104 | *buflen -= 16 * num_blocks; 105 | 106 | /* Update variables in stream. */ 107 | memcpy(stream->pblk + 8, block_counter_be_arr, 8); 108 | stream->bytectr += 16 * num_blocks; 109 | } 110 | 111 | /** 112 | * crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen): 113 | * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor 114 | * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the 115 | * buffers ${inbuf} and ${outbuf} overlap, they must be identical. 116 | */ 117 | void 118 | crypto_aesctr_aesni_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, 119 | uint8_t * outbuf, size_t buflen) 120 | { 121 | 122 | /* Process any bytes before we can process a whole block. */ 123 | if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, 124 | &buflen)) 125 | return; 126 | 127 | /* Process whole blocks of 16 bytes. */ 128 | if (buflen >= 16) 129 | crypto_aesctr_aesni_stream_wholeblocks(stream, &inbuf, 130 | &outbuf, &buflen); 131 | 132 | /* Process any final bytes after finishing all whole blocks. */ 133 | crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); 134 | } 135 | 136 | #endif /* CPUSUPPORT_X86_AESNI */ 137 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr_aesni.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AESCTR_AESNI_H_ 2 | #define CRYPTO_AESCTR_AESNI_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Opaque type. */ 8 | struct crypto_aesctr; 9 | 10 | /** 11 | * crypto_aesctr_aesni_stream(stream, inbuf, outbuf, buflen): 12 | * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor 13 | * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the 14 | * buffers ${inbuf} and ${outbuf} overlap, they must be identical. 15 | */ 16 | void crypto_aesctr_aesni_stream(struct crypto_aesctr *, const uint8_t *, 17 | uint8_t *, size_t); 18 | 19 | #endif /* !CRYPTO_AESCTR_AESNI_H_ */ 20 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr_arm.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | #ifdef CPUSUPPORT_ARM_AES 3 | /** 4 | * CPUSUPPORT CFLAGS: ARM_AES 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef __ARM_NEON 12 | #include 13 | #endif 14 | 15 | #include "crypto_aes.h" 16 | #include "crypto_aes_arm_u8.h" 17 | #include "sysendian.h" 18 | 19 | #include "crypto_aesctr_arm.h" 20 | 21 | /** 22 | * In order to optimize AES-CTR, it is desirable to separate out the handling 23 | * of individual bytes of data vs. the handling of complete (16 byte) blocks. 24 | * The handling of blocks in turn can be optimized further using CPU 25 | * intrinsics, e.g. SSE2 on x86 CPUs; however while the byte-at-once code 26 | * remains the same across platforms it should be inlined into the same (CPU 27 | * feature specific) routines for performance reasons. 28 | * 29 | * In order to allow those generic functions to be inlined into multiple 30 | * functions in separate translation units, we place them into a "shared" C 31 | * file which is included in each of the platform-specific variants. 32 | */ 33 | #include "crypto_aesctr_shared.c" 34 | 35 | /* Process multiple whole blocks by generating & using a cipherblock. */ 36 | static void 37 | crypto_aesctr_arm_stream_wholeblocks(struct crypto_aesctr * stream, 38 | const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen) 39 | { 40 | uint8x16_t bufarm; 41 | uint8x16_t inbufarm; 42 | uint8x8_t nonce_be; 43 | uint8x8_t block_counter_be; 44 | uint8_t block_counter_be_arr[8]; 45 | uint64_t block_counter; 46 | size_t num_blocks; 47 | size_t i; 48 | 49 | /* Load local variables from stream. */ 50 | nonce_be = vld1_u8(stream->pblk); 51 | block_counter = stream->bytectr / 16; 52 | 53 | /* How many blocks should we process? */ 54 | num_blocks = (*buflen) / 16; 55 | 56 | /* 57 | * This is 'for (i = num_blocks; i > 0; i--)', but ensuring that the 58 | * compiler knows that we will execute the loop at least once. 59 | */ 60 | i = num_blocks; 61 | do { 62 | /* Prepare counter. */ 63 | be64enc(block_counter_be_arr, block_counter); 64 | 65 | /* Encrypt the cipherblock. */ 66 | block_counter_be = vld1_u8(block_counter_be_arr); 67 | bufarm = vcombine_u8(nonce_be, block_counter_be); 68 | bufarm = crypto_aes_encrypt_block_arm_u8(bufarm, stream->key); 69 | 70 | /* Encrypt the byte(s). */ 71 | inbufarm = vld1q_u8(*inbuf); 72 | bufarm = veorq_u8(inbufarm, bufarm); 73 | vst1q_u8(*outbuf, bufarm); 74 | 75 | /* Update the positions. */ 76 | block_counter++; 77 | *inbuf += 16; 78 | *outbuf += 16; 79 | 80 | /* Update the counter. */ 81 | i--; 82 | } while (i > 0); 83 | 84 | /* Update the overall buffer length. */ 85 | *buflen -= 16 * num_blocks; 86 | 87 | /* Update variables in stream. */ 88 | memcpy(stream->pblk + 8, block_counter_be_arr, 8); 89 | stream->bytectr += 16 * num_blocks; 90 | } 91 | 92 | /** 93 | * crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen): 94 | * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor 95 | * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the 96 | * buffers ${inbuf} and ${outbuf} overlap, they must be identical. 97 | */ 98 | void 99 | crypto_aesctr_arm_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, 100 | uint8_t * outbuf, size_t buflen) 101 | { 102 | 103 | /* Process any bytes before we can process a whole block. */ 104 | if (crypto_aesctr_stream_pre_wholeblock(stream, &inbuf, &outbuf, 105 | &buflen)) 106 | return; 107 | 108 | /* Process whole blocks of 16 bytes. */ 109 | if (buflen >= 16) 110 | crypto_aesctr_arm_stream_wholeblocks(stream, &inbuf, &outbuf, 111 | &buflen); 112 | 113 | /* Process any final bytes after finishing all whole blocks. */ 114 | crypto_aesctr_stream_post_wholeblock(stream, &inbuf, &outbuf, &buflen); 115 | } 116 | 117 | #endif /* CPUSUPPORT_ARM_AES */ 118 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr_arm.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_AESCTR_ARM_H_ 2 | #define CRYPTO_AESCTR_ARM_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Opaque type. */ 8 | struct crypto_aesctr; 9 | 10 | /** 11 | * crypto_aesctr_arm_stream(stream, inbuf, outbuf, buflen): 12 | * Generate the next ${buflen} bytes of the AES-CTR stream ${stream} and xor 13 | * them with bytes from ${inbuf}, writing the result into ${outbuf}. If the 14 | * buffers ${inbuf} and ${outbuf} overlap, they must be identical. 15 | */ 16 | void crypto_aesctr_arm_stream(struct crypto_aesctr *, const uint8_t *, 17 | uint8_t *, size_t); 18 | 19 | #endif /* !CRYPTO_AESCTR_ARM_H_ */ 20 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_aesctr_shared.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is shared between crypto_aesctr*.c files, and should not be 3 | * compiled as a separate translation unit. For details, see the comments in 4 | * those files. 5 | */ 6 | 7 | /* AES-CTR state. */ 8 | struct crypto_aesctr { 9 | const struct crypto_aes_key * key; 10 | uint64_t bytectr; 11 | uint8_t buf[16]; 12 | uint8_t pblk[16]; 13 | }; 14 | 15 | /* Generate a block of cipherstream. */ 16 | static inline void 17 | crypto_aesctr_stream_cipherblock_generate(struct crypto_aesctr * stream) 18 | { 19 | 20 | /* Sanity check. */ 21 | assert(stream->bytectr % 16 == 0); 22 | 23 | /* Prepare counter. */ 24 | stream->pblk[15]++; 25 | if (stream->pblk[15] == 0) { 26 | /* 27 | * If incrementing the least significant byte resulted in it 28 | * wrapping, re-encode the complete 64-bit value. 29 | */ 30 | be64enc(stream->pblk + 8, stream->bytectr / 16); 31 | } 32 | 33 | /* Encrypt the cipherblock. */ 34 | crypto_aes_encrypt_block(stream->pblk, stream->buf, stream->key); 35 | } 36 | 37 | /* Encrypt ${nbytes} bytes, then update ${inbuf}, ${outbuf}, and ${buflen}. */ 38 | static inline void 39 | crypto_aesctr_stream_cipherblock_use(struct crypto_aesctr * stream, 40 | const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen, size_t nbytes, 41 | size_t bytemod) 42 | { 43 | size_t i; 44 | 45 | /* Encrypt the byte(s). */ 46 | for (i = 0; i < nbytes; i++) 47 | (*outbuf)[i] = (*inbuf)[i] ^ stream->buf[bytemod + i]; 48 | 49 | /* Move to the next byte(s) of cipherstream. */ 50 | stream->bytectr += nbytes; 51 | 52 | /* Update the positions. */ 53 | *inbuf += nbytes; 54 | *outbuf += nbytes; 55 | *buflen -= nbytes; 56 | } 57 | 58 | /* 59 | * Process any bytes before we can process a whole block. Return 1 if there 60 | * are no bytes left to process after calling this function. 61 | */ 62 | static inline int 63 | crypto_aesctr_stream_pre_wholeblock(struct crypto_aesctr * stream, 64 | const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p) 65 | { 66 | size_t bytemod; 67 | 68 | /* Do we have any bytes left in the current cipherblock? */ 69 | bytemod = stream->bytectr % 16; 70 | if (bytemod != 0) { 71 | /* Do we have enough to complete the request? */ 72 | if (bytemod + *buflen_p <= 16) { 73 | /* Process only buflen bytes, then return. */ 74 | crypto_aesctr_stream_cipherblock_use(stream, inbuf, 75 | outbuf, buflen_p, *buflen_p, bytemod); 76 | return (1); 77 | } 78 | 79 | /* Encrypt the byte(s) and update the positions. */ 80 | crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, 81 | buflen_p, 16 - bytemod, bytemod); 82 | } 83 | 84 | /* Success! */ 85 | return (0); 86 | } 87 | 88 | /* Process any final bytes after finishing all whole blocks. */ 89 | static inline void 90 | crypto_aesctr_stream_post_wholeblock(struct crypto_aesctr * stream, 91 | const uint8_t ** inbuf, uint8_t ** outbuf, size_t * buflen_p) 92 | { 93 | 94 | /* Process any final bytes; we need a new cipherblock. */ 95 | if (*buflen_p > 0) { 96 | /* Generate a block of cipherstream. */ 97 | crypto_aesctr_stream_cipherblock_generate(stream); 98 | 99 | /* Encrypt the byte(s) and update the positions. */ 100 | crypto_aesctr_stream_cipherblock_use(stream, inbuf, outbuf, 101 | buflen_p, *buflen_p, 0); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_entropy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "cpusupport.h" 6 | #include "crypto_entropy_rdrand.h" 7 | #include "entropy.h" 8 | #include "insecure_memzero.h" 9 | 10 | #include "sha256.h" 11 | 12 | #include "crypto_entropy.h" 13 | 14 | /** 15 | * This system implements the HMAC_DRBG pseudo-random number generator as 16 | * specified in section 10.1.2 of the NIST SP 800-90 standard. In this 17 | * implementation, the optional personalization_string and additional_input 18 | * specified in the standard are not implemented. 19 | */ 20 | 21 | /* Internal HMAC_DRBG state. */ 22 | static struct { 23 | uint8_t Key[32]; 24 | uint8_t V[32]; 25 | uint32_t reseed_counter; 26 | } drbg; 27 | 28 | /* Set to non-zero once the PRNG has been instantiated. */ 29 | static int instantiated = 0; 30 | 31 | /* Could be as high as 2^48 if we wanted... */ 32 | #define RESEED_INTERVAL 256 33 | 34 | /* Limited to 2^16 by specification. */ 35 | #define GENERATE_MAXLEN 65536 36 | 37 | static int instantiate(void); 38 | static void update(const uint8_t *, size_t); 39 | static int reseed(void); 40 | static void generate(uint8_t *, size_t); 41 | 42 | #ifdef CPUSUPPORT_X86_RDRAND 43 | static void 44 | update_from_rdrand(void) 45 | { 46 | unsigned int buf[8]; 47 | 48 | /* This is only *extra* entropy, so it's ok if it fails. */ 49 | if (generate_seed_rdrand(buf, 8)) 50 | return; 51 | update((uint8_t *)buf, sizeof(buf)); 52 | 53 | /* Clean up. */ 54 | insecure_memzero(buf, sizeof(buf)); 55 | } 56 | #endif 57 | 58 | /** 59 | * instantiate(void): 60 | * Initialize the DRBG state. (Section 10.1.2.3) 61 | */ 62 | static int 63 | instantiate(void) 64 | { 65 | uint8_t seed_material[48]; 66 | 67 | /* Obtain random seed_material = (entropy_input || nonce). */ 68 | if (entropy_read(seed_material, 48)) 69 | return (-1); 70 | 71 | /* Initialize Key, V, and reseed_counter. */ 72 | memset(drbg.Key, 0x00, 32); 73 | memset(drbg.V, 0x01, 32); 74 | drbg.reseed_counter = 1; 75 | 76 | /* Mix the random seed into the state. */ 77 | update(seed_material, 48); 78 | 79 | #ifdef CPUSUPPORT_X86_RDRAND 80 | /* Add output of RDRAND into the state. */ 81 | if (cpusupport_x86_rdrand()) 82 | update_from_rdrand(); 83 | #endif 84 | 85 | /* Clean the stack. */ 86 | insecure_memzero(seed_material, 48); 87 | 88 | /* Success! */ 89 | return (0); 90 | } 91 | 92 | /** 93 | * update(data, datalen): 94 | * Update the DRBG state using the provided data. (Section 10.1.2.2) 95 | */ 96 | static void 97 | update(const uint8_t * data, size_t datalen) 98 | { 99 | HMAC_SHA256_CTX ctx; 100 | uint8_t K[32]; 101 | uint8_t Vx[33]; 102 | 103 | /* Load (Key, V) into (K, Vx). */ 104 | memcpy(K, drbg.Key, 32); 105 | memcpy(Vx, drbg.V, 32); 106 | 107 | /* K <- HMAC(K, V || 0x00 || data). */ 108 | Vx[32] = 0x00; 109 | HMAC_SHA256_Init(&ctx, K, 32); 110 | HMAC_SHA256_Update(&ctx, Vx, 33); 111 | HMAC_SHA256_Update(&ctx, data, datalen); 112 | HMAC_SHA256_Final(K, &ctx); 113 | 114 | /* V <- HMAC(K, V). */ 115 | HMAC_SHA256_Buf(K, 32, Vx, 32, Vx); 116 | 117 | /* If the provided data is non-Null, perform another mixing stage. */ 118 | if (datalen != 0) { 119 | /* K <- HMAC(K, V || 0x01 || data). */ 120 | Vx[32] = 0x01; 121 | HMAC_SHA256_Init(&ctx, K, 32); 122 | HMAC_SHA256_Update(&ctx, Vx, 33); 123 | HMAC_SHA256_Update(&ctx, data, datalen); 124 | HMAC_SHA256_Final(K, &ctx); 125 | 126 | /* V <- HMAC(K, V). */ 127 | HMAC_SHA256_Buf(K, 32, Vx, 32, Vx); 128 | } 129 | 130 | /* Copy (K, Vx) back to (Key, V). */ 131 | memcpy(drbg.Key, K, 32); 132 | memcpy(drbg.V, Vx, 32); 133 | 134 | /* Clean the stack. */ 135 | insecure_memzero(K, 32); 136 | insecure_memzero(Vx, 33); 137 | } 138 | 139 | /** 140 | * reseed(void): 141 | * Reseed the DRBG state (mix in new entropy). (Section 10.1.2.4) 142 | */ 143 | static int 144 | reseed(void) 145 | { 146 | uint8_t seed_material[32]; 147 | 148 | /* Obtain random seed_material = entropy_input. */ 149 | if (entropy_read(seed_material, 32)) 150 | return (-1); 151 | 152 | /* Mix the random seed into the state. */ 153 | update(seed_material, 32); 154 | 155 | #ifdef CPUSUPPORT_X86_RDRAND 156 | /* Add output of RDRAND into the state. */ 157 | if (cpusupport_x86_rdrand()) 158 | update_from_rdrand(); 159 | #endif 160 | 161 | /* Reset the reseed_counter. */ 162 | drbg.reseed_counter = 1; 163 | 164 | /* Clean the stack. */ 165 | insecure_memzero(seed_material, 32); 166 | 167 | /* Success! */ 168 | return (0); 169 | } 170 | 171 | /** 172 | * generate(buf, buflen): 173 | * Fill the provided buffer with random bits, assuming that reseed_counter 174 | * is less than RESEED_INTERVAL (the caller is responsible for calling 175 | * reseed() as needed) and ${buflen} is less than 2^16 (the caller is 176 | * responsible for splitting up larger requests). (Section 10.1.2.5) 177 | */ 178 | static void 179 | generate(uint8_t * buf, size_t buflen) 180 | { 181 | size_t bufpos; 182 | 183 | assert(buflen <= GENERATE_MAXLEN); 184 | assert(drbg.reseed_counter <= RESEED_INTERVAL); 185 | 186 | /* Iterate until we've filled the buffer. */ 187 | for (bufpos = 0; bufpos < buflen; bufpos += 32) { 188 | HMAC_SHA256_Buf(drbg.Key, 32, drbg.V, 32, drbg.V); 189 | if (buflen - bufpos >= 32) 190 | memcpy(&buf[bufpos], drbg.V, 32); 191 | else 192 | memcpy(&buf[bufpos], drbg.V, buflen - bufpos); 193 | } 194 | 195 | /* Mix up state. */ 196 | update(NULL, 0); 197 | 198 | /* We're one data-generation step closer to needing a reseed. */ 199 | drbg.reseed_counter += 1; 200 | } 201 | 202 | /** 203 | * crypto_entropy_read(buf, buflen): 204 | * Fill the buffer with unpredictable bits. 205 | */ 206 | int 207 | crypto_entropy_read(uint8_t * buf, size_t buflen) 208 | { 209 | size_t bytes_to_provide; 210 | 211 | /* Instantiate if needed. */ 212 | if (instantiated == 0) { 213 | /* Try to instantiate the PRNG. */ 214 | if (instantiate()) 215 | return (-1); 216 | 217 | /* We have instantiated the PRNG. */ 218 | instantiated = 1; 219 | } 220 | 221 | /* Loop until we've filled the buffer. */ 222 | while (buflen > 0) { 223 | /* Do we need to reseed? */ 224 | if (drbg.reseed_counter > RESEED_INTERVAL) { 225 | if (reseed()) 226 | return (-1); 227 | } 228 | 229 | /* How much data are we generating in this step? */ 230 | if (buflen > GENERATE_MAXLEN) 231 | bytes_to_provide = GENERATE_MAXLEN; 232 | else 233 | bytes_to_provide = buflen; 234 | 235 | /* Generate bytes. */ 236 | generate(buf, bytes_to_provide); 237 | 238 | /* We've done part of the buffer. */ 239 | buf += bytes_to_provide; 240 | buflen -= bytes_to_provide; 241 | } 242 | 243 | /* Success! */ 244 | return (0); 245 | } 246 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_entropy.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_ENTROPY_H_ 2 | #define CRYPTO_ENTROPY_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * crypto_entropy_read(buf, buflen): 9 | * Fill the buffer with unpredictable bits. 10 | */ 11 | int crypto_entropy_read(uint8_t *, size_t); 12 | 13 | #endif /* !CRYPTO_ENTROPY_H_ */ 14 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_entropy_rdrand.c: -------------------------------------------------------------------------------- 1 | #include "cpusupport.h" 2 | #ifdef CPUSUPPORT_X86_RDRAND 3 | /** 4 | * CPUSUPPORT CFLAGS: X86_RDRAND 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "crypto_entropy_rdrand.h" 11 | 12 | /** 13 | * generate_seed_rdrand(buf, len): 14 | * Fill the ${buf} buffer with values from RDRAND. This implementation uses 15 | * the RDRAND instruction, and should only be used if CPUSUPPORT_X86_RDRAND is 16 | * defined and cpusupport_x86_rdrand() returns nonzero. 17 | */ 18 | int 19 | generate_seed_rdrand(unsigned int * buf, size_t len) 20 | { 21 | size_t i; 22 | 23 | /* Fill buffer. */ 24 | for (i = 0; i < len; i++) { 25 | if (!_rdrand32_step(&buf[i])) 26 | goto err0; 27 | } 28 | 29 | /* Success! */ 30 | return (0); 31 | 32 | err0: 33 | /* Failure! */ 34 | return (1); 35 | } 36 | #endif /* CPUSUPPORT_X86_RDRAND */ 37 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_entropy_rdrand.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_ENTROPY_RDRAND_H_ 2 | #define CRYPTO_ENTROPY_RDRAND_H_ 3 | 4 | #include 5 | 6 | /** 7 | * generate_seed_rdrand(buf, len): 8 | * Fill the ${buf} buffer with values from RDRAND. This implementation uses 9 | * the RDRAND instruction, and should only be used if CPUSUPPORT_X86_RDRAND is 10 | * defined and cpusupport_x86_rdrand() returns nonzero. 11 | */ 12 | int generate_seed_rdrand(unsigned int *, size_t); 13 | 14 | #endif /* !CRYPTO_ENTROPY_RDRAND_H_ */ 15 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_verify_bytes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "crypto_verify_bytes.h" 5 | 6 | /** 7 | * crypto_verify_bytes(buf0, buf1, len): 8 | * Return zero if and only if ${buf0[0 .. len - 1]} and ${buf1[0 .. len - 1]} 9 | * are identical. Do not leak any information via timing side channels. 10 | */ 11 | uint8_t 12 | crypto_verify_bytes(const uint8_t * buf0, const uint8_t * buf1, size_t len) 13 | { 14 | uint8_t rc = 0; 15 | size_t i; 16 | 17 | for (i = 0; i < len; i++) 18 | rc = rc | (buf0[i] ^ buf1[i]); 19 | 20 | return (rc); 21 | } 22 | -------------------------------------------------------------------------------- /libcperciva/crypto/crypto_verify_bytes.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_VERIFY_BYTES_H_ 2 | #define CRYPTO_VERIFY_BYTES_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * crypto_verify_bytes(buf0, buf1, len): 9 | * Return zero if and only if ${buf0[0 .. len - 1]} and ${buf1[0 .. len - 1]} 10 | * are identical. Do not leak any information via timing side channels. 11 | */ 12 | uint8_t crypto_verify_bytes(const uint8_t *, const uint8_t *, size_t); 13 | 14 | #endif /* !CRYPTO_VERIFY_BYTES_H_ */ 15 | -------------------------------------------------------------------------------- /libcperciva/util/align_ptr.h: -------------------------------------------------------------------------------- 1 | #ifndef ALIGN_PTR_H_ 2 | #define ALIGN_PTR_H_ 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * ALIGN_PTR_DECL(type, name, num, alignsize): 9 | * Declare a pointer called ${name}, which points to an array large enough to 10 | * contain ${num} values of ${type} and is aligned to ${alignsize} bytes. The 11 | * pointer must not be used until ALIGN_PTR_INIT(${name}, ${alignsize}) has 12 | * been called. This macro may also create an additional variable called 13 | * "${name}_buf". 14 | */ 15 | #define ALIGN_PTR_DECL(type, name, num, alignsize) \ 16 | uint8_t name##_buf[num * sizeof(type) + (alignsize - 1)]; \ 17 | type * name 18 | 19 | /** 20 | * ALIGN_PTR_INIT(name, alignsize): 21 | * Initialize the variable called ${name} to point to an array which is 22 | * aligned to ${alignsize} bytes. They must have previously been declared 23 | * with ALIGN_PTR_DECL(${name}, ${alignsize}). This macro assumes that 24 | * casting a pointer to uintptr_t behaves naturally, i.e. yields a byte offset 25 | * relative to aligned memory. 26 | */ 27 | #define ALIGN_PTR_INIT(name, alignsize) \ 28 | name = align_ptr(name##_buf, alignsize) 29 | 30 | /** 31 | * align_ptr(arr, alignment): 32 | * Return a pointer to the first memory location within ${arr} which is 33 | * aligned to ${alignsize} bytes. (It is expected that this function will 34 | * only be called via the ALIGN_PTR_INIT macro). 35 | */ 36 | static inline void * 37 | align_ptr(uint8_t * arr, size_t alignment) 38 | { 39 | size_t offset; 40 | 41 | /* 42 | * This assumes that casting a pointer to uintptr_t behaves naturally, 43 | * i.e. yields a byte offset relative to aligned memory. 44 | */ 45 | offset = (uintptr_t)(&arr[0]) % alignment; 46 | offset = (alignment - offset) % alignment; 47 | 48 | /* Return the aligned pointer. */ 49 | return ((void *)&arr[offset]); 50 | } 51 | 52 | #endif /* !ALIGN_PTR_H_ */ 53 | -------------------------------------------------------------------------------- /libcperciva/util/asprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "asprintf.h" 6 | 7 | /** 8 | * asprintf(ret, format, ...): 9 | * Do asprintf(3) like GNU and BSD do. 10 | */ 11 | int 12 | asprintf(char ** ret, const char * format, ...) 13 | { 14 | va_list ap; 15 | int len; 16 | size_t buflen; 17 | 18 | /* Figure out how long the string needs to be. */ 19 | va_start(ap, format); 20 | len = vsnprintf(NULL, 0, format, ap); 21 | va_end(ap); 22 | 23 | /* Did we fail? */ 24 | if (len < 0) 25 | goto err0; 26 | buflen = (size_t)(len) + 1; 27 | 28 | /* Allocate memory. */ 29 | if ((*ret = malloc(buflen)) == NULL) 30 | goto err0; 31 | 32 | /* Actually generate the string. */ 33 | va_start(ap, format); 34 | len = vsnprintf(*ret, buflen, format, ap); 35 | va_end(ap); 36 | 37 | /* Did we fail? */ 38 | if (len < 0) 39 | goto err1; 40 | 41 | /* Success! */ 42 | return (len); 43 | 44 | err1: 45 | free(*ret); 46 | err0: 47 | /* Failure! */ 48 | return (-1); 49 | } 50 | -------------------------------------------------------------------------------- /libcperciva/util/asprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef ASPRINTF_H_ 2 | #define ASPRINTF_H_ 3 | 4 | /* Avoid namespace collisions with BSD/GNU asprintf. */ 5 | #ifdef asprintf 6 | #undef asprintf 7 | #endif 8 | #define asprintf libcperciva_asprintf 9 | 10 | /** 11 | * asprintf(ret, format, ...): 12 | * Do asprintf(3) like GNU and BSD do. 13 | */ 14 | int asprintf(char **, const char *, ...); 15 | 16 | #endif /* !ASPRINTF_H_ */ 17 | -------------------------------------------------------------------------------- /libcperciva/util/entropy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "warnp.h" 10 | 11 | #include "entropy.h" 12 | 13 | /** 14 | * XXX Portability 15 | * XXX We obtain random bytes from the operating system by opening 16 | * XXX /dev/urandom and reading them from that device; this works on 17 | * XXX modern UNIX-like operating systems but not on systems like 18 | * XXX win32 where there is no concept of /dev/urandom. 19 | */ 20 | 21 | /** 22 | * Entropy reader state. At present it holds a file descriptor for 23 | * /dev/urandom, but in the future this structure may gain other OS-dependent 24 | * state, e.g. a Windows Handle. 25 | */ 26 | struct entropy_read_cookie { 27 | int fd; 28 | }; 29 | 30 | /** 31 | * entropy_read_init(void): 32 | * Initialize the ability to produce random bytes from the operating system, 33 | * and return a cookie. 34 | */ 35 | struct entropy_read_cookie * 36 | entropy_read_init(void) 37 | { 38 | struct entropy_read_cookie * er; 39 | 40 | /* Allocate cookie. */ 41 | if ((er = malloc(sizeof(struct entropy_read_cookie))) == NULL) { 42 | warnp("malloc"); 43 | goto err0; 44 | } 45 | 46 | /* Open /dev/urandom. */ 47 | if ((er->fd = open("/dev/urandom", O_RDONLY)) == -1) { 48 | warnp("open(/dev/urandom)"); 49 | goto err1; 50 | } 51 | 52 | /* Success! */ 53 | return (er); 54 | 55 | err1: 56 | free(er); 57 | err0: 58 | /* Failure! */ 59 | return (NULL); 60 | } 61 | 62 | /** 63 | * entropy_read_fill(er, buf, buflen): 64 | * Fill the given buffer with random bytes provided by the operating system 65 | * using the resources in ${er}. 66 | */ 67 | int 68 | entropy_read_fill(struct entropy_read_cookie * er, uint8_t * buf, 69 | size_t buflen) 70 | { 71 | ssize_t lenread; 72 | 73 | /* Sanity checks. */ 74 | assert(er != NULL); 75 | assert(buflen <= SSIZE_MAX); 76 | 77 | /* Read bytes until we have filled the buffer. */ 78 | while (buflen > 0) { 79 | if ((lenread = read(er->fd, buf, buflen)) == -1) { 80 | warnp("read(/dev/urandom)"); 81 | goto err0; 82 | } 83 | 84 | /* The random device should never EOF. */ 85 | if (lenread == 0) { 86 | warn0("EOF on /dev/urandom?"); 87 | goto err0; 88 | } 89 | 90 | /* We've filled a portion of the buffer. */ 91 | buf += (size_t)lenread; 92 | buflen -= (size_t)lenread; 93 | } 94 | 95 | /* Success! */ 96 | return (0); 97 | 98 | err0: 99 | /* Failure! */ 100 | return (-1); 101 | } 102 | 103 | /** 104 | * entropy_read_done(er): 105 | * Release any resources used by ${er}. 106 | */ 107 | int 108 | entropy_read_done(struct entropy_read_cookie * er) 109 | { 110 | 111 | /* Sanity check. */ 112 | assert(er != NULL); 113 | 114 | /* Close the device. */ 115 | while (close(er->fd) == -1) { 116 | if (errno != EINTR) { 117 | warnp("close(/dev/urandom)"); 118 | goto err1; 119 | } 120 | } 121 | 122 | /* Clean up. */ 123 | free(er); 124 | 125 | /* Success! */ 126 | return (0); 127 | 128 | err1: 129 | free(er); 130 | 131 | /* Failure! */ 132 | return (-1); 133 | } 134 | 135 | /** 136 | * entropy_read(buf, buflen): 137 | * Fill the given buffer with random bytes provided by the operating system. 138 | */ 139 | int 140 | entropy_read(uint8_t * buf, size_t buflen) 141 | { 142 | struct entropy_read_cookie * er; 143 | 144 | /* Sanity-check the buffer size. */ 145 | assert(buflen <= SSIZE_MAX); 146 | 147 | /* Open /dev/urandom. */ 148 | if ((er = entropy_read_init()) == NULL) { 149 | warn0("entropy_read_init"); 150 | goto err0; 151 | } 152 | 153 | /* Read bytes until we have filled the buffer. */ 154 | if (entropy_read_fill(er, buf, buflen)) { 155 | warn0("entropy_read_fill"); 156 | goto err1; 157 | } 158 | 159 | /* Close the device. */ 160 | if (entropy_read_done(er)) { 161 | warn0("entropy_read_done"); 162 | goto err0; 163 | } 164 | 165 | /* Success! */ 166 | return (0); 167 | 168 | err1: 169 | entropy_read_done(er); 170 | err0: 171 | /* Failure! */ 172 | return (-1); 173 | } 174 | -------------------------------------------------------------------------------- /libcperciva/util/entropy.h: -------------------------------------------------------------------------------- 1 | #ifndef ENTROPY_H_ 2 | #define ENTROPY_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Opaque type. */ 8 | struct entropy_read_cookie; 9 | 10 | /** 11 | * entropy_read_init(void): 12 | * Initialize the ability to produce random bytes from the operating system, 13 | * and return a cookie. 14 | */ 15 | struct entropy_read_cookie * entropy_read_init(void); 16 | 17 | /** 18 | * entropy_read_fill(er, buf, buflen): 19 | * Fill the given buffer with random bytes provided by the operating system 20 | * using the resources in ${er}. 21 | */ 22 | int entropy_read_fill(struct entropy_read_cookie *, uint8_t *, size_t); 23 | 24 | /** 25 | * entropy_read_done(er): 26 | * Release any resources used by ${er}. 27 | */ 28 | int entropy_read_done(struct entropy_read_cookie *); 29 | 30 | /** 31 | * entropy_read(buf, buflen): 32 | * Fill the given buffer with random bytes provided by the operating system. 33 | */ 34 | int entropy_read(uint8_t *, size_t); 35 | 36 | #endif /* !ENTROPY_H_ */ 37 | -------------------------------------------------------------------------------- /libcperciva/util/humansize.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "asprintf.h" 4 | #include "warnp.h" 5 | 6 | #include "humansize.h" 7 | 8 | /** 9 | * humansize(size): 10 | * Given a size ${size} in bytes, allocate and return a string of the form 11 | * " B" for 0 <= N <= 999 or " B" where either 10 <= X <= 999 or 12 | * 1.0 <= X <= 9.9 and is "k", "M", "G", "T", "P", or "E"; and where 13 | * the value returned is the largest valid value <= the provided size. 14 | */ 15 | char * 16 | humansize(uint64_t size) 17 | { 18 | char * s; 19 | char prefix; 20 | int shiftcnt; 21 | int rc; 22 | 23 | /* Special-case for size < 1000. */ 24 | if (size < 1000) { 25 | rc = asprintf(&s, "%d B", (int)size); 26 | } else { 27 | /* Keep 10 * size / 1000^(3n) in size. */ 28 | for (size /= 100, shiftcnt = 1; size >= 10000; shiftcnt++) 29 | size /= 1000; 30 | 31 | /* 32 | * Figure out what prefix to use. Since 1 EB = 10^18 B and 33 | * the maximum value of a uint64_t is 2^64 which is roughly 34 | * 18.4 * 10^18, this cannot reference beyond the end of the 35 | * string. 36 | */ 37 | prefix = " kMGTPE"[shiftcnt]; 38 | 39 | /* Construct the string. */ 40 | if (size < 100) 41 | rc = asprintf(&s, "%d.%d %cB", (int)size / 10, 42 | (int)size % 10, prefix); 43 | else 44 | rc = asprintf(&s, "%d %cB", (int)size / 10, prefix); 45 | } 46 | 47 | if (rc == -1) { 48 | warnp("asprintf"); 49 | goto err0; 50 | } 51 | 52 | /* Success! */ 53 | return (s); 54 | 55 | err0: 56 | /* Failure! */ 57 | return (NULL); 58 | } 59 | 60 | /** 61 | * humansize_parse(s, size): 62 | * Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size ${size} in bytes. 63 | */ 64 | int 65 | humansize_parse(const char * s, uint64_t * size) 66 | { 67 | int state = 0; 68 | uint64_t multiplier = 1; 69 | 70 | do { 71 | switch (state) { 72 | case -1: 73 | /* Error state. */ 74 | break; 75 | case 0: 76 | /* Initial state. */ 77 | *size = 0; 78 | 79 | /* We must start with at least one digit. */ 80 | if ((*s < '0') || (*s > '9')) { 81 | state = -1; 82 | break; 83 | } 84 | 85 | /* FALLTHROUGH */ 86 | case 1: 87 | /* We're now processing digits. */ 88 | state = 1; 89 | 90 | /* Digit-parsing state. */ 91 | if (('0' <= *s) && (*s <= '9')) { 92 | if (*size > UINT64_MAX / 10) 93 | state = -1; 94 | else 95 | *size *= 10; 96 | if (*size > UINT64_MAX - (uint64_t)(*s - '0')) 97 | state = -1; 98 | else 99 | *size += (uint64_t)(*s - '0'); 100 | break; 101 | } 102 | 103 | /* FALLTHROUGH */ 104 | case 2: 105 | /* We move into state 3 after an optional ' '. */ 106 | state = 3; 107 | if (*s == ' ') 108 | break; 109 | 110 | /* FALLTHROUGH */ 111 | case 3: 112 | /* We may have one SI prefix. */ 113 | switch (*s) { 114 | case 'E': 115 | multiplier *= 1000; 116 | /* FALLTHROUGH */ 117 | case 'P': 118 | multiplier *= 1000; 119 | /* FALLTHROUGH */ 120 | case 'T': 121 | multiplier *= 1000; 122 | /* FALLTHROUGH */ 123 | case 'G': 124 | multiplier *= 1000; 125 | /* FALLTHROUGH */ 126 | case 'M': 127 | multiplier *= 1000; 128 | /* FALLTHROUGH */ 129 | case 'k': 130 | multiplier *= 1000; 131 | break; 132 | } 133 | 134 | /* We move into state 4 after the optional prefix. */ 135 | state = 4; 136 | if (multiplier != 1) 137 | break; 138 | 139 | /* FALLTHROUGH */ 140 | case 4: 141 | /* We move into state 5 after an optional 'B'. */ 142 | state = 5; 143 | if (*s == 'B') 144 | break; 145 | 146 | /* FALLTHROUGH */ 147 | case 5: 148 | /* We have trailing garbage. */ 149 | state = -1; 150 | break; 151 | } 152 | 153 | /* Move on to the next character. */ 154 | s++; 155 | } while ((state != -1) && (*s != '\0')); 156 | 157 | /* Multiply by multiplier. */ 158 | if (*size > UINT64_MAX / multiplier) 159 | state = -1; 160 | else 161 | *size *= multiplier; 162 | 163 | /* Anything other than state -1 is success. */ 164 | return ((state == -1) ? -1 : 0); 165 | } 166 | -------------------------------------------------------------------------------- /libcperciva/util/humansize.h: -------------------------------------------------------------------------------- 1 | #ifndef HUMANSIZE_H_ 2 | #define HUMANSIZE_H_ 3 | 4 | #include 5 | 6 | /** 7 | * humansize(size): 8 | * Given a size ${size} in bytes, allocate and return a string of the form 9 | * " B" for 0 <= N <= 999 or " B" where either 10 <= X <= 999 or 10 | * 1.0 <= X <= 9.9 and is "k", "M", "G", "T", "P", or "E"; and where 11 | * the value returned is the largest valid value <= the provided size. 12 | */ 13 | char * humansize(uint64_t); 14 | 15 | /** 16 | * humansize_parse(s, size): 17 | * Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size ${size} in bytes. 18 | */ 19 | int humansize_parse(const char *, uint64_t *); 20 | 21 | #endif /* !HUMANSIZE_H_ */ 22 | -------------------------------------------------------------------------------- /libcperciva/util/insecure_memzero.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "insecure_memzero.h" 5 | 6 | /* Function which does the zeroing. */ 7 | static void 8 | insecure_memzero_func(volatile void * buf, size_t len) 9 | { 10 | volatile uint8_t * _buf = buf; 11 | size_t i; 12 | 13 | for (i = 0; i < len; i++) 14 | _buf[i] = 0; 15 | } 16 | 17 | /* Pointer to memory-zeroing function. */ 18 | void (* volatile insecure_memzero_ptr)(volatile void *, size_t) = 19 | insecure_memzero_func; 20 | -------------------------------------------------------------------------------- /libcperciva/util/insecure_memzero.h: -------------------------------------------------------------------------------- 1 | #ifndef INSECURE_MEMZERO_H_ 2 | #define INSECURE_MEMZERO_H_ 3 | 4 | #include 5 | 6 | /* Pointer to memory-zeroing function. */ 7 | extern void (* volatile insecure_memzero_ptr)(volatile void *, size_t); 8 | 9 | /** 10 | * insecure_memzero(buf, len): 11 | * Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers' 12 | * best (standards-compliant) attempts to remove the buffer-zeroing. In 13 | * particular, to avoid performing the zeroing, a compiler would need to 14 | * use optimistic devirtualization; recognize that non-volatile objects do not 15 | * need to be treated as volatile, even if they are accessed via volatile 16 | * qualified pointers; and perform link-time optimization; in addition to the 17 | * dead-code elimination which often causes buffer-zeroing to be elided. 18 | * 19 | * Note however that zeroing a buffer does not guarantee that the data held 20 | * in the buffer is not stored elsewhere; in particular, there may be copies 21 | * held in CPU registers or in anonymous allocations on the stack, even if 22 | * every named variable is successfully sanitized. Solving the "wipe data 23 | * from the system" problem will require a C language extension which does not 24 | * yet exist. 25 | * 26 | * For more information, see: 27 | * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html 28 | * http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html 29 | */ 30 | static inline void 31 | insecure_memzero(volatile void * buf, size_t len) 32 | { 33 | 34 | (insecure_memzero_ptr)(buf, len); 35 | } 36 | 37 | #endif /* !INSECURE_MEMZERO_H_ */ 38 | -------------------------------------------------------------------------------- /libcperciva/util/monoclock.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "warnp.h" 7 | 8 | #include "monoclock.h" 9 | 10 | /* Determine which clock(s) to use. */ 11 | #ifndef POSIXFAIL_CLOCK_GETTIME 12 | #ifdef CLOCK_MONOTONIC 13 | #define USE_MONOTONIC 14 | #endif 15 | #ifndef POSIXFAIL_CLOCK_REALTIME 16 | #define USE_REALTIME 17 | #endif 18 | #endif 19 | 20 | /** 21 | * monoclock_get(tv): 22 | * Store the current time in ${tv}. If CLOCK_MONOTONIC is available, use 23 | * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if 24 | * available) or gettimeofday(2). 25 | */ 26 | int 27 | monoclock_get(struct timeval * tv) 28 | { 29 | #if defined(USE_MONOTONIC) || defined(USE_REALTIME) 30 | struct timespec tp; 31 | #endif 32 | 33 | #ifdef USE_MONOTONIC 34 | if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { 35 | tv->tv_sec = tp.tv_sec; 36 | tv->tv_usec = (suseconds_t)(tp.tv_nsec / 1000); 37 | } else if ((errno != ENOSYS) && (errno != EINVAL)) { 38 | warnp("clock_gettime(CLOCK_MONOTONIC)"); 39 | goto err0; 40 | } else 41 | #endif 42 | #ifdef USE_REALTIME 43 | if (clock_gettime(CLOCK_REALTIME, &tp) == 0) { 44 | tv->tv_sec = tp.tv_sec; 45 | tv->tv_usec = (suseconds_t)(tp.tv_nsec / 1000); 46 | } else { 47 | warnp("clock_gettime(CLOCK_REALTIME)"); 48 | goto err0; 49 | } 50 | #else 51 | if (gettimeofday(tv, NULL)) { 52 | warnp("gettimeofday"); 53 | goto err0; 54 | } 55 | #endif 56 | 57 | /* Success! */ 58 | return (0); 59 | 60 | err0: 61 | /* Failure! */ 62 | return (-1); 63 | } 64 | 65 | /** 66 | * monoclock_get_cputime(tv): 67 | * Store in ${tv} the duration the process has been running if 68 | * CLOCK_PROCESS_CPUTIME_ID is available; fall back to monoclock_get() 69 | * otherwise. 70 | */ 71 | int 72 | monoclock_get_cputime(struct timeval * tv) 73 | { 74 | /* Use CLOCK_PROCESS_CPUTIME_ID if available. */ 75 | #ifdef CLOCK_PROCESS_CPUTIME_ID 76 | struct timespec tp; 77 | 78 | if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) == 0) { 79 | tv->tv_sec = tp.tv_sec; 80 | tv->tv_usec = (suseconds_t)(tp.tv_nsec / 1000); 81 | } else if ((errno != ENOSYS) && (errno != EINVAL)) { 82 | warnp("clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"); 83 | goto err0; 84 | } else 85 | #endif 86 | /* Fall back to monoclock_get(). */ 87 | if (monoclock_get(tv)) 88 | goto err0; 89 | 90 | /* Success! */ 91 | return (0); 92 | 93 | err0: 94 | /* Failure! */ 95 | return (-1); 96 | } 97 | 98 | /** 99 | * monoclock_getres(resd): 100 | * Store an upper limit on timer granularity in ${resd}. If CLOCK_MONOTONIC 101 | * is available, use that clock; if CLOCK_MONOTONIC is unavailable, use 102 | * CLOCK_REALTIME (if available) or gettimeofday(2). For this value to be 103 | * meaningful, we assume that clock_getres(x) succeeds iff clock_gettime(x) 104 | * succeeds. 105 | */ 106 | int 107 | monoclock_getres(double * resd) 108 | { 109 | #if defined(USE_MONOTONIC) || defined(USE_REALTIME) 110 | struct timespec res; 111 | #endif 112 | 113 | #ifdef USE_MONOTONIC 114 | if (clock_getres(CLOCK_MONOTONIC, &res) == 0) { 115 | /* Convert clock resolution to a double. */ 116 | *resd = (double)res.tv_sec + (double)res.tv_nsec * 0.000000001; 117 | } else if ((errno != ENOSYS) && (errno != EINVAL)) { 118 | warnp("clock_getres(CLOCK_MONOTONIC)"); 119 | goto err0; 120 | } else 121 | #endif 122 | #ifdef USE_REALTIME 123 | if (clock_getres(CLOCK_REALTIME, &res) == 0) { 124 | /* Convert clock resolution to a double. */ 125 | *resd = (double)res.tv_sec + (double)res.tv_nsec * 0.000000001; 126 | } else { 127 | warnp("clock_getres(CLOCK_REALTIME)"); 128 | goto err0; 129 | } 130 | #else 131 | /* 132 | * We'll be using gettimeofday(). There is no standard way of getting 133 | * the resolution of this clock, but it seems safe to assume that it 134 | * ticks at a minimum rate of CLOCKS_PER_SEC Hz (even though that is 135 | * defined in relation to the measurement of processor time usage, not 136 | * wallclock time); on non-broken systems we'll be relying on 137 | * clock_gettime and clock_getres anyway. 138 | */ 139 | *resd = 1.0 / CLOCKS_PER_SEC; 140 | #endif 141 | 142 | /* Success! */ 143 | return (0); 144 | 145 | #if defined(USE_MONOTONIC) || defined(USE_REALTIME) 146 | err0: 147 | /* Failure! */ 148 | return (-1); 149 | #endif 150 | } 151 | -------------------------------------------------------------------------------- /libcperciva/util/monoclock.h: -------------------------------------------------------------------------------- 1 | #ifndef MONOCLOCK_H_ 2 | #define MONOCLOCK_H_ 3 | 4 | #include 5 | 6 | /* Macro to simplify benchmarks. */ 7 | #define timeval_diff(x, y) ((double)((y).tv_sec - (x).tv_sec) + \ 8 | (double)((y).tv_usec - (x).tv_usec) * 0.000001) 9 | 10 | /** 11 | * monoclock_get(tv): 12 | * Store the current time in ${tv}. If CLOCK_MONOTONIC is available, use 13 | * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if 14 | * available) or gettimeofday(2). 15 | */ 16 | int monoclock_get(struct timeval *); 17 | 18 | /** 19 | * monoclock_get_cputime(tv): 20 | * Store in ${tv} the duration the process has been running if 21 | * CLOCK_PROCESS_CPUTIME_ID is available; fall back to monoclock_get() 22 | * otherwise. 23 | */ 24 | int monoclock_get_cputime(struct timeval *); 25 | 26 | /** 27 | * monoclock_getres(resd): 28 | * Store an upper limit on timer granularity in ${resd}. If CLOCK_MONOTONIC 29 | * is available, use that clock; if CLOCK_MONOTONIC is unavailable, use 30 | * CLOCK_REALTIME (if available) or gettimeofday(2). For this value to be 31 | * meaningful, we assume that clock_getres(x) succeeds iff clock_gettime(x) 32 | * succeeds. 33 | */ 34 | int monoclock_getres(double *); 35 | 36 | #endif /* !MONOCLOCK_H_ */ 37 | -------------------------------------------------------------------------------- /libcperciva/util/parsenum.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSENUM_H_ 2 | #define PARSENUM_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* Handle compiler warnings about implicit variable conversion in PARSENUM. */ 12 | #ifdef __clang__ 13 | 14 | /* Disable clang warnings. */ 15 | #define PARSENUM_PROLOGUE \ 16 | _Pragma("clang diagnostic push") \ 17 | _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \ 18 | _Pragma("clang diagnostic ignored \"-Wfloat-conversion\"") \ 19 | _Pragma("clang diagnostic ignored \"-Wsign-conversion\"") \ 20 | _Pragma("clang diagnostic ignored \"-Wshorten-64-to-32\"") \ 21 | _Pragma("clang diagnostic ignored \"-Wconversion\"") 22 | 23 | /* Enable clang warnings for code outside of PARSENUM. */ 24 | #define PARSENUM_EPILOGUE \ 25 | _Pragma("clang diagnostic pop") 26 | 27 | /* Other compilers don't need any special handling */ 28 | #else 29 | #define PARSENUM_PROLOGUE /* NOTHING */ 30 | #define PARSENUM_EPILOGUE /* NOTHING */ 31 | #endif /* !__clang__ */ 32 | 33 | /* Print a message before assert(). */ 34 | #define ASSERT_FAIL(s) \ 35 | ( \ 36 | fprintf(stderr, "Assertion failed: " s \ 37 | ", function %s, file %s, line %d\n", \ 38 | __func__, __FILE__, __LINE__), \ 39 | abort() \ 40 | ) 41 | 42 | /** 43 | * PARSENUM(x, s, min, max): 44 | * Parse the string ${s} according to the type of the unsigned integer, signed 45 | * integer, or floating-point number variable ${x}. If the string consists of 46 | * optional whitespace followed by a number (and nothing else) and the numeric 47 | * interpretation of the number is between ${min} and ${max} inclusive, store 48 | * the value into ${x}, set errno to zero, and return zero. Otherwise, return 49 | * nonzero with an unspecified value of ${x} and errno set to EINVAL or ERANGE 50 | * as appropriate. 51 | * 52 | * For floating-point and unsigned integer variables ${x}, this can also be 53 | * invoked as PARSENUM(x, s), in which case the minimum and maximum values are 54 | * set to +/- infinity or the limits of the unsigned integer type. 55 | */ 56 | #define PARSENUM2(x, s) \ 57 | PARSENUM_EX4(x, s, 0, 0, "PARSENUM") 58 | #define PARSENUM4(x, s, min, max) \ 59 | PARSENUM_EX6(x, s, min, max, 0, 0, "PARSENUM") 60 | 61 | /* Magic to select which version of PARSENUM to use. */ 62 | #define PARSENUM(...) PARSENUM_(PARSENUM_COUNT(__VA_ARGS__))(__VA_ARGS__) 63 | #define PARSENUM_(N) PARSENUM__(N) 64 | #define PARSENUM__(N) PARSENUM ## N 65 | #define PARSENUM_COUNT(...) PARSENUM_COUNT_(__VA_ARGS__, 4, 3, 2, 1) 66 | #define PARSENUM_COUNT_(_1, _2, _3, _4, N, ...) N 67 | 68 | /** 69 | * PARSENUM_EX(x, s, min, max, base, trailing): 70 | * Parse the string ${s} according to the type of the unsigned integer or 71 | * signed integer variable ${x}, in the specified ${base}. If the string 72 | * consists of optional whitespace followed by a number (and nothing else) and 73 | * the numeric interpretation of the number is between ${min} and ${max} 74 | * inclusive, store the value into ${x}, set errno to zero, and return zero. 75 | * Otherwise, return nonzero with an unspecified value of ${x} and errno set 76 | * to EINVAL or ERANGE as appropriate. The check for trailing characters (and 77 | * EINVAL if they are found) is disabled if ${trailing} is non-zero. 78 | * 79 | * For an unsigned integer variable ${x}, this can also be invoked as 80 | * PARSENUM_EX(x, s, base), in which case the minimum and maximum values are 81 | * set to the limits of the unsigned integer type. 82 | * 83 | * For a floating-point variable ${x}, the ${base} must be 0. 84 | */ 85 | #define PARSENUM_EX4(x, s, base, trailing, _define_name) \ 86 | ( \ 87 | PARSENUM_PROLOGUE \ 88 | errno = 0, \ 89 | (((*(x)) = 1, (*(x)) /= 2) > 0) ? \ 90 | (((base) == 0) ? \ 91 | ((*(x)) = parsenum_float((s), \ 92 | (double)-INFINITY, \ 93 | (double)INFINITY, (trailing))) : \ 94 | (ASSERT_FAIL(_define_name " applied to" \ 95 | " float with base != 0"), 1)) : \ 96 | (((*(x)) = -1) > 0) ? \ 97 | ((*(x)) = parsenum_unsigned((s), 0, (*(x)), \ 98 | (*(x)), (base), (trailing))) : \ 99 | (ASSERT_FAIL(_define_name " applied to signed" \ 100 | " integer without specified bounds"), 1), \ 101 | errno != 0 \ 102 | PARSENUM_EPILOGUE \ 103 | ) 104 | #define PARSENUM_EX6(x, s, min, max, base, trailing, _define_name) \ 105 | ( \ 106 | PARSENUM_PROLOGUE \ 107 | errno = 0, \ 108 | (((*(x)) = 1, (*(x)) /= 2) > 0) ? \ 109 | (((base) == 0) ? \ 110 | ((*(x)) = parsenum_float((s), \ 111 | (double)(min), (double)(max), \ 112 | (trailing))) : \ 113 | (ASSERT_FAIL(_define_name " applied to" \ 114 | " float with base != 0"), 1)) : \ 115 | (((*(x)) = -1) <= 0) ? \ 116 | ((*(x)) = parsenum_signed((s), \ 117 | ((*(x)) <= 0) ? (min) : 0, \ 118 | ((*(x)) <= 0) ? (max) : 0, (base), \ 119 | (trailing))) : \ 120 | (((*(x)) = parsenum_unsigned((s), \ 121 | ((min) <= 0) ? 0 : (min), \ 122 | (uintmax_t)(max), (*(x)), (base), \ 123 | (trailing))), \ 124 | (((max) <= INTMAX_MAX) ? \ 125 | (((intmax_t)(max) < 0) && (errno == 0)) ? \ 126 | (errno = ERANGE) : \ 127 | 0 : 0)), \ 128 | errno != 0 \ 129 | PARSENUM_EPILOGUE \ 130 | ) 131 | 132 | /* Magic to select which version of PARSENUM_EX to use. */ 133 | #define PARSENUM_EX(...) \ 134 | PARSENUM_EX_(PARSENUM_EX_COUNT(__VA_ARGS__))(__VA_ARGS__, "PARSENUM_EX") 135 | #define PARSENUM_EX_(N) PARSENUM_EX__(N) 136 | #define PARSENUM_EX__(N) PARSENUM_EX ## N 137 | #define PARSENUM_EX_COUNT(...) \ 138 | PARSENUM_EX_COUNT_(__VA_ARGS__, 6, 5, 4, 3, 2, 1) 139 | #define PARSENUM_EX_COUNT_(_1, _2, _3, _4, _5, _6, N, ...) N 140 | 141 | /* Functions for performing the parsing and parameter checking. */ 142 | static inline double 143 | parsenum_float(const char * s, double min, double max, int trailing) 144 | { 145 | char * eptr; 146 | double val; 147 | 148 | /* Sanity check. */ 149 | assert(s != NULL); 150 | 151 | val = strtod(s, &eptr); 152 | if (eptr == s || (!trailing && (*eptr != '\0'))) 153 | errno = EINVAL; 154 | else if ((val < min) || (val > max)) 155 | errno = ERANGE; 156 | return (val); 157 | } 158 | 159 | static inline intmax_t 160 | parsenum_signed(const char * s, intmax_t min, intmax_t max, int base, 161 | int trailing) 162 | { 163 | char * eptr; 164 | intmax_t val; 165 | 166 | /* Sanity check. */ 167 | assert(s != NULL); 168 | 169 | val = strtoimax(s, &eptr, base); 170 | if (eptr == s || (!trailing && (*eptr != '\0'))) 171 | errno = EINVAL; 172 | else if ((val < min) || (val > max)) { 173 | errno = ERANGE; 174 | val = 0; 175 | } 176 | return (val); 177 | } 178 | 179 | static inline uintmax_t 180 | parsenum_unsigned(const char * s, uintmax_t min, uintmax_t max, 181 | uintmax_t typemax, int base, int trailing) 182 | { 183 | char * eptr; 184 | uintmax_t val; 185 | 186 | /* Sanity check. */ 187 | assert(s != NULL); 188 | 189 | val = strtoumax(s, &eptr, base); 190 | if (eptr == s || (!trailing && (*eptr != '\0'))) 191 | errno = EINVAL; 192 | else if ((val < min) || (val > max) || (val > typemax)) 193 | errno = ERANGE; 194 | return (val); 195 | } 196 | 197 | #endif /* !PARSENUM_H_ */ 198 | -------------------------------------------------------------------------------- /libcperciva/util/readpass.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "insecure_memzero.h" 8 | #include "warnp.h" 9 | 10 | #include "readpass.h" 11 | 12 | #define MAXPASSLEN 2048 13 | 14 | /* Signals we need to block. */ 15 | static const int badsigs[] = { 16 | SIGALRM, SIGHUP, SIGINT, 17 | SIGPIPE, SIGQUIT, SIGTERM, 18 | SIGTSTP, SIGTTIN, SIGTTOU 19 | }; 20 | #define NSIGS sizeof(badsigs)/sizeof(badsigs[0]) 21 | 22 | /* Highest signal number we care about. */ 23 | #define MAX2(a, b) ((a) > (b) ? (a) : (b)) 24 | #define MAX4(a, b, c, d) MAX2(MAX2(a, b), MAX2(c, d)) 25 | #define MAX8(a, b, c, d, e, f, g, h) MAX2(MAX4(a, b, c, d), MAX4(e, f, g, h)) 26 | #define MAXBADSIG MAX2(SIGALRM, MAX8(SIGHUP, SIGINT, SIGPIPE, SIGQUIT, \ 27 | SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU)) 28 | 29 | /* Has a signal of this type been received? */ 30 | static volatile sig_atomic_t gotsig[MAXBADSIG + 1]; 31 | 32 | /* Signal handler. */ 33 | static void 34 | handle(int sig) 35 | { 36 | 37 | gotsig[sig] = 1; 38 | } 39 | 40 | /* Restore old signals and re-issue intercepted signals. */ 41 | static void 42 | resetsigs(struct sigaction savedsa[NSIGS]) 43 | { 44 | size_t i; 45 | 46 | /* Restore old signals. */ 47 | for (i = 0; i < NSIGS; i++) 48 | sigaction(badsigs[i], &savedsa[i], NULL); 49 | 50 | /* If we intercepted a signal, re-issue it. */ 51 | for (i = 0; i < NSIGS; i++) { 52 | if (gotsig[badsigs[i]]) 53 | raise(badsigs[i]); 54 | } 55 | } 56 | 57 | /** 58 | * readpass(passwd, prompt, confirmprompt, devtty): 59 | * If ${devtty} is 0, read a password from stdin. If ${devtty} is 1, read a 60 | * password from /dev/tty if possible; if not, read from stdin. If ${devtty} 61 | * is 2, read a password from /dev/tty if possible; if not, exit with an error. 62 | * If reading from a tty (either /dev/tty or stdin), disable echo and prompt 63 | * the user by printing ${prompt} to stderr. If ${confirmprompt} is non-NULL, 64 | * read a second password (prompting if a terminal is being used) and repeat 65 | * until the user enters the same password twice. Return the password as a 66 | * malloced NUL-terminated string via ${passwd}. 67 | */ 68 | int 69 | readpass(char ** passwd, const char * prompt, 70 | const char * confirmprompt, int devtty) 71 | { 72 | FILE * readfrom; 73 | char passbuf[MAXPASSLEN]; 74 | char confpassbuf[MAXPASSLEN]; 75 | struct sigaction sa, savedsa[NSIGS]; 76 | struct termios term, term_old; 77 | size_t i; 78 | int usingtty; 79 | 80 | /* Where should we read the password from? */ 81 | switch (devtty) { 82 | case 0: 83 | /* Read directly from stdin. */ 84 | readfrom = stdin; 85 | break; 86 | case 1: 87 | /* Try to open /dev/tty; if that fails, read from stdin. */ 88 | if ((readfrom = fopen("/dev/tty", "r")) == NULL) 89 | readfrom = stdin; 90 | break; 91 | case 2: 92 | /* Try to open /dev/tty; if that fails, bail. */ 93 | if ((readfrom = fopen("/dev/tty", "r")) == NULL) { 94 | warnp("fopen(/dev/tty)"); 95 | goto err1; 96 | } 97 | break; 98 | default: 99 | warn0("readpass does not support devtty=%d", devtty); 100 | goto err1; 101 | } 102 | 103 | /* We have not received any signals yet. */ 104 | for (i = 0; i <= MAXBADSIG; i++) 105 | gotsig[i] = 0; 106 | 107 | /* 108 | * If we receive a signal while we're reading the password, we might 109 | * end up with echo disabled; to prevent this, we catch the signals 110 | * here, and we'll re-send them to ourselves later after we re-enable 111 | * terminal echo. 112 | */ 113 | sa.sa_handler = handle; 114 | sa.sa_flags = 0; 115 | sigemptyset(&sa.sa_mask); 116 | for (i = 0; i < NSIGS; i++) 117 | sigaction(badsigs[i], &sa, &savedsa[i]); 118 | 119 | /* If we're reading from a terminal, try to disable echo. */ 120 | if ((usingtty = isatty(fileno(readfrom))) != 0) { 121 | if (tcgetattr(fileno(readfrom), &term_old)) { 122 | warnp("Cannot read terminal settings"); 123 | goto err2; 124 | } 125 | memcpy(&term, &term_old, sizeof(struct termios)); 126 | term.c_lflag = (term.c_lflag & ~((tcflag_t)ECHO)) | ECHONL; 127 | if (tcsetattr(fileno(readfrom), TCSANOW, &term)) { 128 | warnp("Cannot set terminal settings"); 129 | goto err2; 130 | } 131 | } 132 | 133 | retry: 134 | /* If we have a terminal, prompt the user to enter the password. */ 135 | if (usingtty) 136 | fprintf(stderr, "%s: ", prompt); 137 | 138 | /* Read the password. */ 139 | if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) { 140 | if (feof(readfrom)) 141 | warn0("EOF reading password"); 142 | else 143 | warnp("Cannot read password"); 144 | goto err3; 145 | } 146 | 147 | /* Confirm the password if necessary. */ 148 | if (confirmprompt != NULL) { 149 | if (usingtty) 150 | fprintf(stderr, "%s: ", confirmprompt); 151 | if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) { 152 | if (feof(readfrom)) 153 | warn0("EOF reading password"); 154 | else 155 | warnp("Cannot read password"); 156 | goto err3; 157 | } 158 | if (strcmp(passbuf, confpassbuf)) { 159 | fprintf(stderr, 160 | "Passwords mismatch, please try again\n"); 161 | goto retry; 162 | } 163 | } 164 | 165 | /* Terminate the string at the first "\r" or "\n" (if any). */ 166 | passbuf[strcspn(passbuf, "\r\n")] = '\0'; 167 | 168 | /* If we changed terminal settings, reset them. */ 169 | if (usingtty) 170 | tcsetattr(fileno(readfrom), TCSANOW, &term_old); 171 | 172 | /* Restore old signals and re-issue intercepted signals. */ 173 | resetsigs(savedsa); 174 | 175 | /* Close /dev/tty if we opened it. */ 176 | if ((readfrom != stdin) && fclose(readfrom)) 177 | warnp("fclose"); 178 | 179 | /* Copy the password out. */ 180 | if ((*passwd = strdup(passbuf)) == NULL) { 181 | warnp("Cannot allocate memory"); 182 | goto err1; 183 | } 184 | 185 | /* 186 | * Zero any stored passwords. This is not guaranteed to work, since a 187 | * "sufficiently intelligent" compiler can optimize these out due to 188 | * the values not being accessed again; and even if we outwitted the 189 | * compiler, all we can do is ensure that *a* buffer is zeroed but 190 | * not that it is the only buffer containing the data in question. 191 | * Unfortunately the C standard does not provide any way to mark data 192 | * as "sensitive" in order to prevent extra copies being sprinkled 193 | * around the implementation address space. 194 | */ 195 | insecure_memzero(passbuf, MAXPASSLEN); 196 | insecure_memzero(confpassbuf, MAXPASSLEN); 197 | 198 | /* Success! */ 199 | return (0); 200 | 201 | err3: 202 | /* Reset terminal settings if necessary. */ 203 | if (usingtty) 204 | tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old); 205 | err2: 206 | /* Close /dev/tty if we opened it. */ 207 | if ((readfrom != stdin) && fclose(readfrom)) 208 | warnp("fclose"); 209 | 210 | /* Restore old signals and re-issue intercepted signals. */ 211 | resetsigs(savedsa); 212 | err1: 213 | /* Zero any stored passwords. */ 214 | insecure_memzero(passbuf, MAXPASSLEN); 215 | insecure_memzero(confpassbuf, MAXPASSLEN); 216 | 217 | /* Failure! */ 218 | return (-1); 219 | } 220 | -------------------------------------------------------------------------------- /libcperciva/util/readpass.h: -------------------------------------------------------------------------------- 1 | #ifndef READPASS_H_ 2 | #define READPASS_H_ 3 | 4 | /* Avoid namespace collisions with other "readpass" functions. */ 5 | #ifdef readpass 6 | #undef readpass 7 | #endif 8 | #define readpass libcperciva_readpass 9 | 10 | /** 11 | * readpass(passwd, prompt, confirmprompt, devtty): 12 | * If ${devtty} is 0, read a password from stdin. If ${devtty} is 1, read a 13 | * password from /dev/tty if possible; if not, read from stdin. If ${devtty} 14 | * is 2, read a password from /dev/tty if possible; if not, exit with an error. 15 | * If reading from a tty (either /dev/tty or stdin), disable echo and prompt 16 | * the user by printing ${prompt} to stderr. If ${confirmprompt} is non-NULL, 17 | * read a second password (prompting if a terminal is being used) and repeat 18 | * until the user enters the same password twice. Return the password as a 19 | * malloced NUL-terminated string via ${passwd}. 20 | */ 21 | int readpass(char **, const char *, const char *, int); 22 | 23 | /** 24 | * readpass_file(passwd, filename): 25 | * Read a passphrase from ${filename} and return it as a malloced 26 | * NUL-terminated string via ${passwd}. Print an error and fail if the file 27 | * is 2048 characters or more, or if it contains any newline \n or \r\n 28 | * characters other than at the end of the file. Do not include the \n or 29 | * \r\n characters in the passphrase. 30 | */ 31 | int readpass_file(char **, const char *); 32 | 33 | #endif /* !READPASS_H_ */ 34 | -------------------------------------------------------------------------------- /libcperciva/util/readpass_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "insecure_memzero.h" 5 | #include "warnp.h" 6 | 7 | #include "readpass.h" 8 | 9 | /* Maximum file length. */ 10 | #define MAXPASSLEN 2048 11 | 12 | /** 13 | * readpass_file(passwd, filename): 14 | * Read a passphrase from ${filename} and return it as a malloced 15 | * NUL-terminated string via ${passwd}. Print an error and fail if the file 16 | * is 2048 characters or more, or if it contains any newline \n or \r\n 17 | * characters other than at the end of the file. Do not include the \n or 18 | * \r\n characters in the passphrase. 19 | */ 20 | int 21 | readpass_file(char ** passwd, const char * filename) 22 | { 23 | FILE * f; 24 | char passbuf[MAXPASSLEN]; 25 | 26 | /* Open the file. */ 27 | if ((f = fopen(filename, "r")) == NULL) { 28 | warnp("fopen(%s)", filename); 29 | goto err1; 30 | } 31 | 32 | /* Get a line from the file. */ 33 | if ((fgets(passbuf, MAXPASSLEN, f)) == NULL) { 34 | if (ferror(f)) { 35 | warnp("fread(%s)", filename); 36 | goto err2; 37 | } else { 38 | /* We have a 0-byte password. */ 39 | passbuf[0] = '\0'; 40 | } 41 | } 42 | 43 | /* Bail if there's the line is too long, or if there's a second line. */ 44 | if (fgetc(f) != EOF) { 45 | warn0("line too long, or more than 1 line in %s", filename); 46 | goto err2; 47 | } 48 | 49 | /* Close the file. */ 50 | if (fclose(f)) { 51 | warnp("fclose(%s)", filename); 52 | goto err1; 53 | } 54 | 55 | /* Truncate at any newline character. */ 56 | passbuf[strcspn(passbuf, "\r\n")] = '\0'; 57 | 58 | /* Copy the password out. */ 59 | if ((*passwd = strdup(passbuf)) == NULL) { 60 | warnp("Cannot allocate memory"); 61 | goto err1; 62 | } 63 | 64 | /* Clean up. */ 65 | insecure_memzero(passbuf, MAXPASSLEN); 66 | 67 | /* Success! */ 68 | return (0); 69 | 70 | err2: 71 | if (fclose(f)) 72 | warnp("fclose"); 73 | err1: 74 | /* No harm in running this for all error paths. */ 75 | insecure_memzero(passbuf, MAXPASSLEN); 76 | 77 | /* Failure! */ 78 | return (-1); 79 | } 80 | -------------------------------------------------------------------------------- /libcperciva/util/sysendian.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSENDIAN_H_ 2 | #define SYSENDIAN_H_ 3 | 4 | #include 5 | 6 | /* Avoid namespace collisions with BSD . */ 7 | #define be16dec libcperciva_be16dec 8 | #define be16enc libcperciva_be16enc 9 | #define be32dec libcperciva_be32dec 10 | #define be32enc libcperciva_be32enc 11 | #define be64dec libcperciva_be64dec 12 | #define be64enc libcperciva_be64enc 13 | #define le16dec libcperciva_le16dec 14 | #define le16enc libcperciva_le16enc 15 | #define le32dec libcperciva_le32dec 16 | #define le32enc libcperciva_le32enc 17 | #define le64dec libcperciva_le64dec 18 | #define le64enc libcperciva_le64enc 19 | 20 | static inline uint16_t 21 | be16dec(const void * pp) 22 | { 23 | const uint8_t * p = (uint8_t const *)pp; 24 | 25 | return (uint16_t)((uint16_t)(p[1]) | ((uint16_t)(p[0]) << 8)); 26 | } 27 | 28 | static inline void 29 | be16enc(void * pp, uint16_t x) 30 | { 31 | uint8_t * p = (uint8_t *)pp; 32 | 33 | p[1] = x & 0xff; 34 | p[0] = (x >> 8) & 0xff; 35 | } 36 | 37 | static inline uint32_t 38 | be32dec(const void * pp) 39 | { 40 | const uint8_t * p = (uint8_t const *)pp; 41 | 42 | return ((uint32_t)(p[3]) | ((uint32_t)(p[2]) << 8) | 43 | ((uint32_t)(p[1]) << 16) | ((uint32_t)(p[0]) << 24)); 44 | } 45 | 46 | static inline void 47 | be32enc(void * pp, uint32_t x) 48 | { 49 | uint8_t * p = (uint8_t *)pp; 50 | 51 | p[3] = x & 0xff; 52 | p[2] = (x >> 8) & 0xff; 53 | p[1] = (x >> 16) & 0xff; 54 | p[0] = (x >> 24) & 0xff; 55 | } 56 | 57 | static inline uint64_t 58 | be64dec(const void * pp) 59 | { 60 | const uint8_t * p = (uint8_t const *)pp; 61 | 62 | return ((uint64_t)(p[7]) | ((uint64_t)(p[6]) << 8) | 63 | ((uint64_t)(p[5]) << 16) | ((uint64_t)(p[4]) << 24) | 64 | ((uint64_t)(p[3]) << 32) | ((uint64_t)(p[2]) << 40) | 65 | ((uint64_t)(p[1]) << 48) | ((uint64_t)(p[0]) << 56)); 66 | } 67 | 68 | static inline void 69 | be64enc(void * pp, uint64_t x) 70 | { 71 | uint8_t * p = (uint8_t *)pp; 72 | 73 | p[7] = x & 0xff; 74 | p[6] = (x >> 8) & 0xff; 75 | p[5] = (x >> 16) & 0xff; 76 | p[4] = (x >> 24) & 0xff; 77 | p[3] = (x >> 32) & 0xff; 78 | p[2] = (x >> 40) & 0xff; 79 | p[1] = (x >> 48) & 0xff; 80 | p[0] = (x >> 56) & 0xff; 81 | } 82 | 83 | static inline uint16_t 84 | le16dec(const void * pp) 85 | { 86 | const uint8_t * p = (uint8_t const *)pp; 87 | 88 | return (uint16_t)((uint16_t)(p[0]) | ((uint16_t)(p[1]) << 8)); 89 | } 90 | 91 | static inline void 92 | le16enc(void * pp, uint16_t x) 93 | { 94 | uint8_t * p = (uint8_t *)pp; 95 | 96 | p[0] = x & 0xff; 97 | p[1] = (x >> 8) & 0xff; 98 | } 99 | 100 | static inline uint32_t 101 | le32dec(const void * pp) 102 | { 103 | const uint8_t * p = (uint8_t const *)pp; 104 | 105 | return ((uint32_t)(p[0]) | ((uint32_t)(p[1]) << 8) | 106 | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24)); 107 | } 108 | 109 | static inline void 110 | le32enc(void * pp, uint32_t x) 111 | { 112 | uint8_t * p = (uint8_t *)pp; 113 | 114 | p[0] = x & 0xff; 115 | p[1] = (x >> 8) & 0xff; 116 | p[2] = (x >> 16) & 0xff; 117 | p[3] = (x >> 24) & 0xff; 118 | } 119 | 120 | static inline uint64_t 121 | le64dec(const void * pp) 122 | { 123 | const uint8_t * p = (uint8_t const *)pp; 124 | 125 | return ((uint64_t)(p[0]) | ((uint64_t)(p[1]) << 8) | 126 | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | 127 | ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) | 128 | ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56)); 129 | } 130 | 131 | static inline void 132 | le64enc(void * pp, uint64_t x) 133 | { 134 | uint8_t * p = (uint8_t *)pp; 135 | 136 | p[0] = x & 0xff; 137 | p[1] = (x >> 8) & 0xff; 138 | p[2] = (x >> 16) & 0xff; 139 | p[3] = (x >> 24) & 0xff; 140 | p[4] = (x >> 32) & 0xff; 141 | p[5] = (x >> 40) & 0xff; 142 | p[6] = (x >> 48) & 0xff; 143 | p[7] = (x >> 56) & 0xff; 144 | } 145 | 146 | #endif /* !SYSENDIAN_H_ */ 147 | -------------------------------------------------------------------------------- /libcperciva/util/warnp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "warnp.h" 9 | 10 | static int initialized = 0; 11 | static char * name = NULL; 12 | static int use_syslog = 0; 13 | static int syslog_priority = LOG_WARNING; 14 | 15 | /* Free the name string and clean up writing to the syslog (if applicable). */ 16 | static void 17 | warnp_atexit(void) 18 | { 19 | 20 | /* Clean up writing to the syslog (if applicable). */ 21 | if (use_syslog) 22 | closelog(); 23 | 24 | free(name); 25 | name = NULL; 26 | } 27 | 28 | /** 29 | * warnp_setprogname(progname): 30 | * Set the program name to be used by warn() and warnx() to ${progname}. 31 | */ 32 | void 33 | warnp_setprogname(const char * progname) 34 | { 35 | const char * p; 36 | 37 | /* Free the name if we already have one. */ 38 | free(name); 39 | 40 | /* Find the last segment of the program name. */ 41 | for (p = progname; progname[0] != '\0'; progname++) 42 | if (progname[0] == '/') 43 | p = progname + 1; 44 | 45 | /* Copy the name string. */ 46 | name = strdup(p); 47 | 48 | /* If we haven't already done so, register our exit handler. */ 49 | if (initialized == 0) { 50 | atexit(warnp_atexit); 51 | initialized = 1; 52 | } 53 | } 54 | 55 | /* This function will preserve errno. */ 56 | void 57 | warn(const char * fmt, ...) 58 | { 59 | va_list ap; 60 | char msgbuf[WARNP_SYSLOG_MAX_LINE + 1]; 61 | int saved_errno; 62 | 63 | /* Save errno in case it gets clobbered. */ 64 | saved_errno = errno; 65 | 66 | va_start(ap, fmt); 67 | if (use_syslog == 0) { 68 | /* Stop other threads writing to stderr. */ 69 | flockfile(stderr); 70 | 71 | /* Print to stderr. */ 72 | fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); 73 | if (fmt != NULL) { 74 | fprintf(stderr, ": "); 75 | vfprintf(stderr, fmt, ap); 76 | } 77 | fprintf(stderr, ": %s\n", strerror(saved_errno)); 78 | 79 | /* Allow other threads to write to stderr. */ 80 | funlockfile(stderr); 81 | } else { 82 | /* Print to syslog. */ 83 | if (fmt != NULL) { 84 | /* No need to print "${name}: "; syslog does it. */ 85 | vsnprintf(msgbuf, WARNP_SYSLOG_MAX_LINE + 1, fmt, ap); 86 | syslog(syslog_priority, "%s: %s\n", msgbuf, 87 | strerror(saved_errno)); 88 | } else 89 | syslog(syslog_priority, "%s\n", strerror(saved_errno)); 90 | } 91 | va_end(ap); 92 | 93 | /* Restore saved errno. */ 94 | errno = saved_errno; 95 | } 96 | 97 | /* This function will preserve errno. */ 98 | void 99 | warnx(const char * fmt, ...) 100 | { 101 | va_list ap; 102 | char msgbuf[WARNP_SYSLOG_MAX_LINE + 1]; 103 | int saved_errno; 104 | 105 | /* Save errno in case it gets clobbered. */ 106 | saved_errno = errno; 107 | 108 | va_start(ap, fmt); 109 | if (use_syslog == 0) { 110 | /* Stop other threads writing to stderr. */ 111 | flockfile(stderr); 112 | 113 | /* Print to stderr. */ 114 | fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)"); 115 | if (fmt != NULL) { 116 | fprintf(stderr, ": "); 117 | vfprintf(stderr, fmt, ap); 118 | } 119 | fprintf(stderr, "\n"); 120 | 121 | /* Allow other threads to write to stderr. */ 122 | funlockfile(stderr); 123 | } else { 124 | /* Print to syslog. */ 125 | if (fmt != NULL) { 126 | /* No need to print "${name}: "; syslog does it. */ 127 | vsnprintf(msgbuf, WARNP_SYSLOG_MAX_LINE + 1, fmt, ap); 128 | syslog(syslog_priority, "%s\n", msgbuf); 129 | } else 130 | syslog(syslog_priority, "\n"); 131 | } 132 | va_end(ap); 133 | 134 | /* Restore saved errno. */ 135 | errno = saved_errno; 136 | } 137 | 138 | /** 139 | * warnp_syslog(enable): 140 | * Send future messages to syslog if ${enable} is non-zero. Messages to 141 | * syslog will be truncated at WARNP_SYSLOG_MAX_LINE characters. 142 | */ 143 | void 144 | warnp_syslog(int enable) 145 | { 146 | 147 | /* Clean up writing to the syslog (if applicable). */ 148 | if (use_syslog && !enable) 149 | closelog(); 150 | 151 | use_syslog = enable; 152 | } 153 | 154 | /** 155 | * warnp_syslog_priority(priority): 156 | * Tag future syslog messages with priority ${priority}. Do not enable 157 | * syslog messages; for that, use warnp_syslog(). 158 | */ 159 | void 160 | warnp_syslog_priority(int priority) 161 | { 162 | 163 | syslog_priority = priority; 164 | } 165 | -------------------------------------------------------------------------------- /libcperciva/util/warnp.h: -------------------------------------------------------------------------------- 1 | #ifndef WARNP_H_ 2 | #define WARNP_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Avoid namespace collisions with BSD . */ 8 | #define warn libcperciva_warn 9 | #define warnx libcperciva_warnx 10 | 11 | /* 12 | * Maximum length of messages sent to syslog; longer warnings will 13 | * be truncated. 14 | */ 15 | #define WARNP_SYSLOG_MAX_LINE 4095 16 | 17 | /** 18 | * warnp_setprogname(progname): 19 | * Set the program name to be used by warn() and warnx() to ${progname}. 20 | */ 21 | void warnp_setprogname(const char *); 22 | #define WARNP_INIT do { \ 23 | if (argv[0] != NULL) \ 24 | warnp_setprogname(argv[0]); \ 25 | } while (0) 26 | 27 | /** 28 | * warnp_syslog(enable): 29 | * Send future messages to syslog if ${enable} is non-zero. Messages to 30 | * syslog will be truncated at WARNP_SYSLOG_MAX_LINE characters. 31 | */ 32 | void warnp_syslog(int); 33 | 34 | /** 35 | * warnp_syslog_priority(priority): 36 | * Tag future syslog messages with priority ${priority}. Do not enable 37 | * syslog messages; for that, use warnp_syslog(). 38 | */ 39 | void warnp_syslog_priority(int); 40 | 41 | /* As in BSD . */ 42 | void warn(const char *, ...); 43 | void warnx(const char *, ...); 44 | 45 | /* 46 | * If compiled with DEBUG defined, print __FILE__ and __LINE__. 47 | */ 48 | #ifdef DEBUG 49 | #define warnline do { \ 50 | warnx("%s, %d", __FILE__, __LINE__); \ 51 | } while (0) 52 | #else 53 | #define warnline 54 | #endif 55 | 56 | /* 57 | * Call warn(3) or warnx(3) depending upon whether errno == 0; and clear 58 | * errno (so that the standard error message isn't repeated later). 59 | */ 60 | #define warnp(...) do { \ 61 | warnline; \ 62 | if (errno != 0) { \ 63 | warn(__VA_ARGS__); \ 64 | errno = 0; \ 65 | } else \ 66 | warnx(__VA_ARGS__); \ 67 | } while (0) 68 | 69 | /* 70 | * Call warnx(3) and set errno == 0. Unlike warnp(), this should be used 71 | * in cases where we're reporting a problem which we discover ourselves 72 | * rather than one which is reported to us from a library or the kernel. 73 | */ 74 | #define warn0(...) do { \ 75 | warnline; \ 76 | warnx(__VA_ARGS__); \ 77 | errno = 0; \ 78 | } while (0) 79 | 80 | #endif /* !WARNP_H_ */ 81 | -------------------------------------------------------------------------------- /libscrypt-kdf/scrypt-kdf.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef SCRYPT_KDF_H 30 | #define SCRYPT_KDF_H 31 | 32 | #include 33 | #include 34 | 35 | /* Compatibility for C++. */ 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /* Internal name of function. */ 41 | #define scrypt_kdf crypto_scrypt 42 | 43 | /** 44 | * scrypt_kdf(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 45 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 46 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 47 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 48 | * must be a power of 2 greater than 1. 49 | * 50 | * Return 0 on success; or -1 on error. 51 | */ 52 | int scrypt_kdf(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 53 | uint32_t, uint32_t, uint8_t *, size_t); 54 | 55 | /* End compatibility for C++. */ 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | #endif /* !SCRYPT_KDF_H */ 61 | -------------------------------------------------------------------------------- /m4/check_darwin_paths.m4: -------------------------------------------------------------------------------- 1 | # CHECK_DARWIN_PATHS 2 | # ------------------- 3 | AC_DEFUN([CHECK_DARWIN_PATHS], 4 | [AC_REQUIRE([AC_CANONICAL_TARGET]) 5 | 6 | case $target_os in 7 | *darwin*) 8 | # Get the homebrew directory, which varies based on arch. 9 | case "$(uname -m)" in 10 | arm64) 11 | homebrew_dir=/opt/homebrew 12 | ;; 13 | *) 14 | homebrew_dir=/usr/local 15 | ;; 16 | esac 17 | 18 | # Use the homebrew directory to specify the paths to openssl. 19 | CPPFLAGS="${CPPFLAGS} -I${homebrew_dir}/opt/openssl/include" 20 | LDFLAGS="${LDFLAGS} -L${homebrew_dir}/opt/openssl/lib" 21 | ;; 22 | esac 23 | ])# CHECK_DARWIN_PATHS 24 | -------------------------------------------------------------------------------- /m4/check_disable_compiler_warnings.m4: -------------------------------------------------------------------------------- 1 | # CHECK_DISABLE_COMPILER_WARNINGS 2 | # ------------------------------- 3 | AC_DEFUN([CHECK_DISABLE_COMPILER_WARNINGS], [ 4 | AC_MSG_CHECKING([compiler_warnings]) 5 | AC_ARG_ENABLE(compiler_warnings, 6 | AS_HELP_STRING([--disable-compiler-warnings], 7 | [Do not request compiler warnings. @<:@default=enabled@:>@]), 8 | [ac_compiler_warnings=$enableval], 9 | [ac_compiler_warnings=yes]) 10 | AC_MSG_RESULT([${ac_compiler_warnings}]) 11 | AS_IF([test x${ac_compiler_warnings} = xyes], 12 | [AX_CFLAGS_WARN_ALL]) 13 | ])# CHECK_DISABLE_COMPILER_WARNINGS 14 | -------------------------------------------------------------------------------- /m4/check_libcperciva_posix.m4: -------------------------------------------------------------------------------- 1 | # CHECK_LIBCPERCIVA_POSIX([LIBCPERCIVA_DIR]) 2 | # ------------------------------------------ 3 | AC_DEFUN([CHECK_LIBCPERCIVA_POSIX], [ 4 | AC_REQUIRE([CHECK_POSIX_SH]) 5 | AC_MSG_NOTICE([checking POSIX compatibility...]) 6 | LIBCPERCIVA_DIR="$1" 7 | LDADD_POSIX=`export CC="${CC}"; ${POSIX_SH} ${LIBCPERCIVA_DIR}/POSIX/posix-l.sh "$PATH"` 8 | CFLAGS_POSIX=`export CC="${CC}"; ${POSIX_SH} ${LIBCPERCIVA_DIR}/POSIX/posix-cflags.sh "$PATH"` 9 | AC_SUBST([LDADD_POSIX]) 10 | AC_SUBST([CFLAGS_POSIX]) 11 | AC_MSG_RESULT([... done checking POSIX compatibility]) 12 | ])# CHECK_LIBCPERCIVA_POSIX 13 | -------------------------------------------------------------------------------- /m4/check_memlimit_support.m4: -------------------------------------------------------------------------------- 1 | # CHECK_MEMLIMIT_SUPPORT 2 | # ---------------------- 3 | AC_DEFUN([CHECK_MEMLIMIT_SUPPORT], [ 4 | # Check for a linuxy sysinfo syscall; and while we're doing that, 5 | # check if struct sysinfo is the old version (total RAM == totalmem) 6 | # or the new version (total RAM == totalmem * mem_unit). 7 | AC_CHECK_HEADERS_ONCE([sys/sysinfo.h]) 8 | AC_CHECK_FUNCS_ONCE([sysinfo]) 9 | AC_CHECK_TYPES([struct sysinfo], [], [], [[#include ]]) 10 | AC_CHECK_MEMBERS([struct sysinfo.totalram, struct sysinfo.mem_unit], 11 | [], [], [[#include ]]) 12 | 13 | # Check if we have , since some systems require it for 14 | # sysctl to work. 15 | AC_CHECK_HEADERS_ONCE([sys/param.h]) 16 | 17 | # Check for . If it exists and it defines HW_USERMEM 18 | # and/or HW_MEMSIZE, we'll try using those as memory limits. 19 | AC_CHECK_HEADERS_ONCE([sys/sysctl.h]) 20 | ])# CHECK_MEMLIMIT_SUPPORT 21 | -------------------------------------------------------------------------------- /m4/check_posix_sh.m4: -------------------------------------------------------------------------------- 1 | # CHECK_POSIX_SH 2 | # -------------- 3 | AC_DEFUN([CHECK_POSIX_SH], [ 4 | # Allow users to manually specify the path to a POSIX shell. 5 | AC_ARG_VAR([POSIX_SH], [path of a POSIX shell]) 6 | 7 | AS_IF([test "x${POSIX_SH}" = "x"], [ 8 | # If POSIX_SH is not set, get the default value of PATH which 9 | # is specified to find the standard POSIX utilities. 10 | POSIX_PATH=`command -p getconf PATH` 11 | AS_IF([test "x${POSIX_PATH}" = "x"], 12 | AC_MSG_ERROR(["cannot get the default PATH"])) 13 | # Get the path of sh within POSIX_PATH. 14 | AC_PATH_PROG([POSIX_SH], [sh], [""], [${POSIX_PATH}]) 15 | AS_IF([test "x${POSIX_SH}" = "x"], 16 | AC_MSG_ERROR(["cannot find a POSIX shell"])) 17 | ]) 18 | ])# CHECK_POSIX_SH 19 | -------------------------------------------------------------------------------- /m4/check_solaris_c99.m4: -------------------------------------------------------------------------------- 1 | # CHECK_SOLARIS_C99 2 | # ----------------- 3 | # On Solaris, the default standard library is c89-compatible. Some linkers 4 | # require -std=c99 to link to the c99-compatible library. 5 | AC_DEFUN([CHECK_SOLARIS_C99], 6 | [AC_REQUIRE([AC_CANONICAL_TARGET]) 7 | 8 | case $target_os in 9 | *solaris* | *sunos*) 10 | AC_MSG_CHECKING([Solaris c99 standard library]) 11 | AC_RUN_IFELSE([AC_LANG_SOURCE([[#include 12 | int main(void) { 13 | char * eptr; 14 | strtod("0x1", &eptr); 15 | return (eptr[0] != '\0'); 16 | }]])], 17 | [AC_MSG_RESULT([yes])], 18 | [# If we failed, try adding -std=c99 to the LDFLAGS. 19 | LDFLAGS="${LDFLAGS} -std=c99" 20 | AC_RUN_IFELSE([AC_LANG_SOURCE([[#include 21 | int main(void) { 22 | char * eptr; 23 | strtod("0x1", &eptr); 24 | return (eptr[0] != '\0'); 25 | }]])], 26 | [AC_MSG_RESULT([yes, if linked with -std=c99])], 27 | [AC_MSG_RESULT([no]) 28 | AC_MSG_ERROR([c99 required])], 29 | # This should never arise, because the outer _ifelse 30 | # would jump to the action-if-cross-compiling rather 31 | # than executing its action-if-false. However, adding 32 | # this explicitly makes autoconf happier. 33 | [AC_MSG_RESULT([skipping due to cross-compiling])] 34 | )], 35 | [AC_MSG_RESULT([skipping due to cross-compiling])]) 36 | ;; 37 | *) 38 | ;; 39 | esac 40 | 41 | ])# CHECK_SOLARIS_C99 42 | -------------------------------------------------------------------------------- /release-tools/create-sign-tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Process command-line arguments 4 | SCRYPTVERSION=$1 5 | GNUPG_SIGNING_HOME=$2 6 | 7 | # Check for required arguments 8 | if [ -z "${SCRYPTVERSION}" ] || [ -z "${GNUPG_SIGNING_HOME}" ]; then 9 | echo "Usage: $0 SCRYPTVERSION GNUPG_SIGNING_HOME" 10 | exit 1 11 | fi 12 | 13 | # Check for correct OS 14 | if [ "$(uname)" != "FreeBSD" ]; then 15 | echo "Error: This script only works on FreeBSD due to the" 16 | echo " sha256 \${PKGNAME}.tgz" 17 | echo "command, which has a different meaning on other OSes." 18 | exit 1 19 | fi 20 | 21 | # Constants 22 | PKGNAME=scrypt-${SCRYPTVERSION} 23 | PKGSIGS=scrypt-sigs-${SCRYPTVERSION} 24 | 25 | # Get directory of script 26 | dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P) 27 | 28 | # Create tarball 29 | sh "${dir}/mktarball.sh" "${SCRYPTVERSION}" 30 | 31 | # Sign tarball 32 | sha256 "${PKGNAME}.tgz" | \ 33 | GNUPGHOME=${GNUPG_SIGNING_HOME} gpg --clearsign \ 34 | > "${PKGSIGS}.asc" 35 | -------------------------------------------------------------------------------- /release-tools/mktarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | VERSION=$1 4 | if [ -z "${VERSION}" ]; then 5 | echo "Please specify the version number" 6 | exit 1 7 | fi 8 | DESTDIR=scrypt-${VERSION} 9 | RELEASEDATE=$(date "+%B %d, %Y") 10 | 11 | # Copy bits in 12 | mkdir "${DESTDIR}" "${DESTDIR}/autotools" 13 | cp main.c FORMAT COPYRIGHT BUILDING README.md STYLE "${DESTDIR}" 14 | cp Makefile.am .autom4te.cfg "${DESTDIR}" 15 | cp Makefile.am "${DESTDIR}/autotools" 16 | cp -R lib lib-platform libcperciva libscrypt-kdf m4 tests "${DESTDIR}" 17 | # Copy with substitution 18 | sed -e "s/@DATE@/${RELEASEDATE}/" < scrypt.1 > "${DESTDIR}/scrypt.1" 19 | sed -e "s/\[m4_esyscmd(\[sh get-version\.sh\])]/${VERSION}/" \ 20 | < configure.ac > "${DESTDIR}/configure.ac" 21 | cp "${DESTDIR}/configure.ac" "${DESTDIR}/autotools" 22 | 23 | # Generate autotools files 24 | ( cd "${DESTDIR}" || exit 25 | autoreconf -i 26 | rm .autom4te.cfg Makefile.am aclocal.m4 configure.ac ) 27 | 28 | # Create tarball 29 | tar -czf "${DESTDIR}.tgz" "${DESTDIR}" 30 | rm -r "${DESTDIR}" 31 | -------------------------------------------------------------------------------- /tests/01-known-values.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | # The scenario command requires a lot of memory, so valgrind is only enabled 5 | # if $USE_VALGRIND > 1. 6 | c_valgrind_min=2 7 | test_output="${s_basename}-stdout.txt" 8 | reference="${scriptdir}/verify-strings/test_scrypt.good" 9 | reference_small="${scriptdir}/verify-strings/test_scrypt_small.good" 10 | 11 | ### Actual command 12 | scenario_cmd() { 13 | # Run the binary which tests known input/output strings. 14 | setup_check "test_scrypt" 15 | ( 16 | ${c_valgrind_cmd} "${bindir}/tests/verify-strings/test_scrypt" \ 17 | "${SMALLMEM:-0}" 1> "${test_output}" 18 | echo $? > "${c_exitfile}" 19 | ) 20 | 21 | # The generated values should match the known good values. 22 | setup_check "test_scrypt output against reference" 23 | if [ "${SMALLMEM:-0}" -gt "0" ]; then 24 | cmp -s "${test_output}" "${reference_small}" 25 | else 26 | cmp -s "${test_output}" "${reference}" 27 | fi 28 | echo $? > "${c_exitfile}" 29 | } 30 | -------------------------------------------------------------------------------- /tests/02-decrypt-reference-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | encrypted_reference_file="${scriptdir}/verify-strings/test_scrypt_good.enc" 7 | decrypted_reference_file="${s_basename}-attempt_reference.txt" 8 | decrypted_reference_file_stderr="${s_basename}-attempt_reference.stderr" 9 | decrypted_badpass_file="${s_basename}-decrypt-badpass.txt" 10 | decrypted_badpass_log="${s_basename}-decrypt-badpass.log" 11 | 12 | scenario_cmd() { 13 | # Decrypt a reference file. 14 | setup_check "scrypt dec" 15 | ( 16 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 17 | dec -P "${encrypted_reference_file}" \ 18 | "${decrypted_reference_file}" \ 19 | 2> "${decrypted_reference_file_stderr}" 20 | echo $? > "${c_exitfile}" 21 | ) 22 | 23 | # The decrypted reference file should match the reference. 24 | setup_check "scrypt dec output against reference" 25 | cmp -s "${decrypted_reference_file}" "${reference_file}" 26 | echo $? > "${c_exitfile}" 27 | 28 | # We should not have any output on stderr. 29 | setup_check "scrypt dec no stderr" 30 | test -s "${decrypted_reference_file_stderr}" 31 | expected_exitcode 1 $? > "${c_exitfile}" 32 | 33 | # Attempt to decrypt the reference file with an incorrect passphrase. 34 | # We want this command to fail with 1. 35 | setup_check "scrypt dec bad passphrase" 36 | ( 37 | echo "bad-pass" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 38 | dec -P "${encrypted_reference_file}" \ 39 | "${decrypted_badpass_file}" \ 40 | 2> "${decrypted_badpass_log}" 41 | expected_exitcode 1 $? > "${c_exitfile}" 42 | ) 43 | 44 | # We should have received an error message. 45 | setup_check "scrypt dec bad passphrase error" 46 | if grep -q "scrypt: Passphrase is incorrect" \ 47 | "${decrypted_badpass_log}"; then 48 | echo "0" 49 | else 50 | echo "1" 51 | fi > "${c_exitfile}" 52 | 53 | # We should not have created a file. 54 | setup_check "scrypt dec bad passphrase no file" 55 | if [ -e "${decrypted_badpass_file}" ]; then 56 | echo "1" 57 | else 58 | echo "0" 59 | fi > "${c_exitfile}" 60 | } 61 | -------------------------------------------------------------------------------- /tests/03-encrypt-decrypt-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | encrypted_file="${s_basename}-attempt.enc" 7 | decrypted_file="${s_basename}-attempt.txt" 8 | 9 | scenario_cmd() { 10 | # Encrypt a file. Use --passphrase dev:stdin-once instead of -P. 11 | setup_check "scrypt enc" 12 | ( 13 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 14 | enc --passphrase dev:stdin-once -t 1 \ 15 | "${reference_file}" "${encrypted_file}" 16 | echo $? > "${c_exitfile}" 17 | ) 18 | 19 | # The encrypted file should be different from the original file. 20 | # We cannot check against the "reference" encrypted file, because 21 | # encrypted files include random salt. If successful, don't delete 22 | # ${encrypted_file} yet; we need it for the next test. 23 | setup_check "scrypt enc random salt" 24 | cmp -s "${encrypted_file}" "${reference_file}" 25 | expected_exitcode 1 $? > "${c_exitfile}" 26 | 27 | # Decrypt the file we just encrypted. 28 | setup_check "scrypt enc decrypt" 29 | ( 30 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 31 | dec -P "${encrypted_file}" "${decrypted_file}" 32 | echo $? > "${c_exitfile}" 33 | ) 34 | 35 | # The decrypted file should match the reference. 36 | setup_check "scrypt enc decrypt output against reference" 37 | cmp -s "${decrypted_file}" "${reference_file}" 38 | echo $? > "${c_exitfile}" 39 | } 40 | -------------------------------------------------------------------------------- /tests/04-force-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | longwait_encrypted_file="${s_basename}.enc" 7 | longwait_decrypted_file="${s_basename}.txt" 8 | longwait_failed_log="${s_basename}-failed.log" 9 | 10 | scenario_cmd() { 11 | # Encrypt file which should take a long time to decrypt. 12 | setup_check "scrypt enc 10 seconds" 13 | ( 14 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 15 | enc -P -t 10 "${reference_file}" \ 16 | "${longwait_encrypted_file}" 17 | echo $? > "${c_exitfile}" 18 | ) 19 | 20 | # Attempt to decrypt it with limited time. We want this 21 | # command to fail, so we negate the normal return code. 22 | setup_check "scrypt dec 0.1 seconds" 23 | ( 24 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 25 | dec -P -t 0.1 "${longwait_encrypted_file}" \ 26 | "${longwait_decrypted_file}" \ 27 | 2> "${longwait_failed_log}" 28 | expected_exitcode 1 $? > "${c_exitfile}" 29 | ) 30 | 31 | # We should have received an error message. 32 | setup_check "scrypt dec 1 second error" 33 | grep -q "scrypt: Decrypting file would take too much CPU time" \ 34 | "${longwait_failed_log}" 35 | echo "$?" > "${c_exitfile}" 36 | 37 | # Attempt to decrypt it with limited time, but force success. 38 | setup_check "scrypt dec force" 39 | ( 40 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 41 | dec -P -t 1 -f "${longwait_encrypted_file}" \ 42 | "${longwait_decrypted_file}" 43 | echo $? > "${c_exitfile}" 44 | ) 45 | 46 | # The decrypted reference file should match the reference. 47 | setup_check "scrypt dec force output against reference" 48 | cmp -s "${longwait_decrypted_file}" "${reference_file}" 49 | echo $? > "${c_exitfile}" 50 | } 51 | -------------------------------------------------------------------------------- /tests/05-system-scrypt-encrypt-decrypt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | encrypted_file_1="${s_basename}-sys.enc" 7 | decrypted_file_1="${s_basename}-sys.txt" 8 | encrypted_file_2="${s_basename}-our.enc" 9 | decrypted_file_2="${s_basename}-our.txt" 10 | 11 | scenario_cmd() { 12 | if [ -z "${system_scrypt}" ]; then 13 | printf "no suitable system scrypt: " 1>&2 14 | # Inform test suite that we are skipping. 15 | setup_check "system scrypt skip" 16 | echo "-1" > "${c_exitfile}" 17 | return 18 | fi 19 | 20 | # Encrypt a file with our scrypt. 21 | setup_check "scrypt enc for system" 22 | ( 23 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 24 | enc -P -t 1 "${reference_file}" "${encrypted_file_1}" 25 | echo $? > "${c_exitfile}" 26 | ) 27 | 28 | # Use the system scrypt to decrypt the file we just 29 | # encrypted. Don't use valgrind for this. 30 | setup_check "system scrypt dec" 31 | ( 32 | echo "${password}" | ${system_scrypt} \ 33 | dec -P "${encrypted_file_1}" "${decrypted_file_1}" 34 | echo $? > "${c_exitfile}" 35 | ) 36 | 37 | # The decrypted file should match the reference. 38 | setup_check "system scrypt dec output against reference" 39 | cmp -s "${decrypted_file_1}" "${reference_file}" 40 | echo $? > "${c_exitfile}" 41 | 42 | # Encrypt a file with the system scrypt. Don't use 43 | # valgrind for this. 44 | setup_check "system scrypt enc" 45 | ( 46 | echo "${password}" | ${system_scrypt} \ 47 | enc -P -t 1 "${reference_file}" "${encrypted_file_2}" 48 | echo $? > "${c_exitfile}" 49 | ) 50 | 51 | # Use our scrypt to decrypt the file we just encrypted. 52 | setup_check "scrypt dec for system" 53 | ( 54 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 55 | dec -P "${encrypted_file_2}" "${decrypted_file_2}" 56 | echo $? > "${c_exitfile}" 57 | ) 58 | 59 | # The decrypted file should match the reference. 60 | setup_check "scrypt dec for system output against reference" 61 | cmp -s "${decrypted_file_2}" "${reference_file}" 62 | echo $? > "${c_exitfile}" 63 | } 64 | -------------------------------------------------------------------------------- /tests/06-decrypt-fail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | non_encoded_file="${scriptdir}/06-decrypt-fail.sh" 6 | non_encoded_file_stderr="${s_basename}-stderr.txt" 7 | non_encoded_file_output="${s_basename}-nonfile.txt" 8 | 9 | scenario_cmd() { 10 | # Attempt to decrypt a non-scrypt-encoded file. 11 | # We want this command to fail with 1. 12 | setup_check "scrypt dec non-scrypt" 13 | ( 14 | echo "" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 15 | dec -P "${non_encoded_file}" \ 16 | "${non_encoded_file_output}" \ 17 | 2>> "${non_encoded_file_stderr}" 18 | expected_exitcode 1 $? > "${c_exitfile}" 19 | ) 20 | 21 | # We should have received an error message. 22 | setup_check "scrypt dec non-scrypt error" 23 | grep -q "scrypt: Input is not valid scrypt-encrypted block" \ 24 | "${non_encoded_file_stderr}" 25 | echo "$?" > "${c_exitfile}" 26 | 27 | # We should not have created a file. 28 | setup_check "scrypt dec non-scrypt no file" 29 | if [ -e "${non_encoded_file_output}" ]; then 30 | echo "1" 31 | else 32 | echo "0" 33 | fi > "${c_exitfile}" 34 | } 35 | -------------------------------------------------------------------------------- /tests/07-passphrase-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | encrypted_reference_file="${scriptdir}/verify-strings/test_scrypt_good.enc" 7 | decrypted_reference_file="${s_basename}-attempt_reference.txt" 8 | decrypted_badpass_file="${s_basename}-decrypt-badpass.txt" 9 | decrypted_badpass_log="${s_basename}-decrypt-badpass.log" 10 | decrypted_no_envvar_log="${s_basename}-decrypt-no-envvar.log" 11 | 12 | scenario_cmd() { 13 | # Decrypt a reference file using --passphrase env:VAR. 14 | setup_check "scrypt dec env" 15 | PASSPHRASE="${password}" \ 16 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 17 | dec --passphrase env:PASSPHRASE \ 18 | "${encrypted_reference_file}" "${decrypted_reference_file}" 19 | echo $? > "${c_exitfile}" 20 | 21 | # The decrypted reference file should match the reference. 22 | setup_check "scrypt dec env output against reference" 23 | cmp -s "${decrypted_reference_file}" "${reference_file}" 24 | echo $? > "${c_exitfile}" 25 | 26 | # Attempt to decrypt the reference file with a non-existent envvar. 27 | # We want this command to fail with 1. 28 | setup_check "scrypt dec env none" 29 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 30 | dec --passphrase env:THIS_ENVVAR_DOES_NOT_EXIST \ 31 | "${encrypted_reference_file}" "${decrypted_reference_file}" \ 32 | 2> "${decrypted_no_envvar_log}" 33 | expected_exitcode 1 $? > "${c_exitfile}" 34 | 35 | # We should have received an error message. 36 | setup_check "scrypt dec env none error" 37 | grep -q \ 38 | "scrypt: Failed to read from \${THIS_ENVVAR_DOES_NOT_EXIST}" \ 39 | "${decrypted_no_envvar_log}" 40 | echo "$?" > "${c_exitfile}" 41 | 42 | # We should not have created a file. 43 | setup_check "scrypt dec env no file" 44 | test -e "${decrypted_badpass_file}" 45 | expected_exitcode 1 $? > "${c_exitfile}" 46 | 47 | # Attempt to decrypt the reference file with an incorrect passphrase. 48 | # We want this command to fail with 1. 49 | setup_check "scrypt dec env bad" 50 | PASSPHRASE="bad-pass" \ 51 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 52 | dec --passphrase env:PASSPHRASE \ 53 | "${encrypted_reference_file}" "${decrypted_reference_file}" \ 54 | 2> "${decrypted_badpass_log}" 55 | expected_exitcode 1 $? > "${c_exitfile}" 56 | 57 | # We should have received an error message. 58 | setup_check "scrypt dec env bad error" 59 | grep -q "scrypt: Passphrase is incorrect" "${decrypted_badpass_log}" 60 | echo "$?" > "${c_exitfile}" 61 | 62 | setup_check "scrypt dec env bad no file" 63 | # We should not have created a file. 64 | test -e "${decrypted_badpass_file}" 65 | expected_exitcode 1 $? > "${c_exitfile}" 66 | } 67 | -------------------------------------------------------------------------------- /tests/08-passphrase-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | passphrase_file="${s_basename}-passphrase.txt" 7 | bad_passphrase_file="${s_basename}-passphrase-bad.txt" 8 | encrypted_reference_file="${scriptdir}/verify-strings/test_scrypt_good.enc" 9 | decrypted_reference_file="${s_basename}-attempt_reference.txt" 10 | decrypted_badpass_file="${s_basename}-decrypt-badpass.txt" 11 | decrypted_badpass_log="${s_basename}-decrypt-badpass.log" 12 | decrypted_no_file_log="${s_basename}-decrypt-no-file.log" 13 | 14 | scenario_cmd() { 15 | # Create the passphrase file. 16 | echo "${password}" > "${passphrase_file}" 17 | 18 | # Decrypt a reference file using --passphrase file:FILENAME. 19 | setup_check "scrypt dec file" 20 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 21 | dec --passphrase file:"${passphrase_file}" \ 22 | "${encrypted_reference_file}" "${decrypted_reference_file}" 23 | echo $? > "${c_exitfile}" 24 | 25 | # The decrypted reference file should match the reference. 26 | setup_check "scrypt dec file output against reference" 27 | cmp -s "${decrypted_reference_file}" "${reference_file}" 28 | echo $? > "${c_exitfile}" 29 | 30 | # Attempt to decrypt the reference file with a non-existent file. 31 | # We want this command to fail with 1. 32 | setup_check "scrypt dec file none" 33 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 34 | dec --passphrase file:THIS_FILE_DOES_NOT_EXIST \ 35 | "${encrypted_reference_file}" "${decrypted_reference_file}" \ 36 | 2> "${decrypted_no_file_log}" 37 | expected_exitcode 1 $? > "${c_exitfile}" 38 | 39 | # We should have received an error message. 40 | setup_check "scrypt dec file none error" 41 | grep -q "scrypt: fopen(THIS_FILE_DOES_NOT_EXIST)" \ 42 | "${decrypted_no_file_log}" 43 | echo "$?" > "${c_exitfile}" 44 | 45 | # We should not have created a file. 46 | setup_check "scrypt dec file none no file" 47 | test -e "${decrypted_badpass_file}" 48 | expected_exitcode 1 $? > "${c_exitfile}" 49 | 50 | # Attempt to decrypt the reference file with an incorrect passphrase. 51 | # We want this command to fail with 1. 52 | setup_check "scrypt dec file bad" 53 | echo "bad-pass" > "${bad_passphrase_file}" 54 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 55 | dec --passphrase file:"${bad_passphrase_file}" \ 56 | "${encrypted_reference_file}" "${decrypted_reference_file}" \ 57 | 2> "${decrypted_badpass_log}" 58 | expected_exitcode 1 $? > "${c_exitfile}" 59 | 60 | # We should have received an error message. 61 | setup_check "scrypt dec file bad error" 62 | grep -q "scrypt: Passphrase is incorrect" "${decrypted_badpass_log}" 63 | echo "$?" > "${c_exitfile}" 64 | 65 | # We should not have created a file. 66 | setup_check "scrypt dec file bad no file" 67 | test -e "${decrypted_badpass_file}" 68 | expected_exitcode 1 $? > "${c_exitfile}" 69 | } 70 | -------------------------------------------------------------------------------- /tests/09-explicit-params.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Constants 4 | c_valgrind_min=1 5 | reference_file="${scriptdir}/verify-strings/test_scrypt.good" 6 | encrypted_file="${s_basename}-reference.enc" 7 | stderr="${s_basename}-reference.stderr" 8 | encrypted_file_bad="${s_basename}-reference-bad.enc" 9 | stderr_bad="${s_basename}-reference-bad.stderr" 10 | 11 | scenario_cmd() { 12 | # Encrypt with manually-specified N, r, p. 13 | setup_check "scrypt enc Nrp" 14 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 15 | enc -v --logN 12 -r 2 -p 3 \ 16 | --passphrase dev:stdin-once \ 17 | "${reference_file}" "${encrypted_file}" \ 18 | 2> "${stderr}" 19 | echo $? > "${c_exitfile}" 20 | 21 | # Check that the options were used. 22 | setup_check "scrypt enc Nrp output N" 23 | grep -q "N = 4096" "${stderr}" 24 | echo $? > "${c_exitfile}" 25 | 26 | setup_check "scrypt enc Nrp output r" 27 | grep -q "r = 2" "${stderr}" 28 | echo $? > "${c_exitfile}" 29 | 30 | setup_check "scrypt enc Nrp output p" 31 | grep -q "p = 3" "${stderr}" 32 | echo $? > "${c_exitfile}" 33 | 34 | # Try to encrypt with badly-specified N, r, p; should fail. 35 | setup_check "scrypt enc Nrp bad" 36 | echo "${password}" | ${c_valgrind_cmd} "${bindir}/scrypt" \ 37 | enc -v --logN 2 -r 0 -p 0 \ 38 | --passphrase dev:stdin-once \ 39 | "${reference_file}" "${encrypted_file_bad}" \ 40 | 2> "${stderr_bad}" 41 | expected_exitcode 1 $? > "${c_exitfile}" 42 | 43 | # Check that we got an error. 44 | setup_check "scrypt enc Nrp bad output" 45 | grep -q "\--logN must be between 10 and 40 (inclusive)" "${stderr_bad}" 46 | echo $? > "${c_exitfile}" 47 | 48 | # Check that we can't partially set explicit parameters. 49 | setup_check "scrypt enc --logN only" 50 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 51 | enc --logN 12 "${reference_file}" 2>&1 | \ 52 | grep -q "If --logN is set, -r and -p must also be set" 53 | echo $? > "${c_exitfile}" 54 | 55 | setup_check "scrypt enc -r only" 56 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 57 | enc -r 12 "${reference_file}" 2>&1 | \ 58 | grep -q "If -r is set, --logN and -p must also be set" 59 | echo $? > "${c_exitfile}" 60 | 61 | setup_check "scrypt enc -p only" 62 | ${c_valgrind_cmd} "${bindir}/scrypt" \ 63 | enc -p 12 "${reference_file}" 2>&1 | \ 64 | grep -q "If -p is set, --logN and -r must also be set" 65 | echo $? > "${c_exitfile}" 66 | } 67 | -------------------------------------------------------------------------------- /tests/libscrypt-kdf/sample-libscrypt-kdf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "scrypt-kdf.h" 6 | 7 | /* Parameters controlling memory usage and CPU time. */ 8 | #define N 16384 9 | #define r 8 10 | #define p 1 11 | 12 | /* How much data should scrypt return? */ 13 | #define OUTPUT_BUFLEN 8 14 | 15 | int 16 | main(void) 17 | { 18 | const char * passwd = "hunter2"; 19 | const char * salt = "DANGER -- this should be a random salt -- DANGER"; 20 | uint8_t output[OUTPUT_BUFLEN]; 21 | int exitcode; 22 | 23 | /* Perform hashing. */ 24 | exitcode = scrypt_kdf((const uint8_t *)passwd, strlen(passwd), 25 | (const uint8_t*)salt, strlen(salt), N, r, p, 26 | output, OUTPUT_BUFLEN); 27 | 28 | /* Notify user of success / failure. */ 29 | if (exitcode == 0) 30 | printf("scrypt(): success\n"); 31 | else 32 | printf("scrypt(): failure %d\n", exitcode); 33 | 34 | return (exitcode); 35 | } 36 | -------------------------------------------------------------------------------- /tests/test_scrypt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### Find script directory and load helper functions. 4 | scriptdir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P) 5 | . "${scriptdir}/shared_test_functions.sh" 6 | 7 | 8 | ### Project-specific constants and setup 9 | 10 | out="${bindir}/tests-output" 11 | out_valgrind="${bindir}/tests-valgrind" 12 | 13 | # Constants used in multiple scenarios for this project. 14 | password="hunter2" 15 | 16 | # Find system scrypt, and ensure it supports -P. 17 | system_scrypt=$( find_system scrypt "enc -P" ) 18 | 19 | 20 | ### Run tests using project-specific constants 21 | run_scenarios 22 | -------------------------------------------------------------------------------- /tests/valgrind/potential-memleaks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define FGETS_BUFSIZE 64 6 | 7 | /* Problem with FreeBSD 10.3 fgets() with stdin. */ 8 | static void 9 | pl_freebsd_fgets(void) 10 | { 11 | char buf[FGETS_BUFSIZE]; 12 | 13 | if (fgets(buf, FGETS_BUFSIZE, stdin) == NULL) 14 | exit(1); 15 | } 16 | 17 | /* Problem with FreeBSD 12.0 and printf(). */ 18 | static void 19 | pl_freebsd_printf_space(void) 20 | { 21 | 22 | printf(" "); 23 | } 24 | 25 | /* Problem with FreeBSD 12.0 and printf(). */ 26 | static void 27 | pl_freebsd_printf_space_newline(void) 28 | { 29 | 30 | printf(" \n"); 31 | } 32 | 33 | /* Problem with FreeBSD 12.0 and strerror(). */ 34 | static void 35 | pl_freebsd_strerror(void) 36 | { 37 | char * str = strerror(0); 38 | 39 | (void)str; /* UNUSED */ 40 | } 41 | 42 | #define MEMLEAKTEST(x) { #x, x } 43 | static const struct memleaktest { 44 | const char * const name; 45 | void (* const volatile func)(void); 46 | } tests[] = { 47 | MEMLEAKTEST(pl_freebsd_fgets), 48 | MEMLEAKTEST(pl_freebsd_printf_space), 49 | MEMLEAKTEST(pl_freebsd_printf_space_newline), 50 | MEMLEAKTEST(pl_freebsd_strerror) 51 | }; 52 | static const int num_tests = sizeof(tests) / sizeof(tests[0]); 53 | 54 | int 55 | main(int argc, char * argv[]) 56 | { 57 | int i; 58 | 59 | if (argc == 2) { 60 | /* Run the relevant function. */ 61 | for (i = 0; i < num_tests; i++) { 62 | if ((strcmp(argv[1], tests[i].name)) == 0) { 63 | tests[i].func(); 64 | goto success; 65 | } 66 | } 67 | 68 | /* We didn't find the desired function name. */ 69 | goto err0; 70 | } else { 71 | /* Print test names. */ 72 | for (i = 0; i < num_tests; i++) 73 | printf("%s\n", tests[i].name); 74 | } 75 | 76 | success: 77 | /* Success! */ 78 | exit(0); 79 | 80 | err0: 81 | /* Failure! */ 82 | exit(1); 83 | } 84 | -------------------------------------------------------------------------------- /tests/verify-strings/test_scrypt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "crypto_scrypt.h" 6 | #include "warnp.h" 7 | 8 | static struct scrypt_test { 9 | const char * passwd; 10 | const char * salt; 11 | uint64_t N; 12 | uint32_t r; 13 | uint32_t p; 14 | int largemem; 15 | } tests[4] = { 16 | { "", "", 16, 1, 1, 0 }, 17 | { "password", "NaCl", 1024, 8, 16, 0 }, 18 | { "pleaseletmein", "SodiumChloride", 16384, 8, 1, 0 }, 19 | { "pleaseletmein", "SodiumChloride", 1048576, 8, 1, 1 } 20 | }; 21 | 22 | int 23 | main(int argc, char * argv[]) 24 | { 25 | struct scrypt_test * test; 26 | char kbuf[64]; 27 | size_t i; 28 | int failures = 0; 29 | int skip_largemem = 0; 30 | 31 | WARNP_INIT; 32 | 33 | /* Do we want to skip the large-memory test? */ 34 | if ((argc == 2) && (strcmp(argv[1], "1") == 0)) 35 | skip_largemem = 1; 36 | 37 | for (test = tests; 38 | test < tests + sizeof(tests) / sizeof(tests[0]); 39 | test++) { 40 | /* Skip large memory tests (if desired). */ 41 | if (skip_largemem && test->largemem) 42 | continue; 43 | 44 | if (crypto_scrypt((const uint8_t *)test->passwd, 45 | strlen(test->passwd), (const uint8_t *)test->salt, 46 | strlen(test->salt), test->N, test->r, test->p, 47 | (uint8_t *)kbuf, 64)) { 48 | warnp("crypto_scrypt(%u, %u, %u) failed", 49 | (unsigned int)test->N, (unsigned int)test->r, 50 | (unsigned int)test->p); 51 | failures++; 52 | break; 53 | } 54 | printf("scrypt(\"%s\", \"%s\", %u, %u, %u, 64) =\n", 55 | test->passwd, test->salt, (unsigned int)test->N, 56 | (unsigned int)(test->r), (unsigned int)test->p); 57 | for (i = 0; i < 64; i++) { 58 | printf("%02x", (uint8_t)kbuf[i]); 59 | if ((i % 16) == 15) 60 | printf("\n"); 61 | else 62 | printf(" "); 63 | } 64 | } 65 | 66 | return (failures ? 1 : 0); 67 | } 68 | -------------------------------------------------------------------------------- /tests/verify-strings/test_scrypt.good: -------------------------------------------------------------------------------- 1 | scrypt("", "", 16, 1, 1, 64) = 2 | 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 3 | f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 4 | fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 5 | e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 6 | scrypt("password", "NaCl", 1024, 8, 16, 64) = 7 | fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 8 | 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 9 | 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da 10 | c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 11 | scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1, 64) = 12 | 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb 13 | fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 14 | d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 15 | e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 16 | scrypt("pleaseletmein", "SodiumChloride", 1048576, 8, 1, 64) = 17 | 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 18 | ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 19 | 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 20 | 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 21 | -------------------------------------------------------------------------------- /tests/verify-strings/test_scrypt_good.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tarsnap/scrypt/8a8d5a3409ec9766100a8168013826e8ce00d9bf/tests/verify-strings/test_scrypt_good.enc -------------------------------------------------------------------------------- /tests/verify-strings/test_scrypt_small.good: -------------------------------------------------------------------------------- 1 | scrypt("", "", 16, 1, 1, 64) = 2 | 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 3 | f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 4 | fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 5 | e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 6 | scrypt("password", "NaCl", 1024, 8, 16, 64) = 7 | fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 8 | 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 9 | 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da 10 | c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 11 | scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1, 64) = 12 | 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb 13 | fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 14 | d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 15 | e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 16 | --------------------------------------------------------------------------------