Remove vendor/scrypt
This commit is contained in:
parent
eb8682887f
commit
fedcd95668
1
vendor/CMakeLists.txt
vendored
1
vendor/CMakeLists.txt
vendored
@ -1,4 +1,3 @@
|
||||
add_subdirectory(googletest)
|
||||
add_subdirectory(scrypt)
|
||||
add_subdirectory(spdlog)
|
||||
add_subdirectory(cryptopp)
|
||||
|
2
vendor/README
vendored
2
vendor/README
vendored
@ -1,6 +1,4 @@
|
||||
This directory contains external projects, taken from the following locations:
|
||||
scrypt: http://www.tarsnap.com/scrypt.html
|
||||
- changed: commented out compiler warnings about a workaround for a llvm bug
|
||||
googletest: https://github.com/google/googletest/tree/release-1.8.0
|
||||
- changed: added NOLINT comment as workaround for clang-tidy warning https://github.com/google/googletest/issues/853
|
||||
spdlog: https://github.com/gabime/spdlog/tree/v0.16.3/include/spdlog
|
||||
|
46
vendor/scrypt/CMakeLists.txt
vendored
46
vendor/scrypt/CMakeLists.txt
vendored
@ -1,46 +0,0 @@
|
||||
include(ExternalProject)
|
||||
|
||||
project (scrypt C)
|
||||
|
||||
# This builds the original scrypt source using configure & make. We don't use their build result,
|
||||
# but we use the config.h it creates somewhere on the way (see target_compile_options below).
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILDTYPE)
|
||||
set(SCRYPT_CFLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BUILDTYPE}}")
|
||||
|
||||
# Add a default location for homebrew-installed openssl on Mac OS X to include search path
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(SCRYPT_CFLAGS "${SCRYPT_CFLAGS} -I/usr/local/opt/openssl/include")
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
ExternalProject_Add(scrypt_original
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt
|
||||
CONFIGURE_COMMAND /usr/bin/env CC=${CMAKE_C_COMPILER} CFLAGS=${SCRYPT_CFLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/configure --prefix=${CMAKE_BINARY_DIR}/vendor/scrypt/
|
||||
PREFIX ${CMAKE_BINARY_DIR}/vendor/scrypt/
|
||||
BUILD_COMMAND ${MAKE}
|
||||
)
|
||||
add_library(${PROJECT_NAME} STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/lib/crypto/crypto_scrypt.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/lib/crypto/crypto_scrypt_smix.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/util/warnp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/util/insecure_memzero.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/alg/sha256.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/cpusupport/cpusupport_x86_aesni.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/cpusupport/cpusupport_x86_sse2.c
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/libscrypt_sse2.a
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/libcperciva_aesni.a
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/cpusupport
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/alg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1/scrypt/libcperciva/util
|
||||
)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-DCONFIG_H_FILE=\"${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/config.h\"
|
||||
-DCPUSUPPORT_CONFIG_FILE=\"${CMAKE_CURRENT_BINARY_DIR}/src/scrypt_original-build/cpusupport-config.h\"
|
||||
-std=gnu99
|
||||
)
|
||||
add_dependencies(${PROJECT_NAME} scrypt_original)
|
||||
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/scrypt-1.2.1)
|
46
vendor/scrypt/scrypt-1.2.1/scrypt/BUILDING
vendored
46
vendor/scrypt/scrypt-1.2.1/scrypt/BUILDING
vendored
@ -1,46 +0,0 @@
|
||||
Installing
|
||||
----------
|
||||
|
||||
We strongly recommend that people use the latest official release tarball on
|
||||
https://www.tarsnap.com/scrypt.html, and build with:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
|
||||
Platform-specific notes
|
||||
-----------------------
|
||||
|
||||
- On OS X, the version of OpenSSL included with the operating
|
||||
system is outdated (0.9.8) and deprecated, and it is recommended
|
||||
that scrypt be built with an updated version of OpenSSL. On OS X
|
||||
10.11 "El Capitan" and higher, OpenSSL was removed entirely. After
|
||||
installing a newer version of OpenSSL, use
|
||||
CPPFLAGS="-I /path/to/openssl/headers"
|
||||
LDFLAGS="-L /path/to/openssl/lib"
|
||||
to build scrypt.
|
||||
|
||||
In particular, if you installed OpenSSL using homebrew, you may
|
||||
pass the relevant directories directly to ./configure:
|
||||
./configure CPPFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib"
|
||||
|
||||
Alternatively, you may with to add these lines to your $HOME/.profile file:
|
||||
export CPPFLAGS="-I/usr/local/opt/openssl/include $CPPFLAGS"
|
||||
export LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS"
|
||||
and then close & re-open your terminal window.
|
||||
|
||||
|
||||
Building from git
|
||||
-----------------
|
||||
|
||||
For experimental development from git, build with:
|
||||
|
||||
autoreconf -i
|
||||
./configure
|
||||
make
|
||||
|
||||
- You must have automake 1.11.2 or higher.
|
||||
- In order to support the `AX_CFLAGS_WARN_ALL` autoconf directive, you will
|
||||
need to install the autoconf archive. On Debian systems, use the
|
||||
`autoconf-archive` package; on FreeBSD, use `devel/autoconf-archive`.
|
27
vendor/scrypt/scrypt-1.2.1/scrypt/COPYRIGHT
vendored
27
vendor/scrypt/scrypt-1.2.1/scrypt/COPYRIGHT
vendored
@ -1,27 +0,0 @@
|
||||
The included code and documentation ("scrypt") is distributed under the
|
||||
following terms:
|
||||
|
||||
Copyright 2005-2016 Colin Percival. All rights reserved.
|
||||
Copyright 2005-2016 Tarsnap Backup Inc. All rights reserved.
|
||||
Copyright 2014 Sean Kelly. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
18
vendor/scrypt/scrypt-1.2.1/scrypt/FORMAT
vendored
18
vendor/scrypt/scrypt-1.2.1/scrypt/FORMAT
vendored
@ -1,18 +0,0 @@
|
||||
scrypt encrypted data format
|
||||
----------------------------
|
||||
|
||||
offset length
|
||||
0 6 "scrypt"
|
||||
6 1 scrypt data file version number (== 0)
|
||||
7 1 log2(N) (must be between 1 and 63 inclusive)
|
||||
8 4 r (big-endian integer; must satisfy r * p < 2^30)
|
||||
12 4 p (big-endian integer; must satisfy r * p < 2^30)
|
||||
16 32 salt
|
||||
48 16 first 16 bytes of SHA256(bytes 0 .. 47)
|
||||
64 32 HMAC-SHA256(bytes 0 .. 63)
|
||||
96 X data xor AES256-CTR key stream generated with nonce == 0
|
||||
96+X 32 HMAC-SHA256(bytes 0 .. 96 + (X - 1))
|
||||
|
||||
AES256-CTR is computed with a 256-bit AES key key_enc, and HMAC-SHA256 is
|
||||
computed with a 256-bit key key_hmac, where
|
||||
scrypt(password, salt, N, r, p, 64) == [key_enc][key_hmac]
|
1216
vendor/scrypt/scrypt-1.2.1/scrypt/Makefile.in
vendored
1216
vendor/scrypt/scrypt-1.2.1/scrypt/Makefile.in
vendored
File diff suppressed because it is too large
Load Diff
@ -1,113 +0,0 @@
|
||||
bin_PROGRAMS= scrypt
|
||||
noinst_PROGRAMS= tests/test_scrypt tests/valgrind/potential-memleaks
|
||||
dist_man_MANS=$(scrypt_man_MANS)
|
||||
|
||||
scrypt_SOURCES= main.c \
|
||||
libcperciva/alg/sha256.c \
|
||||
libcperciva/cpusupport/cpusupport_x86_aesni.c \
|
||||
libcperciva/cpusupport/cpusupport_x86_sse2.c \
|
||||
libcperciva/crypto/crypto_aes.c \
|
||||
libcperciva/crypto/crypto_aesctr.c \
|
||||
libcperciva/crypto/crypto_entropy.c \
|
||||
libcperciva/util/asprintf.c \
|
||||
libcperciva/util/entropy.c \
|
||||
libcperciva/util/getopt.c \
|
||||
libcperciva/util/humansize.c \
|
||||
libcperciva/util/insecure_memzero.c \
|
||||
libcperciva/util/readpass.c \
|
||||
libcperciva/util/warnp.c \
|
||||
lib/crypto/crypto_scrypt.c \
|
||||
lib/crypto/crypto_scrypt_smix.c \
|
||||
lib/scryptenc/scryptenc.c \
|
||||
lib/scryptenc/scryptenc_cpuperf.c \
|
||||
lib/util/memlimit.c \
|
||||
lib/crypto/crypto_scrypt.h \
|
||||
lib/crypto/crypto_scrypt_smix.h \
|
||||
lib/crypto/crypto_scrypt_smix_sse2.h \
|
||||
lib/scryptenc/scryptenc.h \
|
||||
lib/scryptenc/scryptenc_cpuperf.h \
|
||||
lib/util/memlimit.h \
|
||||
libcperciva/alg/sha256.h \
|
||||
libcperciva/cpusupport/cpusupport.h \
|
||||
libcperciva/crypto/crypto_aes.h \
|
||||
libcperciva/crypto/crypto_aes_aesni.h \
|
||||
libcperciva/crypto/crypto_aesctr.h \
|
||||
libcperciva/crypto/crypto_entropy.h \
|
||||
libcperciva/util/asprintf.h \
|
||||
libcperciva/util/entropy.h \
|
||||
libcperciva/util/getopt.h \
|
||||
libcperciva/util/humansize.h \
|
||||
libcperciva/util/insecure_memzero.h \
|
||||
libcperciva/util/readpass.h \
|
||||
libcperciva/util/sysendian.h \
|
||||
libcperciva/util/warnp.h \
|
||||
scrypt_platform.h
|
||||
|
||||
AM_CPPFLAGS= -I$(srcdir)/libcperciva/alg \
|
||||
-I$(srcdir)/libcperciva/cpusupport \
|
||||
-I$(srcdir)/libcperciva/crypto \
|
||||
-I$(srcdir)/libcperciva/util \
|
||||
-I$(srcdir)/lib/crypto \
|
||||
-I$(srcdir)/lib/scryptenc \
|
||||
-I$(srcdir)/lib/util \
|
||||
-DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" \
|
||||
-D_POSIX_C_SOURCE=200809L
|
||||
|
||||
scrypt_LDADD= libcperciva_aesni.a libscrypt_sse2.a
|
||||
scrypt_man_MANS= scrypt.1
|
||||
|
||||
cpusupport-config.h:
|
||||
( export CC="${CC}"; export CFLAGS="${CFLAGS}"; command -p sh $(srcdir)/libcperciva/cpusupport/Build/cpusupport.sh "$$PATH") > cpusupport-config.h.tmp && command -p mv cpusupport-config.h.tmp cpusupport-config.h
|
||||
BUILT_SOURCES= cpusupport-config.h
|
||||
CLEANFILES= cpusupport-config.h cpusupport-config.h.tmp
|
||||
|
||||
noinst_LIBRARIES= libcperciva_aesni.a
|
||||
libcperciva_aesni_a_SOURCES= libcperciva/crypto/crypto_aes_aesni.c
|
||||
libcperciva_aesni_a_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_AESNI}`
|
||||
|
||||
noinst_LIBRARIES+= libscrypt_sse2.a
|
||||
libscrypt_sse2_a_SOURCES= lib/crypto/crypto_scrypt_smix_sse2.c
|
||||
libscrypt_sse2_a_CFLAGS=`. ./cpusupport-config.h; echo $${CFLAGS_X86_SSE2}`
|
||||
|
||||
EXTRA_DIST = \
|
||||
COPYRIGHT \
|
||||
FORMAT \
|
||||
lib/README \
|
||||
README.md \
|
||||
lib/crypto/crypto_scrypt-ref.c \
|
||||
libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c \
|
||||
libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c \
|
||||
libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c \
|
||||
libcperciva/cpusupport/Build/cpusupport.sh \
|
||||
tests/test_scrypt.good \
|
||||
tests/test_scrypt_good.enc \
|
||||
tests/shared_test_functions.sh \
|
||||
tests/01-known-values.sh \
|
||||
tests/02-decrypt-reference-file.sh \
|
||||
tests/03-encrypt-decrypt-file.sh \
|
||||
tests/04-force-resources.sh \
|
||||
tests/05-system-scrypt-encrypt-decrypt.sh \
|
||||
tests/test_scrypt.sh
|
||||
|
||||
tests_test_scrypt_SOURCES = tests/test_scrypt.c \
|
||||
libcperciva/alg/sha256.c \
|
||||
libcperciva/alg/sha256.h \
|
||||
libcperciva/cpusupport/cpusupport_x86_sse2.c \
|
||||
libcperciva/util/insecure_memzero.c \
|
||||
libcperciva/util/insecure_memzero.h \
|
||||
libcperciva/util/warnp.c \
|
||||
libcperciva/util/warnp.h \
|
||||
lib/crypto/crypto_scrypt.c \
|
||||
lib/crypto/crypto_scrypt.h \
|
||||
lib/crypto/crypto_scrypt_smix.c \
|
||||
lib/crypto/crypto_scrypt_smix.h
|
||||
|
||||
tests_test_scrypt_LDADD= libscrypt_sse2.a
|
||||
|
||||
tests_valgrind_potential_memleaks_SOURCES = tests/valgrind/potential-memleaks.c
|
||||
|
||||
.PHONY: test
|
||||
# we can't only build "scrypt tests/test_scrypt" because that won't build
|
||||
# the BUILT_SOURCES.
|
||||
test: all
|
||||
$(top_srcdir)/tests/test_scrypt.sh .
|
@ -1,69 +0,0 @@
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([scrypt],1.2.1,
|
||||
[https://github.com/Tarsnap/scrypt],[scrypt],[http://www.tarsnap.com/scrypt/])
|
||||
AC_CONFIG_SRCDIR([lib/scryptenc/scryptenc.c])
|
||||
AC_CONFIG_AUX_DIR([config.aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects -Wall])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_RANLIB
|
||||
AM_PROG_AR
|
||||
|
||||
# Don't rebuild the configure script. I'm distributing a perfectly good one.
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# Check for clock_gettime. On some systems, this is provided via librt.
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
AC_CHECK_FUNCS([clock_gettime])
|
||||
|
||||
AC_SEARCH_LIBS([AES_encrypt], [crypto],,
|
||||
AC_MSG_ERROR([function AES_ENCRYPT not found]))
|
||||
|
||||
# Check for a linuxy sysinfo syscall; and while we're doing that, check if
|
||||
# struct sysinfo is the old version (total RAM == totalmem) or the new
|
||||
# version (total RAM == totalmem * mem_unit).
|
||||
AC_CHECK_HEADERS([sys/sysinfo.h])
|
||||
AC_CHECK_FUNCS([sysinfo])
|
||||
AC_CHECK_TYPES([struct sysinfo], [], [], [[#include <sys/sysinfo.h>]])
|
||||
AC_CHECK_MEMBERS([struct sysinfo.totalram, struct sysinfo.mem_unit], [], [],
|
||||
[[#include <sys/sysinfo.h>]])
|
||||
|
||||
# Check if we have <sys/param.h>, since some systems require it for sysctl
|
||||
# to work.
|
||||
AC_CHECK_HEADERS([sys/param.h])
|
||||
|
||||
# Check if we have <openssl/aes.h>, to fix the make failing when configure
|
||||
# passes.
|
||||
AC_CHECK_HEADERS([openssl/aes.h],,
|
||||
[AC_MSG_ERROR([Unable to find the openssl/aes.h header])])
|
||||
|
||||
# Check for <sys/sysctl.h>. If it exists and it defines HW_USERMEM
|
||||
# and/or HW_MEMSIZE, we'll try using those as memory limits.
|
||||
AC_CHECK_HEADERS([sys/sysctl.h])
|
||||
|
||||
# Check for posix_memalign
|
||||
AC_CHECK_FUNCS([posix_memalign])
|
||||
|
||||
# Check for mmap so we can work around its absence on Minix
|
||||
AC_CHECK_FUNCS([mmap])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
# Check whether the user has requested to disable compiler warnings
|
||||
AC_MSG_CHECKING([compiler_warnings])
|
||||
AC_ARG_ENABLE(compiler_warnings,
|
||||
AS_HELP_STRING([--disable-compiler-warnings],
|
||||
[Do not request compiler warnings. @<:@default=enabled@:>@]),
|
||||
[ac_compiler_warnings=$enableval],
|
||||
[ac_compiler_warnings=yes])
|
||||
AC_MSG_RESULT([${ac_compiler_warnings}])
|
||||
AS_IF([test x${ac_compiler_warnings} = xyes],
|
||||
[AX_CFLAGS_WARN_ALL])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
270
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/ar-lib
vendored
270
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/ar-lib
vendored
@ -1,270 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for Microsoft lib.exe
|
||||
|
||||
me=ar-lib
|
||||
scriptversion=2012-03-01.08; # UTC
|
||||
|
||||
# Copyright (C) 2010-2014 Free Software Foundation, Inc.
|
||||
# Written by Peter Rosin <peda@lysator.liu.se>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
|
||||
# func_error message
|
||||
func_error ()
|
||||
{
|
||||
echo "$me: $1" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv in
|
||||
mingw)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_at_file at_file operation archive
|
||||
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
|
||||
# for each of them.
|
||||
# When interpreting the content of the @FILE, do NOT use func_file_conv,
|
||||
# since the user would need to supply preconverted file names to
|
||||
# binutils ar, at least for MinGW.
|
||||
func_at_file ()
|
||||
{
|
||||
operation=$2
|
||||
archive=$3
|
||||
at_file_contents=`cat "$1"`
|
||||
eval set x "$at_file_contents"
|
||||
shift
|
||||
|
||||
for member
|
||||
do
|
||||
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
|
||||
done
|
||||
}
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
func_error "no command. Try '$0 --help' for more information."
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<EOF
|
||||
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
|
||||
|
||||
Members may be specified in a file named with @FILE.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "$me, version $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test $# -lt 3; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
|
||||
AR=$1
|
||||
shift
|
||||
while :
|
||||
do
|
||||
if test $# -lt 2; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
case $1 in
|
||||
-lib | -LIB \
|
||||
| -ltcg | -LTCG \
|
||||
| -machine* | -MACHINE* \
|
||||
| -subsystem* | -SUBSYSTEM* \
|
||||
| -verbose | -VERBOSE \
|
||||
| -wx* | -WX* )
|
||||
AR="$AR $1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
action=$1
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
orig_archive=$1
|
||||
shift
|
||||
func_file_conv "$orig_archive"
|
||||
archive=$file
|
||||
|
||||
# strip leading dash in $action
|
||||
action=${action#-}
|
||||
|
||||
delete=
|
||||
extract=
|
||||
list=
|
||||
quick=
|
||||
replace=
|
||||
index=
|
||||
create=
|
||||
|
||||
while test -n "$action"
|
||||
do
|
||||
case $action in
|
||||
d*) delete=yes ;;
|
||||
x*) extract=yes ;;
|
||||
t*) list=yes ;;
|
||||
q*) quick=yes ;;
|
||||
r*) replace=yes ;;
|
||||
s*) index=yes ;;
|
||||
S*) ;; # the index is always updated implicitly
|
||||
c*) create=yes ;;
|
||||
u*) ;; # TODO: don't ignore the update modifier
|
||||
v*) ;; # TODO: don't ignore the verbose modifier
|
||||
*)
|
||||
func_error "unknown action specified"
|
||||
;;
|
||||
esac
|
||||
action=${action#?}
|
||||
done
|
||||
|
||||
case $delete$extract$list$quick$replace,$index in
|
||||
yes,* | ,yes)
|
||||
;;
|
||||
yesyes*)
|
||||
func_error "more than one action specified"
|
||||
;;
|
||||
*)
|
||||
func_error "no action specified"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -n "$delete"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -REMOVE "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
elif test -n "$extract"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
if test $# -gt 0; then
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -EXTRACT "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
|
||||
do
|
||||
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
|
||||
done
|
||||
fi
|
||||
|
||||
elif test -n "$quick$replace"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
if test -z "$create"; then
|
||||
echo "$me: creating $orig_archive"
|
||||
fi
|
||||
orig_archive=
|
||||
else
|
||||
orig_archive=$archive
|
||||
fi
|
||||
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_file_conv "${1#@}"
|
||||
set x "$@" "@$file"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
set x "$@" "$file"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
shift
|
||||
done
|
||||
|
||||
if test -n "$orig_archive"; then
|
||||
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
|
||||
else
|
||||
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
|
||||
fi
|
||||
|
||||
elif test -n "$list"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
$AR -NOLOGO -LIST "$archive" || exit $?
|
||||
fi
|
347
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/compile
vendored
347
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/compile
vendored
@ -1,347 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
791
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/depcomp
vendored
791
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/depcomp
vendored
@ -1,791 +0,0 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2013-05-30.07; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
@ -1,501 +0,0 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2013-12-25.23; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
tab=' '
|
||||
nl='
|
||||
'
|
||||
IFS=" $tab$nl"
|
||||
|
||||
# Set DOITPROG to "echo" to test this script.
|
||||
|
||||
doit=${DOITPROG-}
|
||||
doit_exec=${doit:-exec}
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
is_target_a_directory=possibly
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t)
|
||||
is_target_a_directory=always
|
||||
dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) is_target_a_directory=never;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# We allow the use of options -d and -T together, by making -d
|
||||
# take the precedence; this is for compatibility with GNU install.
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
echo "$0: target directory not allowed when installing a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||
if test ! -d "$dst_arg"; then
|
||||
echo "$0: $dst_arg: Is not a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
set +f &&
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
215
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/missing
vendored
215
vendor/scrypt/scrypt-1.2.1/scrypt/config.aux/missing
vendored
@ -1,215 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2013-10-28.13; # UTC
|
||||
|
||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal autoconf autoheader autom4te automake makeinfo
|
||||
bison yacc flex lex help2man
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=http://www.perl.org/
|
||||
flex_URL=http://flex.sourceforge.net/
|
||||
gnu_software_URL=http://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
case $normalized_program in
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified 'configure.ac',"
|
||||
echo "or m4 files included by it."
|
||||
program_details 'autoconf'
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified 'acconfig.h' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'autoheader'
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified 'Makefile.am' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'automake'
|
||||
;;
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'aclocal'
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
program_details 'autom4te'
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
99
vendor/scrypt/scrypt-1.2.1/scrypt/config.h.in
vendored
99
vendor/scrypt/scrypt-1.2.1/scrypt/config.h.in
vendored
@ -1,99 +0,0 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
||||
#undef HAVE_OPENSSL_AES_H
|
||||
|
||||
/* Define to 1 if you have the `posix_memalign' function. */
|
||||
#undef HAVE_POSIX_MEMALIGN
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if the system has the type `struct sysinfo'. */
|
||||
#undef HAVE_STRUCT_SYSINFO
|
||||
|
||||
/* Define to 1 if `mem_unit' is a member of `struct sysinfo'. */
|
||||
#undef HAVE_STRUCT_SYSINFO_MEM_UNIT
|
||||
|
||||
/* Define to 1 if `totalram' is a member of `struct sysinfo'. */
|
||||
#undef HAVE_STRUCT_SYSINFO_TOTALRAM
|
||||
|
||||
/* Define to 1 if you have the `sysinfo' function. */
|
||||
#undef HAVE_SYSINFO
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||
#undef HAVE_SYS_SYSCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sysinfo.h> header file. */
|
||||
#undef HAVE_SYS_SYSINFO_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
6807
vendor/scrypt/scrypt-1.2.1/scrypt/configure
vendored
6807
vendor/scrypt/scrypt-1.2.1/scrypt/configure
vendored
File diff suppressed because it is too large
Load Diff
6
vendor/scrypt/scrypt-1.2.1/scrypt/lib/README
vendored
6
vendor/scrypt/scrypt-1.2.1/scrypt/lib/README
vendored
@ -1,6 +0,0 @@
|
||||
The source code under this directory is taken from the client for the
|
||||
Tarsnap online backup system (and released under the 2-clause BSD license
|
||||
with permission of the author); keeping this code in sync with the Tarsnap
|
||||
code is highly desirable and explains why there is some functionality
|
||||
included here which is not actually used by the scrypt file encryption
|
||||
utility.
|
@ -1,285 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha256.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
|
||||
static void blkcpy(uint8_t *, uint8_t *, size_t);
|
||||
static void blkxor(uint8_t *, uint8_t *, size_t);
|
||||
static void salsa20_8(uint8_t[64]);
|
||||
static void blockmix_salsa8(uint8_t *, uint8_t *, size_t);
|
||||
static uint64_t integerify(uint8_t *, size_t);
|
||||
static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *);
|
||||
|
||||
static void
|
||||
blkcpy(uint8_t * dest, uint8_t * src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(uint8_t * dest, uint8_t * src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dest[i] ^= src[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20_8(B):
|
||||
* Apply the salsa20/8 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20_8(uint8_t B[64])
|
||||
{
|
||||
uint32_t B32[16];
|
||||
uint32_t x[16];
|
||||
size_t i;
|
||||
|
||||
/* Convert little-endian values in. */
|
||||
for (i = 0; i < 16; i++)
|
||||
B32[i] = le32dec(&B[i * 4]);
|
||||
|
||||
/* Compute x = doubleround^4(B32). */
|
||||
for (i = 0; i < 16; i++)
|
||||
x[i] = B32[i];
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
/* Operate on columns. */
|
||||
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
|
||||
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
|
||||
|
||||
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
|
||||
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
|
||||
|
||||
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
|
||||
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
|
||||
|
||||
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
|
||||
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
|
||||
|
||||
/* Operate on rows. */
|
||||
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
|
||||
|
||||
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
|
||||
|
||||
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
|
||||
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
|
||||
|
||||
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
|
||||
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
|
||||
#undef R
|
||||
}
|
||||
|
||||
/* Compute B32 = B32 + x. */
|
||||
for (i = 0; i < 16; i++)
|
||||
B32[i] += x[i];
|
||||
|
||||
/* Convert little-endian values out. */
|
||||
for (i = 0; i < 16; i++)
|
||||
le32enc(&B[4 * i], B32[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(B, Y, r):
|
||||
* Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
|
||||
* length; the temporary space Y must also be the same size.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r)
|
||||
{
|
||||
uint8_t X[64];
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &B[(2 * r - 1) * 64], 64);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &B[i * 64], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
blkcpy(&Y[i * 64], X, 64);
|
||||
}
|
||||
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[i * 64], &Y[(i * 2) * 64], 64);
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(uint8_t * B, size_t r)
|
||||
{
|
||||
uint8_t * X = &B[(2 * r - 1) * 64];
|
||||
|
||||
return (le64dec(X));
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the
|
||||
* temporary storage V must be 128rN bytes in length; the temporary storage
|
||||
* XY must be 256r bytes in length. The value N must be a power of 2.
|
||||
*/
|
||||
static void
|
||||
smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY)
|
||||
{
|
||||
uint8_t * X = XY;
|
||||
uint8_t * Y = &XY[128 * r];
|
||||
uint64_t i;
|
||||
uint64_t j;
|
||||
|
||||
/* 1: X <-- B */
|
||||
blkcpy(X, B, 128 * r);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy(&V[i * (128 * r)], X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(X, &V[j * (128 * r)], 128 * r);
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
blkcpy(B, X, 128 * r);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
uint8_t * B;
|
||||
uint8_t * V;
|
||||
uint8_t * XY;
|
||||
size_t r = _r, p = _p;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N == 0)) {
|
||||
errno = EINVAL;
|
||||
goto err0;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > SIZE_MAX / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
if ((B = malloc(128 * r * p)) == NULL)
|
||||
goto err0;
|
||||
if ((XY = malloc(256 * r)) == NULL)
|
||||
goto err1;
|
||||
if ((V = malloc(128 * r * N)) == NULL)
|
||||
goto err2;
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[i * 128 * r], r, N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
|
||||
/* Free memory. */
|
||||
free(V);
|
||||
free(XY);
|
||||
free(B);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err2:
|
||||
free(XY);
|
||||
err1:
|
||||
free(B);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
@ -1,252 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cpusupport.h"
|
||||
#include "sha256.h"
|
||||
#include "warnp.h"
|
||||
|
||||
#include "crypto_scrypt_smix.h"
|
||||
#include "crypto_scrypt_smix_sse2.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
|
||||
static void (*smix_func)(uint8_t *, size_t, uint64_t, void *, void *) = NULL;
|
||||
|
||||
/**
|
||||
* _crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen, smix):
|
||||
* Perform the requested scrypt computation, using ${smix} as the smix routine.
|
||||
*/
|
||||
static int
|
||||
_crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,
|
||||
uint8_t * buf, size_t buflen,
|
||||
void (*smix)(uint8_t *, size_t, uint64_t, void *, void *))
|
||||
{
|
||||
void * B0, * V0, * XY0;
|
||||
uint8_t * B;
|
||||
uint32_t * V;
|
||||
uint32_t * XY;
|
||||
size_t r = _r, p = _p;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
|
||||
errno = EFBIG;
|
||||
goto err0;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N < 2)) {
|
||||
errno = EINVAL;
|
||||
goto err0;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > (SIZE_MAX - 64) / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
#ifdef HAVE_POSIX_MEMALIGN
|
||||
if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)
|
||||
goto err0;
|
||||
B = (uint8_t *)(B0);
|
||||
if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)
|
||||
goto err1;
|
||||
XY = (uint32_t *)(XY0);
|
||||
#if !defined(MAP_ANON) || !defined(HAVE_MMAP)
|
||||
if ((errno = posix_memalign(&V0, 64, (size_t)(128 * r * N))) != 0)
|
||||
goto err2;
|
||||
V = (uint32_t *)(V0);
|
||||
#endif
|
||||
#else
|
||||
if ((B0 = malloc(128 * r * p + 63)) == NULL)
|
||||
goto err0;
|
||||
B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));
|
||||
if ((XY0 = malloc(256 * r + 64 + 63)) == NULL)
|
||||
goto err1;
|
||||
XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));
|
||||
#if !defined(MAP_ANON) || !defined(HAVE_MMAP)
|
||||
if ((V0 = malloc(128 * r * N + 63)) == NULL)
|
||||
goto err2;
|
||||
V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MAP_ANON) && defined(HAVE_MMAP)
|
||||
if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
|
||||
#else
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
#endif
|
||||
-1, 0)) == MAP_FAILED)
|
||||
goto err2;
|
||||
V = (uint32_t *)(V0);
|
||||
#endif
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
(smix)(&B[i * 128 * r], r, N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);
|
||||
|
||||
/* Free memory. */
|
||||
#if defined(MAP_ANON) && defined(HAVE_MMAP)
|
||||
if (munmap(V0, 128 * r * N))
|
||||
goto err2;
|
||||
#else
|
||||
free(V0);
|
||||
#endif
|
||||
free(XY0);
|
||||
free(B0);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err2:
|
||||
free(XY0);
|
||||
err1:
|
||||
free(B0);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#define TESTLEN 64
|
||||
static struct scrypt_test {
|
||||
const char * passwd;
|
||||
const char * salt;
|
||||
uint64_t N;
|
||||
uint32_t r;
|
||||
uint32_t p;
|
||||
uint8_t result[TESTLEN];
|
||||
} testcase = {
|
||||
.passwd = "pleaseletmein",
|
||||
.salt = "SodiumChloride",
|
||||
.N = 16,
|
||||
.r = 8,
|
||||
.p = 1,
|
||||
.result = {
|
||||
0x25, 0xa9, 0xfa, 0x20, 0x7f, 0x87, 0xca, 0x09,
|
||||
0xa4, 0xef, 0x8b, 0x9f, 0x77, 0x7a, 0xca, 0x16,
|
||||
0xbe, 0xb7, 0x84, 0xae, 0x18, 0x30, 0xbf, 0xbf,
|
||||
0xd3, 0x83, 0x25, 0xaa, 0xbb, 0x93, 0x77, 0xdf,
|
||||
0x1b, 0xa7, 0x84, 0xd7, 0x46, 0xea, 0x27, 0x3b,
|
||||
0xf5, 0x16, 0xa4, 0x6f, 0xbf, 0xac, 0xf5, 0x11,
|
||||
0xc5, 0xbe, 0xba, 0x4c, 0x4a, 0xb3, 0xac, 0xc7,
|
||||
0xfa, 0x6f, 0x46, 0x0b, 0x6c, 0x0f, 0x47, 0x7b,
|
||||
}
|
||||
};
|
||||
|
||||
static int
|
||||
testsmix(void (*smix)(uint8_t *, size_t, uint64_t, void *, void *))
|
||||
{
|
||||
uint8_t hbuf[TESTLEN];
|
||||
|
||||
/* Perform the computation. */
|
||||
if (_crypto_scrypt(
|
||||
(const uint8_t *)testcase.passwd, strlen(testcase.passwd),
|
||||
(const uint8_t *)testcase.salt, strlen(testcase.salt),
|
||||
testcase.N, testcase.r, testcase.p, hbuf, TESTLEN, smix))
|
||||
return (-1);
|
||||
|
||||
/* Does it match? */
|
||||
return (memcmp(testcase.result, hbuf, TESTLEN));
|
||||
}
|
||||
|
||||
static void
|
||||
selectsmix(void)
|
||||
{
|
||||
|
||||
#ifdef CPUSUPPORT_X86_SSE2
|
||||
/* If we're running on an SSE2-capable CPU, try that code. */
|
||||
if (cpusupport_x86_sse2()) {
|
||||
/* If SSE2ized smix works, use it. */
|
||||
if (!testsmix(crypto_scrypt_smix_sse2)) {
|
||||
smix_func = crypto_scrypt_smix_sse2;
|
||||
return;
|
||||
}
|
||||
warn0("Disabling broken SSE2 scrypt support - please report bug!");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If generic smix works, use it. */
|
||||
if (!testsmix(crypto_scrypt_smix)) {
|
||||
smix_func = crypto_scrypt_smix;
|
||||
return;
|
||||
}
|
||||
warn0("Generic scrypt code is broken - please report bug!");
|
||||
|
||||
/* If we get here, something really bad happened. */
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
|
||||
if (smix_func == NULL)
|
||||
selectsmix();
|
||||
|
||||
return (_crypto_scrypt(passwd, passwdlen, salt, saltlen, N, _r, _p,
|
||||
buf, buflen, smix_func));
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _CRYPTO_SCRYPT_H_
|
||||
#define _CRYPTO_SCRYPT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,
|
||||
uint32_t, uint32_t, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_CRYPTO_SCRYPT_H_ */
|
@ -1,213 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt_smix.h"
|
||||
|
||||
static void blkcpy(void *, const void *, size_t);
|
||||
static void blkxor(void *, const void *, size_t);
|
||||
static void salsa20_8(uint32_t[16]);
|
||||
static void blockmix_salsa8(const uint32_t *, uint32_t *, uint32_t *, size_t);
|
||||
static uint64_t integerify(const void *, size_t);
|
||||
|
||||
static void
|
||||
blkcpy(void * dest, const void * src, size_t len)
|
||||
{
|
||||
size_t * D = dest;
|
||||
const size_t * S = src;
|
||||
size_t L = len / sizeof(size_t);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = S[i];
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(void * dest, const void * src, size_t len)
|
||||
{
|
||||
size_t * D = dest;
|
||||
const size_t * S = src;
|
||||
size_t L = len / sizeof(size_t);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] ^= S[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20_8(B):
|
||||
* Apply the salsa20/8 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20_8(uint32_t B[16])
|
||||
{
|
||||
uint32_t x[16];
|
||||
size_t i;
|
||||
|
||||
blkcpy(x, B, 64);
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
/* Operate on columns. */
|
||||
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
|
||||
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
|
||||
|
||||
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
|
||||
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
|
||||
|
||||
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
|
||||
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
|
||||
|
||||
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
|
||||
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
|
||||
|
||||
/* Operate on rows. */
|
||||
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
|
||||
|
||||
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
|
||||
|
||||
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
|
||||
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
|
||||
|
||||
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
|
||||
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
|
||||
#undef R
|
||||
}
|
||||
for (i = 0; i < 16; i++)
|
||||
B[i] += x[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(Bin, Bout, X, r):
|
||||
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
|
||||
* bytes in length; the output Bout must also be the same size. The
|
||||
* temporary space X must be 64 bytes.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < 2 * r; i += 2) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 16], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[i * 8], X, 64);
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 16 + 16], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[i * 8 + r * 16], X, 64);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(const void * B, size_t r)
|
||||
{
|
||||
const uint32_t * X = (const void *)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
|
||||
return (((uint64_t)(X[1]) << 32) + X[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt_smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*/
|
||||
void
|
||||
crypto_scrypt_smix(uint8_t * B, size_t r, uint64_t N, void * _V, void * XY)
|
||||
{
|
||||
uint32_t * X = XY;
|
||||
uint32_t * Y = (void *)((uint8_t *)(XY) + 128 * r);
|
||||
uint32_t * Z = (void *)((uint8_t *)(XY) + 256 * r);
|
||||
uint32_t * V = _V;
|
||||
uint64_t i;
|
||||
uint64_t j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
for (k = 0; k < 32 * r; k++)
|
||||
X[k] = le32dec(&B[4 * k]);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy(&V[i * (32 * r)], X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(X, &V[j * (32 * r)], 128 * r);
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(Y, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(Y, &V[j * (32 * r)], 128 * r);
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 32 * r; k++)
|
||||
le32enc(&B[4 * k], X[k]);
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#ifndef _CRYPTO_SCRYPT_SMIX_H_
|
||||
#define _CRYPTO_SCRYPT_SMIX_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* crypto_scrypt_smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*/
|
||||
void crypto_scrypt_smix(uint8_t *, size_t, uint64_t, void *, void *);
|
||||
|
||||
#endif /* !_CRYPTO_SCRYPT_SMIX_H_ */
|
@ -1,248 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "cpusupport.h"
|
||||
#ifdef CPUSUPPORT_X86_SSE2
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt_smix_sse2.h"
|
||||
|
||||
static void blkcpy(void *, const void *, size_t);
|
||||
static void blkxor(void *, const void *, size_t);
|
||||
static void salsa20_8(__m128i *);
|
||||
static void blockmix_salsa8(const __m128i *, __m128i *, __m128i *, size_t);
|
||||
static uint64_t integerify(const void *, size_t);
|
||||
|
||||
static void
|
||||
blkcpy(void * dest, const void * src, size_t len)
|
||||
{
|
||||
__m128i * D = dest;
|
||||
const __m128i * S = src;
|
||||
size_t L = len / 16;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = S[i];
|
||||
}
|
||||
|
||||
static void
|
||||
blkxor(void * dest, const void * src, size_t len)
|
||||
{
|
||||
__m128i * D = dest;
|
||||
const __m128i * S = src;
|
||||
size_t L = len / 16;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < L; i++)
|
||||
D[i] = _mm_xor_si128(D[i], S[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20_8(B):
|
||||
* Apply the salsa20/8 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20_8(__m128i B[4])
|
||||
{
|
||||
__m128i X0, X1, X2, X3;
|
||||
__m128i T;
|
||||
size_t i;
|
||||
|
||||
X0 = B[0];
|
||||
X1 = B[1];
|
||||
X2 = B[2];
|
||||
X3 = B[3];
|
||||
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
/* Operate on "columns". */
|
||||
T = _mm_add_epi32(X0, X3);
|
||||
X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7));
|
||||
X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25));
|
||||
T = _mm_add_epi32(X1, X0);
|
||||
X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
|
||||
X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
|
||||
T = _mm_add_epi32(X2, X1);
|
||||
X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13));
|
||||
X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19));
|
||||
T = _mm_add_epi32(X3, X2);
|
||||
X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
|
||||
X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
|
||||
|
||||
/* Rearrange data. */
|
||||
X1 = _mm_shuffle_epi32(X1, 0x93);
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E);
|
||||
X3 = _mm_shuffle_epi32(X3, 0x39);
|
||||
|
||||
/* Operate on "rows". */
|
||||
T = _mm_add_epi32(X0, X1);
|
||||
X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7));
|
||||
X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25));
|
||||
T = _mm_add_epi32(X3, X0);
|
||||
X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
|
||||
X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
|
||||
T = _mm_add_epi32(X2, X3);
|
||||
X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13));
|
||||
X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19));
|
||||
T = _mm_add_epi32(X1, X2);
|
||||
X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
|
||||
X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));
|
||||
|
||||
/* Rearrange data. */
|
||||
X1 = _mm_shuffle_epi32(X1, 0x39);
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E);
|
||||
X3 = _mm_shuffle_epi32(X3, 0x93);
|
||||
}
|
||||
|
||||
B[0] = _mm_add_epi32(B[0], X0);
|
||||
B[1] = _mm_add_epi32(B[1], X1);
|
||||
B[2] = _mm_add_epi32(B[2], X2);
|
||||
B[3] = _mm_add_epi32(B[3], X3);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(Bin, Bout, X, r):
|
||||
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
|
||||
* bytes in length; the output Bout must also be the same size. The
|
||||
* temporary space X must be 64 bytes.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(const __m128i * Bin, __m128i * Bout, __m128i * X, size_t r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &Bin[8 * r - 4], 64);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < r; i++) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 8], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[i * 4], X, 64);
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor(X, &Bin[i * 8 + 4], 64);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy(&Bout[(r + i) * 4], X, 64);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
* Note that B's layout is permuted compared to the generic implementation.
|
||||
*/
|
||||
static uint64_t
|
||||
integerify(const void * B, size_t r)
|
||||
{
|
||||
const uint32_t * X = (const void *)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
|
||||
return (((uint64_t)(X[13]) << 32) + X[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_scrypt_smix_sse2(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*
|
||||
* Use SSE2 instructions.
|
||||
*/
|
||||
void
|
||||
crypto_scrypt_smix_sse2(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)
|
||||
{
|
||||
__m128i * X = XY;
|
||||
__m128i * Y = (void *)((uintptr_t)(XY) + 128 * r);
|
||||
__m128i * Z = (void *)((uintptr_t)(XY) + 256 * r);
|
||||
uint32_t * X32 = (void *)X;
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
for (k = 0; k < 2 * r; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
X32[k * 16 + i] =
|
||||
le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),
|
||||
Y, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(Y, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
le32enc(&B[(k * 16 + (i * 5 % 16)) * 4],
|
||||
X32[k * 16 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CPUSUPPORT_X86_SSE2 */
|
@ -1,19 +0,0 @@
|
||||
#ifndef _CRYPTO_SCRYPT_SMIX_SSE2_H_
|
||||
#define _CRYPTO_SCRYPT_SMIX_SSE2_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* crypto_scrypt_smix_sse2(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*
|
||||
* Use SSE2 instructions.
|
||||
*/
|
||||
void crypto_scrypt_smix_sse2(uint8_t *, size_t, uint64_t, void *, void *);
|
||||
|
||||
#endif /* !_CRYPTO_SCRYPT_SMIX_SSE2_H_ */
|
@ -1,609 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_aes.h"
|
||||
#include "crypto_aesctr.h"
|
||||
#include "crypto_entropy.h"
|
||||
#include "humansize.h"
|
||||
#include "insecure_memzero.h"
|
||||
#include "sha256.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
#include "memlimit.h"
|
||||
#include "scryptenc_cpuperf.h"
|
||||
|
||||
#include "scryptenc.h"
|
||||
|
||||
#define ENCBLOCK 65536
|
||||
|
||||
static int pickparams(size_t, double, double,
|
||||
int *, uint32_t *, uint32_t *, int);
|
||||
static int checkparams(size_t, double, double, int, uint32_t, uint32_t, int,
|
||||
int);
|
||||
|
||||
static void
|
||||
display_params(int logN, uint32_t r, uint32_t p, size_t memlimit,
|
||||
double opps, double maxtime)
|
||||
{
|
||||
uint64_t N = (uint64_t)(1) << logN;
|
||||
uint64_t mem_minimum = 128 * r * N;
|
||||
double expected_seconds = 4 * N * p / opps;
|
||||
char * human_memlimit = humansize(memlimit);
|
||||
char * human_mem_minimum = humansize(mem_minimum);
|
||||
|
||||
fprintf(stderr, "Parameters used: N = %" PRIu64 "; r = %" PRIu32
|
||||
"; p = %" PRIu32 ";\n", N, r, p);
|
||||
fprintf(stderr, " This requires at least %s bytes of memory "
|
||||
"(%s available),\n", human_mem_minimum, human_memlimit);
|
||||
fprintf(stderr, " and will take approximately %.1f seconds "
|
||||
"(limit: %.1f seconds).\n", expected_seconds, maxtime);
|
||||
|
||||
free(human_memlimit);
|
||||
free(human_mem_minimum);
|
||||
}
|
||||
|
||||
static int
|
||||
pickparams(size_t maxmem, double maxmemfrac, double maxtime,
|
||||
int * logN, uint32_t * r, uint32_t * p, int verbose)
|
||||
{
|
||||
size_t memlimit;
|
||||
double opps;
|
||||
double opslimit;
|
||||
double maxN, maxrp;
|
||||
int rc;
|
||||
|
||||
/* Figure out how much memory to use. */
|
||||
if (memtouse(maxmem, maxmemfrac, &memlimit))
|
||||
return (1);
|
||||
|
||||
/* Figure out how fast the CPU is. */
|
||||
if ((rc = scryptenc_cpuperf(&opps)) != 0)
|
||||
return (rc);
|
||||
opslimit = opps * maxtime;
|
||||
|
||||
/* Allow a minimum of 2^15 salsa20/8 cores. */
|
||||
if (opslimit < 32768)
|
||||
opslimit = 32768;
|
||||
|
||||
/* Fix r = 8 for now. */
|
||||
*r = 8;
|
||||
|
||||
/*
|
||||
* The memory limit requires that 128Nr <= memlimit, while the CPU
|
||||
* limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32,
|
||||
* opslimit imposes the stronger limit on N.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n",
|
||||
memlimit, opslimit);
|
||||
#endif
|
||||
if (opslimit < (double)memlimit / 32) {
|
||||
/* Set p = 1 and choose N based on the CPU limit. */
|
||||
*p = 1;
|
||||
maxN = opslimit / (*r * 4);
|
||||
for (*logN = 1; *logN < 63; *logN += 1) {
|
||||
if ((uint64_t)(1) << *logN > maxN / 2)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Set N based on the memory limit. */
|
||||
maxN = memlimit / (*r * 128);
|
||||
for (*logN = 1; *logN < 63; *logN += 1) {
|
||||
if ((uint64_t)(1) << *logN > maxN / 2)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Choose p based on the CPU limit. */
|
||||
maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN);
|
||||
if (maxrp > 0x3fffffff)
|
||||
maxrp = 0x3fffffff;
|
||||
*p = (uint32_t)(maxrp) / *r;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
display_params(*logN, *r, *p, memlimit, opps, maxtime);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
checkparams(size_t maxmem, double maxmemfrac, double maxtime,
|
||||
int logN, uint32_t r, uint32_t p, int verbose, int force)
|
||||
{
|
||||
size_t memlimit;
|
||||
double opps;
|
||||
double opslimit;
|
||||
uint64_t N;
|
||||
int rc;
|
||||
|
||||
/* Sanity-check values. */
|
||||
if ((logN < 1) || (logN > 63))
|
||||
return (7);
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000)
|
||||
return (7);
|
||||
|
||||
/* Are we forcing decryption, regardless of resource limits? */
|
||||
if (!force) {
|
||||
/* Figure out the maximum amount of memory we can use. */
|
||||
if (memtouse(maxmem, maxmemfrac, &memlimit))
|
||||
return (1);
|
||||
|
||||
/* Figure out how fast the CPU is. */
|
||||
if ((rc = scryptenc_cpuperf(&opps)) != 0)
|
||||
return (rc);
|
||||
opslimit = opps * maxtime;
|
||||
|
||||
/* Check limits. */
|
||||
N = (uint64_t)(1) << logN;
|
||||
if ((memlimit / N) / r < 128)
|
||||
return (9);
|
||||
if ((opslimit / N) / (r * p) < 4)
|
||||
return (10);
|
||||
} else {
|
||||
/* We have no limit. */
|
||||
memlimit = 0;
|
||||
opps = 0;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
display_params(logN, r, p, memlimit, opps, maxtime);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
scryptenc_setup(uint8_t header[96], uint8_t dk[64],
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
size_t maxmem, double maxmemfrac, double maxtime, int verbose)
|
||||
{
|
||||
uint8_t salt[32];
|
||||
uint8_t hbuf[32];
|
||||
int logN;
|
||||
uint64_t N;
|
||||
uint32_t r;
|
||||
uint32_t p;
|
||||
SHA256_CTX ctx;
|
||||
uint8_t * key_hmac = &dk[32];
|
||||
HMAC_SHA256_CTX hctx;
|
||||
int rc;
|
||||
|
||||
/* Pick values for N, r, p. */
|
||||
if ((rc = pickparams(maxmem, maxmemfrac, maxtime,
|
||||
&logN, &r, &p, verbose)) != 0)
|
||||
return (rc);
|
||||
N = (uint64_t)(1) << logN;
|
||||
|
||||
/* Sanity check. */
|
||||
assert((logN > 0) && (logN < 256));
|
||||
|
||||
/* Get some salt. */
|
||||
if (crypto_entropy_read(salt, 32))
|
||||
return (4);
|
||||
|
||||
/* Generate the derived keys. */
|
||||
if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
|
||||
return (3);
|
||||
|
||||
/* Construct the file header. */
|
||||
memcpy(header, "scrypt", 6);
|
||||
header[6] = 0;
|
||||
header[7] = logN & 0xff;
|
||||
be32enc(&header[8], r);
|
||||
be32enc(&header[12], p);
|
||||
memcpy(&header[16], salt, 32);
|
||||
|
||||
/* Add header checksum. */
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, header, 48);
|
||||
SHA256_Final(hbuf, &ctx);
|
||||
memcpy(&header[48], hbuf, 16);
|
||||
|
||||
/* Add header signature (used for verifying password). */
|
||||
HMAC_SHA256_Init(&hctx, key_hmac, 32);
|
||||
HMAC_SHA256_Update(&hctx, header, 64);
|
||||
HMAC_SHA256_Final(hbuf, &hctx);
|
||||
memcpy(&header[64], hbuf, 32);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
size_t maxmem, double maxmemfrac, double maxtime, int verbose,
|
||||
int force)
|
||||
{
|
||||
uint8_t salt[32];
|
||||
uint8_t hbuf[32];
|
||||
int logN;
|
||||
uint32_t r;
|
||||
uint32_t p;
|
||||
uint64_t N;
|
||||
SHA256_CTX ctx;
|
||||
uint8_t * key_hmac = &dk[32];
|
||||
HMAC_SHA256_CTX hctx;
|
||||
int rc;
|
||||
|
||||
/* Parse N, r, p, salt. */
|
||||
logN = header[7];
|
||||
r = be32dec(&header[8]);
|
||||
p = be32dec(&header[12]);
|
||||
memcpy(salt, &header[16], 32);
|
||||
|
||||
/* Verify header checksum. */
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, header, 48);
|
||||
SHA256_Final(hbuf, &ctx);
|
||||
if (memcmp(&header[48], hbuf, 16))
|
||||
return (7);
|
||||
|
||||
/*
|
||||
* Check whether the provided parameters are valid and whether the
|
||||
* key derivation function can be computed within the allowed memory
|
||||
* and CPU time, unless the user chose to disable this test.
|
||||
*/
|
||||
if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p,
|
||||
verbose, force)) != 0)
|
||||
return (rc);
|
||||
|
||||
/* Compute the derived keys. */
|
||||
N = (uint64_t)(1) << logN;
|
||||
if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
|
||||
return (3);
|
||||
|
||||
/* Check header signature (i.e., verify password). */
|
||||
HMAC_SHA256_Init(&hctx, key_hmac, 32);
|
||||
HMAC_SHA256_Update(&hctx, header, 64);
|
||||
HMAC_SHA256_Final(hbuf, &hctx);
|
||||
if (memcmp(hbuf, &header[64], 32))
|
||||
return (11);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose):
|
||||
* Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
|
||||
* bytes to outbuf.
|
||||
*/
|
||||
int
|
||||
scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
size_t maxmem, double maxmemfrac, double maxtime, int verbose)
|
||||
{
|
||||
uint8_t dk[64];
|
||||
uint8_t hbuf[32];
|
||||
uint8_t header[96];
|
||||
uint8_t * key_enc = dk;
|
||||
uint8_t * key_hmac = &dk[32];
|
||||
int rc;
|
||||
HMAC_SHA256_CTX hctx;
|
||||
struct crypto_aes_key * key_enc_exp;
|
||||
struct crypto_aesctr * AES;
|
||||
|
||||
/* Generate the header and derived key. */
|
||||
if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
|
||||
maxmem, maxmemfrac, maxtime, verbose)) != 0)
|
||||
return (rc);
|
||||
|
||||
/* Copy header into output buffer. */
|
||||
memcpy(outbuf, header, 96);
|
||||
|
||||
/* Encrypt data. */
|
||||
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
|
||||
return (5);
|
||||
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
|
||||
return (6);
|
||||
crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen);
|
||||
crypto_aesctr_free(AES);
|
||||
crypto_aes_key_free(key_enc_exp);
|
||||
|
||||
/* Add signature. */
|
||||
HMAC_SHA256_Init(&hctx, key_hmac, 32);
|
||||
HMAC_SHA256_Update(&hctx, outbuf, 96 + inbuflen);
|
||||
HMAC_SHA256_Final(hbuf, &hctx);
|
||||
memcpy(&outbuf[96 + inbuflen], hbuf, 32);
|
||||
|
||||
/* Zero sensitive data. */
|
||||
insecure_memzero(dk, 64);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose, force):
|
||||
* Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the
|
||||
* decrypted data length to outlen. The allocated length of outbuf must
|
||||
* be at least inbuflen. If ${force} is 1, do not check whether
|
||||
* decryption will exceed the estimated available memory or time.
|
||||
*/
|
||||
int
|
||||
scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
|
||||
size_t * outlen, const uint8_t * passwd, size_t passwdlen,
|
||||
size_t maxmem, double maxmemfrac, double maxtime, int verbose,
|
||||
int force)
|
||||
{
|
||||
uint8_t hbuf[32];
|
||||
uint8_t dk[64];
|
||||
uint8_t * key_enc = dk;
|
||||
uint8_t * key_hmac = &dk[32];
|
||||
int rc;
|
||||
HMAC_SHA256_CTX hctx;
|
||||
struct crypto_aes_key * key_enc_exp;
|
||||
struct crypto_aesctr * AES;
|
||||
|
||||
/*
|
||||
* All versions of the scrypt format will start with "scrypt" and
|
||||
* have at least 7 bytes of header.
|
||||
*/
|
||||
if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0))
|
||||
return (7);
|
||||
|
||||
/* Check the format. */
|
||||
if (inbuf[6] != 0)
|
||||
return (8);
|
||||
|
||||
/* We must have at least 128 bytes. */
|
||||
if (inbuflen < 128)
|
||||
return (7);
|
||||
|
||||
/* Parse the header and generate derived keys. */
|
||||
if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
|
||||
maxmem, maxmemfrac, maxtime, verbose, force)) != 0)
|
||||
return (rc);
|
||||
|
||||
/* Decrypt data. */
|
||||
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
|
||||
return (5);
|
||||
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
|
||||
return (6);
|
||||
crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128);
|
||||
crypto_aesctr_free(AES);
|
||||
crypto_aes_key_free(key_enc_exp);
|
||||
*outlen = inbuflen - 128;
|
||||
|
||||
/* Verify signature. */
|
||||
HMAC_SHA256_Init(&hctx, key_hmac, 32);
|
||||
HMAC_SHA256_Update(&hctx, inbuf, inbuflen - 32);
|
||||
HMAC_SHA256_Final(hbuf, &hctx);
|
||||
if (memcmp(hbuf, &inbuf[inbuflen - 32], 32))
|
||||
return (7);
|
||||
|
||||
/* Zero sensitive data. */
|
||||
insecure_memzero(dk, 64);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptenc_file(infile, outfile, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose):
|
||||
* Read a stream from infile and encrypt it, writing the resulting stream to
|
||||
* outfile.
|
||||
*/
|
||||
int
|
||||
scryptenc_file(FILE * infile, FILE * outfile,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
size_t maxmem, double maxmemfrac, double maxtime, int verbose)
|
||||
{
|
||||
uint8_t buf[ENCBLOCK];
|
||||
uint8_t dk[64];
|
||||
uint8_t hbuf[32];
|
||||
uint8_t header[96];
|
||||
uint8_t * key_enc = dk;
|
||||
uint8_t * key_hmac = &dk[32];
|
||||
size_t readlen;
|
||||
HMAC_SHA256_CTX hctx;
|
||||
struct crypto_aes_key * key_enc_exp;
|
||||
struct crypto_aesctr * AES;
|
||||
int rc;
|
||||
|
||||
/* Generate the header and derived key. */
|
||||
if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
|
||||
maxmem, maxmemfrac, maxtime, verbose)) != 0)
|
||||
return (rc);
|
||||
|
||||
/* Hash and write the header. */
|
||||
HMAC_SHA256_Init(&hctx, key_hmac, 32);
|
||||
HMAC_SHA256_Update(&hctx, header, 96);
|
||||
if (fwrite(header, 96, 1, outfile) != 1)
|
||||
return (12);
|
||||
|
||||
/*
|
||||
* Read blocks of data, encrypt them, and write them out; hash the
|
||||
* data as it is produced.
|
||||
*/
|
||||
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
|
||||
return (5);
|
||||
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
|
||||
return (6);
|
||||
do {
|
||||
if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0)
|
||||
break;
|
||||
crypto_aesctr_stream(AES, buf, buf, readlen);
|
||||
HMAC_SHA256_Update(&hctx, buf, readlen);
|
||||
if (fwrite(buf, 1, readlen, outfile) < readlen) {
|
||||
crypto_aesctr_free(AES);
|
||||
return (12);
|
||||
}
|
||||
} while (1);
|
||||
crypto_aesctr_free(AES);
|
||||
crypto_aes_key_free(key_enc_exp);
|
||||
|
||||
/* Did we exit the loop due to a read error? */
|
||||
if (ferror(infile))
|
||||
return (13);
|
||||
|
||||
/* Compute the final HMAC and output it. */
|
||||
HMAC_SHA256_Final(hbuf, &hctx);
|
||||
if (fwrite(hbuf, 32, 1, outfile) != 1)
|
||||
return (12);
|
||||
|
||||
/* Zero sensitive data. */
|
||||
insecure_memzero(dk, 64);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptdec_file(infile, outfile, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose, force):
|
||||
* Read a stream from infile and decrypt it, writing the resulting stream to
|
||||
* outfile. If ${force} is 1, do not check whether decryption
|
||||
* will exceed the estimated available memory or time.
|
||||
*/
|
||||
int
|
||||
scryptdec_file(FILE * infile, FILE * outfile,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
size_t maxmem, double maxmemfrac, double maxtime, int verbose,
|
||||
int force)
|
||||
{
|
||||
uint8_t buf[ENCBLOCK + 32];
|
||||
uint8_t header[96];
|
||||
uint8_t hbuf[32];
|
||||
uint8_t dk[64];
|
||||
uint8_t * key_enc = dk;
|
||||
uint8_t * key_hmac = &dk[32];
|
||||
size_t buflen = 0;
|
||||
size_t readlen;
|
||||
HMAC_SHA256_CTX hctx;
|
||||
struct crypto_aes_key * key_enc_exp;
|
||||
struct crypto_aesctr * AES;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Read the first 7 bytes of the file; all future versions of scrypt
|
||||
* are guaranteed to have at least 7 bytes of header.
|
||||
*/
|
||||
if (fread(header, 7, 1, infile) < 1) {
|
||||
if (ferror(infile))
|
||||
return (13);
|
||||
else
|
||||
return (7);
|
||||
}
|
||||
|
||||
/* Do we have the right magic? */
|
||||
if (memcmp(header, "scrypt", 6))
|
||||
return (7);
|
||||
if (header[6] != 0)
|
||||
return (8);
|
||||
|
||||
/*
|
||||
* Read another 89 bytes of the file; version 0 of the scrypt file
|
||||
* format has a 96-byte header.
|
||||
*/
|
||||
if (fread(&header[7], 89, 1, infile) < 1) {
|
||||
if (ferror(infile))
|
||||
return (13);
|
||||
else
|
||||
return (7);
|
||||
}
|
||||
|
||||
/* Parse the header and generate derived keys. */
|
||||
if ((rc = scryptdec_setup(header, dk, passwd, passwdlen,
|
||||
maxmem, maxmemfrac, maxtime, verbose, force)) != 0)
|
||||
return (rc);
|
||||
|
||||
/* Start hashing with the header. */
|
||||
HMAC_SHA256_Init(&hctx, key_hmac, 32);
|
||||
HMAC_SHA256_Update(&hctx, header, 96);
|
||||
|
||||
/*
|
||||
* We don't know how long the encrypted data block is (we can't know,
|
||||
* since data can be streamed into 'scrypt enc') so we need to read
|
||||
* data and decrypt all of it except the final 32 bytes, then check
|
||||
* if that final 32 bytes is the correct signature.
|
||||
*/
|
||||
if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
|
||||
return (5);
|
||||
if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
|
||||
return (6);
|
||||
do {
|
||||
/* Read data until we have more than 32 bytes of it. */
|
||||
if ((readlen = fread(&buf[buflen], 1,
|
||||
ENCBLOCK + 32 - buflen, infile)) == 0)
|
||||
break;
|
||||
buflen += readlen;
|
||||
if (buflen <= 32)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Decrypt, hash, and output everything except the last 32
|
||||
* bytes out of what we have in our buffer.
|
||||
*/
|
||||
HMAC_SHA256_Update(&hctx, buf, buflen - 32);
|
||||
crypto_aesctr_stream(AES, buf, buf, buflen - 32);
|
||||
if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32) {
|
||||
crypto_aesctr_free(AES);
|
||||
return (12);
|
||||
}
|
||||
|
||||
/* Move the last 32 bytes to the start of the buffer. */
|
||||
memmove(buf, &buf[buflen - 32], 32);
|
||||
buflen = 32;
|
||||
} while (1);
|
||||
crypto_aesctr_free(AES);
|
||||
crypto_aes_key_free(key_enc_exp);
|
||||
|
||||
/* Did we exit the loop due to a read error? */
|
||||
if (ferror(infile))
|
||||
return (13);
|
||||
|
||||
/* Did we read enough data that we *might* have a valid signature? */
|
||||
if (buflen < 32)
|
||||
return (7);
|
||||
|
||||
/* Verify signature. */
|
||||
HMAC_SHA256_Final(hbuf, &hctx);
|
||||
if (memcmp(hbuf, buf, 32))
|
||||
return (7);
|
||||
|
||||
/* Zero sensitive data. */
|
||||
insecure_memzero(dk, 64);
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _SCRYPTENC_H_
|
||||
#define _SCRYPTENC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* NOTE: This file provides prototypes for routines which encrypt/decrypt data
|
||||
* using a key derived from a password by using the scrypt key derivation
|
||||
* function. If you are just trying to "hash" a password for user logins,
|
||||
* this is not the code you are looking for. You want to use the crypto_scrypt
|
||||
* function directly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The parameters maxmem, maxmemfrac, and maxtime used by all of these
|
||||
* functions are defined as follows:
|
||||
* maxmem - maximum number of bytes of storage to use for V array (which is
|
||||
* by far the largest consumer of memory). If this value is set to 0, no
|
||||
* maximum will be enforced; any other value less than 1 MiB will be
|
||||
* treated as 1 MiB.
|
||||
* maxmemfrac - maximum fraction of available storage to use for the V array,
|
||||
* where "available storage" is defined as the minimum out of the
|
||||
* RLIMIT_AS, RLIMIT_DATA. and RLIMIT_RSS resource limits (if any are
|
||||
* set). If this value is set to 0 or more than 0.5 it will be treated
|
||||
* as 0.5; and this value will never cause a limit of less than 1 MiB to
|
||||
* be enforced.
|
||||
* maxtime - maximum amount of CPU time to spend computing the derived keys,
|
||||
* in seconds. This limit is only approximately enforced; the CPU
|
||||
* performance is estimated and parameter limits are chosen accordingly.
|
||||
* For the encryption functions, the parameters to the scrypt key derivation
|
||||
* function are chosen to make the key as strong as possible subject to the
|
||||
* specified limits; for the decryption functions, the parameters used are
|
||||
* compared to the computed limits and an error is returned if decrypting
|
||||
* the data would take too much memory or CPU time.
|
||||
*/
|
||||
/**
|
||||
* Return codes from scrypt(enc|dec)_(buf|file):
|
||||
* 0 success
|
||||
* 1 getrlimit or sysctl(hw.usermem) failed
|
||||
* 2 clock_getres or clock_gettime failed
|
||||
* 3 error computing derived key
|
||||
* 4 could not read salt from /dev/urandom
|
||||
* 5 error in OpenSSL
|
||||
* 6 malloc failed
|
||||
* 7 data is not a valid scrypt-encrypted block
|
||||
* 8 unrecognized scrypt format
|
||||
* 9 decrypting file would take too much memory
|
||||
* 10 decrypting file would take too long
|
||||
* 11 password is incorrect
|
||||
* 12 error writing output file
|
||||
* 13 error reading input file
|
||||
*/
|
||||
|
||||
/**
|
||||
* scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose):
|
||||
* Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
|
||||
* bytes to outbuf.
|
||||
*/
|
||||
int scryptenc_buf(const uint8_t *, size_t, uint8_t *,
|
||||
const uint8_t *, size_t, size_t, double, double, int);
|
||||
|
||||
/**
|
||||
* scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose, force):
|
||||
* Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the
|
||||
* decrypted data length to outlen. The allocated length of outbuf must
|
||||
* be at least inbuflen. If ${force} is 1, do not check whether
|
||||
* decryption will exceed the estimated available memory or time.
|
||||
*/
|
||||
int scryptdec_buf(const uint8_t *, size_t, uint8_t *, size_t *,
|
||||
const uint8_t *, size_t, size_t, double, double, int, int);
|
||||
|
||||
/**
|
||||
* scryptenc_file(infile, outfile, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose):
|
||||
* Read a stream from infile and encrypt it, writing the resulting stream to
|
||||
* outfile.
|
||||
*/
|
||||
int scryptenc_file(FILE *, FILE *, const uint8_t *, size_t,
|
||||
size_t, double, double, int);
|
||||
|
||||
/**
|
||||
* scryptdec_file(infile, outfile, passwd, passwdlen,
|
||||
* maxmem, maxmemfrac, maxtime, verbose, force):
|
||||
* Read a stream from infile and decrypt it, writing the resulting stream to
|
||||
* outfile. If ${force} is 1, do not check whether decryption
|
||||
* will exceed the estimated available memory or time.
|
||||
*/
|
||||
int scryptdec_file(FILE *, FILE *, const uint8_t *, size_t,
|
||||
size_t, double, double, int, int);
|
||||
|
||||
#endif /* !_SCRYPTENC_H_ */
|
@ -1,185 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
|
||||
#include "scryptenc_cpuperf.h"
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
|
||||
static clockid_t clocktouse;
|
||||
|
||||
static int
|
||||
getclockres(double * resd)
|
||||
{
|
||||
struct timespec res;
|
||||
|
||||
/*
|
||||
* Try clocks in order of preference until we find one which works.
|
||||
* (We assume that if clock_getres works, clock_gettime will, too.)
|
||||
* The use of if/else/if/else/if/else rather than if/elif/elif/else
|
||||
* is ugly but legal, and allows us to #ifdef things appropriately.
|
||||
*/
|
||||
#ifdef CLOCK_VIRTUAL
|
||||
if (clock_getres(CLOCK_VIRTUAL, &res) == 0)
|
||||
clocktouse = CLOCK_VIRTUAL;
|
||||
else
|
||||
#endif
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
if (clock_getres(CLOCK_MONOTONIC, &res) == 0)
|
||||
clocktouse = CLOCK_MONOTONIC;
|
||||
else
|
||||
#endif
|
||||
if (clock_getres(CLOCK_REALTIME, &res) == 0)
|
||||
clocktouse = CLOCK_REALTIME;
|
||||
else
|
||||
return (-1);
|
||||
|
||||
/* Convert clock resolution to a double. */
|
||||
*resd = res.tv_sec + res.tv_nsec * 0.000000001;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getclocktime(struct timespec * ts)
|
||||
{
|
||||
|
||||
if (clock_gettime(clocktouse, ts))
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
static int
|
||||
getclockres(double * resd)
|
||||
{
|
||||
|
||||
*resd = 1.0 / CLOCKS_PER_SEC;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getclocktime(struct timespec * ts)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (gettimeofday(&tv, NULL))
|
||||
return (-1);
|
||||
ts->tv_sec = tv.tv_sec;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
getclockdiff(struct timespec * st, double * diffd)
|
||||
{
|
||||
struct timespec en;
|
||||
|
||||
if (getclocktime(&en))
|
||||
return (1);
|
||||
*diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 +
|
||||
(en.tv_sec - st->tv_sec);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* scryptenc_cpuperf(opps):
|
||||
* Estimate the number of salsa20/8 cores which can be executed per second,
|
||||
* and return the value via opps.
|
||||
*/
|
||||
int
|
||||
scryptenc_cpuperf(double * opps)
|
||||
{
|
||||
struct timespec st;
|
||||
double resd, diffd;
|
||||
uint64_t i = 0;
|
||||
|
||||
/* Get the clock resolution. */
|
||||
if (getclockres(&resd))
|
||||
return (2);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Clock resolution is %f\n", resd);
|
||||
#endif
|
||||
|
||||
/* Loop until the clock ticks. */
|
||||
if (getclocktime(&st))
|
||||
return (2);
|
||||
do {
|
||||
/* Do an scrypt. */
|
||||
if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0))
|
||||
return (3);
|
||||
|
||||
/* Has the clock ticked? */
|
||||
if (getclockdiff(&st, &diffd))
|
||||
return (2);
|
||||
if (diffd > 0)
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
/* Count how many scrypts we can do before the next tick. */
|
||||
if (getclocktime(&st))
|
||||
return (2);
|
||||
do {
|
||||
/* Do an scrypt. */
|
||||
if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0))
|
||||
return (3);
|
||||
|
||||
/* We invoked the salsa20/8 core 512 times. */
|
||||
i += 512;
|
||||
|
||||
/* Check if we have looped for long enough. */
|
||||
if (getclockdiff(&st, &diffd))
|
||||
return (2);
|
||||
if (diffd > resd)
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%ju salsa20/8 cores performed in %f seconds\n",
|
||||
(uintmax_t)i, diffd);
|
||||
#endif
|
||||
|
||||
/* We can do approximately i salsa20/8 cores per diffd seconds. */
|
||||
*opps = i / diffd;
|
||||
return (0);
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _SCRYPTENC_CPUPERF_H_
|
||||
#define _SCRYPTENC_CPUPERF_H_
|
||||
|
||||
/**
|
||||
* scryptenc_cpuperf(opps):
|
||||
* Estimate the number of salsa20/8 cores which can be executed per second,
|
||||
* and return the value via opps.
|
||||
*/
|
||||
int scryptenc_cpuperf(double *);
|
||||
|
||||
#endif /* !_SCRYPTENC_CPUPERF_H_ */
|
@ -1,325 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
|
||||
/* We use non-POSIX functionality in this file. */
|
||||
#undef _POSIX_C_SOURCE
|
||||
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SYSCTL_H
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SYSINFO_H
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "memlimit.h"
|
||||
|
||||
/* If we don't have CTL_HW, we can't use HW_USERMEM. */
|
||||
#ifndef CTL_HW
|
||||
#undef HW_USERMEM
|
||||
#endif
|
||||
|
||||
#ifdef CTL_HW
|
||||
static int
|
||||
memlimit_sysctl_hw(size_t * memlimit, int mibleaf)
|
||||
{
|
||||
int mib[2];
|
||||
uint8_t sysctlbuf[8];
|
||||
size_t sysctlbuflen = 8;
|
||||
uint64_t sysctlval;
|
||||
|
||||
/* Ask the kernel how much RAM we have. */
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = mibleaf;
|
||||
if (sysctl(mib, 2, sysctlbuf, &sysctlbuflen, NULL, 0))
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* If we read 8 bytes out, assume this is a system-endian uint64_t.
|
||||
* If we only read 4 bytes out, the OS is trying to give us a
|
||||
* uint32_t answer -- but given how many systems now have 4GB+ of RAM,
|
||||
* it's probably truncating, and we really can't trust the value we
|
||||
* have returned to us.
|
||||
*/
|
||||
if (sysctlbuflen == sizeof(uint64_t))
|
||||
memcpy(&sysctlval, sysctlbuf, sizeof(uint64_t));
|
||||
else if (sysctlbuflen == sizeof(uint32_t))
|
||||
sysctlval = SIZE_MAX;
|
||||
else
|
||||
return (1);
|
||||
|
||||
/* Return the sysctl value, but clamp to SIZE_MAX if necessary. */
|
||||
#if UINT64_MAX > SIZE_MAX
|
||||
if (sysctlval > SIZE_MAX)
|
||||
*memlimit = SIZE_MAX;
|
||||
else
|
||||
*memlimit = (size_t)sysctlval;
|
||||
#else
|
||||
*memlimit = sysctlval;
|
||||
#endif
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */
|
||||
#ifndef HAVE_STRUCT_SYSINFO
|
||||
#undef HAVE_SYSINFO
|
||||
#endif
|
||||
|
||||
/* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */
|
||||
#ifndef HAVE_STRUCT_SYSINFO_TOTALRAM
|
||||
#undef HAVE_SYSINFO
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSINFO
|
||||
static int
|
||||
memlimit_sysinfo(size_t * memlimit)
|
||||
{
|
||||
struct sysinfo info;
|
||||
uint64_t totalmem;
|
||||
|
||||
/* Get information from the kernel. */
|
||||
if (sysinfo(&info))
|
||||
return (1);
|
||||
totalmem = info.totalram;
|
||||
|
||||
/* If we're on a modern kernel, adjust based on mem_unit. */
|
||||
#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT
|
||||
totalmem = totalmem * info.mem_unit;
|
||||
#endif
|
||||
|
||||
/* Return the value, but clamp to SIZE_MAX if necessary. */
|
||||
#if UINT64_MAX > SIZE_MAX
|
||||
if (totalmem > SIZE_MAX)
|
||||
*memlimit = SIZE_MAX;
|
||||
else
|
||||
*memlimit = (size_t)totalmem;
|
||||
#else
|
||||
*memlimit = totalmem;
|
||||
#endif
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
#endif /* HAVE_SYSINFO */
|
||||
|
||||
static int
|
||||
memlimit_rlimit(size_t * memlimit)
|
||||
{
|
||||
struct rlimit rl;
|
||||
uint64_t memrlimit;
|
||||
|
||||
/* Find the least of... */
|
||||
memrlimit = (uint64_t)(-1);
|
||||
|
||||
/* ... RLIMIT_AS... */
|
||||
#ifdef RLIMIT_AS
|
||||
if (getrlimit(RLIMIT_AS, &rl))
|
||||
return (1);
|
||||
if ((rl.rlim_cur != RLIM_INFINITY) &&
|
||||
((uint64_t)rl.rlim_cur < memrlimit))
|
||||
memrlimit = (uint64_t)rl.rlim_cur;
|
||||
#endif
|
||||
|
||||
/* ... RLIMIT_DATA... */
|
||||
if (getrlimit(RLIMIT_DATA, &rl))
|
||||
return (1);
|
||||
if ((rl.rlim_cur != RLIM_INFINITY) &&
|
||||
((uint64_t)rl.rlim_cur < memrlimit))
|
||||
memrlimit = (uint64_t)rl.rlim_cur;
|
||||
|
||||
/* ... and RLIMIT_RSS. */
|
||||
#ifdef RLIMIT_RSS
|
||||
if (getrlimit(RLIMIT_RSS, &rl))
|
||||
return (1);
|
||||
if ((rl.rlim_cur != RLIM_INFINITY) &&
|
||||
((uint64_t)rl.rlim_cur < memrlimit))
|
||||
memrlimit = (uint64_t)rl.rlim_cur;
|
||||
#endif
|
||||
|
||||
/* Return the value, but clamp to SIZE_MAX if necessary. */
|
||||
#if UINT64_MAX > SIZE_MAX
|
||||
if (memrlimit > SIZE_MAX)
|
||||
*memlimit = SIZE_MAX;
|
||||
else
|
||||
*memlimit = (size_t)memrlimit;
|
||||
#else
|
||||
*memlimit = memrlimit;
|
||||
#endif
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef _SC_PHYS_PAGES
|
||||
|
||||
/* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */
|
||||
#ifndef _SC_PAGE_SIZE
|
||||
#define _SC_PAGE_SIZE _SC_PAGESIZE
|
||||
#endif
|
||||
|
||||
static int
|
||||
memlimit_sysconf(size_t * memlimit)
|
||||
{
|
||||
long pagesize;
|
||||
long physpages;
|
||||
uint64_t totalmem;
|
||||
|
||||
/* Set errno to 0 in order to distinguish "no limit" from "error". */
|
||||
errno = 0;
|
||||
|
||||
/* Read the two limits. */
|
||||
if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) ||
|
||||
((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) {
|
||||
/*
|
||||
* Did an error occur? OS X may return EINVAL due to not
|
||||
* supporting _SC_PHYS_PAGES in spite of defining it.
|
||||
*/
|
||||
if (errno != 0 && errno != EINVAL)
|
||||
return (1);
|
||||
|
||||
/* If not, there is no limit. */
|
||||
totalmem = (uint64_t)(-1);
|
||||
} else {
|
||||
/* Compute the limit. */
|
||||
totalmem = (uint64_t)(pagesize) * (uint64_t)(physpages);
|
||||
}
|
||||
|
||||
/* Return the value, but clamp to SIZE_MAX if necessary. */
|
||||
#if UINT64_MAX > SIZE_MAX
|
||||
if (totalmem > SIZE_MAX)
|
||||
*memlimit = SIZE_MAX;
|
||||
else
|
||||
*memlimit = (size_t)totalmem;
|
||||
#else
|
||||
*memlimit = totalmem;
|
||||
#endif
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit)
|
||||
{
|
||||
size_t usermem_memlimit, memsize_memlimit;
|
||||
size_t sysinfo_memlimit, rlimit_memlimit;
|
||||
size_t sysconf_memlimit;
|
||||
size_t memlimit_min;
|
||||
size_t memavail;
|
||||
|
||||
/* Get memory limits. */
|
||||
#ifdef HW_USERMEM
|
||||
if (memlimit_sysctl_hw(&usermem_memlimit, HW_USERMEM))
|
||||
return (1);
|
||||
#else
|
||||
usermem_memlimit = SIZE_MAX;
|
||||
#endif
|
||||
#ifdef HW_MEMSIZE
|
||||
if (memlimit_sysctl_hw(&memsize_memlimit, HW_MEMSIZE))
|
||||
return (1);
|
||||
#else
|
||||
memsize_memlimit = SIZE_MAX;
|
||||
#endif
|
||||
#ifdef HAVE_SYSINFO
|
||||
if (memlimit_sysinfo(&sysinfo_memlimit))
|
||||
return (1);
|
||||
#else
|
||||
sysinfo_memlimit = SIZE_MAX;
|
||||
#endif
|
||||
if (memlimit_rlimit(&rlimit_memlimit))
|
||||
return (1);
|
||||
#ifdef _SC_PHYS_PAGES
|
||||
if (memlimit_sysconf(&sysconf_memlimit))
|
||||
return (1);
|
||||
#else
|
||||
sysconf_memlimit = SIZE_MAX;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Memory limits are %zu %zu %zu %zu %zu\n",
|
||||
usermem_memlimit, memsize_memlimit,
|
||||
sysinfo_memlimit, rlimit_memlimit,
|
||||
sysconf_memlimit);
|
||||
#endif
|
||||
|
||||
/* Find the smallest of them. */
|
||||
memlimit_min = SIZE_MAX;
|
||||
if (memlimit_min > usermem_memlimit)
|
||||
memlimit_min = usermem_memlimit;
|
||||
if (memlimit_min > memsize_memlimit)
|
||||
memlimit_min = memsize_memlimit;
|
||||
if (memlimit_min > sysinfo_memlimit)
|
||||
memlimit_min = sysinfo_memlimit;
|
||||
if (memlimit_min > rlimit_memlimit)
|
||||
memlimit_min = rlimit_memlimit;
|
||||
if (memlimit_min > sysconf_memlimit)
|
||||
memlimit_min = sysconf_memlimit;
|
||||
|
||||
/* Only use the specified fraction of the available memory. */
|
||||
if ((maxmemfrac > 0.5) || (maxmemfrac == 0.0))
|
||||
maxmemfrac = 0.5;
|
||||
memavail = (size_t)(maxmemfrac * memlimit_min);
|
||||
|
||||
/* Don't use more than the specified maximum. */
|
||||
if ((maxmem > 0) && (memavail > maxmem))
|
||||
memavail = maxmem;
|
||||
|
||||
/* But always allow at least 1 MiB. */
|
||||
if (memavail < 1048576)
|
||||
memavail = 1048576;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Allowing up to %zu memory to be used\n", memavail);
|
||||
#endif
|
||||
|
||||
/* Return limit via the provided pointer. */
|
||||
*memlimit = memavail;
|
||||
return (0);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _MEMLIMIT_H_
|
||||
#define _MEMLIMIT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* memtouse(maxmem, maxmemfrac, memlimit):
|
||||
* Examine the system and return via memlimit the amount of RAM which should
|
||||
* be used -- the specified fraction of the available RAM, but no more than
|
||||
* maxmem, and no less than 1MiB.
|
||||
*/
|
||||
int memtouse(size_t, double, size_t *);
|
||||
|
||||
#endif /* !_MEMLIMIT_H_ */
|
@ -1,527 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
/*
|
||||
* Encode a length len/4 vector of (uint32_t) into a length len vector of
|
||||
* (uint8_t) in big-endian form. Assumes len is a multiple of 4.
|
||||
*/
|
||||
static void
|
||||
be32enc_vect(uint8_t * dst, const uint32_t * src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Sanity-check. */
|
||||
assert(len % 4 == 0);
|
||||
|
||||
/* Encode vector, one word at a time. */
|
||||
for (i = 0; i < len / 4; i++)
|
||||
be32enc(dst + i * 4, src[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a big-endian length len vector of (uint8_t) into a length
|
||||
* len/4 vector of (uint32_t). Assumes len is a multiple of 4.
|
||||
*/
|
||||
static void
|
||||
be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Sanity-check. */
|
||||
assert(len % 4 == 0);
|
||||
|
||||
/* Decode vector, one word at a time. */
|
||||
for (i = 0; i < len / 4; i++)
|
||||
dst[i] = be32dec(src + i * 4);
|
||||
}
|
||||
|
||||
/* SHA256 round constants. */
|
||||
static const uint32_t Krnd[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
/* Elementary functions used by SHA256 */
|
||||
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
|
||||
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
|
||||
#define SHR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
|
||||
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
/* SHA256 round function */
|
||||
#define RND(a, b, c, d, e, f, g, h, k) \
|
||||
h += S1(e) + Ch(e, f, g) + k; \
|
||||
d += h; \
|
||||
h += S0(a) + Maj(a, b, c);
|
||||
|
||||
/* Adjusted round function for rotating state */
|
||||
#define RNDr(S, W, i, ii) \
|
||||
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
|
||||
S[(66 - i) % 8], S[(67 - i) % 8], \
|
||||
S[(68 - i) % 8], S[(69 - i) % 8], \
|
||||
S[(70 - i) % 8], S[(71 - i) % 8], \
|
||||
W[i + ii] + Krnd[i + ii])
|
||||
|
||||
/* Message schedule computation */
|
||||
#define MSCH(W, ii, i) \
|
||||
W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
|
||||
|
||||
/*
|
||||
* SHA256 block compression function. The 256-bit state is transformed via
|
||||
* the 512-bit input block to produce a new state.
|
||||
*/
|
||||
static void
|
||||
SHA256_Transform(uint32_t state[static restrict 8],
|
||||
const uint8_t block[static restrict 64],
|
||||
uint32_t W[static restrict 64], uint32_t S[static restrict 8])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* 1. Prepare the first part of the message schedule W. */
|
||||
be32dec_vect(W, block, 64);
|
||||
|
||||
/* 2. Initialize working variables. */
|
||||
memcpy(S, state, 32);
|
||||
|
||||
/* 3. Mix. */
|
||||
for (i = 0; i < 64; i += 16) {
|
||||
RNDr(S, W, 0, i);
|
||||
RNDr(S, W, 1, i);
|
||||
RNDr(S, W, 2, i);
|
||||
RNDr(S, W, 3, i);
|
||||
RNDr(S, W, 4, i);
|
||||
RNDr(S, W, 5, i);
|
||||
RNDr(S, W, 6, i);
|
||||
RNDr(S, W, 7, i);
|
||||
RNDr(S, W, 8, i);
|
||||
RNDr(S, W, 9, i);
|
||||
RNDr(S, W, 10, i);
|
||||
RNDr(S, W, 11, i);
|
||||
RNDr(S, W, 12, i);
|
||||
RNDr(S, W, 13, i);
|
||||
RNDr(S, W, 14, i);
|
||||
RNDr(S, W, 15, i);
|
||||
|
||||
if (i == 48)
|
||||
break;
|
||||
MSCH(W, 0, i);
|
||||
MSCH(W, 1, i);
|
||||
MSCH(W, 2, i);
|
||||
MSCH(W, 3, i);
|
||||
MSCH(W, 4, i);
|
||||
MSCH(W, 5, i);
|
||||
MSCH(W, 6, i);
|
||||
MSCH(W, 7, i);
|
||||
MSCH(W, 8, i);
|
||||
MSCH(W, 9, i);
|
||||
MSCH(W, 10, i);
|
||||
MSCH(W, 11, i);
|
||||
MSCH(W, 12, i);
|
||||
MSCH(W, 13, i);
|
||||
MSCH(W, 14, i);
|
||||
MSCH(W, 15, i);
|
||||
}
|
||||
|
||||
/* 4. Mix local working variables into global state. */
|
||||
for (i = 0; i < 8; i++)
|
||||
state[i] += S[i];
|
||||
}
|
||||
|
||||
static const uint8_t PAD[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* Add padding and terminating bit-count. */
|
||||
static void
|
||||
SHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
size_t r;
|
||||
|
||||
/* Figure out how many bytes we have buffered. */
|
||||
r = (ctx->count >> 3) & 0x3f;
|
||||
|
||||
/* Pad to 56 mod 64, transforming if we finish a block en route. */
|
||||
if (r < 56) {
|
||||
/* Pad to 56 mod 64. */
|
||||
memcpy(&ctx->buf[r], PAD, 56 - r);
|
||||
} else {
|
||||
/* Finish the current block and mix. */
|
||||
memcpy(&ctx->buf[r], PAD, 64 - r);
|
||||
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
|
||||
|
||||
/* The start of the final block is all zeroes. */
|
||||
memset(&ctx->buf[0], 0, 56);
|
||||
}
|
||||
|
||||
/* Add the terminating bit-count. */
|
||||
be64enc(&ctx->buf[56], ctx->count);
|
||||
|
||||
/* Mix in the final block. */
|
||||
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
|
||||
}
|
||||
|
||||
/* Magic initialization constants. */
|
||||
static const uint32_t initial_state[8] = {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
||||
};
|
||||
|
||||
/**
|
||||
* SHA256_Init(ctx):
|
||||
* Initialize the SHA256 context ${ctx}.
|
||||
*/
|
||||
void
|
||||
SHA256_Init(SHA256_CTX * ctx)
|
||||
{
|
||||
|
||||
/* Zero bits processed so far. */
|
||||
ctx->count = 0;
|
||||
|
||||
/* Initialize state. */
|
||||
memcpy(ctx->state, initial_state, sizeof(initial_state));
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
|
||||
*/
|
||||
static void
|
||||
_SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len,
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
uint32_t r;
|
||||
const uint8_t * src = in;
|
||||
|
||||
/* Return immediately if we have nothing to do. */
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
/* Number of bytes left in the buffer from previous updates. */
|
||||
r = (ctx->count >> 3) & 0x3f;
|
||||
|
||||
/* Update number of bits. */
|
||||
ctx->count += (uint64_t)(len) << 3;
|
||||
|
||||
/* Handle the case where we don't need to perform any transforms. */
|
||||
if (len < 64 - r) {
|
||||
memcpy(&ctx->buf[r], src, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finish the current block. */
|
||||
memcpy(&ctx->buf[r], src, 64 - r);
|
||||
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
|
||||
src += 64 - r;
|
||||
len -= 64 - r;
|
||||
|
||||
/* Perform complete blocks. */
|
||||
while (len >= 64) {
|
||||
SHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]);
|
||||
src += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Copy left over data into buffer. */
|
||||
memcpy(ctx->buf, src, len);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
|
||||
/* Call the real function. */
|
||||
_SHA256_Update(ctx, in, len, tmp32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256_Final(digest, ctx):
|
||||
* Output the SHA256 hash of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
static void
|
||||
_SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx,
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
|
||||
/* Add padding. */
|
||||
SHA256_Pad(ctx, tmp32);
|
||||
|
||||
/* Write the hash. */
|
||||
be32enc_vect(digest, ctx->state, 32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
|
||||
/* Call the real function. */
|
||||
_SHA256_Final(digest, ctx, tmp32);
|
||||
|
||||
/* Clear the context state. */
|
||||
insecure_memzero(ctx, sizeof(SHA256_CTX));
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256_Buf(in, len, digest):
|
||||
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
|
||||
*/
|
||||
void
|
||||
SHA256_Buf(const void * in, size_t len, uint8_t digest[32])
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
uint32_t tmp32[72];
|
||||
|
||||
SHA256_Init(&ctx);
|
||||
_SHA256_Update(&ctx, in, len, tmp32);
|
||||
_SHA256_Final(digest, &ctx, tmp32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(&ctx, sizeof(SHA256_CTX));
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Init(ctx, K, Klen):
|
||||
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
|
||||
* ${K}.
|
||||
*/
|
||||
static void
|
||||
_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen,
|
||||
uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64],
|
||||
uint8_t khash[static restrict 32])
|
||||
{
|
||||
const uint8_t * K = _K;
|
||||
size_t i;
|
||||
|
||||
/* If Klen > 64, the key is really SHA256(K). */
|
||||
if (Klen > 64) {
|
||||
SHA256_Init(&ctx->ictx);
|
||||
_SHA256_Update(&ctx->ictx, K, Klen, tmp32);
|
||||
_SHA256_Final(khash, &ctx->ictx, tmp32);
|
||||
K = khash;
|
||||
Klen = 32;
|
||||
}
|
||||
|
||||
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
|
||||
SHA256_Init(&ctx->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
_SHA256_Update(&ctx->ictx, pad, 64, tmp32);
|
||||
|
||||
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
|
||||
SHA256_Init(&ctx->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
_SHA256_Update(&ctx->octx, pad, 64, tmp32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
uint8_t pad[64];
|
||||
uint8_t khash[32];
|
||||
|
||||
/* Call the real function. */
|
||||
_HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(khash, 32);
|
||||
insecure_memzero(pad, 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
|
||||
*/
|
||||
static void
|
||||
_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len,
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
|
||||
/* Feed data to the inner SHA256 operation. */
|
||||
_SHA256_Update(&ctx->ictx, in, len, tmp32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
|
||||
/* Call the real function. */
|
||||
_HMAC_SHA256_Update(ctx, in, len, tmp32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Final(digest, ctx):
|
||||
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
static void
|
||||
_HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx,
|
||||
uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32])
|
||||
{
|
||||
|
||||
/* Finish the inner SHA256 operation. */
|
||||
_SHA256_Final(ihash, &ctx->ictx, tmp32);
|
||||
|
||||
/* Feed the inner hash to the outer SHA256 operation. */
|
||||
_SHA256_Update(&ctx->octx, ihash, 32, tmp32);
|
||||
|
||||
/* Finish the outer SHA256 operation. */
|
||||
_SHA256_Final(digest, &ctx->octx, tmp32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
uint8_t ihash[32];
|
||||
|
||||
/* Call the real function. */
|
||||
_HMAC_SHA256_Final(digest, ctx, tmp32, ihash);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(ihash, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Buf(K, Klen, in, len, digest):
|
||||
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
|
||||
* length ${Klen}, and write the result to ${digest}.
|
||||
*/
|
||||
void
|
||||
HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len,
|
||||
uint8_t digest[32])
|
||||
{
|
||||
HMAC_SHA256_CTX ctx;
|
||||
uint32_t tmp32[72];
|
||||
uint8_t tmp8[96];
|
||||
|
||||
_HMAC_SHA256_Init(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]);
|
||||
_HMAC_SHA256_Update(&ctx, in, len, tmp32);
|
||||
_HMAC_SHA256_Final(digest, &ctx, tmp32, &tmp8[0]);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(tmp8, 96);
|
||||
}
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
|
||||
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
|
||||
{
|
||||
HMAC_SHA256_CTX Phctx, PShctx, hctx;
|
||||
uint32_t tmp32[72];
|
||||
uint8_t tmp8[96];
|
||||
size_t i;
|
||||
uint8_t ivec[4];
|
||||
uint8_t U[32];
|
||||
uint8_t T[32];
|
||||
uint64_t j;
|
||||
int k;
|
||||
size_t clen;
|
||||
|
||||
/* Sanity-check. */
|
||||
assert(dkLen <= 32 * (size_t)(UINT32_MAX));
|
||||
|
||||
/* Compute HMAC state after processing P. */
|
||||
_HMAC_SHA256_Init(&Phctx, passwd, passwdlen,
|
||||
tmp32, &tmp8[0], &tmp8[64]);
|
||||
|
||||
/* Compute HMAC state after processing P and S. */
|
||||
memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX));
|
||||
_HMAC_SHA256_Update(&PShctx, salt, saltlen, tmp32);
|
||||
|
||||
/* Iterate through the blocks. */
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
/* Generate INT(i + 1). */
|
||||
be32enc(ivec, (uint32_t)(i + 1));
|
||||
|
||||
/* Compute U_1 = PRF(P, S || INT(i)). */
|
||||
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
|
||||
_HMAC_SHA256_Update(&hctx, ivec, 4, tmp32);
|
||||
_HMAC_SHA256_Final(U, &hctx, tmp32, tmp8);
|
||||
|
||||
/* T_i = U_1 ... */
|
||||
memcpy(T, U, 32);
|
||||
|
||||
for (j = 2; j <= c; j++) {
|
||||
/* Compute U_j. */
|
||||
memcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX));
|
||||
_HMAC_SHA256_Update(&hctx, U, 32, tmp32);
|
||||
_HMAC_SHA256_Final(U, &hctx, tmp32, tmp8);
|
||||
|
||||
/* ... xor U_j ... */
|
||||
for (k = 0; k < 32; k++)
|
||||
T[k] ^= U[k];
|
||||
}
|
||||
|
||||
/* Copy as many bytes as necessary into buf. */
|
||||
clen = dkLen - i * 32;
|
||||
if (clen > 32)
|
||||
clen = 32;
|
||||
memcpy(&buf[i * 32], T, clen);
|
||||
}
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(tmp8, 96);
|
||||
insecure_memzero(U, 32);
|
||||
insecure_memzero(T, 32);
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
#ifndef _SHA256_H_
|
||||
#define _SHA256_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Use #defines in order to avoid namespace collisions with anyone else's
|
||||
* SHA256 code (e.g., the code in OpenSSL).
|
||||
*/
|
||||
#define SHA256_Init libcperciva_SHA256_Init
|
||||
#define SHA256_Update libcperciva_SHA256_Update
|
||||
#define SHA256_Final libcperciva_SHA256_Final
|
||||
#define SHA256_Buf libcperciva_SHA256_Buf
|
||||
#define SHA256_CTX libcperciva_SHA256_CTX
|
||||
#define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init
|
||||
#define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update
|
||||
#define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final
|
||||
#define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf
|
||||
#define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX
|
||||
|
||||
/* Context structure for SHA256 operations. */
|
||||
typedef struct {
|
||||
uint32_t state[8];
|
||||
uint64_t count;
|
||||
uint8_t buf[64];
|
||||
} SHA256_CTX;
|
||||
|
||||
/**
|
||||
* SHA256_Init(ctx):
|
||||
* Initialize the SHA256 context ${ctx}.
|
||||
*/
|
||||
void SHA256_Init(SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
|
||||
*/
|
||||
void SHA256_Update(SHA256_CTX *, const void *, size_t);
|
||||
|
||||
/**
|
||||
* SHA256_Final(digest, ctx):
|
||||
* Output the SHA256 hash of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
void SHA256_Final(uint8_t[32], SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* SHA256_Buf(in, len, digest):
|
||||
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
|
||||
*/
|
||||
void SHA256_Buf(const void *, size_t, uint8_t[32]);
|
||||
|
||||
/* Context structure for HMAC-SHA256 operations. */
|
||||
typedef struct {
|
||||
SHA256_CTX ictx;
|
||||
SHA256_CTX octx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Init(ctx, K, Klen):
|
||||
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
|
||||
* ${K}.
|
||||
*/
|
||||
void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
|
||||
*/
|
||||
void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Final(digest, ctx):
|
||||
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Buf(K, Klen, in, len, digest):
|
||||
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
|
||||
* length ${Klen}, and write the result to ${digest}.
|
||||
*/
|
||||
void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]);
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||
uint64_t, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_SHA256_H_ */
|
@ -1,14 +0,0 @@
|
||||
#include <wmmintrin.h>
|
||||
|
||||
static char a[16];
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
__m128i x, y;
|
||||
|
||||
x = _mm_loadu_si128((__m128i *)a);
|
||||
y = _mm_aesenc_si128(x, x);
|
||||
_mm_storeu_si128((__m128i *)a, y);
|
||||
return (a[0]);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#include <cpuid.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
unsigned int a, b, c, d;
|
||||
|
||||
return __get_cpuid(0, &a, &b, &c, &d);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#include <emmintrin.h>
|
||||
|
||||
static char a[16];
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
__m128i x;
|
||||
|
||||
x = _mm_loadu_si128((__m128i *)a);
|
||||
_mm_storeu_si128((__m128i *)a, x);
|
||||
return (a[0]);
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
# Should be sourced by `command -p sh path/to/cpusupport.sh "$PATH"` from
|
||||
# within a Makefile.
|
||||
if ! [ ${PATH} = "$1" ]; then
|
||||
echo "WARNING: POSIX violation: $SHELL's command -p resets \$PATH" 1>&2
|
||||
PATH=$1
|
||||
fi
|
||||
# Standard output should be written to cpusupport-config.h, which is both a
|
||||
# C header file defining CPUSUPPORT_ARCH_FEATURE macros and sourceable sh
|
||||
# code which sets CFLAGS_ARCH_FEATURE environment variables.
|
||||
SRCDIR=`command -p dirname "$0"`
|
||||
|
||||
feature() {
|
||||
ARCH=$1
|
||||
FEATURE=$2
|
||||
shift 2;
|
||||
if ! [ -f ${SRCDIR}/cpusupport-$ARCH-$FEATURE.c ]; then
|
||||
return
|
||||
fi
|
||||
printf "Checking if compiler supports $ARCH $FEATURE feature..." 1>&2
|
||||
for CFLAG in "$@"; do
|
||||
if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L ${CFLAG} \
|
||||
${SRCDIR}/cpusupport-$ARCH-$FEATURE.c 2>/dev/null; then
|
||||
rm -f a.out
|
||||
break;
|
||||
fi
|
||||
CFLAG=NOTSUPPORTED;
|
||||
done
|
||||
case $CFLAG in
|
||||
NOTSUPPORTED)
|
||||
echo " no" 1>&2
|
||||
;;
|
||||
"")
|
||||
echo " yes" 1>&2
|
||||
echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1"
|
||||
;;
|
||||
*)
|
||||
echo " yes, via $CFLAG" 1>&2
|
||||
echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1"
|
||||
echo "#ifdef cpusupport_dummy"
|
||||
echo "export CFLAGS_${ARCH}_${FEATURE}=\"${CFLAG}\""
|
||||
echo "#endif"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
feature X86 CPUID ""
|
||||
feature X86 SSE2 "" "-msse2" "-msse2 -Wno-cast-align"
|
||||
feature X86 AESNI "" "-maes" "-maes -Wno-cast-align" "-maes -Wno-missing-prototypes -Wno-cast-qual"
|
@ -1,106 +0,0 @@
|
||||
#ifndef _CPUSUPPORT_H_
|
||||
#define _CPUSUPPORT_H_
|
||||
|
||||
/*
|
||||
* To enable support for non-portable CPU features at compile time, one or
|
||||
* more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done
|
||||
* directly on the compiler command line via -D CPUSUPPORT_ARCH_FEATURE or
|
||||
* -D CPUSUPPORT_ARCH_FEATURE=1; or a file can be created with the
|
||||
* necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h
|
||||
* (or similar) can be provided to include that file here.
|
||||
*/
|
||||
#ifdef CPUSUPPORT_CONFIG_FILE
|
||||
#include CPUSUPPORT_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The CPUSUPPORT_FEATURE macro declares the necessary variables and
|
||||
* functions for detecting CPU feature support at run time. The function
|
||||
* defined in the macro acts to cache the result of the ..._detect function
|
||||
* using the ..._present and ..._init variables. The _detect function and the
|
||||
* _present and _init variables are turn defined by CPUSUPPORT_FEATURE_DECL in
|
||||
* appropriate cpusupport_foo_bar.c file.
|
||||
*
|
||||
* In order to allow CPUSUPPORT_FEATURE to be used for features which do not
|
||||
* have corresponding CPUSUPPORT_FEATURE_DECL blocks in another source file,
|
||||
* we abuse the C preprocessor: If CPUSUPPORT_${enabler} is defined to 1, then
|
||||
* we access _present_1, _init_1, and _detect_1; but if it is not defined, we
|
||||
* access _present_CPUSUPPORT_${enabler} etc., which we define as static, thus
|
||||
* preventing the compiler from emitting a reference to an external symbol.
|
||||
*
|
||||
* In this way, it becomes possible to issue CPUSUPPORT_FEATURE invocations
|
||||
* for nonexistent features without running afoul of the requirement that
|
||||
* "If an identifier declared with external linkage is used... in the entire
|
||||
* program there shall be exactly one external definition" (C99 standard, 6.9
|
||||
* paragraph 5). In practice, this means that users of the cpusupport code
|
||||
* can omit build and runtime detection files without changing the framework
|
||||
* code.
|
||||
*/
|
||||
#define CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) \
|
||||
static int cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \
|
||||
static int cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \
|
||||
static inline int cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler(void) { return (0); } \
|
||||
extern int cpusupport_ ## arch_feature ## _present_ ## enabled; \
|
||||
extern int cpusupport_ ## arch_feature ## _init_ ## enabled; \
|
||||
int cpusupport_ ## arch_feature ## _detect_ ## enabled(void); \
|
||||
\
|
||||
static inline int \
|
||||
cpusupport_ ## arch_feature(void) \
|
||||
{ \
|
||||
\
|
||||
if (cpusupport_ ## arch_feature ## _present_ ## enabled) \
|
||||
return (1); \
|
||||
else if (cpusupport_ ## arch_feature ## _init_ ## enabled) \
|
||||
return (0); \
|
||||
cpusupport_ ## arch_feature ## _present_ ## enabled = \
|
||||
cpusupport_ ## arch_feature ## _detect_ ## enabled(); \
|
||||
cpusupport_ ## arch_feature ## _init_ ## enabled = 1; \
|
||||
return (cpusupport_ ## arch_feature ## _present_ ## enabled); \
|
||||
} \
|
||||
static void (* cpusupport_ ## arch_feature ## _dummyptr)(void); \
|
||||
static inline void \
|
||||
cpusupport_ ## arch_feature ## _dummyfunc(void) \
|
||||
{ \
|
||||
\
|
||||
(void)cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \
|
||||
(void)cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \
|
||||
(void)cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler; \
|
||||
(void)cpusupport_ ## arch_feature ## _present_ ## enabled; \
|
||||
(void)cpusupport_ ## arch_feature ## _init_ ## enabled; \
|
||||
(void)cpusupport_ ## arch_feature ## _detect_ ## enabled; \
|
||||
(void)cpusupport_ ## arch_feature ## _dummyptr; \
|
||||
} \
|
||||
static void (* cpusupport_ ## arch_feature ## _dummyptr)(void) = cpusupport_ ## arch_feature ## _dummyfunc; \
|
||||
struct cpusupport_ ## arch_feature ## _dummy
|
||||
#define CPUSUPPORT_FEATURE_(arch_feature, enabler, enabled) \
|
||||
CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled)
|
||||
#define CPUSUPPORT_FEATURE(arch, feature, enabler) \
|
||||
CPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler)
|
||||
|
||||
/*
|
||||
* CPUSUPPORT_FEATURE_DECL(arch, feature):
|
||||
* Macro which defines variables and provides a function declaration for
|
||||
* detecting the presence of "feature" on the "arch" architecture. The
|
||||
* function body following this macro expansion must return nonzero if the
|
||||
* feature is present, or zero if the feature is not present or the detection
|
||||
* fails for any reason.
|
||||
*/
|
||||
#define CPUSUPPORT_FEATURE_DECL(arch, feature) \
|
||||
int cpusupport_ ## arch ## _ ## feature ## _present_1 = 0; \
|
||||
int cpusupport_ ## arch ## _ ## feature ## _init_1 = 0; \
|
||||
int cpusupport_ ## arch ## _ ## feature ## _detect_1(void); \
|
||||
int \
|
||||
cpusupport_ ## arch ## _ ## feature ## _detect_1(void)
|
||||
|
||||
/*
|
||||
* List of features. If a feature here is not enabled by the appropriate
|
||||
* CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the
|
||||
* relevant macro may be defined (e.g., by Build/cpusupport.sh successfully
|
||||
* compiling Build/cpusupport-ARCH-FEATURE.c) then the C file containing the
|
||||
* corresponding run-time detection code (cpusupport_arch_feature.c) must be
|
||||
* compiled and linked in.
|
||||
*/
|
||||
CPUSUPPORT_FEATURE(x86, aesni, X86_AESNI);
|
||||
CPUSUPPORT_FEATURE(x86, sse2, X86_SSE2);
|
||||
|
||||
#endif /* !_CPUSUPPORT_H_ */
|
@ -1,30 +0,0 @@
|
||||
#include "cpusupport.h"
|
||||
|
||||
#ifdef CPUSUPPORT_X86_CPUID
|
||||
#include <cpuid.h>
|
||||
|
||||
#define CPUID_AESNI_BIT (1 << 25)
|
||||
#endif
|
||||
|
||||
CPUSUPPORT_FEATURE_DECL(x86, aesni)
|
||||
{
|
||||
#ifdef CPUSUPPORT_X86_CPUID
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
/* Check if CPUID supports the level we need. */
|
||||
if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx))
|
||||
goto unsupported;
|
||||
if (eax < 1)
|
||||
goto unsupported;
|
||||
|
||||
/* Ask about CPU features. */
|
||||
if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
|
||||
goto unsupported;
|
||||
|
||||
/* Return the relevant feature bit. */
|
||||
return ((ecx & CPUID_AESNI_BIT) ? 1 : 0);
|
||||
|
||||
unsupported:
|
||||
#endif
|
||||
return (0);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#include "cpusupport.h"
|
||||
|
||||
#ifdef CPUSUPPORT_X86_CPUID
|
||||
#include <cpuid.h>
|
||||
|
||||
#define CPUID_SSE2_BIT (1 << 26)
|
||||
#endif
|
||||
|
||||
CPUSUPPORT_FEATURE_DECL(x86, sse2)
|
||||
{
|
||||
#ifdef CPUSUPPORT_X86_CPUID
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
/* Check if CPUID supports the level we need. */
|
||||
if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx))
|
||||
goto unsupported;
|
||||
if (eax < 1)
|
||||
goto unsupported;
|
||||
|
||||
/* Ask about CPU features. */
|
||||
if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
|
||||
goto unsupported;
|
||||
|
||||
/* Return the relevant feature bit. */
|
||||
return ((edx & CPUID_SSE2_BIT) ? 1 : 0);
|
||||
|
||||
unsupported:
|
||||
#endif
|
||||
return (0);
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#include "cpusupport.h"
|
||||
#include "crypto_aes_aesni.h"
|
||||
#include "insecure_memzero.h"
|
||||
#include "warnp.h"
|
||||
|
||||
#include "crypto_aes.h"
|
||||
|
||||
/**
|
||||
* This represents either an AES_KEY or a struct crypto_aes_key_aesni; we
|
||||
* know which it is based on whether we're using AESNI code or not. As such,
|
||||
* it's just an opaque pointer; but declaring it as a named structure type
|
||||
* prevents type-mismatch bugs in upstream code.
|
||||
*/
|
||||
struct crypto_aes_key;
|
||||
|
||||
#ifdef CPUSUPPORT_X86_AESNI
|
||||
/* Test whether OpenSSL and AESNI code produce the same AES ciphertext. */
|
||||
static int
|
||||
aesnitest(uint8_t ptext[16], uint8_t * key, size_t len)
|
||||
{
|
||||
AES_KEY kexp_openssl;
|
||||
void * kexp_aesni;
|
||||
uint8_t ctext_openssl[16];
|
||||
uint8_t ctext_aesni[16];
|
||||
|
||||
/* Sanity-check. */
|
||||
assert((len == 16) || (len == 32));
|
||||
|
||||
/* Expand the key. */
|
||||
AES_set_encrypt_key(key, (int)(len * 8), &kexp_openssl);
|
||||
if ((kexp_aesni = crypto_aes_key_expand_aesni(key, len)) == NULL)
|
||||
goto err0;
|
||||
|
||||
/* Encrypt the block. */
|
||||
AES_encrypt(ptext, ctext_openssl, &kexp_openssl);
|
||||
crypto_aes_encrypt_block_aesni(ptext, ctext_aesni, kexp_aesni);
|
||||
|
||||
/* Free the AESNI expanded key. */
|
||||
crypto_aes_key_free_aesni(kexp_aesni);
|
||||
|
||||
/* Do the outputs match? */
|
||||
return (memcmp(ctext_openssl, ctext_aesni, 16));
|
||||
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Should we use AESNI? */
|
||||
static int
|
||||
useaesni(void)
|
||||
{
|
||||
static int aesnigood = -1;
|
||||
uint8_t key[32];
|
||||
uint8_t ptext[16];
|
||||
size_t i;
|
||||
|
||||
/* If we haven't decided which code to use yet, decide now. */
|
||||
while (aesnigood == -1) {
|
||||
/* Default to OpenSSL. */
|
||||
aesnigood = 0;
|
||||
|
||||
/* If the CPU doesn't claim to support AESNI, stop here. */
|
||||
if (!cpusupport_x86_aesni())
|
||||
break;
|
||||
|
||||
/* Test cases: key is 0x00010203..., ptext is 0x00112233... */
|
||||
for (i = 0; i < 16; i++)
|
||||
ptext[i] = (0x11 * i) & 0xff;
|
||||
for (i = 0; i < 32; i++)
|
||||
key[i] = i & 0xff;
|
||||
|
||||
/* Test that AESNI and OpenSSL produce the same results. */
|
||||
if (aesnitest(ptext, key, 16) || aesnitest(ptext, key, 32)) {
|
||||
warn0("Disabling AESNI due to failed self-test");
|
||||
break;
|
||||
}
|
||||
|
||||
/* AESNI works; use it. */
|
||||
aesnigood = 1;
|
||||
}
|
||||
|
||||
return (aesnigood);
|
||||
}
|
||||
#endif /* CPUSUPPORT_X86_AESNI */
|
||||
|
||||
/**
|
||||
* crypto_aes_key_expand(key, len):
|
||||
* Expand the ${len}-byte AES key ${key} into a structure which can be passed
|
||||
* to crypto_aes_encrypt_block. The length must be 16 or 32.
|
||||
*/
|
||||
struct crypto_aes_key *
|
||||
crypto_aes_key_expand(const uint8_t * key, size_t len)
|
||||
{
|
||||
AES_KEY * kexp;
|
||||
|
||||
/* Sanity-check. */
|
||||
assert((len == 16) || (len == 32));
|
||||
|
||||
#ifdef CPUSUPPORT_X86_AESNI
|
||||
/* Use AESNI if we can. */
|
||||
if (useaesni())
|
||||
return (crypto_aes_key_expand_aesni(key, len));
|
||||
#endif
|
||||
|
||||
/* Allocate structure. */
|
||||
if ((kexp = malloc(sizeof(AES_KEY))) == NULL)
|
||||
goto err0;
|
||||
|
||||
/* Expand the key. */
|
||||
AES_set_encrypt_key(key, (int)(len * 8), kexp);
|
||||
|
||||
/* Success! */
|
||||
return ((void *)kexp);
|
||||
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aes_encrypt_block(in, out, key):
|
||||
* Using the expanded AES key ${key}, encrypt the block ${in} and write the
|
||||
* resulting ciphertext to ${out}.
|
||||
*/
|
||||
void
|
||||
crypto_aes_encrypt_block(const uint8_t * in, uint8_t * out,
|
||||
const struct crypto_aes_key * key)
|
||||
{
|
||||
|
||||
#ifdef CPUSUPPORT_X86_AESNI
|
||||
if (useaesni()) {
|
||||
crypto_aes_encrypt_block_aesni(in, out, (const void *)key);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get AES to do the work. */
|
||||
AES_encrypt(in, out, (const void *)key);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aes_key_free(key):
|
||||
* Free the expanded AES key ${key}.
|
||||
*/
|
||||
void
|
||||
crypto_aes_key_free(struct crypto_aes_key * key)
|
||||
{
|
||||
|
||||
#ifdef CPUSUPPORT_X86_AESNI
|
||||
if (useaesni()) {
|
||||
crypto_aes_key_free_aesni((void *)key);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Behave consistently with free(NULL). */
|
||||
if (key == NULL)
|
||||
return;
|
||||
|
||||
/* Attempt to zero the expanded key. */
|
||||
insecure_memzero(key, sizeof(AES_KEY));
|
||||
|
||||
/* Free the key. */
|
||||
free(key);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef _CRYPTO_AES_H_
|
||||
#define _CRYPTO_AES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Opaque structure. */
|
||||
struct crypto_aes_key;
|
||||
|
||||
/**
|
||||
* crypto_aes_key_expand(key, len):
|
||||
* Expand the ${len}-byte AES key ${key} into a structure which can be passed
|
||||
* to crypto_aes_encrypt_block. The length must be 16 or 32.
|
||||
*/
|
||||
struct crypto_aes_key * crypto_aes_key_expand(const uint8_t *, size_t);
|
||||
|
||||
/**
|
||||
* crypto_aes_encrypt_block(in, out, key):
|
||||
* Using the expanded AES key ${key}, encrypt the block ${in} and write the
|
||||
* resulting ciphertext to ${out}.
|
||||
*/
|
||||
void crypto_aes_encrypt_block(const uint8_t *, uint8_t *,
|
||||
const struct crypto_aes_key *);
|
||||
|
||||
/**
|
||||
* crypto_aes_key_free(key):
|
||||
* Free the expanded AES key ${key}.
|
||||
*/
|
||||
void crypto_aes_key_free(struct crypto_aes_key *);
|
||||
|
||||
#endif /* !_CRYPTO_AES_H_ */
|
@ -1,239 +0,0 @@
|
||||
#include "cpusupport.h"
|
||||
#ifdef CPUSUPPORT_X86_AESNI
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <wmmintrin.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
#include "warnp.h"
|
||||
|
||||
#include "crypto_aes_aesni.h"
|
||||
|
||||
/* Expanded-key structure. */
|
||||
struct crypto_aes_key_aesni {
|
||||
uint8_t rkeys_buf[15 * sizeof(__m128i) + (sizeof(__m128i) - 1)];
|
||||
__m128i * rkeys;
|
||||
size_t nr;
|
||||
};
|
||||
|
||||
/* Compute an AES-128 round key. */
|
||||
#define MKRKEY128(rkeys, i, rcon) do { \
|
||||
__m128i _s = rkeys[i - 1]; \
|
||||
__m128i _t = rkeys[i - 1]; \
|
||||
_s = _mm_xor_si128(_s, _mm_slli_si128(_s, 4)); \
|
||||
_s = _mm_xor_si128(_s, _mm_slli_si128(_s, 8)); \
|
||||
_t = _mm_aeskeygenassist_si128(_t, rcon); \
|
||||
_t = _mm_shuffle_epi32(_t, 0xff); \
|
||||
rkeys[i] = _mm_xor_si128(_s, _t); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* crypto_aes_key_expand_128_aesni(key, rkeys):
|
||||
* Expand the 128-bit AES key ${key} into the 11 round keys ${rkeys}. This
|
||||
* implementation uses x86 AESNI instructions, and should only be used if
|
||||
* CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero.
|
||||
*/
|
||||
static void
|
||||
crypto_aes_key_expand_128_aesni(const uint8_t key[16], __m128i rkeys[11])
|
||||
{
|
||||
|
||||
/* The first round key is just the key. */
|
||||
/**
|
||||
* XXX Compiler breakage:
|
||||
* The intrinsic defined by Intel for _mm_loadu_si128 defines it as
|
||||
* taking a (const __m128i *) parameter. This forces us to write a
|
||||
* bug: The cast to (const __m128i *) is invalid since it increases
|
||||
* the alignment requirement of the pointer. Alas, until compilers
|
||||
* get fixed intrinsics, all we can do is code the bug and require
|
||||
* that alignment-requirement-increasing compiler warnings get
|
||||
* disabled.
|
||||
*/
|
||||
rkeys[0] = _mm_loadu_si128((const __m128i *)&key[0]);
|
||||
|
||||
/*
|
||||
* Each of the remaining round keys are computed from the preceding
|
||||
* round key: rotword+subword+rcon (provided as aeskeygenassist) to
|
||||
* compute the 'temp' value, then xor with 1, 2, 3, or all 4 of the
|
||||
* 32-bit words from the preceding round key. Unfortunately, 'rcon'
|
||||
* is encoded as an immediate value, so we need to write the loop out
|
||||
* ourselves rather than allowing the compiler to expand it.
|
||||
*/
|
||||
MKRKEY128(rkeys, 1, 0x01);
|
||||
MKRKEY128(rkeys, 2, 0x02);
|
||||
MKRKEY128(rkeys, 3, 0x04);
|
||||
MKRKEY128(rkeys, 4, 0x08);
|
||||
MKRKEY128(rkeys, 5, 0x10);
|
||||
MKRKEY128(rkeys, 6, 0x20);
|
||||
MKRKEY128(rkeys, 7, 0x40);
|
||||
MKRKEY128(rkeys, 8, 0x80);
|
||||
MKRKEY128(rkeys, 9, 0x1b);
|
||||
MKRKEY128(rkeys, 10, 0x36);
|
||||
}
|
||||
|
||||
/* Compute an AES-256 round key. */
|
||||
#define MKRKEY256(rkeys, i, shuffle, rcon) do { \
|
||||
__m128i _s = rkeys[i - 2]; \
|
||||
__m128i _t = rkeys[i - 1]; \
|
||||
_s = _mm_xor_si128(_s, _mm_slli_si128(_s, 4)); \
|
||||
_s = _mm_xor_si128(_s, _mm_slli_si128(_s, 8)); \
|
||||
_t = _mm_aeskeygenassist_si128(_t, rcon); \
|
||||
_t = _mm_shuffle_epi32(_t, shuffle); \
|
||||
rkeys[i] = _mm_xor_si128(_s, _t); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* crypto_aes_key_expand_256_aesni(key, rkeys):
|
||||
* Expand the 256-bit AES key ${key} into the 15 round keys ${rkeys}. This
|
||||
* implementation uses x86 AESNI instructions, and should only be used if
|
||||
* CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero.
|
||||
*/
|
||||
static void
|
||||
crypto_aes_key_expand_256_aesni(const uint8_t key[32], __m128i rkeys[15])
|
||||
{
|
||||
|
||||
/* The first two round keys are just the key. */
|
||||
/**
|
||||
* XXX Compiler breakage:
|
||||
* The intrinsic defined by Intel for _mm_loadu_si128 defines it as
|
||||
* taking a (const __m128i *) parameter. This forces us to write a
|
||||
* bug: The cast to (const __m128i *) is invalid since it increases
|
||||
* the alignment requirement of the pointer. Alas, until compilers
|
||||
* get fixed intrinsics, all we can do is code the bug and require
|
||||
* that alignment-requirement-increasing compiler warnings get
|
||||
* disabled.
|
||||
*/
|
||||
rkeys[0] = _mm_loadu_si128((const __m128i *)&key[0]);
|
||||
rkeys[1] = _mm_loadu_si128((const __m128i *)&key[16]);
|
||||
|
||||
/*
|
||||
* Each of the remaining round keys are computed from the preceding
|
||||
* pair of keys. Even rounds use rotword+subword+rcon, while odd
|
||||
* rounds just use subword; the aeskeygenassist instruction computes
|
||||
* both, and we use 0xff or 0xaa to select the one we need. The rcon
|
||||
* value used is irrelevant for odd rounds since we ignore the value
|
||||
* which it feeds into. Unfortunately, the 'shuffle' and 'rcon'
|
||||
* values are encoded into the instructions as immediates, so we need
|
||||
* to write the loop out ourselves rather than allowing the compiler
|
||||
* to expand it.
|
||||
*/
|
||||
MKRKEY256(rkeys, 2, 0xff, 0x01);
|
||||
MKRKEY256(rkeys, 3, 0xaa, 0x00);
|
||||
MKRKEY256(rkeys, 4, 0xff, 0x02);
|
||||
MKRKEY256(rkeys, 5, 0xaa, 0x00);
|
||||
MKRKEY256(rkeys, 6, 0xff, 0x04);
|
||||
MKRKEY256(rkeys, 7, 0xaa, 0x00);
|
||||
MKRKEY256(rkeys, 8, 0xff, 0x08);
|
||||
MKRKEY256(rkeys, 9, 0xaa, 0x00);
|
||||
MKRKEY256(rkeys, 10, 0xff, 0x10);
|
||||
MKRKEY256(rkeys, 11, 0xaa, 0x00);
|
||||
MKRKEY256(rkeys, 12, 0xff, 0x20);
|
||||
MKRKEY256(rkeys, 13, 0xaa, 0x00);
|
||||
MKRKEY256(rkeys, 14, 0xff, 0x40);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aes_key_expand_aesni(key, len):
|
||||
* Expand the ${len}-byte AES key ${key} into a structure which can be passed
|
||||
* to crypto_aes_encrypt_block_aesni. The length must be 16 or 32. This
|
||||
* implementation uses x86 AESNI instructions, and should only be used if
|
||||
* CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero.
|
||||
*/
|
||||
void *
|
||||
crypto_aes_key_expand_aesni(const uint8_t * key, size_t len)
|
||||
{
|
||||
struct crypto_aes_key_aesni * kexp;
|
||||
size_t rkey_offset;
|
||||
|
||||
/* Allocate structure. */
|
||||
if ((kexp = malloc(sizeof(struct crypto_aes_key_aesni))) == NULL)
|
||||
goto err0;
|
||||
|
||||
/* Figure out where to put the round keys. */
|
||||
rkey_offset = (uintptr_t)(&kexp->rkeys_buf[0]) % sizeof(__m128i);
|
||||
rkey_offset = (sizeof(__m128i) - rkey_offset) % sizeof(__m128i);
|
||||
kexp->rkeys = (void *)&kexp->rkeys_buf[rkey_offset];
|
||||
|
||||
/* Compute round keys. */
|
||||
if (len == 16) {
|
||||
kexp->nr = 10;
|
||||
crypto_aes_key_expand_128_aesni(key, kexp->rkeys);
|
||||
} else if (len == 32) {
|
||||
kexp->nr = 14;
|
||||
crypto_aes_key_expand_256_aesni(key, kexp->rkeys);
|
||||
} else {
|
||||
warn0("Unsupported AES key length: %zu bytes", len);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return (kexp);
|
||||
|
||||
err1:
|
||||
free(kexp);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aes_encrypt_block_aesni(in, out, key):
|
||||
* Using the expanded AES key ${key}, encrypt the block ${in} and write the
|
||||
* resulting ciphertext to ${out}. This implementation uses x86 AESNI
|
||||
* instructions, and should only be used if CPUSUPPORT_X86_AESNI is defined
|
||||
* and cpusupport_x86_aesni() returns nonzero.
|
||||
*/
|
||||
void
|
||||
crypto_aes_encrypt_block_aesni(const uint8_t * in, uint8_t * out,
|
||||
const void * key)
|
||||
{
|
||||
const struct crypto_aes_key_aesni * _key = key;
|
||||
const __m128i * aes_key = _key->rkeys;
|
||||
__m128i aes_state;
|
||||
size_t nr = _key->nr;
|
||||
|
||||
aes_state = _mm_loadu_si128((const __m128i *)in);
|
||||
aes_state = _mm_xor_si128(aes_state, aes_key[0]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[1]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[2]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[3]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[4]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[5]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[6]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[7]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[8]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[9]);
|
||||
if (nr > 10) {
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[10]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[11]);
|
||||
|
||||
if (nr > 12) {
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[12]);
|
||||
aes_state = _mm_aesenc_si128(aes_state, aes_key[13]);
|
||||
}
|
||||
}
|
||||
|
||||
aes_state = _mm_aesenclast_si128(aes_state, aes_key[nr]);
|
||||
_mm_storeu_si128((__m128i *)out, aes_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aes_key_free_aesni(key):
|
||||
* Free the expanded AES key ${key}.
|
||||
*/
|
||||
void
|
||||
crypto_aes_key_free_aesni(void * key)
|
||||
{
|
||||
|
||||
/* Behave consistently with free(NULL). */
|
||||
if (key == NULL)
|
||||
return;
|
||||
|
||||
/* Attempt to zero the expanded key. */
|
||||
insecure_memzero(key, sizeof(struct crypto_aes_key_aesni));
|
||||
|
||||
/* Free the key. */
|
||||
free(key);
|
||||
}
|
||||
|
||||
#endif /* CPUSUPPORT_X86_AESNI */
|
@ -1,31 +0,0 @@
|
||||
#ifndef _CRYPTO_AES_AESNI_H_
|
||||
#define _CRYPTO_AES_AESNI_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* crypto_aes_key_expand_aesni(key, len):
|
||||
* Expand the ${len}-byte AES key ${key} into a structure which can be passed
|
||||
* to crypto_aes_encrypt_block_aesni. The length must be 16 or 32. This
|
||||
* implementation uses x86 AESNI instructions, and should only be used if
|
||||
* CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero.
|
||||
*/
|
||||
void * crypto_aes_key_expand_aesni(const uint8_t *, size_t);
|
||||
|
||||
/**
|
||||
* crypto_aes_encrypt_block_aesni(in, out, key):
|
||||
* Using the expanded AES key ${key}, encrypt the block ${in} and write the
|
||||
* resulting ciphertext to ${out}. This implementation uses x86 AESNI
|
||||
* instructions, and should only be used if CPUSUPPORT_X86_AESNI is defined
|
||||
* and cpusupport_x86_aesni() returns nonzero.
|
||||
*/
|
||||
void crypto_aes_encrypt_block_aesni(const uint8_t *, uint8_t *, const void *);
|
||||
|
||||
/**
|
||||
* crypto_aes_key_free_aesni(key):
|
||||
* Free the expanded AES key ${key}.
|
||||
*/
|
||||
void crypto_aes_key_free_aesni(void *);
|
||||
|
||||
#endif /* !_CRYPTO_AES_AESNI_H_ */
|
@ -1,119 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_aes.h"
|
||||
#include "insecure_memzero.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "crypto_aesctr.h"
|
||||
|
||||
struct crypto_aesctr {
|
||||
const struct crypto_aes_key * key;
|
||||
uint64_t nonce;
|
||||
uint64_t bytectr;
|
||||
uint8_t buf[16];
|
||||
};
|
||||
|
||||
/**
|
||||
* crypto_aesctr_init(key, nonce):
|
||||
* Prepare to encrypt/decrypt data with AES in CTR mode, using the provided
|
||||
* expanded key and nonce. The key provided must remain valid for the
|
||||
* lifetime of the stream.
|
||||
*/
|
||||
struct crypto_aesctr *
|
||||
crypto_aesctr_init(const struct crypto_aes_key * key, uint64_t nonce)
|
||||
{
|
||||
struct crypto_aesctr * stream;
|
||||
|
||||
/* Allocate memory. */
|
||||
if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL)
|
||||
goto err0;
|
||||
|
||||
/* Initialize values. */
|
||||
stream->key = key;
|
||||
stream->nonce = nonce;
|
||||
stream->bytectr = 0;
|
||||
|
||||
/* Success! */
|
||||
return (stream);
|
||||
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
|
||||
* Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
|
||||
* bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers
|
||||
* ${inbuf} and ${outbuf} overlap, they must be identical.
|
||||
*/
|
||||
void
|
||||
crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf,
|
||||
uint8_t * outbuf, size_t buflen)
|
||||
{
|
||||
uint8_t pblk[16];
|
||||
size_t pos;
|
||||
int bytemod;
|
||||
|
||||
for (pos = 0; pos < buflen; pos++) {
|
||||
/* How far through the buffer are we? */
|
||||
bytemod = stream->bytectr % 16;
|
||||
|
||||
/* Generate a block of cipherstream if needed. */
|
||||
if (bytemod == 0) {
|
||||
be64enc(pblk, stream->nonce);
|
||||
be64enc(pblk + 8, stream->bytectr / 16);
|
||||
crypto_aes_encrypt_block(pblk, stream->buf,
|
||||
stream->key);
|
||||
}
|
||||
|
||||
/* Encrypt a byte. */
|
||||
outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod];
|
||||
|
||||
/* Move to the next byte of cipherstream. */
|
||||
stream->bytectr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aesctr_free(stream):
|
||||
* Free the provided stream object.
|
||||
*/
|
||||
void
|
||||
crypto_aesctr_free(struct crypto_aesctr * stream)
|
||||
{
|
||||
|
||||
/* Behave consistently with free(NULL). */
|
||||
if (stream == NULL)
|
||||
return;
|
||||
|
||||
/* Zero potentially sensitive information. */
|
||||
insecure_memzero(stream, sizeof(struct crypto_aesctr));
|
||||
|
||||
/* Free the stream. */
|
||||
free(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen):
|
||||
* Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free().
|
||||
*/
|
||||
void
|
||||
crypto_aesctr_buf(const struct crypto_aes_key * key, uint64_t nonce,
|
||||
const uint8_t * inbuf, uint8_t * outbuf, size_t buflen)
|
||||
{
|
||||
struct crypto_aesctr stream_rec;
|
||||
struct crypto_aesctr * stream = &stream_rec;
|
||||
|
||||
/* Initialize values. */
|
||||
stream->key = key;
|
||||
stream->nonce = nonce;
|
||||
stream->bytectr = 0;
|
||||
|
||||
/* Perform the encryption. */
|
||||
crypto_aesctr_stream(stream, inbuf, outbuf, buflen);
|
||||
|
||||
/* Zero potentially sensitive information. */
|
||||
insecure_memzero(stream, sizeof(struct crypto_aesctr));
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
#ifndef _CRYPTO_AESCTR_H_
|
||||
#define _CRYPTO_AESCTR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Opaque types. */
|
||||
struct crypto_aes_key;
|
||||
struct crypto_aesctr;
|
||||
|
||||
/**
|
||||
* crypto_aesctr_init(key, nonce):
|
||||
* Prepare to encrypt/decrypt data with AES in CTR mode, using the provided
|
||||
* expanded key and nonce. The key provided must remain valid for the
|
||||
* lifetime of the stream.
|
||||
*/
|
||||
struct crypto_aesctr * crypto_aesctr_init(const struct crypto_aes_key *,
|
||||
uint64_t);
|
||||
|
||||
/**
|
||||
* crypto_aesctr_stream(stream, inbuf, outbuf, buflen):
|
||||
* Generate the next ${buflen} bytes of the AES-CTR stream and xor them with
|
||||
* bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers
|
||||
* ${inbuf} and ${outbuf} overlap, they must be identical.
|
||||
*/
|
||||
void crypto_aesctr_stream(struct crypto_aesctr *, const uint8_t *,
|
||||
uint8_t *, size_t);
|
||||
|
||||
/**
|
||||
* crypto_aesctr_free(stream):
|
||||
* Free the provided stream object.
|
||||
*/
|
||||
void crypto_aesctr_free(struct crypto_aesctr *);
|
||||
|
||||
/**
|
||||
* crypto_aesctr_buf(key, nonce, inbuf, outbuf, buflen):
|
||||
* Equivalent to _init(key, nonce); _stream(inbuf, outbuf, buflen); _free().
|
||||
*/
|
||||
void crypto_aesctr_buf(const struct crypto_aes_key *, uint64_t,
|
||||
const uint8_t *, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_CRYPTO_AESCTR_H_ */
|
@ -1,215 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "entropy.h"
|
||||
#include "insecure_memzero.h"
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#include "crypto_entropy.h"
|
||||
|
||||
/**
|
||||
* This system implements the HMAC_DRBG pseudo-random number generator as
|
||||
* specified in section 10.1.2 of the NIST SP 800-90 standard. In this
|
||||
* implementation, the optional personalization_string and additional_input
|
||||
* specified in the standard are not implemented.
|
||||
*/
|
||||
|
||||
/* Internal HMAC_DRBG state. */
|
||||
static struct {
|
||||
uint8_t Key[32];
|
||||
uint8_t V[32];
|
||||
uint32_t reseed_counter;
|
||||
} drbg;
|
||||
|
||||
/* Set to non-zero once the PRNG has been instantiated. */
|
||||
static int instantiated = 0;
|
||||
|
||||
/* Could be as high as 2^48 if we wanted... */
|
||||
#define RESEED_INTERVAL 256
|
||||
|
||||
/* Limited to 2^16 by specification. */
|
||||
#define GENERATE_MAXLEN 65536
|
||||
|
||||
static int instantiate(void);
|
||||
static void update(uint8_t *, size_t);
|
||||
static int reseed(void);
|
||||
static void generate(uint8_t *, size_t);
|
||||
|
||||
/**
|
||||
* instantiate(void):
|
||||
* Initialize the DRBG state. (Section 10.1.2.3)
|
||||
*/
|
||||
static int
|
||||
instantiate(void)
|
||||
{
|
||||
uint8_t seed_material[48];
|
||||
|
||||
/* Obtain random seed_material = (entropy_input || nonce). */
|
||||
if (entropy_read(seed_material, 48))
|
||||
return (-1);
|
||||
|
||||
/* Initialize Key, V, and reseed_counter. */
|
||||
memset(drbg.Key, 0x00, 32);
|
||||
memset(drbg.V, 0x01, 32);
|
||||
drbg.reseed_counter = 1;
|
||||
|
||||
/* Mix the random seed into the state. */
|
||||
update(seed_material, 48);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(seed_material, 48);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* update(data, datalen):
|
||||
* Update the DRBG state using the provided data. (Section 10.1.2.2)
|
||||
*/
|
||||
static void
|
||||
update(uint8_t * data, size_t datalen)
|
||||
{
|
||||
HMAC_SHA256_CTX ctx;
|
||||
uint8_t K[32];
|
||||
uint8_t Vx[33];
|
||||
|
||||
/* Load (Key, V) into (K, Vx). */
|
||||
memcpy(K, drbg.Key, 32);
|
||||
memcpy(Vx, drbg.V, 32);
|
||||
|
||||
/* K <- HMAC(K, V || 0x00 || data). */
|
||||
Vx[32] = 0x00;
|
||||
HMAC_SHA256_Init(&ctx, K, 32);
|
||||
HMAC_SHA256_Update(&ctx, Vx, 33);
|
||||
HMAC_SHA256_Update(&ctx, data, datalen);
|
||||
HMAC_SHA256_Final(K, &ctx);
|
||||
|
||||
/* V <- HMAC(K, V). */
|
||||
HMAC_SHA256_Buf(K, 32, Vx, 32, Vx);
|
||||
|
||||
/* If the provided data is non-Null, perform another mixing stage. */
|
||||
if (datalen != 0) {
|
||||
/* K <- HMAC(K, V || 0x01 || data). */
|
||||
Vx[32] = 0x01;
|
||||
HMAC_SHA256_Init(&ctx, K, 32);
|
||||
HMAC_SHA256_Update(&ctx, Vx, 33);
|
||||
HMAC_SHA256_Update(&ctx, data, datalen);
|
||||
HMAC_SHA256_Final(K, &ctx);
|
||||
|
||||
/* V <- HMAC(K, V). */
|
||||
HMAC_SHA256_Buf(K, 32, Vx, 32, Vx);
|
||||
}
|
||||
|
||||
/* Copy (K, Vx) back to (Key, V). */
|
||||
memcpy(drbg.Key, K, 32);
|
||||
memcpy(drbg.V, Vx, 32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(K, 32);
|
||||
insecure_memzero(Vx, 33);
|
||||
}
|
||||
|
||||
/**
|
||||
* reseed(void):
|
||||
* Reseed the DRBG state (mix in new entropy). (Section 10.1.2.4)
|
||||
*/
|
||||
static int
|
||||
reseed(void)
|
||||
{
|
||||
uint8_t seed_material[32];
|
||||
|
||||
/* Obtain random seed_material = entropy_input. */
|
||||
if (entropy_read(seed_material, 32))
|
||||
return (-1);
|
||||
|
||||
/* Mix the random seed into the state. */
|
||||
update(seed_material, 32);
|
||||
|
||||
/* Reset the reseed_counter. */
|
||||
drbg.reseed_counter = 1;
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(seed_material, 32);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate(buf, buflen):
|
||||
* Fill the provided buffer with random bits, assuming that reseed_counter
|
||||
* is less than RESEED_INTERVAL (the caller is responsible for calling
|
||||
* reseed() as needed) and ${buflen} is less than 2^16 (the caller is
|
||||
* responsible for splitting up larger requests). (Section 10.1.2.5)
|
||||
*/
|
||||
static void
|
||||
generate(uint8_t * buf, size_t buflen)
|
||||
{
|
||||
size_t bufpos;
|
||||
|
||||
assert(buflen <= GENERATE_MAXLEN);
|
||||
assert(drbg.reseed_counter <= RESEED_INTERVAL);
|
||||
|
||||
/* Iterate until we've filled the buffer. */
|
||||
for (bufpos = 0; bufpos < buflen; bufpos += 32) {
|
||||
HMAC_SHA256_Buf(drbg.Key, 32, drbg.V, 32, drbg.V);
|
||||
if (buflen - bufpos >= 32)
|
||||
memcpy(&buf[bufpos], drbg.V, 32);
|
||||
else
|
||||
memcpy(&buf[bufpos], drbg.V, buflen - bufpos);
|
||||
}
|
||||
|
||||
/* Mix up state. */
|
||||
update(NULL, 0);
|
||||
|
||||
/* We're one data-generation step closer to needing a reseed. */
|
||||
drbg.reseed_counter += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* crypto_entropy_read(buf, buflen):
|
||||
* Fill the buffer with unpredictable bits.
|
||||
*/
|
||||
int
|
||||
crypto_entropy_read(uint8_t * buf, size_t buflen)
|
||||
{
|
||||
size_t bytes_to_provide;
|
||||
|
||||
/* Instantiate if needed. */
|
||||
if (instantiated == 0) {
|
||||
/* Try to instantiate the PRNG. */
|
||||
if (instantiate())
|
||||
return (-1);
|
||||
|
||||
/* We have instantiated the PRNG. */
|
||||
instantiated = 1;
|
||||
}
|
||||
|
||||
/* Loop until we've filled the buffer. */
|
||||
while (buflen > 0) {
|
||||
/* Do we need to reseed? */
|
||||
if (drbg.reseed_counter > RESEED_INTERVAL) {
|
||||
if (reseed())
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* How much data are we generating in this step? */
|
||||
if (buflen > GENERATE_MAXLEN)
|
||||
bytes_to_provide = GENERATE_MAXLEN;
|
||||
else
|
||||
bytes_to_provide = buflen;
|
||||
|
||||
/* Generate bytes. */
|
||||
generate(buf, bytes_to_provide);
|
||||
|
||||
/* We've done part of the buffer. */
|
||||
buf += bytes_to_provide;
|
||||
buflen -= bytes_to_provide;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
#ifndef _CRYPTO_ENTROPY_H_
|
||||
#define _CRYPTO_ENTROPY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* crypto_entropy_read(buf, buflen):
|
||||
* Fill the buffer with unpredictable bits. The value ${buflen} must be
|
||||
* less than 2^16.
|
||||
*/
|
||||
int crypto_entropy_read(uint8_t *, size_t);
|
||||
|
||||
#endif /* !_CRYPTO_ENTROPY_H_ */
|
@ -1,49 +0,0 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asprintf.h"
|
||||
|
||||
/**
|
||||
* asprintf(ret, format, ...):
|
||||
* Do asprintf(3) like GNU and BSD do.
|
||||
*/
|
||||
int
|
||||
asprintf(char ** ret, const char * format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int len;
|
||||
size_t buflen;
|
||||
|
||||
/* Figure out how long the string needs to be. */
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(NULL, 0, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Did we fail? */
|
||||
if (len < 0)
|
||||
goto err0;
|
||||
buflen = (size_t)(len) + 1;
|
||||
|
||||
/* Allocate memory. */
|
||||
if ((*ret = malloc(buflen)) == NULL)
|
||||
goto err0;
|
||||
|
||||
/* Actually generate the string. */
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(*ret, buflen, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Did we fail? */
|
||||
if (len < 0)
|
||||
goto err1;
|
||||
|
||||
/* Success! */
|
||||
return (len);
|
||||
|
||||
err1:
|
||||
free(*ret);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#ifndef _ASPRINTF_H_
|
||||
#define _ASPRINTF_H_
|
||||
|
||||
/* Avoid namespace collisions with BSD/GNU asprintf. */
|
||||
#ifdef asprintf
|
||||
#undef asprintf
|
||||
#endif
|
||||
#define asprintf libcperciva_asprintf
|
||||
|
||||
/**
|
||||
* asprintf(ret, format, ...):
|
||||
* Do asprintf(3) like GNU and BSD do.
|
||||
*/
|
||||
int asprintf(char **, const char *, ...);
|
||||
|
||||
#endif /* !_ASPRINTF_H_ */
|
@ -1,77 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "warnp.h"
|
||||
|
||||
#include "entropy.h"
|
||||
|
||||
/**
|
||||
* XXX Portability
|
||||
* XXX We obtain random bytes from the operating system by opening
|
||||
* XXX /dev/urandom and reading them from that device; this works on
|
||||
* XXX modern UNIX-like operating systems but not on systems like
|
||||
* XXX win32 where there is no concept of /dev/urandom.
|
||||
*/
|
||||
|
||||
/**
|
||||
* entropy_read(buf, buflen):
|
||||
* Fill the given buffer with random bytes provided by the operating system.
|
||||
*/
|
||||
int
|
||||
entropy_read(uint8_t * buf, size_t buflen)
|
||||
{
|
||||
int fd;
|
||||
ssize_t lenread;
|
||||
|
||||
/* Sanity-check the buffer size. */
|
||||
if (buflen > SSIZE_MAX) {
|
||||
warn0("Programmer error: "
|
||||
"Trying to read insane amount of random data: %zu",
|
||||
buflen);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Open /dev/urandom. */
|
||||
if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
|
||||
warnp("open(/dev/urandom)");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Read bytes until we have filled the buffer. */
|
||||
while (buflen > 0) {
|
||||
if ((lenread = read(fd, buf, buflen)) == -1) {
|
||||
warnp("read(/dev/urandom)");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* The random device should never EOF. */
|
||||
if (lenread == 0) {
|
||||
warn0("EOF on /dev/urandom?");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* We've filled a portion of the buffer. */
|
||||
buf += (size_t)lenread;
|
||||
buflen -= (size_t)lenread;
|
||||
}
|
||||
|
||||
/* Close the device. */
|
||||
while (close(fd) == -1) {
|
||||
if (errno != EINTR) {
|
||||
warnp("close(/dev/urandom)");
|
||||
goto err0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err1:
|
||||
close(fd);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#ifndef _ENTROPY_H_
|
||||
#define _ENTROPY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* entropy_read(buf, buflen):
|
||||
* Fill the given buffer with random bytes provided by the operating system.
|
||||
*/
|
||||
int entropy_read(uint8_t *, size_t);
|
||||
|
||||
#endif /* !_ENTROPY_H_ */
|
@ -1,358 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
/*
|
||||
* Standard getopt global variables. optreset starts as non-zero in order to
|
||||
* trigger initialization behaviour.
|
||||
*/
|
||||
const char * optarg = NULL;
|
||||
int optind = 1;
|
||||
int opterr = 1;
|
||||
int optreset = 1;
|
||||
|
||||
/*
|
||||
* Quasi-internal global variables -- these are used via GETOPT macros.
|
||||
*/
|
||||
const char * getopt_dummy = "(dummy)";
|
||||
int getopt_initialized = 0;
|
||||
|
||||
/*
|
||||
* Internal variables.
|
||||
*/
|
||||
static const char * cmdname = NULL;
|
||||
static struct opt {
|
||||
const char * os;
|
||||
size_t olen;
|
||||
int hasarg;
|
||||
} * opts = NULL;
|
||||
static size_t nopts;
|
||||
static size_t opt_missing;
|
||||
static size_t opt_default;
|
||||
static size_t opt_found;
|
||||
static const char * packedopts;
|
||||
static char popt[3];
|
||||
static int atexit_registered = 0;
|
||||
|
||||
/* Print a message. */
|
||||
#define PRINTMSG(...) do { \
|
||||
if (cmdname != NULL) \
|
||||
fprintf(stderr, "%s: ", cmdname); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Print an error message and die. */
|
||||
#define DIE(...) do { \
|
||||
PRINTMSG(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
/* Print a warning, if warnings are enabled. */
|
||||
#define WARN(...) do { \
|
||||
if (opterr == 0) \
|
||||
break; \
|
||||
if (opt_missing != opt_default) \
|
||||
break; \
|
||||
PRINTMSG(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* Free allocated options array. */
|
||||
static void
|
||||
atexit_handler(void)
|
||||
{
|
||||
|
||||
free(opts);
|
||||
opts = NULL;
|
||||
}
|
||||
|
||||
/* Reset internal state. */
|
||||
static void
|
||||
reset(int argc, char * const argv[])
|
||||
{
|
||||
const char * p;
|
||||
|
||||
/* If we have arguments, stash argv[0] for error messages. */
|
||||
if (argc > 0) {
|
||||
/* Find the basename, without leading directories. */
|
||||
for (p = cmdname = argv[0]; *p != '\0'; p++) {
|
||||
if (*p == '/')
|
||||
cmdname = p + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard any registered command-line options. */
|
||||
free(opts);
|
||||
opts = NULL;
|
||||
|
||||
/* Register atexit handler if we haven't done so already. */
|
||||
if (!atexit_registered) {
|
||||
atexit(atexit_handler);
|
||||
atexit_registered = 1;
|
||||
}
|
||||
|
||||
/* We will start scanning from the first option. */
|
||||
optind = 1;
|
||||
|
||||
/* We're not in the middle of any packed options. */
|
||||
packedopts = NULL;
|
||||
|
||||
/* We haven't found any option yet. */
|
||||
opt_found = (size_t)(-1);
|
||||
|
||||
/* We're not initialized yet. */
|
||||
getopt_initialized = 0;
|
||||
|
||||
/* Finished resetting state. */
|
||||
optreset = 0;
|
||||
}
|
||||
|
||||
/* Search for an option string. */
|
||||
static size_t
|
||||
searchopt(const char * os)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Scan the array of options. */
|
||||
for (i = 0; i < nopts; i++) {
|
||||
/* Is there an option in this slot? */
|
||||
if (opts[i].os == NULL)
|
||||
continue;
|
||||
|
||||
/* Does this match up to the length of the option string? */
|
||||
if (strncmp(opts[i].os, os, opts[i].olen))
|
||||
continue;
|
||||
|
||||
/* Do we have <option>\0 or <option>= ? */
|
||||
if ((os[opts[i].olen] == '\0') || (os[opts[i].olen] == '='))
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* Not found. */
|
||||
return (opt_default);
|
||||
}
|
||||
|
||||
const char *
|
||||
getopt(int argc, char * const argv[])
|
||||
{
|
||||
const char * os = NULL;
|
||||
const char * canonical_os = NULL;
|
||||
|
||||
/* No argument yet. */
|
||||
optarg = NULL;
|
||||
|
||||
/* Reset the getopt state if needed. */
|
||||
if (optreset)
|
||||
reset(argc, argv);
|
||||
|
||||
/* If not initialized, return dummy option. */
|
||||
if (!getopt_initialized)
|
||||
return (GETOPT_DUMMY);
|
||||
|
||||
/* If we've run out of arguments, we're done. */
|
||||
if (optind >= argc)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* If we're not already in the middle of a packed single-character
|
||||
* options, see if we should start.
|
||||
*/
|
||||
if ((packedopts == NULL) && (argv[optind][0] == '-') &&
|
||||
(argv[optind][1] != '-') && (argv[optind][1] != '\0')) {
|
||||
/* We have one or more single-character options. */
|
||||
packedopts = &argv[optind][1];
|
||||
}
|
||||
|
||||
/* If we're processing single-character options, fish one out. */
|
||||
if (packedopts != NULL) {
|
||||
/* Construct the option string. */
|
||||
popt[0] = '-';
|
||||
popt[1] = *packedopts;
|
||||
popt[2] = '\0';
|
||||
os = popt;
|
||||
|
||||
/* We've done this character. */
|
||||
packedopts++;
|
||||
|
||||
/* Are we done with this string? */
|
||||
if (*packedopts == '\0') {
|
||||
packedopts = NULL;
|
||||
optind++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have an option yet, do we have dash-dash? */
|
||||
if ((os == NULL) && (argv[optind][0] == '-') &&
|
||||
(argv[optind][1] == '-')) {
|
||||
/* If this is not "--\0", it's an option. */
|
||||
if (argv[optind][2] != '\0')
|
||||
os = argv[optind];
|
||||
|
||||
/* Either way, we want to eat the string. */
|
||||
optind++;
|
||||
}
|
||||
|
||||
/* If we have found nothing which looks like an option, we're done. */
|
||||
if (os == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Search for the potential option. */
|
||||
opt_found = searchopt(os);
|
||||
|
||||
/* If the option is not registered, give up now. */
|
||||
if (opt_found == opt_default) {
|
||||
WARN("unknown option: %s", os);
|
||||
return (os);
|
||||
}
|
||||
|
||||
/* The canonical option string is the one registered. */
|
||||
canonical_os = opts[opt_found].os;
|
||||
|
||||
/* Does the option take an argument? */
|
||||
if (opts[opt_found].hasarg) {
|
||||
/*
|
||||
* If we're processing packed single-character options, the
|
||||
* rest of the string is the argument to this option.
|
||||
*/
|
||||
if (packedopts != NULL) {
|
||||
optarg = packedopts;
|
||||
packedopts = NULL;
|
||||
optind++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the option string is <option>=<value>, extract that
|
||||
* value as the option argument.
|
||||
*/
|
||||
if (os[opts[opt_found].olen] == '=')
|
||||
optarg = &os[opts[opt_found].olen + 1];
|
||||
|
||||
/*
|
||||
* If we don't have an argument yet, take one from the
|
||||
* remaining command line.
|
||||
*/
|
||||
if ((optarg == NULL) && (optind < argc))
|
||||
optarg = argv[optind++];
|
||||
|
||||
/* If we still have no option, declare it MIA. */
|
||||
if (optarg == NULL) {
|
||||
WARN("option requires an argument: %s",
|
||||
opts[opt_found].os);
|
||||
opt_found = opt_missing;
|
||||
}
|
||||
} else {
|
||||
/* If we have --foo=bar, something went wrong. */
|
||||
if (os[opts[opt_found].olen] == '=') {
|
||||
WARN("option doesn't take an argument: %s",
|
||||
opts[opt_found].os);
|
||||
opt_found = opt_default;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the canonical option string. */
|
||||
return (canonical_os);
|
||||
}
|
||||
|
||||
size_t
|
||||
getopt_lookup(const char * os)
|
||||
{
|
||||
|
||||
/* Can't reset here. */
|
||||
if (optreset)
|
||||
DIE("Can't reset in the middle of getopt loop");
|
||||
|
||||
/* We should only be called after initialization is complete. */
|
||||
assert(getopt_initialized);
|
||||
|
||||
/* GETOPT_DUMMY should never get passed back to us. */
|
||||
assert(os != GETOPT_DUMMY);
|
||||
|
||||
/*
|
||||
* Make sure the option passed back to us corresponds to the one we
|
||||
* found earlier.
|
||||
*/
|
||||
assert((opt_found == opt_missing) || (opt_found == opt_default) ||
|
||||
((opt_found < nopts) && (strcmp(os, opts[opt_found].os) == 0)));
|
||||
|
||||
/* Return the option number we identified earlier. */
|
||||
return (opt_found);
|
||||
}
|
||||
|
||||
void
|
||||
getopt_register_opt(const char * os, size_t ln, int hasarg)
|
||||
{
|
||||
|
||||
/* Can't reset here. */
|
||||
if (optreset)
|
||||
DIE("Can't reset in the middle of getopt loop");
|
||||
|
||||
/* We should only be called during initialization. */
|
||||
assert(!getopt_initialized);
|
||||
|
||||
/* We should have space allocated for registering options. */
|
||||
assert(opts != NULL);
|
||||
|
||||
/* We should not have registered an option here yet. */
|
||||
assert(opts[ln].os == NULL);
|
||||
|
||||
/* Options should be "-X" or "--foo". */
|
||||
if ((os[0] != '-') || (os[1] == '\0') ||
|
||||
((os[1] == '-') && (os[2] == '\0')) ||
|
||||
((os[1] != '-') && (os[2] != '\0')))
|
||||
DIE("Not a valid command-line option: %s", os);
|
||||
|
||||
/* Make sure we haven't already registered this option. */
|
||||
if (searchopt(os) != opt_default)
|
||||
DIE("Command-line option registered twice: %s", os);
|
||||
|
||||
/* Record option. */
|
||||
opts[ln].os = os;
|
||||
opts[ln].olen = strlen(os);
|
||||
opts[ln].hasarg = hasarg;
|
||||
}
|
||||
|
||||
void
|
||||
getopt_register_missing(size_t ln)
|
||||
{
|
||||
|
||||
/* Can't reset here. */
|
||||
if (optreset)
|
||||
DIE("Can't reset in the middle of getopt loop");
|
||||
|
||||
/* We should only be called during initialization. */
|
||||
assert(!getopt_initialized);
|
||||
|
||||
/* Record missing-argument value. */
|
||||
opt_missing = ln;
|
||||
}
|
||||
|
||||
void
|
||||
getopt_setrange(size_t ln)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Can't reset here. */
|
||||
if (optreset)
|
||||
DIE("Can't reset in the middle of getopt loop");
|
||||
|
||||
/* We should only be called during initialization. */
|
||||
assert(!getopt_initialized);
|
||||
|
||||
/* Allocate space for options. */
|
||||
opts = malloc(ln * sizeof(struct opt));
|
||||
if ((ln > 0) && (opts == NULL))
|
||||
DIE("Failed to allocate memory in getopt");
|
||||
|
||||
/* Initialize options. */
|
||||
for (i = 0; i < ln; i++)
|
||||
opts[i].os = NULL;
|
||||
|
||||
/* Record the number of (potential) options. */
|
||||
nopts = ln;
|
||||
|
||||
/* Record default missing-argument and no-such-option values. */
|
||||
opt_missing = opt_default = ln + 1;
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
#ifndef _GETOPT_H_
|
||||
#define _GETOPT_H_
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* This getopt implementation parses options of the following forms:
|
||||
* -a -b -c foo (single-character options)
|
||||
* -abc foo (packed single-character options)
|
||||
* -abcfoo (packed single-character options and an argument)
|
||||
* --foo bar (long option)
|
||||
* --foo=bar (long option and argument separated by '=')
|
||||
*
|
||||
* It does not support abbreviated options (e.g., interpreting --foo as
|
||||
* --foobar when there are no other --foo* options) since that misfeature
|
||||
* results in breakage when new options are added. It also does not support
|
||||
* options appearing after non-options (e.g., "cp foo bar -R") since that is
|
||||
* a horrible GNU perversion.
|
||||
*/
|
||||
|
||||
/* Work around LLVM bug. */
|
||||
#ifdef __clang__
|
||||
//#warning Working around bug in LLVM optimizer
|
||||
//#warning For more details see https://llvm.org/bugs/show_bug.cgi?id=27190
|
||||
#define DO_SETJMP _DO_SETJMP(__LINE__)
|
||||
#define _DO_SETJMP(x) __DO_SETJMP(x)
|
||||
#define __DO_SETJMP(x) \
|
||||
void * getopt_initloop = && getopt_initloop_ ## x; \
|
||||
getopt_initloop_ ## x:
|
||||
#define DO_LONGJMP \
|
||||
goto *getopt_initloop
|
||||
#else
|
||||
#define DO_SETJMP \
|
||||
sigjmp_buf getopt_initloop; \
|
||||
if (!getopt_initialized) \
|
||||
sigsetjmp(getopt_initloop, 0)
|
||||
#define DO_LONGJMP \
|
||||
siglongjmp(getopt_initloop, 1)
|
||||
#endif
|
||||
|
||||
/* Avoid namespace collisions with libc getopt. */
|
||||
#define getopt libcperciva_getopt
|
||||
#define optarg libcperciva_optarg
|
||||
#define optind libcperciva_optind
|
||||
#define opterr libcperciva_opterr
|
||||
#define optreset libcperciva_optreset
|
||||
|
||||
/* Standard getopt global variables. */
|
||||
extern const char * optarg;
|
||||
extern int optind, opterr, optreset;
|
||||
|
||||
/* Dummy option string, equal to "(dummy)". */
|
||||
#define GETOPT_DUMMY getopt_dummy
|
||||
|
||||
/**
|
||||
* GETOPT(argc, argv):
|
||||
* When called for the first time (or the first time after optreset is set to
|
||||
* a nonzero value), return GETOPT_DUMMY, aka. "(dummy)". Thereafter, return
|
||||
* the next option string and set optarg / optind appropriately; abort if not
|
||||
* properly initialized when not being called for the first time.
|
||||
*/
|
||||
#define GETOPT(argc, argv) getopt(argc, argv)
|
||||
|
||||
/**
|
||||
* GETOPT_SWITCH(ch):
|
||||
* Jump to the appropriate GETOPT_OPT, GETOPT_OPTARG, GETOPT_MISSING_ARG, or
|
||||
* GETOPT_DEFAULT based on the option string ${ch}. When called for the first
|
||||
* time, perform magic to index the options.
|
||||
*
|
||||
* GETOPT_SWITCH(ch) is equivalent to "switch (ch)" in a standard getopt loop.
|
||||
*/
|
||||
#define GETOPT_SWITCH(ch) \
|
||||
volatile size_t getopt_ln_min = __LINE__; \
|
||||
volatile size_t getopt_ln = getopt_ln_min - 1; \
|
||||
volatile int getopt_default_missing = 0; \
|
||||
DO_SETJMP; \
|
||||
switch (getopt_initialized ? getopt_lookup(ch) + getopt_ln_min : getopt_ln++)
|
||||
|
||||
/**
|
||||
* GETOPT_OPT(os):
|
||||
* Jump to this point when the option string ${os} is passed to GETOPT_SWITCH.
|
||||
*
|
||||
* GETOPT_OPT("-x") is equivalent to "case 'x'" in a standard getopt loop
|
||||
* which has an optstring containing "x".
|
||||
*/
|
||||
#define GETOPT_OPT(os) _GETOPT_OPT(os, __LINE__)
|
||||
#define _GETOPT_OPT(os, ln) __GETOPT_OPT(os, ln)
|
||||
#define __GETOPT_OPT(os, ln) \
|
||||
case ln: \
|
||||
if (getopt_initialized) \
|
||||
goto getopt_skip_ ## ln; \
|
||||
getopt_register_opt(os, ln - getopt_ln_min, 0); \
|
||||
DO_LONGJMP; \
|
||||
getopt_skip_ ## ln
|
||||
|
||||
/**
|
||||
* GETOPT_OPTARG(os):
|
||||
* Jump to this point when the option string ${os} is passed to GETOPT_SWITCH,
|
||||
* unless no argument is available, in which case jump to GETOPT_MISSING_ARG
|
||||
* (if present) or GETOPT_DEFAULT (if not).
|
||||
*
|
||||
* GETOPT_OPTARG("-x") is equivalent to "case 'x'" in a standard getopt loop
|
||||
* which has an optstring containing "x:".
|
||||
*/
|
||||
#define GETOPT_OPTARG(os) _GETOPT_OPTARG(os, __LINE__)
|
||||
#define _GETOPT_OPTARG(os, ln) __GETOPT_OPTARG(os, ln)
|
||||
#define __GETOPT_OPTARG(os, ln) \
|
||||
case ln: \
|
||||
if (getopt_initialized) \
|
||||
goto getopt_skip_ ## ln; \
|
||||
getopt_register_opt(os, ln - getopt_ln_min, 1); \
|
||||
DO_LONGJMP; \
|
||||
getopt_skip_ ## ln
|
||||
|
||||
/**
|
||||
* GETOPT_MISSING_ARG:
|
||||
* Jump to this point if an option string specified in GETOPT_OPTARG is seen
|
||||
* but no argument is available.
|
||||
*
|
||||
* GETOPT_MISSING_ARG is equivalent to "case ':'" in a standard getopt loop
|
||||
* which has an optstring starting with ":". As such, it also has the effect
|
||||
* of disabling warnings about invalid options, as if opterr had been zeroed.
|
||||
*/
|
||||
#define GETOPT_MISSING_ARG _GETOPT_MISSING_ARG(__LINE__)
|
||||
#define _GETOPT_MISSING_ARG(ln) __GETOPT_MISSING_ARG(ln)
|
||||
#define __GETOPT_MISSING_ARG(ln) \
|
||||
case ln: \
|
||||
if (getopt_initialized) \
|
||||
goto getopt_skip_ ## ln; \
|
||||
getopt_register_missing(ln - getopt_ln_min); \
|
||||
DO_LONGJMP; \
|
||||
getopt_skip_ ## ln
|
||||
|
||||
/**
|
||||
* GETOPT_DEFAULT:
|
||||
* Jump to this point if an unrecognized option is seen or if an option
|
||||
* specified in GETOPT_OPTARG is seen, no argument is available, and there is
|
||||
* no GETOPT_MISSING_ARG label.
|
||||
*
|
||||
* GETOPT_DEFAULT is equivalent to "case '?'" in a standard getopt loop.
|
||||
*
|
||||
* NOTE: This MUST be present in the GETOPT_SWITCH statement, and MUST occur
|
||||
* after all other GETOPT_* labels.
|
||||
*/
|
||||
#define GETOPT_DEFAULT _GETOPT_DEFAULT(__LINE__)
|
||||
#define _GETOPT_DEFAULT(ln) __GETOPT_DEFAULT(ln)
|
||||
#define __GETOPT_DEFAULT(ln) \
|
||||
goto getopt_skip_ ## ln; \
|
||||
case ln: \
|
||||
getopt_initialized = 1; \
|
||||
break; \
|
||||
default: \
|
||||
if (getopt_initialized) \
|
||||
goto getopt_skip_ ## ln; \
|
||||
if (!getopt_default_missing) { \
|
||||
getopt_setrange(ln - getopt_ln_min); \
|
||||
getopt_default_missing = 1; \
|
||||
} \
|
||||
DO_LONGJMP; \
|
||||
getopt_skip_ ## ln
|
||||
|
||||
/*
|
||||
* The back-end implementation. These should be considered internal
|
||||
* interfaces and not used directly.
|
||||
*/
|
||||
const char * getopt(int, char * const []);
|
||||
size_t getopt_lookup(const char *);
|
||||
void getopt_register_opt(const char *, size_t, int);
|
||||
void getopt_register_missing(size_t);
|
||||
void getopt_setrange(size_t);
|
||||
extern const char * getopt_dummy;
|
||||
extern int getopt_initialized;
|
||||
|
||||
#endif /* !_GETOPT_H_ */
|
@ -1,165 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "asprintf.h"
|
||||
#include "warnp.h"
|
||||
|
||||
#include "humansize.h"
|
||||
|
||||
/**
|
||||
* humansize(size):
|
||||
* Given a size in bytes, allocate and return a string of the form "<N> B"
|
||||
* for 0 <= N <= 999 or "<X> <prefix>B" where either 10 <= X <= 999 or
|
||||
* 1.0 <= X <= 9.9 and <prefix> is "k", "M", "G", "T", "P", or "E"; and where
|
||||
* the value returned is the largest valid value <= the provided size.
|
||||
*/
|
||||
char *
|
||||
humansize(uint64_t size)
|
||||
{
|
||||
char * s;
|
||||
char prefix;
|
||||
int shiftcnt;
|
||||
int rc;
|
||||
|
||||
/* Special-case for size < 1000. */
|
||||
if (size < 1000) {
|
||||
rc = asprintf(&s, "%d B", (int)size);
|
||||
} else {
|
||||
/* Keep 10 * size / 1000^(3n) in size. */
|
||||
for (size /= 100, shiftcnt = 1; size >= 10000; shiftcnt++)
|
||||
size /= 1000;
|
||||
|
||||
/*
|
||||
* Figure out what prefix to use. Since 1 EB = 10^18 B and
|
||||
* the maximum value of a uint64_t is 2^64 which is roughly
|
||||
* 18.4 * 10^18, this cannot reference beyond the end of the
|
||||
* string.
|
||||
*/
|
||||
prefix = " kMGTPE"[shiftcnt];
|
||||
|
||||
/* Construct the string. */
|
||||
if (size < 100)
|
||||
rc = asprintf(&s, "%d.%d %cB", (int)size / 10,
|
||||
(int)size % 10, prefix);
|
||||
else
|
||||
rc = asprintf(&s, "%d %cB", (int)size / 10, prefix);
|
||||
}
|
||||
|
||||
if (rc == -1) {
|
||||
warnp("asprintf");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return (s);
|
||||
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* humansize_parse(s, size):
|
||||
* Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size in bytes.
|
||||
*/
|
||||
int
|
||||
humansize_parse(const char * s, uint64_t * size)
|
||||
{
|
||||
int state = 0;
|
||||
uint64_t multiplier = 1;
|
||||
|
||||
do {
|
||||
switch (state) {
|
||||
case -1:
|
||||
/* Error state. */
|
||||
break;
|
||||
case 0:
|
||||
/* Initial state. */
|
||||
*size = 0;
|
||||
|
||||
/* We must start with at least one digit. */
|
||||
if ((*s < '0') || (*s > '9')) {
|
||||
state = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
/* We're now processing digits. */
|
||||
state = 1;
|
||||
|
||||
/* Digit-parsing state. */
|
||||
if (('0' <= *s) && (*s <= '9')) {
|
||||
if (*size > UINT64_MAX / 10)
|
||||
state = -1;
|
||||
else
|
||||
*size *= 10;
|
||||
if (*size > UINT64_MAX - (uint64_t)(*s - '0'))
|
||||
state = -1;
|
||||
else
|
||||
*size += (uint64_t)(*s - '0');
|
||||
break;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
/* We move into state 3 after an optional ' '. */
|
||||
state = 3;
|
||||
if (*s == ' ')
|
||||
break;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
/* We may have one SI prefix. */
|
||||
switch (*s) {
|
||||
case 'E':
|
||||
multiplier *= 1000;
|
||||
/* FALLTHROUGH */
|
||||
case 'P':
|
||||
multiplier *= 1000;
|
||||
/* FALLTHROUGH */
|
||||
case 'T':
|
||||
multiplier *= 1000;
|
||||
/* FALLTHROUGH */
|
||||
case 'G':
|
||||
multiplier *= 1000;
|
||||
/* FALLTHROUGH */
|
||||
case 'M':
|
||||
multiplier *= 1000;
|
||||
/* FALLTHROUGH */
|
||||
case 'k':
|
||||
multiplier *= 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We move into state 4 after the optional prefix. */
|
||||
state = 4;
|
||||
if (multiplier != 1)
|
||||
break;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
/* We move into state 5 after an optional 'B'. */
|
||||
state = 5;
|
||||
if (*s == 'B')
|
||||
break;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 5:
|
||||
/* We have trailing garbage. */
|
||||
state = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move on to the next character. */
|
||||
s++;
|
||||
} while (*s != '\0');
|
||||
|
||||
/* Multiply by multiplier. */
|
||||
if (*size > UINT64_MAX / multiplier)
|
||||
state = -1;
|
||||
else
|
||||
*size *= multiplier;
|
||||
|
||||
/* Anything other than state -1 is success. */
|
||||
return ((state == -1) ? -1 : 0);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#ifndef _HUMANSIZE_H_
|
||||
#define _HUMANSIZE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* humansize(size):
|
||||
* Given a size in bytes, allocate and return a string of the form "<N> B"
|
||||
* for 0 <= N <= 999 or "<X> <prefix>B" where either 10 <= X <= 999 or
|
||||
* 1.0 <= X <= 9.9 and <prefix> is "k", "M", "G", "T", "P", or "E"; and where
|
||||
* the value returned is the largest valid value <= the provided size.
|
||||
*/
|
||||
char * humansize(uint64_t);
|
||||
|
||||
/**
|
||||
* humansize_parse(s, size):
|
||||
* Parse a string matching /[0-9]+ ?[kMGTPE]?B?/ as a size in bytes.
|
||||
*/
|
||||
int humansize_parse(const char *, uint64_t *);
|
||||
|
||||
#endif /* !_HUMANSIZE_H_ */
|
@ -1,19 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
|
||||
/* Function which does the zeroing. */
|
||||
static void
|
||||
insecure_memzero_func(volatile void * buf, size_t len)
|
||||
{
|
||||
volatile uint8_t * _buf = buf;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
_buf[i] = 0;
|
||||
}
|
||||
|
||||
/* Pointer to memory-zeroing function. */
|
||||
void (* volatile insecure_memzero_ptr)(volatile void *, size_t) =
|
||||
insecure_memzero_func;
|
@ -1,37 +0,0 @@
|
||||
#ifndef _INSECURE_MEMZERO_H_
|
||||
#define _INSECURE_MEMZERO_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Pointer to memory-zeroing function. */
|
||||
extern void (* volatile insecure_memzero_ptr)(volatile void *, size_t);
|
||||
|
||||
/**
|
||||
* insecure_memzero(buf, len):
|
||||
* Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers'
|
||||
* best (standards-compliant) attempts to remove the buffer-zeroing. In
|
||||
* particular, to avoid performing the zeroing, a compiler would need to
|
||||
* use optimistic devirtualization; recognize that non-volatile objects do not
|
||||
* need to be treated as volatile, even if they are accessed via volatile
|
||||
* qualified pointers; and perform link-time optimization; in addition to the
|
||||
* dead-code elimination which often causes buffer-zeroing to be elided.
|
||||
*
|
||||
* Note however that zeroing a buffer does not guarantee that the data held
|
||||
* in the buffer is not stored elsewhere; in particular, there may be copies
|
||||
* held in CPU registers or in anonymous allocations on the stack, even if
|
||||
* every named variable is successfully sanitized. Solving the "wipe data
|
||||
* from the system" problem will require a C language extension which does not
|
||||
* yet exist.
|
||||
*
|
||||
* For more information, see:
|
||||
* http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
|
||||
* http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html
|
||||
*/
|
||||
static inline void
|
||||
insecure_memzero(volatile void * buf, size_t len)
|
||||
{
|
||||
|
||||
(insecure_memzero_ptr)(buf, len);
|
||||
}
|
||||
|
||||
#endif /* !_INSECURE_MEMZERO_H_ */
|
@ -1,202 +0,0 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
#include "warnp.h"
|
||||
|
||||
#include "readpass.h"
|
||||
|
||||
#define MAXPASSLEN 2048
|
||||
|
||||
/* Signals we need to block. */
|
||||
static const int badsigs[] = {
|
||||
SIGALRM, SIGHUP, SIGINT,
|
||||
SIGPIPE, SIGQUIT, SIGTERM,
|
||||
SIGTSTP, SIGTTIN, SIGTTOU
|
||||
};
|
||||
#define NSIGS sizeof(badsigs)/sizeof(badsigs[0])
|
||||
|
||||
/* Highest signal number we care about. */
|
||||
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MAX4(a, b, c, d) MAX2(MAX2(a, b), MAX2(c, d))
|
||||
#define MAX8(a, b, c, d, e, f, g, h) MAX2(MAX4(a, b, c, d), MAX4(e, f, g, h))
|
||||
#define MAXBADSIG MAX2(SIGALRM, MAX8(SIGHUP, SIGINT, SIGPIPE, SIGQUIT, \
|
||||
SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU))
|
||||
|
||||
/* Has a signal of this type been received? */
|
||||
static volatile sig_atomic_t gotsig[MAXBADSIG + 1];
|
||||
|
||||
/* Signal handler. */
|
||||
static void
|
||||
handle(int sig)
|
||||
{
|
||||
|
||||
gotsig[sig] = 1;
|
||||
}
|
||||
|
||||
/* Restore old signals and re-issue intercepted signals. */
|
||||
static void
|
||||
resetsigs(struct sigaction savedsa[NSIGS])
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Restore old signals. */
|
||||
for (i = 0; i < NSIGS; i++)
|
||||
sigaction(badsigs[i], &savedsa[i], NULL);
|
||||
|
||||
/* If we intercepted a signal, re-issue it. */
|
||||
for (i = 0; i < NSIGS; i++) {
|
||||
if (gotsig[badsigs[i]])
|
||||
raise(badsigs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* readpass(passwd, prompt, confirmprompt, devtty)
|
||||
* If ${devtty} is non-zero, read a password from /dev/tty if possible; if
|
||||
* not, read from stdin. If reading from a tty (either /dev/tty or stdin),
|
||||
* disable echo and prompt the user by printing ${prompt} to stderr. If
|
||||
* ${confirmprompt} is non-NULL, read a second password (prompting if a
|
||||
* terminal is being used) and repeat until the user enters the same password
|
||||
* twice. Return the password as a malloced NUL-terminated string via
|
||||
* ${passwd}.
|
||||
*/
|
||||
int
|
||||
readpass(char ** passwd, const char * prompt,
|
||||
const char * confirmprompt, int devtty)
|
||||
{
|
||||
FILE * readfrom;
|
||||
char passbuf[MAXPASSLEN];
|
||||
char confpassbuf[MAXPASSLEN];
|
||||
struct sigaction sa, savedsa[NSIGS];
|
||||
struct termios term, term_old;
|
||||
size_t i;
|
||||
int usingtty;
|
||||
|
||||
/*
|
||||
* If devtty != 0, try to open /dev/tty; if that fails, or if devtty
|
||||
* is zero, we'll read the password from stdin instead.
|
||||
*/
|
||||
if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL))
|
||||
readfrom = stdin;
|
||||
|
||||
/* We have not received any signals yet. */
|
||||
for (i = 0; i <= MAXBADSIG; i++)
|
||||
gotsig[i] = 0;
|
||||
|
||||
/*
|
||||
* If we receive a signal while we're reading the password, we might
|
||||
* end up with echo disabled; to prevent this, we catch the signals
|
||||
* here, and we'll re-send them to ourselves later after we re-enable
|
||||
* terminal echo.
|
||||
*/
|
||||
sa.sa_handler = handle;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
for (i = 0; i < NSIGS; i++)
|
||||
sigaction(badsigs[i], &sa, &savedsa[i]);
|
||||
|
||||
/* If we're reading from a terminal, try to disable echo. */
|
||||
if ((usingtty = isatty(fileno(readfrom))) != 0) {
|
||||
if (tcgetattr(fileno(readfrom), &term_old)) {
|
||||
warnp("Cannot read terminal settings");
|
||||
goto err2;
|
||||
}
|
||||
memcpy(&term, &term_old, sizeof(struct termios));
|
||||
term.c_lflag = (term.c_lflag & ~((tcflag_t)ECHO)) | ECHONL;
|
||||
if (tcsetattr(fileno(readfrom), TCSANOW, &term)) {
|
||||
warnp("Cannot set terminal settings");
|
||||
goto err2;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
/* If we have a terminal, prompt the user to enter the password. */
|
||||
if (usingtty)
|
||||
fprintf(stderr, "%s: ", prompt);
|
||||
|
||||
/* Read the password. */
|
||||
if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) {
|
||||
if (feof(readfrom))
|
||||
warn0("EOF reading password");
|
||||
else
|
||||
warnp("Cannot read password");
|
||||
goto err3;
|
||||
}
|
||||
|
||||
/* Confirm the password if necessary. */
|
||||
if (confirmprompt != NULL) {
|
||||
if (usingtty)
|
||||
fprintf(stderr, "%s: ", confirmprompt);
|
||||
if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) {
|
||||
if (feof(readfrom))
|
||||
warn0("EOF reading password");
|
||||
else
|
||||
warnp("Cannot read password");
|
||||
goto err3;
|
||||
}
|
||||
if (strcmp(passbuf, confpassbuf)) {
|
||||
fprintf(stderr,
|
||||
"Passwords mismatch, please try again\n");
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the string at the first "\r" or "\n" (if any). */
|
||||
passbuf[strcspn(passbuf, "\r\n")] = '\0';
|
||||
|
||||
/* If we changed terminal settings, reset them. */
|
||||
if (usingtty)
|
||||
tcsetattr(fileno(readfrom), TCSANOW, &term_old);
|
||||
|
||||
/* Restore old signals and re-issue intercepted signals. */
|
||||
resetsigs(savedsa);
|
||||
|
||||
/* Close /dev/tty if we opened it. */
|
||||
if (readfrom != stdin)
|
||||
fclose(readfrom);
|
||||
|
||||
/* Copy the password out. */
|
||||
if ((*passwd = strdup(passbuf)) == NULL) {
|
||||
warnp("Cannot allocate memory");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero any stored passwords. This is not guaranteed to work, since a
|
||||
* "sufficiently intelligent" compiler can optimize these out due to
|
||||
* the values not being accessed again; and even if we outwitted the
|
||||
* compiler, all we can do is ensure that *a* buffer is zeroed but
|
||||
* not that it is the only buffer containing the data in question.
|
||||
* Unfortunately the C standard does not provide any way to mark data
|
||||
* as "sensitive" in order to prevent extra copies being sprinkled
|
||||
* around the implementation address space.
|
||||
*/
|
||||
insecure_memzero(passbuf, MAXPASSLEN);
|
||||
insecure_memzero(confpassbuf, MAXPASSLEN);
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
|
||||
err3:
|
||||
/* Reset terminal settings if necessary. */
|
||||
if (usingtty)
|
||||
tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old);
|
||||
err2:
|
||||
/* Close /dev/tty if we opened it. */
|
||||
if (readfrom != stdin)
|
||||
fclose(readfrom);
|
||||
|
||||
/* Restore old signals and re-issue intercepted signals. */
|
||||
resetsigs(savedsa);
|
||||
err1:
|
||||
/* Zero any stored passwords. */
|
||||
insecure_memzero(passbuf, MAXPASSLEN);
|
||||
insecure_memzero(confpassbuf, MAXPASSLEN);
|
||||
|
||||
/* Failure! */
|
||||
return (-1);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#ifndef _READPASS_H_
|
||||
#define _READPASS_H_
|
||||
|
||||
/* Avoid namespace collisions with other "readpass" functions. */
|
||||
#ifdef readpass
|
||||
#undef readpass
|
||||
#endif
|
||||
#define readpass libcperciva_readpass
|
||||
|
||||
/**
|
||||
* readpass(passwd, prompt, confirmprompt, devtty)
|
||||
* If ${devtty} is non-zero, read a password from /dev/tty if possible; if
|
||||
* not, read from stdin. If reading from a tty (either /dev/tty or stdin),
|
||||
* disable echo and prompt the user by printing ${prompt} to stderr. If
|
||||
* ${confirmprompt} is non-NULL, read a second password (prompting if a
|
||||
* terminal is being used) and repeat until the user enters the same password
|
||||
* twice. Return the password as a malloced NUL-terminated string via
|
||||
* ${passwd}.
|
||||
*/
|
||||
int readpass(char **, const char *, const char *, int);
|
||||
|
||||
#endif /* !_READPASS_H_ */
|
@ -1,146 +0,0 @@
|
||||
#ifndef _SYSENDIAN_H_
|
||||
#define _SYSENDIAN_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Avoid namespace collisions with BSD <sys/endian.h>. */
|
||||
#define be16dec libcperciva_be16dec
|
||||
#define be16enc libcperciva_be16enc
|
||||
#define be32dec libcperciva_be32dec
|
||||
#define be32enc libcperciva_be32enc
|
||||
#define be64dec libcperciva_be64dec
|
||||
#define be64enc libcperciva_be64enc
|
||||
#define le16dec libcperciva_le16dec
|
||||
#define le16enc libcperciva_le16enc
|
||||
#define le32dec libcperciva_le32dec
|
||||
#define le32enc libcperciva_le32enc
|
||||
#define le64dec libcperciva_le64dec
|
||||
#define le64enc libcperciva_le64enc
|
||||
|
||||
static inline uint16_t
|
||||
be16dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return (uint16_t)((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be16enc(void * pp, uint16_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[1] = x & 0xff;
|
||||
p[0] = (x >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
be32dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be32enc(void * pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
be64dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
|
||||
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
|
||||
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
|
||||
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be64enc(void * pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[7] = x & 0xff;
|
||||
p[6] = (x >> 8) & 0xff;
|
||||
p[5] = (x >> 16) & 0xff;
|
||||
p[4] = (x >> 24) & 0xff;
|
||||
p[3] = (x >> 32) & 0xff;
|
||||
p[2] = (x >> 40) & 0xff;
|
||||
p[1] = (x >> 48) & 0xff;
|
||||
p[0] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
le16dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return (uint16_t)((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le16enc(void * pp, uint16_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
le32dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
|
||||
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le32enc(void * pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
le64dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
|
||||
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
|
||||
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
|
||||
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le64enc(void * pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
p[4] = (x >> 32) & 0xff;
|
||||
p[5] = (x >> 40) & 0xff;
|
||||
p[6] = (x >> 48) & 0xff;
|
||||
p[7] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
#endif /* !_SYSENDIAN_H_ */
|
@ -1,76 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "warnp.h"
|
||||
|
||||
static int initialized = 0;
|
||||
static char * name = NULL;
|
||||
|
||||
/* Free the name string. */
|
||||
static void
|
||||
done(void)
|
||||
{
|
||||
|
||||
free(name);
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* warnp_setprogname(progname):
|
||||
* Set the program name to be used by warn() and warnx() to ${progname}.
|
||||
*/
|
||||
void
|
||||
warnp_setprogname(const char * progname)
|
||||
{
|
||||
const char * p;
|
||||
|
||||
/* Free the name if we already have one. */
|
||||
free(name);
|
||||
|
||||
/* Find the last segment of the program name. */
|
||||
for (p = progname; progname[0] != '\0'; progname++)
|
||||
if (progname[0] == '/')
|
||||
p = progname + 1;
|
||||
|
||||
/* Copy the name string. */
|
||||
name = strdup(p);
|
||||
|
||||
/* If we haven't already done so, register our exit handler. */
|
||||
if (initialized == 0) {
|
||||
atexit(done);
|
||||
initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
warn(const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)");
|
||||
if (fmt != NULL) {
|
||||
fprintf(stderr, ": ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
fprintf(stderr, ": %s\n", strerror(errno));
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
warnx(const char * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s", (name != NULL) ? name : "(unknown)");
|
||||
if (fmt != NULL) {
|
||||
fprintf(stderr, ": ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
#ifndef _WARNP_H_
|
||||
#define _WARNP_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Avoid namespace collisions with BSD <err.h>. */
|
||||
#define warn libcperciva_warn
|
||||
#define warnx libcperciva_warnx
|
||||
|
||||
/**
|
||||
* warnp_setprogname(progname):
|
||||
* Set the program name to be used by warn() and warnx() to ${progname}.
|
||||
*/
|
||||
void warnp_setprogname(const char *);
|
||||
#define WARNP_INIT do { \
|
||||
if (argv[0] != NULL) \
|
||||
warnp_setprogname(argv[0]); \
|
||||
} while (0)
|
||||
|
||||
/* As in BSD <err.h>. */
|
||||
void warn(const char *, ...);
|
||||
void warnx(const char *, ...);
|
||||
|
||||
/*
|
||||
* If compiled with DEBUG defined, print __FILE__ and __LINE__.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define warnline do { \
|
||||
warnx("%s, %d", __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define warnline
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Call warn(3) or warnx(3) depending upon whether errno == 0; and clear
|
||||
* errno (so that the standard error message isn't repeated later).
|
||||
*/
|
||||
#define warnp(...) do { \
|
||||
warnline; \
|
||||
if (errno != 0) { \
|
||||
warn(__VA_ARGS__); \
|
||||
errno = 0; \
|
||||
} else \
|
||||
warnx(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Call warnx(3) and set errno == 0. Unlike warnp, this should be used
|
||||
* in cases where we're reporting a problem which we discover ourselves
|
||||
* rather than one which is reported to us from a library or the kernel.
|
||||
*/
|
||||
#define warn0(...) do { \
|
||||
warnline; \
|
||||
warnx(__VA_ARGS__); \
|
||||
errno = 0; \
|
||||
} while (0)
|
||||
|
||||
#endif /* !_WARNP_H_ */
|
226
vendor/scrypt/scrypt-1.2.1/scrypt/main.c
vendored
226
vendor/scrypt/scrypt-1.2.1/scrypt/main.c
vendored
@ -1,226 +0,0 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include "scrypt_platform.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "getopt.h"
|
||||
#include "humansize.h"
|
||||
#include "insecure_memzero.h"
|
||||
#include "readpass.h"
|
||||
#include "scryptenc.h"
|
||||
#include "warnp.h"
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: scrypt {enc | dec} [-f] [-M maxmem]"
|
||||
" [-m maxmemfrac]\n"
|
||||
" [-t maxtime] [-v] [-P] infile [outfile]\n"
|
||||
" scrypt --version\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FILE * infile;
|
||||
FILE * outfile;
|
||||
int devtty = 1;
|
||||
int dec = 0;
|
||||
size_t maxmem = 0;
|
||||
int force_resources = 0;
|
||||
uint64_t maxmem64;
|
||||
double maxmemfrac = 0.5;
|
||||
double maxtime = 300.0;
|
||||
const char * ch;
|
||||
char * passwd;
|
||||
int rc;
|
||||
int verbose = 0;
|
||||
|
||||
WARNP_INIT;
|
||||
|
||||
/* We should have "enc" or "dec" first. */
|
||||
if (argc < 2)
|
||||
usage();
|
||||
if (strcmp(argv[1], "enc") == 0) {
|
||||
maxmem = 0;
|
||||
maxmemfrac = 0.125;
|
||||
maxtime = 5.0;
|
||||
} else if (strcmp(argv[1], "dec") == 0) {
|
||||
dec = 1;
|
||||
} else if (strcmp(argv[1], "--version") == 0) {
|
||||
fprintf(stdout, "scrypt %s\n", PACKAGE_VERSION);
|
||||
exit(0);
|
||||
} else {
|
||||
warn0("First argument must be 'enc' or 'dec'.\n");
|
||||
usage();
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
/* Parse arguments. */
|
||||
while ((ch = GETOPT(argc, argv)) != NULL) {
|
||||
GETOPT_SWITCH(ch) {
|
||||
GETOPT_OPT("-f"):
|
||||
force_resources = 1;
|
||||
break;
|
||||
GETOPT_OPTARG("-M"):
|
||||
if (humansize_parse(optarg, &maxmem64)) {
|
||||
warn0("Could not parse the parameter to -M.");
|
||||
exit(1);
|
||||
}
|
||||
if (maxmem64 > SIZE_MAX) {
|
||||
warn0("The parameter to -M is too large.");
|
||||
exit(1);
|
||||
}
|
||||
maxmem = (size_t)maxmem64;
|
||||
break;
|
||||
GETOPT_OPTARG("-m"):
|
||||
maxmemfrac = strtod(optarg, NULL);
|
||||
break;
|
||||
GETOPT_OPTARG("-t"):
|
||||
maxtime = strtod(optarg, NULL);
|
||||
break;
|
||||
GETOPT_OPT("-v"):
|
||||
verbose = 1;
|
||||
break;
|
||||
GETOPT_OPT("-P"):
|
||||
devtty = 0;
|
||||
break;
|
||||
GETOPT_MISSING_ARG:
|
||||
warn0("Missing argument to %s\n", ch);
|
||||
usage();
|
||||
GETOPT_DEFAULT:
|
||||
warn0("illegal option -- %s\n", ch);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* We must have one or two parameters left. */
|
||||
if ((argc < 1) || (argc > 2))
|
||||
usage();
|
||||
|
||||
/* If the input isn't stdin, open the file. */
|
||||
if (strcmp(argv[0], "-")) {
|
||||
if ((infile = fopen(argv[0], "rb")) == NULL) {
|
||||
warnp("Cannot open input file: %s", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
infile = stdin;
|
||||
}
|
||||
|
||||
/* If we have an output file, open it. */
|
||||
if (argc > 1) {
|
||||
if ((outfile = fopen(argv[1], "wb")) == NULL) {
|
||||
warnp("Cannot open output file: %s", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
outfile = stdout;
|
||||
}
|
||||
|
||||
/* Prompt for a password. */
|
||||
if (readpass(&passwd, "Please enter passphrase",
|
||||
(dec || !devtty) ? NULL : "Please confirm passphrase", devtty))
|
||||
exit(1);
|
||||
|
||||
/* Encrypt or decrypt. */
|
||||
if (dec)
|
||||
rc = scryptdec_file(infile, outfile, (uint8_t *)passwd,
|
||||
strlen(passwd), maxmem, maxmemfrac, maxtime, verbose,
|
||||
force_resources);
|
||||
else
|
||||
rc = scryptenc_file(infile, outfile, (uint8_t *)passwd,
|
||||
strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);
|
||||
|
||||
/* Zero and free the password. */
|
||||
insecure_memzero(passwd, strlen(passwd));
|
||||
free(passwd);
|
||||
|
||||
/* Close any files we opened. */
|
||||
if (infile != stdin)
|
||||
fclose(infile);
|
||||
if (outfile != stdout)
|
||||
fclose(outfile);
|
||||
|
||||
/* If we failed, print the right error message and exit. */
|
||||
if (rc != 0) {
|
||||
switch (rc) {
|
||||
case 1:
|
||||
warnp("Error determining amount of available memory");
|
||||
break;
|
||||
case 2:
|
||||
warnp("Error reading clocks");
|
||||
break;
|
||||
case 3:
|
||||
warnp("Error computing derived key");
|
||||
break;
|
||||
case 4:
|
||||
warnp("Error reading salt");
|
||||
break;
|
||||
case 5:
|
||||
warnp("OpenSSL error");
|
||||
break;
|
||||
case 6:
|
||||
warnp("Error allocating memory");
|
||||
break;
|
||||
case 7:
|
||||
warn0("Input is not valid scrypt-encrypted block");
|
||||
break;
|
||||
case 8:
|
||||
warn0("Unrecognized scrypt format version");
|
||||
break;
|
||||
case 9:
|
||||
warn0("Decrypting file would require too much memory");
|
||||
break;
|
||||
case 10:
|
||||
warn0("Decrypting file would take too much CPU time");
|
||||
break;
|
||||
case 11:
|
||||
warn0("Passphrase is incorrect");
|
||||
break;
|
||||
case 12:
|
||||
warnp("Error writing file: %s",
|
||||
(argc > 1) ? argv[1] : "standard output");
|
||||
break;
|
||||
case 13:
|
||||
warnp("Error reading file: %s", argv[0]);
|
||||
break;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
140
vendor/scrypt/scrypt-1.2.1/scrypt/scrypt.1
vendored
140
vendor/scrypt/scrypt-1.2.1/scrypt/scrypt.1
vendored
@ -1,140 +0,0 @@
|
||||
.\" Copyright 2009 Colin Percival
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.Dd February 10, 2017
|
||||
.Dt SCRYPT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm scrypt
|
||||
.Nd encrypt and decrypt files.
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Brq Cm enc | Cm dec
|
||||
.Op Fl f
|
||||
.Op Fl M Ar maxmem
|
||||
.Op Fl m Ar maxmemfrac
|
||||
.Op Fl t Ar maxtime
|
||||
.Op Fl P
|
||||
.Ar infile
|
||||
.Op Ar outfile
|
||||
.Nm
|
||||
.Fl -version
|
||||
.Sh DESCRIPTION
|
||||
.Nm Cm enc
|
||||
encrypts
|
||||
.Ar infile
|
||||
and writes the result to
|
||||
.Ar outfile
|
||||
if specified, or the standard output otherwise.
|
||||
The user will be prompted to enter a passphrase (twice) to
|
||||
be used to generate a derived encryption key.
|
||||
.Pp
|
||||
.Nm Cm dec
|
||||
decrypts
|
||||
.Ar infile
|
||||
and writes the result to
|
||||
.Ar outfile
|
||||
if specified, or the standard output otherwise.
|
||||
The user will be prompted to enter the passphrase used at
|
||||
encryption time to generate the derived encryption key.
|
||||
.Pp
|
||||
If
|
||||
.Fl P
|
||||
is not given,
|
||||
.Nm
|
||||
reads passphrases from its controlling terminal, or failing that,
|
||||
from stdin. Prompts are only printed when
|
||||
.Nm
|
||||
is reading passphrases from some terminal. If
|
||||
.Fl P
|
||||
is given, then
|
||||
.Nm
|
||||
does not print any prompts, and reads a passphrase from stdin.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width "-m maxmemfrac"
|
||||
.It Fl f
|
||||
Force the decryption to proceed even if it is anticipated to
|
||||
require an excessive amount of memory or CPU time.
|
||||
.It Fl M Ar maxmem
|
||||
Use at most
|
||||
.Ar maxmem
|
||||
bytes of RAM to compute the derived encryption key.
|
||||
.It Fl m Ar maxmemfrac
|
||||
Use at most the fraction
|
||||
.Ar maxmemfrac
|
||||
of the available RAM to compute the derived encryption key.
|
||||
.It Fl t Ar maxtime
|
||||
Use at most
|
||||
.Ar maxtime
|
||||
seconds of CPU time to compute the derived encryption key.
|
||||
.It Fl P
|
||||
Always read passphrase from stdin, and do so only once even
|
||||
when encrypting.
|
||||
.It Fl -version
|
||||
Print version of scrypt, and exit.
|
||||
.El
|
||||
.Pp
|
||||
In
|
||||
.Nm Cm enc ,
|
||||
the memory and CPU time limits are enforced by picking
|
||||
appropriate parameters to the
|
||||
.Nm
|
||||
key derivation function.
|
||||
In
|
||||
.Nm Cm dec ,
|
||||
the memory and CPU time limits are enforced by exiting with
|
||||
an error if decrypting the file would require too much memory
|
||||
or CPU time.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.Pp
|
||||
Note that if the input encrypted file is corrupted,
|
||||
.Nm Cm dec
|
||||
may produce output prior to determining that the input
|
||||
was corrupt and exiting with a non-zero status; so
|
||||
users should direct the output to a safe location and
|
||||
check the exit status of
|
||||
.Nm
|
||||
before using the decrypted data.
|
||||
.Sh SEE ALSO
|
||||
.Rs
|
||||
.%A "Colin Percival"
|
||||
.%T "Stronger Key Derivation via Sequential Memory-Hard Functions"
|
||||
.%O "Presented at BSDCan'09"
|
||||
.%D "May 2009"
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility was written in May 2009 by Colin Percival as a
|
||||
demonstration of the
|
||||
.Nm
|
||||
key derivation function.
|
||||
The
|
||||
.Nm
|
||||
key derivation function was invented in March 2009 by Colin
|
||||
Percival in order to allow key files from the
|
||||
.Nm tarsnap
|
||||
backup system to be passphrase protected.
|
@ -1,12 +0,0 @@
|
||||
#ifndef _SCRYPT_PLATFORM_H_
|
||||
#define _SCRYPT_PLATFORM_H_
|
||||
|
||||
#if defined(CONFIG_H_FILE)
|
||||
#include CONFIG_H_FILE
|
||||
#elif defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#else
|
||||
#error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined.
|
||||
#endif
|
||||
|
||||
#endif /* !_SCRYPT_PLATFORM_H_ */
|
@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Constants
|
||||
# The scenario command requires a lot of memory, so valgrind is only enabled
|
||||
# if $USE_VALGRIND > 1.
|
||||
c_valgrind_min=2
|
||||
test_output="${s_basename}-stdout.txt"
|
||||
reference="${scriptdir}/test_scrypt.good"
|
||||
|
||||
### Actual command
|
||||
scenario_cmd() {
|
||||
# Run the binary which tests known input/output strings.
|
||||
setup_check_variables
|
||||
(
|
||||
${c_valgrind_cmd} ${bindir}/tests/test_scrypt 1> ${test_output}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The generated values should match the known good values.
|
||||
setup_check_variables
|
||||
if cmp -s ${test_output} ${reference}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Constants
|
||||
c_valgrind_min=1
|
||||
reference_file="${scriptdir}/test_scrypt.good"
|
||||
encrypted_reference_file="${scriptdir}/test_scrypt_good.enc"
|
||||
decrypted_reference_file="${out}/attempt_reference.txt"
|
||||
|
||||
scenario_cmd() {
|
||||
# Decrypt a reference file.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
dec -P ${encrypted_reference_file} \
|
||||
${decrypted_reference_file}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The decrypted reference file should match the reference.
|
||||
setup_check_variables
|
||||
if cmp -s ${decrypted_reference_file} ${reference_file}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Constants
|
||||
c_valgrind_min=1
|
||||
reference_file="${scriptdir}/test_scrypt.good"
|
||||
encrypted_file="${out}/attempt.enc"
|
||||
decrypted_file="${out}/attempt.txt"
|
||||
|
||||
scenario_cmd() {
|
||||
# Encrypt a file.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
enc -P -t 1 ${reference_file} ${encrypted_file}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The encrypted file should be different from the original file.
|
||||
# We cannot check against the "reference" encrypted file, because
|
||||
# encrypted files include random salt. If successful, don't delete
|
||||
# ${encrypted_file} yet; we need it for the next test.
|
||||
setup_check_variables
|
||||
if cmp -s ${encrypted_file} ${reference_file}; then
|
||||
echo "1"
|
||||
else
|
||||
echo "0"
|
||||
fi > ${c_exitfile}
|
||||
|
||||
# Decrypt the file we just encrypted.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
dec -P ${encrypted_file} ${decrypted_file}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The decrypted file should match the reference.
|
||||
setup_check_variables
|
||||
if cmp -s ${decrypted_file} ${reference_file}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Constants
|
||||
c_valgrind_min=1
|
||||
reference_file="${scriptdir}/test_scrypt.good"
|
||||
longwait_encrypted_file="${out}/longwait.enc"
|
||||
longwait_decrypted_file="${out}/longwait.txt"
|
||||
longwait_failed_log="${out}/longwait-failed.log"
|
||||
|
||||
scenario_cmd() {
|
||||
# Encrypt file which should take a long time to decrypt.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
enc -P -t 10 ${reference_file} \
|
||||
${longwait_encrypted_file}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# Attempt to decrypt it with limited time. We want this
|
||||
# command to fail, so we negate the normal return code.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
dec -P -t 1 ${longwait_encrypted_file} \
|
||||
${longwait_decrypted_file} \
|
||||
2> ${longwait_failed_log}
|
||||
test ! $? -eq 0
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# We should have received an error message.
|
||||
setup_check_variables
|
||||
if grep -q "scrypt: Decrypting file would take too much CPU time" \
|
||||
${longwait_failed_log}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
|
||||
# Attempt to decrypt it with limited time, but force success.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
dec -P -t 1 -f ${longwait_encrypted_file} \
|
||||
${longwait_decrypted_file}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The decrypted reference file should match the reference.
|
||||
setup_check_variables
|
||||
if cmp -s ${longwait_decrypted_file} ${reference_file}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Constants
|
||||
c_valgrind_min=1
|
||||
reference_file="${scriptdir}/test_scrypt.good"
|
||||
encrypted_file_1="${out}/sys-scrypt.enc"
|
||||
decrypted_file_1="${out}/sys-scrypt.txt"
|
||||
encrypted_file_2="${out}/our-scrypt.enc"
|
||||
decrypted_file_2="${out}/our-scrypt.txt"
|
||||
|
||||
scenario_cmd() {
|
||||
if [ -z "${system_scrypt}" ]; then
|
||||
printf "no suitable system scrypt: "
|
||||
# Inform test suite that we are skipping.
|
||||
setup_check_variables
|
||||
echo "-1" > ${c_exitfile}
|
||||
return
|
||||
fi
|
||||
|
||||
# Encrypt a file with our scrypt.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
enc -P -t 1 ${reference_file} ${encrypted_file_1}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# Use the system scrypt to decrypt the file we just
|
||||
# encrypted. Don't use valgrind for this.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${system_scrypt} \
|
||||
dec -P ${encrypted_file_1} ${decrypted_file_1}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The decrypted file should match the reference.
|
||||
setup_check_variables
|
||||
if cmp -s ${decrypted_file_1} ${reference_file}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
|
||||
# Encrypt a file with the system scrypt. Don't use
|
||||
# valgrind for this.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${system_scrypt} \
|
||||
enc -P -t 1 ${reference_file} ${encrypted_file_2}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# Use our scrypt to decrypt the file we just encrypted.
|
||||
setup_check_variables
|
||||
(
|
||||
echo ${password} | ${c_valgrind_cmd} ${bindir}/scrypt \
|
||||
dec -P ${encrypted_file_2} ${decrypted_file_2}
|
||||
echo $? > ${c_exitfile}
|
||||
)
|
||||
|
||||
# The decrypted file should match the reference.
|
||||
setup_check_variables
|
||||
if cmp -s ${decrypted_file_2} ${reference_file}; then
|
||||
echo "0"
|
||||
else
|
||||
echo "1"
|
||||
fi > ${c_exitfile}
|
||||
}
|
@ -1,268 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### Definitions
|
||||
#
|
||||
# This test suite uses the following terminology:
|
||||
# - scenario: a series of commands to test. Each must be in a
|
||||
# separate file, and must be completely self-contained
|
||||
# (other than the variables listed below).
|
||||
# - check: a series of commands that produces an exit code which
|
||||
# the test suite should check. A scenario may contain any
|
||||
# number of checks.
|
||||
#
|
||||
### Design
|
||||
#
|
||||
# The main function is scenario_runner(scenario_filename), which
|
||||
# takes a scenario file as the argument, and runs a
|
||||
# scenario_cmd()
|
||||
# function which was defined in that file.
|
||||
#
|
||||
### Variables
|
||||
#
|
||||
# Wherever possible, this suite uses local variables and
|
||||
# explicitly-passed arguments, with the following exceptions:
|
||||
# - s_basename: this is the basename for the scenario's temporary
|
||||
# and log files.
|
||||
# - s_val_basename: this is the basename for the scenario's
|
||||
# valgrind log files.
|
||||
# - s_count: this is the count of the scenario's checks (so that
|
||||
# each check can have distinct files).
|
||||
# - s_retval: this is the overall exit code of the scenario.
|
||||
# - c_exitfile: this contains the exit code of each check.
|
||||
# - c_valgrind_min: this is the minimum value of USE_VALGRIND
|
||||
# which will enable valgrind checking for this check.
|
||||
# - c_valgrind_cmd: this is the valgrind command (including
|
||||
# appropriate log file) if necessary, or is "" otherwise.
|
||||
|
||||
set -o nounset
|
||||
|
||||
### Constants
|
||||
out="tests-output"
|
||||
out_valgrind="tests-valgrind"
|
||||
valgrind_suppressions="${out_valgrind}/suppressions"
|
||||
valgrind_suppressions_log="${out_valgrind}/suppressions.pre"
|
||||
|
||||
# Keep the user-specified ${USE_VALGRIND}, or initialize to 0.
|
||||
USE_VALGRIND=${USE_VALGRIND:-0}
|
||||
|
||||
# A non-zero value unlikely to be used as an exit code by the programs being
|
||||
# tested.
|
||||
valgrind_exit_code=108
|
||||
|
||||
## prepare_directories():
|
||||
# Delete any old directories, and create new ones as necessary. Must be run
|
||||
# after check_optional_valgrind().
|
||||
prepare_directories() {
|
||||
# Clean up previous directories.
|
||||
if [ -d "${out}" ]; then
|
||||
rm -rf ${out}
|
||||
fi
|
||||
if [ -d "${out_valgrind}" ]; then
|
||||
rm -rf ${out_valgrind}
|
||||
fi
|
||||
|
||||
# Make new directories.
|
||||
mkdir ${out}
|
||||
if [ "$USE_VALGRIND" -gt 0 ]; then
|
||||
mkdir ${out_valgrind}
|
||||
fi
|
||||
}
|
||||
|
||||
## find_system (cmd, args...):
|
||||
# Looks for ${cmd} in the $PATH, and ensure that it supports ${args}.
|
||||
find_system() {
|
||||
cmd=$1
|
||||
cmd_with_args=$@
|
||||
# Look for ${cmd}.
|
||||
system_binary=`command -v ${cmd}`
|
||||
if [ -z "${system_binary}" ]; then
|
||||
system_binary=""
|
||||
printf "System ${cmd} not found.\n" 1>&2
|
||||
# If the command exists, check it ensures the ${args}.
|
||||
elif ${cmd_with_args} 2>&1 >/dev/null | \
|
||||
grep -qE "(invalid|illegal) option"; then
|
||||
system_binary=""
|
||||
printf "Cannot use system ${cmd}; does not" 1>&2
|
||||
printf " support necessary arguments.\n" 1>&2
|
||||
fi
|
||||
echo "${system_binary}"
|
||||
}
|
||||
|
||||
## check_optional_valgrind ():
|
||||
# Return a $USE_VALGRIND variable defined; if it was previously defined and
|
||||
# was greater than 0, then check that valgrind is available in the $PATH.
|
||||
check_optional_valgrind() {
|
||||
if [ "$USE_VALGRIND" -gt 0 ]; then
|
||||
# Look for valgrind in $PATH.
|
||||
if ! command -v valgrind >/dev/null 2>&1; then
|
||||
printf "valgrind not found\n" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## ensure_valgrind_suppresssion (potential_memleaks_binary):
|
||||
# Runs the ${potential_memleaks_binary} through valgrind, keeping
|
||||
# track of any apparent memory leak in order to suppress reporting
|
||||
# those leaks when testing other binaries.
|
||||
ensure_valgrind_suppression() {
|
||||
potential_memleaks_binary=$1
|
||||
|
||||
# Quit if we're not using valgrind.
|
||||
if [ ! "$USE_VALGRIND" -gt 0 ]; then
|
||||
return
|
||||
fi;
|
||||
printf "Generating valgrind suppressions... "
|
||||
|
||||
# Run valgrind on the binary, sending it a "\n" so that
|
||||
# a test which uses STDIN will not wait for user input.
|
||||
printf "\n" | (valgrind --leak-check=full --show-leak-kinds=all \
|
||||
--gen-suppressions=all \
|
||||
--log-file=${valgrind_suppressions_log} \
|
||||
${potential_memleaks_binary})
|
||||
|
||||
# Strip out useless parts from the log file, as well as
|
||||
# removing references to the main and "pl_*" ("potential
|
||||
# loss") functions so that the suppressions can apply to
|
||||
# other binaries.
|
||||
(grep -v "^==" ${valgrind_suppressions_log} \
|
||||
| grep -v " fun:pl_" - \
|
||||
| grep -v " fun:main" - \
|
||||
> ${valgrind_suppressions} )
|
||||
|
||||
# Clean up
|
||||
rm -f ${valgrind_suppressions_log}
|
||||
printf "done.\n"
|
||||
}
|
||||
|
||||
## setup_check_variables ():
|
||||
# Set up the "check" variables ${c_exitfile} and ${c_valgrind_cmd}, the
|
||||
# latter depending on the previously-defined ${c_valgrind_min}.
|
||||
# Advances the number of checks ${s_count} so that the next call to this
|
||||
# function will set up new filenames.
|
||||
setup_check_variables() {
|
||||
# Set up the "exit" file.
|
||||
c_exitfile="${s_basename}-`printf %02d ${s_count}`.exit"
|
||||
|
||||
# If we don't have a suppressions file, don't try to use it.
|
||||
if [ ! -e ${valgrind_suppressions} ]; then
|
||||
valgrind_suppressions=/dev/null
|
||||
fi
|
||||
|
||||
# Set up the valgrind command if $USE_VALGRIND is greater
|
||||
# than or equal to ${valgrind_min}; otherwise, produce an
|
||||
# empty string. Using --error-exitcode means that if
|
||||
# there is a serious problem (such that scrypt calls
|
||||
# exit(1)) *and* a memory leak, the test suite reports an
|
||||
# exit value of ${valgrind_exit_code}. However, if there
|
||||
# is a serious problem but no memory leak, we still
|
||||
# receive a non-zero exit code. The most important thing
|
||||
# is that we only receive an exit code of 0 if both the
|
||||
# program and valgrind are happy.
|
||||
if [ "$USE_VALGRIND" -ge "${c_valgrind_min}" ]; then
|
||||
val_logfilename=${s_val_basename}-`printf %02d ${s_count}`.log
|
||||
c_valgrind_cmd="valgrind \
|
||||
--log-file=${val_logfilename} \
|
||||
--leak-check=full --show-leak-kinds=all \
|
||||
--errors-for-leak-kinds=all \
|
||||
--suppressions=${valgrind_suppressions} \
|
||||
--error-exitcode=${valgrind_exit_code} "
|
||||
else
|
||||
c_valgrind_cmd=""
|
||||
fi
|
||||
|
||||
# Advances the number of checks.
|
||||
s_count=$((s_count + 1))
|
||||
}
|
||||
|
||||
## get_val_logfile (val_basename, exitfile):
|
||||
# Return the valgrind logfile corresponding to ${exitfile}.
|
||||
get_val_logfile() {
|
||||
val_basename=$1
|
||||
exitfile=$2
|
||||
num=`echo "${exitfile}" | rev | cut -c 1-7 | rev | cut -c 1-2 `
|
||||
echo "${val_basename}-${num}.log"
|
||||
}
|
||||
|
||||
## notify_success_or_fail (log_basename, val_log_basename):
|
||||
# Examine all "exit code" files beginning with ${log_basename} and
|
||||
# print "SUCCESS!" or "FAILED!" as appropriate. If the test failed
|
||||
# with the code ${valgrind_exit_code}, output the appropriate
|
||||
# valgrind logfile to stdout.
|
||||
notify_success_or_fail() {
|
||||
log_basename=$1
|
||||
val_log_basename=$2
|
||||
|
||||
# Check each exitfile.
|
||||
for exitfile in `ls ${log_basename}-*.exit | sort`; do
|
||||
ret=`cat ${exitfile}`
|
||||
if [ "${ret}" -lt 0 ]; then
|
||||
echo "SKIP!"
|
||||
return
|
||||
fi
|
||||
if [ "${ret}" -gt 0 ]; then
|
||||
echo "FAILED!"
|
||||
retval=${ret}
|
||||
if [ "${ret}" -eq "${valgrind_exit_code}" ]; then
|
||||
val_logfilename=$( get_val_logfile \
|
||||
${val_log_basename} ${exitfile} )
|
||||
cat ${val_logfilename}
|
||||
fi
|
||||
s_retval=${ret}
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
echo "SUCCESS!"
|
||||
}
|
||||
|
||||
## scenario_runner (scenario_filename):
|
||||
# Runs a test scenario from ${scenario_filename}.
|
||||
scenario_runner() {
|
||||
scenario_filename=$1
|
||||
basename=`basename ${scenario_filename} .sh`
|
||||
printf " ${basename}... " 1>&2
|
||||
|
||||
# Initialize "scenario" and "check" variables.
|
||||
s_basename=${out}/${basename}
|
||||
s_val_basename=${out_valgrind}/${basename}
|
||||
s_count=0
|
||||
c_exitfile=/dev/null
|
||||
c_valgrind_min=9
|
||||
c_valgrind_cmd=""
|
||||
|
||||
# Load scenario_cmd() from the scenario file.
|
||||
unset scenario_cmd
|
||||
. ${scenario_filename}
|
||||
if ! command -v scenario_cmd 1>/dev/null ; then
|
||||
printf "ERROR: scenario_cmd() is not defined in\n"
|
||||
printf " ${scenario_filename}\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run the scenario command.
|
||||
scenario_cmd
|
||||
|
||||
# Print PASS or FAIL, and return result.
|
||||
s_retval=0
|
||||
notify_success_or_fail ${s_basename} ${s_val_basename}
|
||||
|
||||
return "${s_retval}"
|
||||
}
|
||||
|
||||
## run_scenarios (scenario_filenames):
|
||||
# Runs all scenarios matching ${scenario_filenames}.
|
||||
run_scenarios() {
|
||||
printf -- "Running tests\n"
|
||||
printf -- "-------------\n"
|
||||
scenario_filenames=$@
|
||||
for scenario in ${scenario_filenames}; do
|
||||
# We can't call this function with $( ... ) because we
|
||||
# want to allow it to echo values to stdout.
|
||||
scenario_runner ${scenario}
|
||||
retval=$?
|
||||
if [ ${retval} -gt 0 ]; then
|
||||
exit ${retval}
|
||||
fi
|
||||
done
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
#include "warnp.h"
|
||||
|
||||
static struct scrypt_test {
|
||||
const char * passwd;
|
||||
const char * salt;
|
||||
uint64_t N;
|
||||
uint32_t r;
|
||||
uint32_t p;
|
||||
} tests[4] = {
|
||||
{ "", "", 16, 1, 1 },
|
||||
{ "password", "NaCl", 1024, 8, 16 },
|
||||
{ "pleaseletmein", "SodiumChloride", 16384, 8, 1 },
|
||||
{ "pleaseletmein", "SodiumChloride", 1048576, 8, 1 }
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char * argv[])
|
||||
{
|
||||
struct scrypt_test * test;
|
||||
char kbuf[64];
|
||||
size_t i;
|
||||
|
||||
WARNP_INIT;
|
||||
|
||||
(void)argc; /* UNUSED */
|
||||
(void)argv; /* UNUSED */
|
||||
|
||||
for (test = tests;
|
||||
test < tests + sizeof(tests) / sizeof(tests[0]);
|
||||
test++) {
|
||||
crypto_scrypt((const uint8_t *)test->passwd,
|
||||
strlen(test->passwd), (const uint8_t *)test->salt,
|
||||
strlen(test->salt), test->N, test->r, test->p,
|
||||
(uint8_t *)kbuf, 64);
|
||||
printf("scrypt(\"%s\", \"%s\", %u, %u, %u, 64) =\n",
|
||||
test->passwd, test->salt, (unsigned int)test->N,
|
||||
(unsigned int)(test->r), (unsigned int)test->p);
|
||||
for (i = 0; i < 64; i++) {
|
||||
printf("%02x ", (uint8_t)kbuf[i]);
|
||||
if ((i % 16) == 15)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
scrypt("", "", 16, 1, 1, 64) =
|
||||
77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97
|
||||
f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42
|
||||
fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17
|
||||
e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06
|
||||
scrypt("password", "NaCl", 1024, 8, 16, 64) =
|
||||
fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe
|
||||
7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62
|
||||
2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da
|
||||
c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40
|
||||
scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1, 64) =
|
||||
70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb
|
||||
fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2
|
||||
d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9
|
||||
e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87
|
||||
scrypt("pleaseletmein", "SodiumChloride", 1048576, 8, 1, 64) =
|
||||
21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81
|
||||
ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47
|
||||
8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3
|
||||
37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4
|
@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Build directory (allowing flexible out-of-tree builds).
|
||||
bindir=$1
|
||||
|
||||
# Constants used in multiple scenarios.
|
||||
password="hunter2"
|
||||
|
||||
# Find script directory and load helper functions.
|
||||
scriptdir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
|
||||
. ${scriptdir}/shared_test_functions.sh
|
||||
|
||||
# We need a ${bindir}.
|
||||
if [ -z ${bindir} ]; then
|
||||
printf "Warning: Scrypt binary directory not given.\n"
|
||||
printf "Attempting to use default values for in-source-tree build.\n"
|
||||
bindir=".."
|
||||
fi
|
||||
|
||||
# Find system scrypt, and ensure it supports -P.
|
||||
system_scrypt=$( find_system scrypt enc -P )
|
||||
|
||||
# Check for optional valgrind.
|
||||
check_optional_valgrind
|
||||
|
||||
# Clean up previous directories, and create new ones.
|
||||
prepare_directories
|
||||
|
||||
# Generate valgrind suppression file if it is required. Must be
|
||||
# done after preparing directories.
|
||||
ensure_valgrind_suppression ${bindir}/tests/valgrind/potential-memleaks
|
||||
|
||||
# Run the test scenarios; this will exit on the first failure.
|
||||
run_scenarios ${scriptdir}/??-*.sh
|
Binary file not shown.
@ -1,25 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FGETS_BUFSIZE 64
|
||||
|
||||
/* Problem with FreeBSD 10.3 fgets() with stdin. */
|
||||
static void
|
||||
pl_freebsd_fgets()
|
||||
{
|
||||
char buf[FGETS_BUFSIZE];
|
||||
|
||||
if (fgets(buf, FGETS_BUFSIZE, stdin) == NULL)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
/* Test potential memory leaks. */
|
||||
pl_freebsd_fgets();
|
||||
|
||||
/* Success! */
|
||||
exit(0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user