Merge branch 'release/0.10' into develop

This commit is contained in:
Sebastian Messmer 2019-03-02 21:38:07 -08:00
commit 5596aa2a4f
135 changed files with 24073 additions and 2925 deletions

View File

@ -3,6 +3,10 @@ Version 0.10.1 (unreleased)
Fixed bugs:
* If file system migration encounters files or folders with the wrong format in the base directory, it now just ignores them instead of crashing.
* When trying to migrate a file system from CryFS 0.9.3 or older, show an error message suggesting to first open it with 0.9.10 because we can't load that anymore.
* The '--unmount-idle' parameter works again
Other:
* Updated to crypto++ 8.1
Version 0.10.0

View File

@ -52,15 +52,34 @@ namespace cpputils {
void ThreadSystem::_stopAllThreadsForRestart() {
_mutex.lock(); // Is unlocked in the after-fork handler. This way, the whole fork() is protected.
for (RunningThread &thread : _runningThreads) {
if (boost::this_thread::get_id() == thread.thread.get_id()) {
// This means fork was called from within one of our _runningThreads.
// We cannot wait or ourselves to die.
// Forking from within a thread is usually chaos since the forked process only gets a copy
// of the calling thread as its new main thread. So we (hopefully) never should do this.
// This is, however, a valid pattern when fork() is directly followed by an exec().
// So let's just ignore this situation and continue as if nothing happened, assuming an exec()
// follows soon.
continue;
}
thread.thread.interrupt();
}
for (RunningThread &thread : _runningThreads) {
if (boost::this_thread::get_id() == thread.thread.get_id()) {
// This means fork was called from within one of our _runningThreads. See comment above.
continue;
}
thread.thread.join();
}
}
void ThreadSystem::_restartAllThreads() {
for (RunningThread &thread : _runningThreads) {
if (thread.thread.joinable()) {
// Because all non-self threads have been terminated in _stopAllThreadsForRestart,
// this means fork was called from within one of our _runningThreads. See comment above.
continue;
}
thread.thread = _startThread(thread.loopIteration, thread.threadName);
}
_mutex.unlock(); // Was locked in the before-fork handler

View File

@ -252,7 +252,11 @@ namespace cryfs_cli {
ASSERT(_device != none, "File system not ready to be initialized. Was it already initialized before?");
//TODO Test auto unmounting after idle timeout
_idleUnmounter = _createIdleCallback(options.unmountAfterIdleMinutes(), [fs] {fs->stop();});
const boost::optional<double> idle_minutes = options.unmountAfterIdleMinutes();
_idleUnmounter = _createIdleCallback(idle_minutes, [fs, idle_minutes] {
LOG(INFO, "Unmounting because file system was idle for {} minutes", *idle_minutes);
fs->stop();
});
if (_idleUnmounter != none) {
(*_device)->onFsAction(std::bind(&CallAfterTimeout::resetTimer, _idleUnmounter->get()));
}

View File

@ -292,8 +292,11 @@ void Fuse::_removeAndWarnIfExists(vector<string> *fuseOptions, const std::string
}
void Fuse::_run(const bf::path &mountdir, const vector<string> &fuseOptions) {
#if defined(__GLIBC__)|| defined(__APPLE__) || defined(_MSC_VER)
// Avoid encoding errors for non-utf8 characters, see https://github.com/cryfs/cryfs/issues/247
// this is ifdef'd out for non-glibc linux, because musl doesn't handle this correctly.
bf::path::imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16<wchar_t>()));
#endif
_mountdir = mountdir;

View File

@ -1,6 +1,8 @@
#include <cpp-utils/process/subprocess.h>
#include <gtest/gtest.h>
#include <cpp-utils/lock/ConditionBarrier.h>
using cpputils::Subprocess;
using cpputils::SubprocessError;
@ -98,3 +100,25 @@ TEST(SubprocessTest, Call_error5withoutput_output) {
TEST(SubprocessTest, Call_error5withoutput_exitcode) {
EXPECT_EQ(5, Subprocess::call(exit_with_message_and_status("hello", 5)).exitcode);
}
// TODO Move this test to a test suite for ThreadSystem/LoopThread
#include <cpp-utils/thread/LoopThread.h>
TEST(SubprocessTest, CallFromThreadSystemThread) {
cpputils::ConditionBarrier barrier;
cpputils::LoopThread thread(
[&barrier] () {
auto result = Subprocess::check_call(exit_with_message_and_status("hello", 0));
EXPECT_EQ(0, result.exitcode);
EXPECT_EQ("hello", result.output);
barrier.release();
return false; // don't run loop again
},
"child_thread"
);
thread.start();
barrier.wait();
thread.stop(); // just to make sure it's stopped before the test exits. Returning false above should already stop it, but we don't know when exactly. thread.stop() will block until it's actually stopped.
}

View File

@ -53,6 +53,7 @@ TEST(ThreadDebuggingTest_ThreadName, givenChildThread_whenGettingFromOutside_the
});
nameIsSet.wait();
set_thread_name("outer_thread_name"); // just to make sure the next line doesn't read the outer thread name
string name = get_thread_name(&child);
EXPECT_EQ("my_thread_name", name);

9
vendor/README vendored
View File

@ -1,11 +1,6 @@
This directory contains external projects, taken from the following locations:
googletest: https://github.com/google/googletest/tree/release-1.8.1
spdlog: https://github.com/gabime/spdlog/tree/v0.16.3/include/spdlog
cryptopp: https://github.com/weidai11/cryptopp/tree/CRYPTOPP_8_0_0
- changed: added CMakeLists.txt and cryptopp-config.cmake from https://github.com/noloader/cryptopp-cmake/tree/CRYPTOPP_8_0_0
cryptopp: https://github.com/weidai11/cryptopp/tree/CRYPTOPP_8_1_0
- changed: added CMakeLists.txt and cryptopp-config.cmake from https://github.com/noloader/cryptopp-cmake/tree/07a064d57d97477cb055f994a498f45425df0c1d
- changed: commented out line including winapifamily.h in CMakeLists.txt
- cherry-picked commits to get OpenMP for scrypt on Windows:
- https://github.com/weidai11/cryptopp/commit/aa043b38a7930725c31a0cd7016986d1c581c573
- https://github.com/weidai11/cryptopp/commit/672f5c7f3dad8ae12b2d0ce0940ccb7c8e257bf8
- https://github.com/weidai11/cryptopp/commit/7e96a283a3192d29aac5b60e5b4ff19248f00d9a
- https://github.com/weidai11/cryptopp/commit/ca32b63038d5f7b13e2e00809cd9184a1efe8c24

View File

@ -1,54 +0,0 @@
# Appveyor's documentation is at https://www.appveyor.com/docs/build-phase/,
# and a sample configuration file is at https://www.appveyor.com/docs/appveyor-yml/.
# I have to admit its a bit complex and I don't fully understand it.
version: 1.0.{build}
clone_depth: 3
skip_tags: true
configuration:
- Debug
- Release
platform:
- Win32
- x64
image:
- Visual Studio 2017
- Visual Studio 2015
- Visual Studio 2013
environment:
matrix:
- BUILD_MODE: MSBuild
# Disable build through solution file
build: off
# Build through commands in script below
test_script:
- ps: >-
msbuild /t:Build /p:platform="$env:platform" /p:configuration="$env:configuration" cryptlib.vcxproj
msbuild /t:Build /p:platform="$env:platform" /p:configuration="$env:configuration" cryptest.vcxproj
msbuild /t:CopyCryptestToRoot cryptest.vcxproj
.\cryptest.exe v
.\cryptest.exe tv all
notifications:
- provider: Email
to:
- cryptopp-build@googlegroups.com
on_build_success: true
on_build_failure: true

View File

@ -1 +0,0 @@
*.sh eol=lf

View File

@ -1,15 +0,0 @@
### Crypto++ Issue Report
Thanks for taking the time to report an issue. Reporting issues helps us improve stability and reliability for all users, so it is a valuable contribution.
Please do not ask questions in the bug tracker. Please ask questions on the Crypto++ Users List at http://groups.google.com/forum/#!forum/cryptopp-users.
There is a wiki page with information on filing useful bug reports. If you have some time please visit http://www.cryptopp.com/wiki/Bug_Report on the wiki. The executive summary is:
* State the operating system and version (Ubutnu 17 x86_64, Windows 7 Professional x64, etc)
* State the version of the Crypto++ library (Crypto++ 5.6.5, Master, etc)
* State how you built the library (Makefile, Cmake, distro, etc)
* Show a typical command line (the output of the compiler for cryptlib.cpp)
* Show the link command (the output of the linker for libcryptopp.so or cryptest.exe)
* Show the exact error message you are receiving (copy and paste it); or
* Clearly state the undesired behavior (and state the expected behavior)

View File

@ -1,3 +1,10 @@
####################################
# C++ generic ignore
# Allows you to use test.cxx and
# avoid getting in the way of things
####################################
*.cxx
####################
## Crypto++ specific
####################

View File

@ -1,149 +0,0 @@
language: cpp
os:
- linux
- osx
dist: trusty
sudo: required
# OS X only supports one image. Use the latest.
osx_image: xcode9.1
git:
depth: 3
compiler:
- clang
- gcc
env:
global:
- BUILD_JOBS=2
- ANDROID_HOME=$HOME/android/sdk
- ANDROID_NDK=$HOME/android/sdk/ndk-bundle
- ANDROID_SDK_ROOT=$ANDROID_HOME
- ANDROID_NDK_ROOT=$ANDROID_NDK
matrix:
- BUILD_MODE="all"
- BUILD_MODE="native"
- BUILD_MODE="no-asm"
- BUILD_MODE="debug"
- BUILD_MODE="asan"
- BUILD_MODE="ubsan"
matrix:
exclude:
# Skip GCC on OS X entirely
- os: osx
compiler: gcc
# Skip UBsan due to GCC 4.8
- os: linux
compiler: gcc
env: BUILD_MODE="ubsan"
# Skip UBsan due to Clang 3.4
- os: osx
compiler: clang
env: BUILD_MODE="ubsan"
include:
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=armeabi
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=armeabi-v7a
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=armv7a-neon
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=aarch64
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=mipsel
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=mipsel64
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=x86
- os: linux
env:
- BUILD_MODE=android
- PLATFORM=x86_64
- os: osx
env:
- BUILD_MODE=ios
- PLATFORM=iPhoneOS
- os: osx
env:
- BUILD_MODE=ios
- PLATFORM=WatchOS
- os: osx
env:
- BUILD_MODE=ios
- PLATFORM=AppleTVOS
- os: osx
env:
- BUILD_MODE=ios
- PLATFORM=iPhoneSimulator
allow_failures:
- os: osx
env:
- BUILD_MODE=ios
- PLATFORM=WatchOS
before_install:
- |
if [[ "$BUILD_MODE" == "android" ]]; then
TestScripts/install-android.sh
fi
script:
- |
if [[ "$BUILD_MODE" == "ios" ]]; then
cp ./TestScripts/setenv-ios.sh .
TestScripts/cryptest-ios.sh
elif [[ "$BUILD_MODE" == "android" ]]; then
cp ./TestScripts/setenv-android.sh .
TestScripts/cryptest-android.sh
elif [[ "$BUILD_MODE" == "debug" ]]; then
CXXFLAGS="-DDEBUG -g2 -O1" make -j "$BUILD_JOBS"
./cryptest.exe v
./cryptest.exe tv all
else
make "$BUILD_MODE" -j "$BUILD_JOBS"
./cryptest.exe v
./cryptest.exe tv all
fi
# whitelist branches to avoid testing feature branches twice
branches:
only:
- master
addons:
sonarcloud: false
coverity_scan:
project:
name: "cryptopp"
build_command: "make -j 2"
notifications:
email:
recipients:
- cryptopp-build@googlegroups.com
on_success: always # default: change
on_failure: always # default: always

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@ PROJECT_NAME = Crypto++
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 8.0
PROJECT_NUMBER = 8.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@ -18,6 +18,7 @@ aria.cpp
aria_simd.cpp
aria.h
argnames.h
arm_simd.h
asn.cpp
asn.h
authenc.cpp
@ -55,6 +56,8 @@ chacha.cpp
chacha_avx.cpp
chacha_simd.cpp
chacha.h
chachapoly.cpp
chachapoly.h
cham.cpp
cham_simd.cpp
cham.h
@ -146,6 +149,7 @@ gf256.cpp
gf256.h
gf2_32.cpp
gf2_32.h
gf2n_simd.cpp
gf2n.cpp
gf2n.h
gfpcrypt.cpp
@ -182,9 +186,9 @@ kalynatab.cpp
kalyna.cpp
kalyna.h
keccak.cpp
keccak_core.cpp
keccak_simd.cpp
keccak.h
keccakc.cpp
keccakc.h
lubyrack.h
lea.cpp
lea_simd.cpp
@ -305,6 +309,8 @@ sha3.h
shacal2.cpp
shacal2_simd.cpp
shacal2.h
shake.cpp
shake.h
shark.cpp
shark.h
sharkbox.cpp
@ -473,6 +479,7 @@ TestData/x25519v0.dat
TestData/x25519v1.dat
TestData/xtrdh171.dat
TestData/xtrdh342.dat
TestVectors/aead.txt
TestVectors/aes.txt
TestVectors/all.txt
TestVectors/aria.txt
@ -483,6 +490,7 @@ TestVectors/camellia.txt
TestVectors/ccm.txt
TestVectors/chacha.txt
TestVectors/chacha_tls.txt
TestVectors/chacha20poly1305.txt
TestVectors/cham.txt
TestVectors/cmac.txt
TestVectors/dlies.txt
@ -502,8 +510,9 @@ TestVectors/keccak.txt
TestVectors/lea.txt
TestVectors/mars.txt
TestVectors/nr.txt
TestVectors/ocb.txt
TestVectors/panama.txt
TestVectors/poly1305aes.txt
TestVectors/poly1305_tls.txt
TestVectors/rabbit.txt
TestVectors/Readme.txt
TestVectors/rsa_oaep.txt
@ -528,6 +537,7 @@ TestVectors/sha3_256_fips_202.txt
TestVectors/sha3_384_fips_202.txt
TestVectors/sha3_512_fips_202.txt
TestVectors/sha3_fips_202.txt
TestVectors/shake.txt
TestVectors/shacal2.txt
TestVectors/simeck.txt
TestVectors/simon.txt
@ -542,6 +552,7 @@ TestVectors/ttmac.txt
TestVectors/vmac.txt
TestVectors/wake.txt
TestVectors/whrlpool.txt
TestVectors/xchacha.txt
TestPrograms/test_32bit.cxx
TestPrograms/test_64bit.cxx
TestPrograms/test_arm_acle.cxx

View File

@ -24,21 +24,16 @@ RANLIB ?= ranlib
CP ?= cp
MV ?= mv
RM ?= rm -f
GREP ?= grep
CHMOD ?= chmod
MKDIR ?= mkdir -p
LN ?= ln -sf
LDCONF ?= /sbin/ldconfig -n
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
# Solaris provides a non-Posix grep at /usr/bin
ifneq ($(wildcard /usr/xpg4/bin/grep),)
GREP ?= /usr/xpg4/bin/grep
else
GREP ?= grep
GREP := /usr/xpg4/bin/grep
endif
# Attempt to determine target machine, fallback to "this" machine.
@ -67,6 +62,7 @@ ifeq ($(SYSTEMX),)
endif
IS_LINUX := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "Linux")
IS_HURD := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c -E "GNU|Hurd")
IS_MINGW := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "MinGW")
IS_CYGWIN := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "Cygwin")
IS_DARWIN := $(shell echo "$(SYSTEMX)" | $(GREP) -i -c "Darwin")
@ -91,7 +87,7 @@ endif
# Enable shared object versioning for Linux and Solaris
HAS_SOLIB_VERSION ?= 0
ifneq ($(IS_LINUX)$(IS_SUN),00)
ifneq ($(IS_LINUX)$(IS_HURD)$(IS_SUN),000)
HAS_SOLIB_VERSION := 1
endif
@ -100,9 +96,9 @@ ifeq ($(wildcard adhoc.cpp),)
$(shell cp adhoc.cpp.proto adhoc.cpp)
endif
# Tell MacPorts and Homebrew GCC to use Clang integrated assembler
# Tell MacPorts and Homebrew GCC to use Clang integrated assembler (only on Intel-based Macs)
# http://github.com/weidai11/cryptopp/issues/190
ifeq ($(GCC_COMPILER)$(OSXPORT_COMPILER),11)
ifeq ($(GCC_COMPILER)$(OSXPORT_COMPILER)$(IS_PPC32)$(IS_PPC64),1100)
ifeq ($(findstring -Wa,-q,$(CXXFLAGS)),)
CXXFLAGS += -Wa,-q
endif
@ -126,6 +122,9 @@ ifeq ($(DETECT_FEATURES),1)
ifneq ($(strip $(TCXXFLAGS)),)
$(info Using testing flags: $(TCXXFLAGS))
endif
#TPROG = TestPrograms/test_cxx.cxx
#$(info Testing compile... )
#$(info $(shell $(CXX) $(TCXXFLAGS) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) 1>/dev/null))
endif
# Fixup AIX
@ -271,6 +270,7 @@ ifeq ($(DETECT_FEATURES),1)
ifeq ($(strip $(HAVE_OPT)),0)
ARIA_FLAG = $(SSSE3_FLAG)
CHAM_FLAG = $(SSSE3_FLAG)
KECCAK_FLAG = $(SSSE3_FLAG)
LEA_FLAG = $(SSSE3_FLAG)
SIMECK_FLAG = $(SSSE3_FLAG)
SIMON64_FLAG = $(SSSE3_FLAG)
@ -310,6 +310,7 @@ ifeq ($(DETECT_FEATURES),1)
HAVE_OPT = $(shell $(CXX) $(TCXXFLAGS) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) 2>&1 | tr ' ' '\n' | wc -l)
ifeq ($(strip $(HAVE_OPT)),0)
GCM_FLAG = $(SSSE3_FLAG) $(CLMUL_FLAG)
GF2N_FLAG = $(CLMUL_FLAG)
SUN_LDFLAGS += $(CLMUL_FLAG)
else
CLMUL_FLAG =
@ -392,6 +393,13 @@ ifeq ($(DETECT_FEATURES),1)
endif
endif
# Drop to SSE2 if available
ifeq ($(GCM_FLAG),)
ifneq ($(SSE2_FLAG),)
GCM_FLAG = $(SSE2_FLAG)
endif
endif
# DETECT_FEATURES
endif
@ -521,6 +529,7 @@ ifeq ($(IS_ARMV8),1)
HAVE_OPT = $(shell $(CXX) $(CXXFLAGS) $(ACLE_FLAG) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) 2>&1 | tr ' ' '\n' | wc -l)
ifeq ($(strip $(HAVE_OPT)),0)
GCM_FLAG = -march=armv8-a+crypto
GF2N_FLAG = -march=armv8-a+crypto
else
CXXFLAGS += -DCRYPTOPP_ARM_PMULL_AVAILABLE=0
endif
@ -616,6 +625,7 @@ ifeq ($(DETECT_FEATURES),1)
BLAKE2B_FLAG = $(POWER8_FLAG)
CRC_FLAG = $(POWER8_FLAG)
GCM_FLAG = $(POWER8_FLAG)
GF2N_FLAG = $(POWER8_FLAG)
AES_FLAG = $(POWER8_FLAG)
SHA_FLAG = $(POWER8_FLAG)
SHACAL2_FLAG = $(POWER8_FLAG)
@ -808,22 +818,22 @@ ifeq ($(IS_SUN)$(SUN_COMPILER),11)
endif # SunOS
# TODO: can we remove this since removing sockets?
ifneq ($(IS_MINGW),0)
LDLIBS += -lws2_32
endif
#ifneq ($(IS_MINGW),0)
# LDLIBS += -lws2_32
#endif
# TODO: can we remove this since removing sockets?
ifneq ($(IS_SUN),0)
LDLIBS += -lnsl -lsocket
endif
#ifneq ($(IS_SUN),0)
# LDLIBS += -lnsl -lsocket
#endif
ifeq ($(IS_LINUX),1)
ifneq ($(IS_LINUX)$(IS_HURD),00)
ifeq ($(findstring -fopenmp,$(CXXFLAGS)),-fopenmp)
ifeq ($(findstring -lgomp,$(LDLIBS)),)
LDLIBS += -lgomp
endif # LDLIBS
endif # OpenMP
endif # IS_LINUX
endif # IS_LINUX or IS_HURD
# Add -errtags=yes to get the name for a warning suppression
ifneq ($(SUN_COMPILER),0) # override flags for CC Sun C++ compiler
@ -1007,7 +1017,7 @@ ifeq ($(HAS_SOLIB_VERSION),1)
# Different patchlevels and minors are compatible since 6.1
SOLIB_COMPAT_SUFFIX=.$(LIB_MAJOR)
# Linux uses -Wl,-soname
ifeq ($(IS_LINUX),1)
ifneq ($(IS_LINUX)$(IS_HURD),00)
# Linux uses full version suffix for shared library
SOLIB_VERSION_SUFFIX=.$(LIB_MAJOR).$(LIB_MINOR).$(LIB_PATCH)
SOLIB_FLAGS=-Wl,-soname,libcryptopp.so$(SOLIB_COMPAT_SUFFIX)
@ -1122,9 +1132,13 @@ lcov coverage: cryptest.exe
lcov --base-directory . --directory . --zerocounters -q
./cryptest.exe v
./cryptest.exe tv all
./cryptest.exe b 0.25
lcov --base-directory . --directory . -c -o cryptest.info
lcov --remove cryptest.info "adhoc.cpp" "wait.*" "network.*" "socketft.*" "fips140.*" "*test.*" "bench*.cpp" "validat*.*" "/usr/*" -o cryptest.info
genhtml -o ./TestCoverage/ -t "cryptest.exe test coverage" --num-spaces 4 cryptest.info
lcov --remove cryptest.info "adhoc.*" -o cryptest.info
lcov --remove cryptest.info "fips140.*" -o cryptest.info
lcov --remove cryptest.info "*test.*" -o cryptest.info
lcov --remove cryptest.info "/usr/*" -o cryptest.info
genhtml -o ./TestCoverage/ -t "Crypto++ test coverage" --num-spaces 4 cryptest.info
# Travis CI and CodeCov rule
.PHONY: gcov codecov
@ -1218,11 +1232,14 @@ distclean: clean autotools-clean cmake-clean
.PHONY: install
install: cryptest.exe install-lib
@-$(MKDIR) $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) cryptest.exe $(DESTDIR)$(BINDIR)
$(CP) cryptest.exe $(DESTDIR)$(BINDIR)
$(CHMOD) 0755 $(DESTDIR)$(BINDIR)/cryptest.exe
@-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestData
@-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(INSTALL_DATA) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData
$(INSTALL_DATA) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(CP) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData
$(CHMOD) 0644 $(DESTDIR)$(DATADIR)/cryptopp/TestData/*.dat
$(CP) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(CHMOD) 0644 $(DESTDIR)$(DATADIR)/cryptopp/TestVectors/*.txt
# A recipe to install only the library, and not cryptest.exe. Also
# see https://github.com/weidai11/cryptopp/issues/653. Some users
@ -1231,19 +1248,23 @@ install: cryptest.exe install-lib
.PHONY: install-lib
install-lib:
@-$(MKDIR) $(DESTDIR)$(INCLUDEDIR)/cryptopp
$(INSTALL_DATA) *.h $(DESTDIR)$(INCLUDEDIR)/cryptopp
$(CP) *.h $(DESTDIR)$(INCLUDEDIR)/cryptopp
$(CHMOD) 0644 $(DESTDIR)$(INCLUDEDIR)/cryptopp/*.h
ifneq ($(wildcard libcryptopp.a),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libcryptopp.a $(DESTDIR)$(LIBDIR)
$(CP) libcryptopp.a $(DESTDIR)$(LIBDIR)
$(CHMOD) 0644 $(DESTDIR)$(LIBDIR)/libcryptopp.a
endif
ifneq ($(wildcard libcryptopp.dylib),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_PROGRAM) libcryptopp.dylib $(DESTDIR)$(LIBDIR)
$(CP) libcryptopp.dylib $(DESTDIR)$(LIBDIR)
$(CHMOD) 0755 $(DESTDIR)$(LIBDIR)/libcryptopp.dylib
-install_name_tool -id $(DESTDIR)$(LIBDIR)/libcryptopp.dylib $(DESTDIR)$(LIBDIR)/libcryptopp.dylib
endif
ifneq ($(wildcard libcryptopp.so$(SOLIB_VERSION_SUFFIX)),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_PROGRAM) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)
$(CP) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)
$(CHMOD) 0755 $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_VERSION_SUFFIX)
ifeq ($(HAS_SOLIB_VERSION),1)
-$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)/libcryptopp.so
$(LDCONF) $(DESTDIR)$(LIBDIR)
@ -1251,7 +1272,8 @@ endif
endif
ifneq ($(wildcard libcryptopp.pc),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)/pkgconfig
$(INSTALL_DATA) libcryptopp.pc $(DESTDIR)$(LIBDIR)/pkgconfig/libcryptopp.pc
$(CP) libcryptopp.pc $(DESTDIR)$(LIBDIR)/pkgconfig
$(CHMOD) 0644 $(DESTDIR)$(LIBDIR)/pkgconfig/libcryptopp.pc
endif
.PHONY: remove uninstall
@ -1327,7 +1349,7 @@ libcryptopp.pc:
@echo '' >> libcryptopp.pc
@echo 'Name: Crypto++' >> libcryptopp.pc
@echo 'Description: Crypto++ cryptographic library' >> libcryptopp.pc
@echo 'Version: 8.0' >> libcryptopp.pc
@echo 'Version: 8.1' >> libcryptopp.pc
@echo 'URL: https://cryptopp.com/' >> libcryptopp.pc
@echo '' >> libcryptopp.pc
@echo 'Cflags: -I$${includedir}' >> libcryptopp.pc
@ -1380,7 +1402,7 @@ ifneq ($(IS_DARWIN),0)
$(CP) cryptopp$(LIB_VER).zip $(PWD)/cryptopp$(LIB_VER)
hdiutil makehybrid -iso -joliet -o cryptopp$(LIB_VER).iso $(PWD)/cryptopp$(LIB_VER)
@-$(RM) -r $(PWD)/cryptopp$(LIB_VER)
else ifneq ($(IS_LINUX),0)
else ifneq ($(IS_LINUX)$(IS_HURD),00)
$(MKDIR) $(PWD)/cryptopp$(LIB_VER)
$(CP) cryptopp$(LIB_VER).zip $(PWD)/cryptopp$(LIB_VER)
genisoimage -q -o cryptopp$(LIB_VER).iso $(PWD)/cryptopp$(LIB_VER)
@ -1434,6 +1456,10 @@ chacha_avx.o : chacha_avx.cpp
cham_simd.o : cham_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(CHAM_FLAG) -c) $<
# SSE4.2 or ARMv8a available
crc_simd.o : crc_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(CRC_FLAG) -c) $<
# Power9 available
darn.o : darn.cpp
$(CXX) $(strip $(CXXFLAGS) $(DARN_FLAG) -c) $<
@ -1442,18 +1468,18 @@ darn.o : darn.cpp
donna_sse.o : donna_sse.cpp
$(CXX) $(strip $(CXXFLAGS) $(SSE2_FLAG) -c) $<
# SSE2 on i686
sse_simd.o : sse_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SSE2_FLAG) -c) $<
# SSE4.2 or ARMv8a available
crc_simd.o : crc_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(CRC_FLAG) -c) $<
# PCLMUL or ARMv7a/ARMv8a available
# Carryless multiply
gcm_simd.o : gcm_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(GCM_FLAG) -c) $<
# Carryless multiply
gf2n_simd.o : gf2n_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(GF2N_FLAG) -c) $<
# SSSE3 available
keccak_simd.o : keccak_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(KECCAK_FLAG) -c) $<
# SSSE3 available
lea_simd.o : lea_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(LEA_FLAG) -c) $<
@ -1525,8 +1551,16 @@ sm4_simd.o : sm4_simd.cpp
ifeq ($(XLC_COMPILER),1)
sm3.o : sm3.cpp
$(CXX) $(strip $(subst -O3,-O2,$(CXXFLAGS)) -c) $<
donna_32.o : donna_32.cpp
$(CXX) $(strip $(subst -O3,-O2,$(CXXFLAGS)) -c) $<
donna_64.o : donna_64.cpp
$(CXX) $(strip $(subst -O3,-O2,$(CXXFLAGS)) -c) $<
endif
# SSE2 on i686
sse_simd.o : sse_simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SSE2_FLAG) -c) $<
# Don't build Rijndael with UBsan. Too much noise due to unaligned data accesses.
ifneq ($(findstring -fsanitize=undefined,$(CXXFLAGS)),)
rijndael.o : rijndael.cpp

View File

@ -26,10 +26,6 @@ EGREP ?= egrep
LN ?= ln -sf
LDCONF ?= /sbin/ldconfig -n
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
IS_IOS ?= 0
IS_ANDROID ?= 0
IS_ARM_EMBEDDED ?= 0
@ -188,6 +184,9 @@ ifeq ($(DETECT_FEATURES),1)
ifneq ($(strip $(TCXXFLAGS)),)
$(info Using testing flags: $(TCXXFLAGS))
endif
#TPROG = TestPrograms/test_cxx.cxx
#$(info Testing compile... )
#$(info $(shell $(CXX) $(TCXXFLAGS) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) 1>/dev/null))
endif
# For the previous messages
@ -335,6 +334,13 @@ ifeq ($(DETECT_FEATURES),1)
endif
endif
# Drop to SSE2 if available
ifeq ($(GCM_FLAG),)
ifneq ($(SSE2_FLAG),)
GCM_FLAG = $(SSE2_FLAG)
endif
endif
# DETECT_FEATURES
endif
@ -693,34 +699,47 @@ distclean: clean autotools-clean cmake-clean
.PHONY: install
install: cryptest.exe install-lib
@-$(MKDIR) $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) cryptest.exe $(DESTDIR)$(BINDIR)
$(CP) cryptest.exe $(DESTDIR)$(BINDIR)
$(CHMOD) 0755 $(DESTDIR)$(BINDIR)/cryptest.exe
@-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestData
@-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(INSTALL_DATA) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData
$(INSTALL_DATA) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(CP) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData
$(CHMOD) 0644 $(DESTDIR)$(DATADIR)/cryptopp/TestData/*.dat
$(CP) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(CHMOD) 0644 $(DESTDIR)$(DATADIR)/cryptopp/TestVectors/*.txt
# A recipe to install only the library, and not cryptest.exe. Also
# see https://github.com/weidai11/cryptopp/issues/653.
.PHONY: install-lib
install-lib:
@-$(MKDIR) $(DESTDIR)$(INCLUDEDIR)/cryptopp
$(INSTALL_DATA) *.h $(DESTDIR)$(INCLUDEDIR)/cryptopp
$(CP) *.h $(DESTDIR)$(INCLUDEDIR)/cryptopp
$(CHMOD) 0644 $(DESTDIR)$(INCLUDEDIR)/cryptopp/*.h
ifneq ($(wildcard libcryptopp.a),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libcryptopp.a $(DESTDIR)$(LIBDIR)
$(CP) libcryptopp.a $(DESTDIR)$(LIBDIR)
$(CHMOD) 0644 $(DESTDIR)$(LIBDIR)/libcryptopp.a
endif
ifneq ($(wildcard libcryptopp.dylib),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_PROGRAM) libcryptopp.dylib $(DESTDIR)$(LIBDIR)
$(CP) libcryptopp.dylib $(DESTDIR)$(LIBDIR)
$(CHMOD) 0755 $(DESTDIR)$(LIBDIR)/libcryptopp.dylib
-install_name_tool -id $(DESTDIR)$(LIBDIR)/libcryptopp.dylib $(DESTDIR)$(LIBDIR)/libcryptopp.dylib
endif
ifneq ($(wildcard libcryptopp.so$(SOLIB_VERSION_SUFFIX)),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_PROGRAM) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)
$(CP) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)
$(CHMOD) 0755 $(DESTDIR)$(LIBDIR)/libcryptopp.so$(SOLIB_VERSION_SUFFIX)
ifeq ($(HAS_SOLIB_VERSION),1)
-$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)/libcryptopp.so
$(LDCONF) $(DESTDIR)$(LIBDIR)
endif
endif
ifneq ($(wildcard libcryptopp.pc),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR)/pkgconfig
$(CP) libcryptopp.pc $(DESTDIR)$(LIBDIR)/pkgconfig
$(CHMOD) 0644 $(DESTDIR)$(LIBDIR)/pkgconfig/libcryptopp.pc
endif
.PHONY: remove uninstall
remove uninstall:

View File

@ -435,7 +435,6 @@ last several releases.
MacPorts GCC 7.0, Clang 4.0, Intel C++ 17.00, IBM XL C/C++ 13.1
8.0.0 - December 28, 2018
- major release, recompile of programs required
- expanded community input and support
* 54 unique contributors as of this release
@ -451,4 +450,20 @@ last several releases.
- avoid Singleton<T> when possible, avoid std::call_once completely
- fix SPARC alignment problems due to GetAlignmentOf<T>() on word64
- add ARM AES asm implementation from Cryptogams
- remove CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS support
- remove CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS support
8.1.0 - February 22, 2019
- minor release, no recompile of programs required
- expanded community input and support
56 unique contributors as of this release
- fix OS X PowerPC builds with Clang
- add Microsoft ARM64 support
- fix iPhone Simulator build due to missign symbols
- add CRYPTOPP_BUGGY_SIMD_LOAD_AND_STORE
- add carryless multiplies for NIST b233 and k233 curves
- fix OpenMP build due to use of OpenMP 4 with down-level compilers
- add SignStream and VerifyStream for ed25519 and large files
- fix missing AlgorithmProvider in PanamaHash
- add SHAKE-128 and SHAKE-256
- fix AVX2 build due to _mm256_broadcastsi128_si256
- add IETF ChaCha, XChaCha, ChaChaPoly1305 and XChaChaPoly1305

View File

@ -1,4 +1,4 @@
Compilation Copyright (c) 1995-2016 by Wei Dai. All rights reserved.
Compilation Copyright (c) 1995-2019 by Wei Dai. All rights reserved.
This copyright applies only to this software distribution package
as a compilation, and does not imply a copyright on any particular
file in the package.
@ -22,6 +22,18 @@ Richard De Moliner - safer.cpp
Matthew Skala - twofish.cpp
Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp
Ronny Van Keer - sha3.cpp
Aumasson, Neves, Wilcox-O'Hearn and Winnerlein - blake2.cpp, blake2b_simd.cpp, blake2s_simd.cpp
Aaram Yun - aria.cpp, aria_simd.cpp
Han Lulu, Markku-Juhani O. Saarinen - sm4.cpp sm4_simd.cpp
Daniel J. Bernstein, Jack Lloyd - chacha.cpp, chacha_simd.cpp, chacha_avx.cpp
Andrew Moon - ed25519, x25519, donna_32.cpp, donna_64.cpp, donna_sse.cpp
The Crypto++ Library uses portions of Andy Polyakov's CRYPTOGAMS for Poly1305
scalar multiplication and aes_armv4.S. CRYPTOGAMS is dual licensed with a
permissive BSD-style license. The CRYPTOGAMS license is reproduced below.
The Crypto++ Library uses portions of Jack Lloyd's Botan for ChaCha SSE2 and
AVX. Botan placed the code in public domain for Crypto++ to use.
The Crypto++ Library (as a compilation) is currently licensed under the Boost
Software License 1.0 (http://www.boost.org/users/license.html).
@ -49,3 +61,22 @@ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
CRYPTOGAMS License
Copyright (c) 2006-2017, CRYPTOGAMS by <appro@openssl.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain copyright notices,
this list of conditions and the following disclaimer.
* 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.
* Neither the name of the CRYPTOGAMS nor the names of its copyright
holder and contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

View File

@ -6,30 +6,32 @@ Currently the library contains the following algorithms:
algorithm type name
authenticated encryption schemes GCM, CCM, EAX
authenticated encryption schemes GCM, CCM, EAX, ChaCha20Poly1305 and
XChaCha20Poly1305
high speed stream ciphers ChaCha (8/12/20), Panama, Sosemanuk, Salsa20,
XSalsa20
high speed stream ciphers ChaCha (8/12/20), ChaCha (IETF), Panama, Salsa20,
Sosemanuk, XSalsa20, XChaCha20
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
CAST-256
ARIA, IDEA, Blowfish, Triple-DES (DES-EDE2 and
DES-EDE3), Camellia, SEED, Kalyna (128/256/512),
other block ciphers RC5, SIMON-64, SIMON-128, SPECK-64, SPECK-128,
Skipjack, SHACAL-2, SM4, Threefish (256/512/1024),
TEA, XTEA
ARIA, Blowfish, Camellia, CHAM, HIGHT, IDEA,
Kalyna (128/256/512), LEA, SEED, RC5, SHACAL-2,
other block ciphers SIMON (64/128), Skipjack, SPECK (64/128),
Simeck, SM4, Threefish (256/512/1024),
Triple-DES (DES-EDE2 and DES-EDE3), TEA, XTEA
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
CFB, OFB, counter mode (CTR)
message authentication codes BLAKE2s, BLAKE2b, CMAC, CBC-MAC, DMAC, GMAC, HMAC,
Poly1305, SipHash, Two-Track-MAC, VMAC,
Poly1305, Poly1305 (IETF), SipHash, Two-Track-MAC,
VMAC
BLAKE2s, BLAKE2b, Keccack (F1600), SHA-1,
hash functions SHA-2 (224/256/384/512), SHA-3 (224/256/384/512),
SipHash, SM3, Tiger, RIPEMD-128, RIPEMD-160,
RIPEMD-256, RIPEMD-320, WHIRLPOOL
SHAKE (128/256), SipHash, SM3, Tiger,
RIPEMD (128/160/256/320), WHIRLPOOL
RSA, DSA, Determinsitic DSA, ElGamal,
public-key cryptography Nyberg-Rueppel (NR), Rabin-Williams (RW), LUC,
@ -69,8 +71,6 @@ Other features include:
+ 32-bit CRC, CRC-C and Adler32 checksum
* class wrappers for these platform and operating system features (optional):
+ high resolution timers on Windows, Unix, and Mac OS
+ Berkeley and Windows style sockets
+ Windows named pipes
+ /dev/random, /dev/urandom, /dev/srandom
+ Microsoft's CryptGenRandom or BCryptGenRandom on Windows
* A high level interface for most of the above, using a filter/pipeline
@ -206,16 +206,23 @@ library in your programs to help avoid unwanted redirections.
*** Side Channel Attacks ***
Crypto++ attempts to resist side channel attacks using various remediations. We
believe the library is hardened but the remdiations may be incomplete. The first
line of defense uses hardware instructions when possible. The library also uses
cache-aware algoirthms and access patterns to minimize leakage. If you suspect
or find an information leak then please report it.
believe the library is mostly hardened but the remdiations may be incomplete. The
first line of defense uses hardware instructions when possible for block ciphers,
hashes and other primitives. Hardware acceleration remediates many timing attacks.
The library also uses cache-aware algoirthms and access patterns to minimize leakage.
Some of the public key algorithms have branches and some of the branches depend on
data that can be private or secret. The branching occurs in some field operations
like exponentiation over integers and elliptic curves. The branching has been
minimized but not completely eliminated.
Crypto++ does not enagage Specter remediations at this time. The GCC options for
Specter are -mfunction-return=thunk and -mindirect-branch=thunk, and the library
uses them during testing. If you want the Specter workarounds then add the GCC
options to your CXXFLAGS when building the library.
If you suspect or find an information leak then please report it.
*** Documentation and Support ***
Crypto++ is documented through inline comments in header files, which are

View File

@ -141,13 +141,13 @@ if ! "$MAKE" -j2 -f Makefile; then
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi
if ! ./cryptestcwd v; then
echo "cryptestcwd v failed."
if ! ./cryptest v; then
echo "cryptest v failed."
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi
if ! ./cryptestcwd tv all; then
echo "cryptestcwd tv all failed."
if ! ./cryptest tv all; then
echo "cryptest tv all failed."
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi

View File

@ -1,10 +1,11 @@
#!/usr/bin/env bash
# cryptest.sh - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
# Copyright assigned to Crypto++ project.
# cryptest.sh - written and placed in public domain by Jeffrey Walton and Uri
# Blumenthal.
# This is a test script that can be used on some Linux/Unix/Apple machines to automate testing
# of the shared object to ensure linking and symbols don't go missing from release to release.
# This is a test script that can be used on some Linux/Unix/Apple machines to
# automate testing of the shared object to ensure linking and symbols don't go
# missing from release to release.
# Fixup ancient Bash
# https://unix.stackexchange.com/q/468579/56041
@ -12,10 +13,20 @@ if [[ -z "$BASH_SOURCE" ]]; then
BASH_SOURCE="$0"
fi
############################################
# Cleanup
PWD_DIR=$(pwd)
function cleanup {
rm -f adhoc.cpp *.a *.o *.so *.dylib GNUmakefile-symbols
cd "$PWD_DIR"
}
trap cleanup EXIT
############################################
# Tags to test
OLD_VERSION_TAG=CRYPTOPP_7_0_0
OLD_VERSION_TAG=CRYPTOPP_8_0_0
NEW_VERSION_TAG=master
############################################

View File

@ -108,6 +108,7 @@ fi
THIS_SYSTEM=$(uname -s 2>&1)
IS_AIX=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c aix)
IS_DARWIN=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c darwin)
IS_HURD=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c gnu)
IS_LINUX=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c linux)
IS_CYGWIN=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c cygwin)
IS_MINGW=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c mingw)
@ -155,6 +156,8 @@ if [[ ("$IS_X86" -ne "0" || "$IS_X64" -ne "0") ]]; then
X86_CPU_FLAGS=$(grep Features /var/run/dmesg.boot)
elif [[ ("$IS_DRAGONFLY" -ne "0") ]]; then
X86_CPU_FLAGS=$(dmesg | grep Features)
elif [[ ("$IS_HURD" -ne "0") ]]; then
: # Do nothing... cpuid is not helpful at the moment
else
X86_CPU_FLAGS="$($AWK '{IGNORECASE=1}{if ($1 == "flags"){print;exit}}' < /proc/cpuinfo | cut -f 2 -d ':')"
fi

View File

@ -63,26 +63,31 @@ do
# ARMv5
if [ "$CL" == "armv5" ]; then
BACK_ARCH=armv5
APPLE_SDK=iPhoneOS
fi
# ARMv6
if [ "$CL" == "armv6" ]; then
BACK_ARCH=armv6
APPLE_SDK=iPhoneOS
fi
# ARMv7
if [ "$CL" == "armv7" ]; then
BACK_ARCH=armv7
APPLE_SDK=iPhoneOS
fi
# ARMv7s
if [ "$CL" == "armv7s" ]; then
BACK_ARCH=armv7s
APPLE_SDK=iPhoneOS
fi
# ARM64
if [[ ("$CL" == "arm64" || "$CL" == "armv8" || "$CL" == "aarch64") ]]; then
BACK_ARCH=arm64
APPLE_SDK=iPhoneOS
fi
# iPhone
@ -201,7 +206,7 @@ fi
# Simulator fixup. LD fails to link dylib.
if [ "$APPLE_SDK" == "iPhoneSimulator" ] && [ "$IOS_ARCH" == "i386" ]; then
IOS_FLAGS="$IOS_FLAGS -miphoneos-version-min=5 -DCRYPTOPP_DISABLE_ASM"
IOS_FLAGS="$IOS_FLAGS -miphoneos-version-min=5"
fi
# ARMv7s fixup. Xcode 4/iOS 6
@ -219,12 +224,6 @@ if [ "$APPLE_SDK" == "AppleTVOS" ]; then
IOS_FLAGS=""
fi
# ARM64 Simulator fixup. Under Xcode 6/iOS 8, it uses x86_64 and not i386
# -ios_simulator_version_min does not work though it is in LLVM sources.
if [ "$IOS_ARCH" == "x86_64" ]; then
IOS_FLAGS="$IOS_FLAGS -DCRYPTOPP_DISABLE_ASM"
fi
# Disable ASM for simulator. We are failing on Travis due to missing _start.
# We may need to link against crt1.o for simulator builds. Also see
# https://stackoverflow.com/q/24841283/608639

View File

@ -0,0 +1,6 @@
AlgorithmType: FileList
Name: aead.txt collection
Test: TestVectors/ccm.txt
Test: TestVectors/eax.txt
Test: TestVectors/gcm.txt
Test: TestVectors/chacha20poly1305.txt

View File

@ -1,55 +1,61 @@
AlgorithmType: FileList
Name: all.txt collection
Test: TestVectors/tea.txt
Test: TestVectors/wake.txt
Test: TestVectors/aes.txt
Test: TestVectors/aria.txt
Test: TestVectors/blake2b.txt
Test: TestVectors/blake2s.txt
Test: TestVectors/camellia.txt
Test: TestVectors/shacal2.txt
Test: TestVectors/ttmac.txt
Test: TestVectors/whrlpool.txt
Test: TestVectors/ccm.txt
Test: TestVectors/chacha_tls.txt
Test: TestVectors/chacha20poly1305.txt
Test: TestVectors/chacha.txt
Test: TestVectors/xchacha.txt
Test: TestVectors/cham.txt
Test: TestVectors/cmac.txt
Test: TestVectors/dlies.txt
Test: TestVectors/dsa.txt
Test: TestVectors/dsa_1363.txt
Test: TestVectors/dsa_rfc6979.txt
Test: TestVectors/dsa.txt
Test: TestVectors/eax.txt
Test: TestVectors/esign.txt
Test: TestVectors/gcm.txt
Test: TestVectors/hc128.txt
Test: TestVectors/hc256.txt
Test: TestVectors/hight.txt
Test: TestVectors/hkdf.txt
Test: TestVectors/hmac.txt
Test: TestVectors/kalyna.txt
Test: TestVectors/keccak.txt
Test: TestVectors/lea.txt
Test: TestVectors/mars.txt
Test: TestVectors/nr.txt
Test: TestVectors/panama.txt
Test: TestVectors/poly1305aes.txt
Test: TestVectors/poly1305_tls.txt
Test: TestVectors/rabbit.txt
Test: TestVectors/rsa_oaep.txt
Test: TestVectors/rsa_pkcs1_1_5.txt
Test: TestVectors/rsa_pss.txt
Test: TestVectors/rw.txt
Test: TestVectors/salsa.txt
Test: TestVectors/seal.txt
Test: TestVectors/sha.txt
Test: TestVectors/keccak.txt
Test: TestVectors/seed.txt
Test: TestVectors/sha1_fips_180.txt
Test: TestVectors/sha2_fips_180.txt
Test: TestVectors/sha3_fips_202.txt
Test: TestVectors/panama.txt
Test: TestVectors/sm3.txt
Test: TestVectors/aes.txt
Test: TestVectors/aria.txt
Test: TestVectors/kalyna.txt
Test: TestVectors/threefish.txt
Test: TestVectors/sm4.txt
Test: TestVectors/hight.txt
Test: TestVectors/cham.txt
Test: TestVectors/lea.txt
Test: TestVectors/shake.txt
Test: TestVectors/shacal2.txt
Test: TestVectors/sha.txt
Test: TestVectors/simeck.txt
Test: TestVectors/simon.txt
Test: TestVectors/speck.txt
Test: TestVectors/salsa.txt
Test: TestVectors/chacha.txt
#Test: TestVectors/tls_chacha.txt
Test: TestVectors/sosemanuk.txt
Test: TestVectors/rabbit.txt
Test: TestVectors/hc128.txt
Test: TestVectors/hc256.txt
Test: TestVectors/vmac.txt
Test: TestVectors/ccm.txt
Test: TestVectors/gcm.txt
Test: TestVectors/cmac.txt
Test: TestVectors/eax.txt
Test: TestVectors/mars.txt
Test: TestVectors/blake2s.txt
Test: TestVectors/blake2b.txt
Test: TestVectors/siphash.txt
Test: TestVectors/hkdf.txt
Test: TestVectors/sm3.txt
Test: TestVectors/sm4.txt
Test: TestVectors/sosemanuk.txt
Test: TestVectors/speck.txt
Test: TestVectors/tea.txt
Test: TestVectors/threefish.txt
Test: TestVectors/ttmac.txt
Test: TestVectors/vmac.txt
Test: TestVectors/wake.txt
Test: TestVectors/whrlpool.txt

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,337 @@
AlgorithmType: SymmetricCipher
Name: ChaCha20
Name: ChaChaTLS
Source: http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305
Comment: Section 7, Test 1
Key: 0000000000000000000000000000000000000000000000000000000000000000
IV: 0000000000000000
Plaintext:
Ciphertext: 76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669
#
Comment: Section A.1, ChaCha20 Block Function, Test 1
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r64 00
Ciphertext: 76 b8 e0 ad a0 f1 3d 90 40 5d 6a e5 53 86 bd 28 \
bd d2 19 b8 a0 8d ed 1a a8 36 ef cc 8b 77 0d c7 \
da 41 59 7c 51 57 48 8d 77 24 e0 3f b8 d8 4a 37 \
6a 43 b8 f4 15 18 a1 1c c3 87 b6 69 b2 ee 65 86
Test: Encrypt
Comment: Section 7, Test 2
Key: 0000000000000000000000000000000000000000000000000000000000000001
IV: 0000000000000000
Plaintext:
Ciphertext: 4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275
#
Comment: Section A.1, ChaCha20 Block Function, Test 2
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r64 00
Ciphertext: 9f 07 e7 be 55 51 38 7a 98 ba 97 7c 73 2d 08 0d \
cb 0f 29 a0 48 e3 65 69 12 c6 53 3e 32 ee 7a ed \
29 b7 21 76 9c e6 4e 43 d5 71 33 b0 74 d8 39 d5 \
31 ed 1f 28 51 0a fb 45 ac e1 0a 1f 4b 79 4d 6f
InitialBlock: 1
Test: Encrypt
Comment: Section 7, Test 3
Key: 0000000000000000000000000000000000000000000000000000000000000000
IV: 0000000000000001
Plaintext:
Ciphertext: de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3
#
Comment: Section A.1, ChaCha20 Block Function, Test 3
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r64 00
Ciphertext: 3a eb 52 24 ec f8 49 92 9b 9d 82 8d b1 ce d4 dd \
83 20 25 e8 01 8b 81 60 b8 22 84 f3 c9 49 aa 5a \
8e ca 00 bb b4 a7 3b da d1 92 b5 c4 2f 73 f2 fd \
4e 27 36 44 c8 b3 61 25 a6 4a dd eb 00 6c 13 a0
InitialBlock: 1
Test: Encrypt
Comment: Section 7, Test 4
Key: 0000000000000000000000000000000000000000000000000000000000000000
IV: 0100000000000000
Plaintext:
Ciphertext: ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb004
#
Comment: Section A.1, ChaCha20 Block Function, Test 4
Key: 00ff000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r64 00
Ciphertext: 72 d5 4d fb f1 2e c4 4b 36 26 92 df 94 13 7f 32 \
8f ea 8d a7 39 90 26 5e c1 bb be a1 ae 9a f0 ca \
13 b2 5a a2 6c b4 a6 48 cb 9b 9d 1b e6 5b 2c 09 \
24 a6 6c 54 d5 45 ec 1b 73 74 f4 87 2e 99 f0 96
InitialBlock: 2
Test: Encrypt
Comment: Section 7, Test 5
Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
IV: 0001020304050607
Plaintext:
Ciphertext: f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1 \
5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e \
09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5 \
07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2 \
ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb
#
Comment: Section A.1, ChaCha20 Block Function, Test 5
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 02
Plaintext: r64 00
Ciphertext: c2 c6 4d 37 8c d5 36 37 4a e2 04 b9 ef 93 3f cd \
1a 8b 22 88 b3 df a4 96 72 ab 76 5b 54 ee 27 c7 \
8a 97 0e 0e 95 5c 14 f3 a8 8e 74 1b 97 c2 86 f7 \
5f 8f c2 99 e8 14 83 62 fa 19 8a 39 53 1b ed 6d
Test: Encrypt
#
Comment: Section A.2, ChaCha20 Encryption, Test 1
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Ciphertext: 76 b8 e0 ad a0 f1 3d 90 40 5d 6a e5 53 86 bd 28 \
bd d2 19 b8 a0 8d ed 1a a8 36 ef cc 8b 77 0d c7 \
da 41 59 7c 51 57 48 8d 77 24 e0 3f b8 d8 4a 37 \
6a 43 b8 f4 15 18 a1 1c c3 87 b6 69 b2 ee 65 86
Test: Encrypt
#
Comment: Section A.2, ChaCha20 Encryption, Test 2
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
IV: 00 00 00 00 00 00 00 00 00 00 00 02
Plaintext: 41 6e 79 20 73 75 62 6d 69 73 73 69 6f 6e 20 74 \
6f 20 74 68 65 20 49 45 54 46 20 69 6e 74 65 6e \
64 65 64 20 62 79 20 74 68 65 20 43 6f 6e 74 72 \
69 62 75 74 6f 72 20 66 6f 72 20 70 75 62 6c 69 \
63 61 74 69 6f 6e 20 61 73 20 61 6c 6c 20 6f 72 \
20 70 61 72 74 20 6f 66 20 61 6e 20 49 45 54 46 \
20 49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 20 \
6f 72 20 52 46 43 20 61 6e 64 20 61 6e 79 20 73 \
74 61 74 65 6d 65 6e 74 20 6d 61 64 65 20 77 69 \
74 68 69 6e 20 74 68 65 20 63 6f 6e 74 65 78 74 \
20 6f 66 20 61 6e 20 49 45 54 46 20 61 63 74 69 \
76 69 74 79 20 69 73 20 63 6f 6e 73 69 64 65 72 \
65 64 20 61 6e 20 22 49 45 54 46 20 43 6f 6e 74 \
72 69 62 75 74 69 6f 6e 22 2e 20 53 75 63 68 20 \
73 74 61 74 65 6d 65 6e 74 73 20 69 6e 63 6c 75 \
64 65 20 6f 72 61 6c 20 73 74 61 74 65 6d 65 6e \
74 73 20 69 6e 20 49 45 54 46 20 73 65 73 73 69 \
6f 6e 73 2c 20 61 73 20 77 65 6c 6c 20 61 73 20 \
77 72 69 74 74 65 6e 20 61 6e 64 20 65 6c 65 63 \
74 72 6f 6e 69 63 20 63 6f 6d 6d 75 6e 69 63 61 \
74 69 6f 6e 73 20 6d 61 64 65 20 61 74 20 61 6e \
79 20 74 69 6d 65 20 6f 72 20 70 6c 61 63 65 2c \
20 77 68 69 63 68 20 61 72 65 20 61 64 64 72 65 \
73 73 65 64 20 74 6f
Ciphertext: a3 fb f0 7d f3 fa 2f de 4f 37 6c a2 3e 82 73 70 \
41 60 5d 9f 4f 4f 57 bd 8c ff 2c 1d 4b 79 55 ec \
2a 97 94 8b d3 72 29 15 c8 f3 d3 37 f7 d3 70 05 \
0e 9e 96 d6 47 b7 c3 9f 56 e0 31 ca 5e b6 25 0d \
40 42 e0 27 85 ec ec fa 4b 4b b5 e8 ea d0 44 0e \
20 b6 e8 db 09 d8 81 a7 c6 13 2f 42 0e 52 79 50 \
42 bd fa 77 73 d8 a9 05 14 47 b3 29 1c e1 41 1c \
68 04 65 55 2a a6 c4 05 b7 76 4d 5e 87 be a8 5a \
d0 0f 84 49 ed 8f 72 d0 d6 62 ab 05 26 91 ca 66 \
42 4b c8 6d 2d f8 0e a4 1f 43 ab f9 37 d3 25 9d \
c4 b2 d0 df b4 8a 6c 91 39 dd d7 f7 69 66 e9 28 \
e6 35 55 3b a7 6c 5c 87 9d 7b 35 d4 9e b2 e6 2b \
08 71 cd ac 63 89 39 e2 5e 8a 1e 0e f9 d5 28 0f \
a8 ca 32 8b 35 1c 3c 76 59 89 cb cf 3d aa 8b 6c \
cc 3a af 9f 39 79 c9 2b 37 20 fc 88 dc 95 ed 84 \
a1 be 05 9c 64 99 b9 fd a2 36 e7 e8 18 b0 4b 0b \
c3 9c 1e 87 6b 19 3b fe 55 69 75 3f 88 12 8c c0 \
8a aa 9b 63 d1 a1 6f 80 ef 25 54 d7 18 9c 41 1f \
58 69 ca 52 c5 b8 3f a3 6f f2 16 b9 c1 d3 00 62 \
be bc fd 2d c5 bc e0 91 19 34 fd a7 9a 86 f6 e6 \
98 ce d7 59 c3 ff 9b 64 77 33 8f 3d a4 f9 cd 85 \
14 ea 99 82 cc af b3 41 b2 38 4d d9 02 f3 d1 ab \
7a c6 1d d2 9c 6f 21 ba 5b 86 2f 37 30 e3 7c fd \
c4 fd 80 6c 22 f2 21
InitialBlock: 1
Test: Encrypt
#
Comment: Section A.2, ChaCha20 Encryption, Test 3
Key: 1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0 \
47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0
IV: 00 00 00 00 00 00 00 00 00 00 00 02
Plaintext: 27 54 77 61 73 20 62 72 69 6c 6c 69 67 2c 20 61 \
6e 64 20 74 68 65 20 73 6c 69 74 68 79 20 74 6f \
76 65 73 0a 44 69 64 20 67 79 72 65 20 61 6e 64 \
20 67 69 6d 62 6c 65 20 69 6e 20 74 68 65 20 77 \
61 62 65 3a 0a 41 6c 6c 20 6d 69 6d 73 79 20 77 \
65 72 65 20 74 68 65 20 62 6f 72 6f 67 6f 76 65 \
73 2c 0a 41 6e 64 20 74 68 65 20 6d 6f 6d 65 20 \
72 61 74 68 73 20 6f 75 74 67 72 61 62 65 2e
Ciphertext: 62 e6 34 7f 95 ed 87 a4 5f fa e7 42 6f 27 a1 df \
5f b6 91 10 04 4c 0d 73 11 8e ff a9 5b 01 e5 cf \
16 6d 3d f2 d7 21 ca f9 b2 1e 5f b1 4c 61 68 71 \
fd 84 c5 4f 9d 65 b2 83 19 6c 7f e4 f6 05 53 eb \
f3 9c 64 02 c4 22 34 e3 2a 35 6b 3e 76 43 12 a6 \
1a 55 32 05 57 16 ea d6 96 25 68 f8 7d 3f 3f 77 \
04 c6 a8 d1 bc d1 bf 4d 50 d6 15 4b 6d a7 31 b1 \
87 b5 8d fd 72 8a fa 36 75 7a 79 7a c1 88 d1
InitialBlock: 42
Test: Encrypt
#
Source: Modified Bernstein ref impl using chacha-ref.c ver 20080118
Comment: All 0 key, all 0 iv, 0 counter block, 1024 bytes
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r1024 00
Ciphertext: \
76B8E0ADA0F13D90405D6AE55386BD28BDD219B8A08DED1AA836EFCC8B770DC7 \
DA41597C5157488D7724E03FB8D84A376A43B8F41518A11CC387B669B2EE6586 \
9F07E7BE5551387A98BA977C732D080DCB0F29A048E3656912C6533E32EE7AED \
29B721769CE64E43D57133B074D839D531ED1F28510AFB45ACE10A1F4B794D6F \
2D09A0E663266CE1AE7ED1081968A0758E718E997BD362C6B0C34634A9A0B35D \
012737681F7B5D0F281E3AFDE458BC1E73D2D313C9CF94C05FF3716240A248F2 \
1320A058D7B3566BD520DAAA3ED2BF0AC5B8B120FB852773C3639734B45C91A4 \
2DD4CB83F8840D2EEDB158131062AC3F1F2CF8FF6DCD1856E86A1E6C3167167E \
E5A688742B47C5ADFB59D4DF76FD1DB1E51EE03B1CA9F82ACA173EDB8B729347 \
4EBE980F904D10C916442B4783A0E984860CB6C957B39C38ED8F51CFFAA68A4D \
E01025A39C504546B9DC1406A7EB28151E5150D7B204BAA719D4F091021217DB \
5CF1B5C84C4FA71A879610A1A695AC527C5B56774A6B8A21AAE88685868E094C \
F29EF4090AF7A90CC07E8817AA528763797D3C332B67CA4BC110642C2151EC47 \
EE84CB8C42D85F10E2A8CB18C3B7335F26E8C39A12B1BCC1707177B76138732E \
EDAAB74DA1410FC055EA068C99E9260ACBE337CF5D3E00E5B3230FFEDB0B9907 \
87D0C70E0BFE4198EA6758DD5A61FB5FEC2DF981F31BEFE153F81D17161784DB \
1C8822D53CD1EE7DB532364828BDF404B040A8DCC522F3D3D99AEC4B8057EDB8 \
500931A2C42D2F0C570847100B5754DAFC5FBDB894BBEF1A2DE1A07F8BA0C4B9 \
19301066EDBC056B7B481E7A0C46297BBB589D9DA5B675A6723E152E5E63A4CE \
034E9E83E58A013AF0E7352FB7908514E3B3D1040D0BB963B3954B636B5FD4BF \
6D0AADBAF8157D062ACB2418C176A475511B35C3F6218A5668EA5BC6F54B8782 \
F8B340F00AC1BEBA5E62CD632A7CE7809C725608ACA5EFBF7C41F237643F06C0 \
997207171DE867F9D697BF5EA6011ABCCE6C8CDB211394D2C02DD0FB60DB5A2C \
17AC3DC85878A90BED3809DBB96EAA5426FC8EAE0D2D65C42A479F088648BE2D \
C801D82A366FDDC0EF234263C0B6417D5F9DA41817B88D68E5E67195C5C1EE30 \
95E821F22524B20BE41CEB590412E41DC648843FA9BFEC7A3DCF61AB05415733 \
16D3FA8151629303FE9741562ED065DB4EBC0050EF558364AE81124A28F5C013 \
13232FBC496DFD8A2568657B686D7214382A1A00903017DDA969878442BA5AFF \
F6613F553CBB233CE46D9AEE93A7876CF5E9E82912B18CADF0B34327B2E0427E \
CF66B7CEB7C0918DC47BDFF12A062ADF07133009CE7A5E5C917E0168306109B7 \
CB49653A6D2CAEF005DE783A9A9BFE05381ED1348D94EC65886F9C0B619C52C5 \
533800B16C836172B95182DBC5EEC042B89E22F11A085B739A3611CD8D836018
Test: Encrypt
#
Comment: Random key, random iv, 0 counter block, 1024 bytes
Key: 2923BE84E16CD6AE 529049F1F1BBE9EB B3A6DB3C870C3E99 245E0D1C06B747DE
IV: B3 12 4D C8 43 BB 8B A6 1F 03 5A 7D
Plaintext: r1024 00
Ciphertext: \
C60E2330687F93D615A03CA1AD4FB4A64F2E0380A65F1277ADE647360F531A6D \
7D39AC85F9064B49529B796F8220D44B2573449C0CAB7AD7704BA9E1F370A52B \
45561EC56EB1AC85FEDCB4EE72957AA3445E6449373EA3CF82E2F5D2EA63889B \
7349441FFF021C19458CB815AC334DB6159180CE3E743E67896F74F4DA12B3A6 \
2FB45A2069151A1C0DAE260302905EF520F1838CBE8859400F0B4723F47518D4 \
7EA9A557D00788B5796EFC9C4BC0F14484C64C27348BAC9621A18EF805F771A9 \
BDE4B0288B0F6B06562A3D5B7A9655DA8A89C391F28B5C4B0FBE498B92DD8B30 \
2F5B43B58C93C7C5161CAE0413D36E868E2C81D7204AEA96649A67B6439D04C2 \
93A97046DEF4D31F49D32BAFBF814808A2E83EF0B212D7287D6AC6714A4A74F1 \
A2BC057BFBC3023986FAE970A306E214B9400416B876A8F689BE3B9E36FD7AEB \
49BA3E8DC1F24900AB41605921CFBBEE005CF5D577849183CB7F6742A908A7AE \
1D2077353A42B86659A3676131A497B652BFAED4088BCE32E9B42D7A3BCAFD46 \
63E252539D4853D2C482FED427F49CC9683C48B0158A7CA47490D5EAD0447527 \
9AD0B47788F65A9E09A38681AC6B65E22A901155B9C66307C8E6854D6F041E5B \
348A0D6F20A3C2DCB53E8444C280455EBBF9F34D34B18ABEAAC748093A310289 \
0234453454C662718C67379D3D0D1C68EB42009EDC67CF6B3E6DEEAAAD969F53 \
B0906F8B63351081F02F7BA65370A6E6A71E0EF82E38A910F9B875523376E66D \
EC1107FA4CC4F66175A8A32F1D0D7FF5FC5241165BEA75B4F73ADB6F5FC0B49A \
E287B04D67D351E87BA176EAC1E9C1BC0B67FC6C13C35F14BA08466002CC8BB6 \
A064BBB5A6F1B193AEE1F7458C6954C24DBED0969193D61953AE2B4909A738F7 \
B0CD0A330EB89323C22AF554A794CFE24B590C079077812B4DFD14CEF87536B8 \
844C810DAEDC25CC71338935FB92E260BDB46138666B90536D6CDC500A02EA7A \
AE3DEF84933BBA3960C1DA76C70AED10CE65C2F4EB91D82CAE36E33B75AE2D88 \
0F73CAD4D4C2C2A76523D10FCC60B15CF0793928B43FF7DDD1B3E8F34C2174EF \
2666BC91107223CF44D2F61AF44BBE918CCBF5998C315510B14B643996793CE0 \
EF642967134BC88CC793F735A21F5A01345CE10ABA43DECD4E6AD41A105A3B0E \
E38E217950A1AA6BEE330075B18331DC5A6DA5D731336F0F2543E1F2396DF25C \
BF92399907A7325352AB7CEF98D0582EEE3E8130515D214FA0BF37B31AF5D74D \
889ADB8D9DA438D1D5ADD7F70A3EDB089501189EA4F61BFFF406E7C961113827 \
986B0483E7A8E6F3F81DC31CB2C7C48B92160D3452D717A759D5DDF71671529F \
B187A0CCE7F5B9EAE3A851B13CAFFD19502D22CBB1073A4E68CB2EB5319D0E02 \
F1B418A34AA18F15DE0B9667D7925B4651F8E73D4191B2C868915344BDBD18E5
Test: Encrypt
#
Comment: All 0 key, all 0 iv, 0xfffffffe counter block, 256 bytes
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r256 00
Ciphertext: \
032CC123482C31711F94C941AF5AB1F4155784332ED5348FE79AEC5EAD4C06C3 \
F13C280D8CC49925E4A6A5922EC80E13A4CDFA840C70A1427A3CB699166991A5 \
ACE4CD09E294D1912D4AD205D06F95D9C2F2BFCF453E8753F128765B62215F4D \
92C74F2F626C6A640C0B1284D839EC81F1696281DAFC3E684593937023B58B1D \
76B8E0ADA0F13D90405D6AE55386BD28BDD219B8A08DED1AA836EFCC8B770DC7 \
DA41597C5157488D7724E03FB8D84A376A43B8F41518A11CC387B669B2EE6586 \
9F07E7BE5551387A98BA977C732D080DCB0F29A048E3656912C6533E32EE7AED \
29B721769CE64E43D57133B074D839D531ED1F28510AFB45ACE10A1F4B794D6F
InitialBlock: 0xfffffffe
Test: Encrypt
#
Comment: Random key, random iv, 0xfffffffe counter block, 256 bytes
Key: 26C680F84915A586 E2C569044F083FE2 D26B93B242B8152F 001B547F2D838EB5
IV: 41 F5 01 94 29 2E C7 32 BF 61 90 F6
Plaintext: r256 00
Ciphertext: \
0DF0FE21D4FF132A29220F340103B6726820A36CC41D705B062F3F1A3896938A \
38478CFE0B19C58D590D5B63226A0A6474D43EBC4179BBD1549022C2A8B8ED01 \
01BC1028D34C84AC523D1CE9A831A5B9F07F182DB65F1034FD5C3E13652C75F8 \
E586719766250643E494CE5FD72AD2C9875812D79949B2719B6FD05C78068CE9 \
38203067821A13D2EEA66AC3972D3F86F10584B03F3EC51E9E1767AAFDE7AAA1 \
37762D8972070B6F74DDE1F91B3E8A334B6A12B21BBDA74FC6D69B645A3F0ADF \
3251856773A27556B06F9DEB8E6B99680258F8EE70C062880794FAAB992DD7E4 \
8655FC852FF891DF70788C9AF948A86D33837F1C847CB70121929076904C261E
InitialBlock: 0xfffffffe
Test: Encrypt
#
Comment: All 0 key, all 0 iv, 0xfffffffe counter block, 1024 bytes
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IV: 00 00 00 00 00 00 00 00 00 00 00 00
Plaintext: r1024 00
Ciphertext: \
032CC123482C31711F94C941AF5AB1F4155784332ED5348FE79AEC5EAD4C06C3 \
F13C280D8CC49925E4A6A5922EC80E13A4CDFA840C70A1427A3CB699166991A5 \
ACE4CD09E294D1912D4AD205D06F95D9C2F2BFCF453E8753F128765B62215F4D \
92C74F2F626C6A640C0B1284D839EC81F1696281DAFC3E684593937023B58B1D \
76B8E0ADA0F13D90405D6AE55386BD28BDD219B8A08DED1AA836EFCC8B770DC7 \
DA41597C5157488D7724E03FB8D84A376A43B8F41518A11CC387B669B2EE6586 \
9F07E7BE5551387A98BA977C732D080DCB0F29A048E3656912C6533E32EE7AED \
29B721769CE64E43D57133B074D839D531ED1F28510AFB45ACE10A1F4B794D6F \
2D09A0E663266CE1AE7ED1081968A0758E718E997BD362C6B0C34634A9A0B35D \
012737681F7B5D0F281E3AFDE458BC1E73D2D313C9CF94C05FF3716240A248F2 \
1320A058D7B3566BD520DAAA3ED2BF0AC5B8B120FB852773C3639734B45C91A4 \
2DD4CB83F8840D2EEDB158131062AC3F1F2CF8FF6DCD1856E86A1E6C3167167E \
E5A688742B47C5ADFB59D4DF76FD1DB1E51EE03B1CA9F82ACA173EDB8B729347 \
4EBE980F904D10C916442B4783A0E984860CB6C957B39C38ED8F51CFFAA68A4D \
E01025A39C504546B9DC1406A7EB28151E5150D7B204BAA719D4F091021217DB \
5CF1B5C84C4FA71A879610A1A695AC527C5B56774A6B8A21AAE88685868E094C \
F29EF4090AF7A90CC07E8817AA528763797D3C332B67CA4BC110642C2151EC47 \
EE84CB8C42D85F10E2A8CB18C3B7335F26E8C39A12B1BCC1707177B76138732E \
EDAAB74DA1410FC055EA068C99E9260ACBE337CF5D3E00E5B3230FFEDB0B9907 \
87D0C70E0BFE4198EA6758DD5A61FB5FEC2DF981F31BEFE153F81D17161784DB \
1C8822D53CD1EE7DB532364828BDF404B040A8DCC522F3D3D99AEC4B8057EDB8 \
500931A2C42D2F0C570847100B5754DAFC5FBDB894BBEF1A2DE1A07F8BA0C4B9 \
19301066EDBC056B7B481E7A0C46297BBB589D9DA5B675A6723E152E5E63A4CE \
034E9E83E58A013AF0E7352FB7908514E3B3D1040D0BB963B3954B636B5FD4BF \
6D0AADBAF8157D062ACB2418C176A475511B35C3F6218A5668EA5BC6F54B8782 \
F8B340F00AC1BEBA5E62CD632A7CE7809C725608ACA5EFBF7C41F237643F06C0 \
997207171DE867F9D697BF5EA6011ABCCE6C8CDB211394D2C02DD0FB60DB5A2C \
17AC3DC85878A90BED3809DBB96EAA5426FC8EAE0D2D65C42A479F088648BE2D \
C801D82A366FDDC0EF234263C0B6417D5F9DA41817B88D68E5E67195C5C1EE30 \
95E821F22524B20BE41CEB590412E41DC648843FA9BFEC7A3DCF61AB05415733 \
16D3FA8151629303FE9741562ED065DB4EBC0050EF558364AE81124A28F5C013 \
13232FBC496DFD8A2568657B686D7214382A1A00903017DDA969878442BA5AFF
InitialBlock: 0xfffffffe
Test: Encrypt
#
Comment: Random key, random iv, 0xfffffffe counter block, 1024 bytes
Key: CF3F6640B3830E2A 8D7013F3E974FE8E 4133B1E81E1EA81B 80477EE48073B357
IV: 7C 80 D7 1C 23 77 6E 20 F7 99 74 12
Plaintext: r1024 00
Ciphertext: \
F0F4771DA359A1CC0BCC92101E8830A88258ED4134A8B15282CAD3E3B727D8C5 \
34F1FE108F8626A5BC4F4F0559AF9AD996F281A77E3195A9B7606FF0DB6351A8 \
5E6E00281DFB032AED7478FA2AB65DFFE781680AD4243EC933C6E2040B6FE22D \
1EC0DD83F385BF2152BAA00B21F001E64860360D0C25E7B28BCA888C88391EB8 \
89D76D3E4E6CC4BC4BFACCB758DE288A7B523CBDD65662D55D464CE393C6A016 \
590D09A2C2117084619C6AEE14EF3D54092B2FBD40B86AFC6614237FB4B01AD1 \
590F4BB4715114B373A5E170F9FF18F87D5D033DEDB61B72946C755673D3CFDE \
A960F52F7DAE25C942ECE2CEB0C33B258A5CAEE89BB7FF6711B42FE12C8D9AB1 \
78826EECE976C58D05B6EB9F4B770A9715EBF96AE79515972375202782D343EE \
564B36037F49432197C1E977462BE17620B786E1DB2EF3CC759E3E3BD9B29373 \
367E66EEE529515BAAC37DC2B26BAA3A5587EA35F064CFEDBE5705779A72A53A \
2ED02D6F459768521BB1F0EB0D4A4EDCD9B0BB3E1148BDBF6A0918BFEF352FD2 \
149F95DE307CC388FF3ED0C72118D1AE27A112B58B2819A0976CF949DAA99AD0 \
1237B4BB5963E274F801FE25E62B7DC2D4B17BF85816DA5078EAE4FE676CBCAD \
C772811C93A4F94C5198F2C542CC71CAF3E3480678B37AF2FA42061F870A3AFA \
5146DFE5F4969F223D3909B20CB53344EF72B7C861ADA20D4EBC1AE3DB5431C1 \
300DC1CC32C5A2544E8707DC040CE2559293A54D070A48B18F18CB1E6F715D8C \
FE437BD03F55657CBB3DC95284C6830C7D7FB48249AB9EA08174FF8A04D89206 \
3EDDBE22D402C249718899A9E06169D49C6B723283F01EBF2707972CCA039F4A \
D1D92449E3CA011722E03119FEED32F63F22303C73C75B413FEC2EDA0C069236 \
880EAA26E5226233B216D059D664AF7D5737F0F12A1D34DA3CEB83826666F4B8 \
D7F60D917E033FBFEF756726DCA873E63ABD2A470F8CABBE21C6DDEEE668BCA0 \
C833AC0DEEE73155C1723BA2E5EC70985F2F239822FBE628EFCC68938630D9FB \
E88BF757A28BD8925DAD67666091BE7602D36DE65E248964469C44DBFBA76E13 \
3978E9DD5088BB4C314AEB56D9D553229110C7C939A129522C5F6B01F96D67ED \
97629A5E9DC4923745739A02151F53C8CE2CE48B33A7E359A574D9C8A48542E1 \
EA20DDFA7E9BA5B01DDC256786026160DA6A113E553F30A4F37A7ED2D3ACA6D4 \
3F90516417477C3778A80AB875E90F8D81977F51973184242A4BD2EC002216CA \
5631F1740F558E1CDC42A252A15CB954AB2DBB1CAC199313EF657FA2D5F8405A \
C60AC8BFCD0645CDCD0547D4433A6093C9A24F17902F5B37F2E60390C9EF30A9 \
853407FFF342D4787C56B665AFF0F94F1B6A0A213FB7E73F7EC1990C8C7CB1D7 \
7E0C233586EB00D9B10020986A31CCECFC26B435FC92E8707B7AC3CB8275FDA4
InitialBlock: 0xfffffffe
Test: Encrypt

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,75 @@
AlgorithmType: SymmetricCipher
Name: XChaCha20
Source: https://tools.ietf.org/html/draft-arciszewski-xchacha
#
Comment: A.2. Example and Test Vector for XChaCha20
Key: 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f \
90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
IV: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f \
50 51 52 53 54 55 56 58
Plaintext: r304 00
Ciphertext: 29 62 4b 4b 1b 14 0a ce 53 74 0e 40 5b 21 68 54 \
0f d7 d6 30 c1 f5 36 fe cd 72 2f c3 cd db a7 f4 \
cc a9 8c f9 e4 7e 5e 64 d1 15 45 0f 9b 12 5b 54 \
44 9f f7 61 41 ca 62 0a 1f 9c fc ab 2a 1a 8a 25 \
5e 76 6a 52 66 b8 78 84 61 20 ea 64 ad 99 aa 47 \
94 71 e6 3b ef cb d3 7c d1 c2 2a 22 1f e4 62 21 \
5c f3 2c 74 89 5b f5 05 86 3c cd dd 48 f6 29 16 \
dc 65 21 f1 ec 50 a5 ae 08 90 3a a2 59 d9 bf 60 \
7c d8 02 6f ba 54 86 04 f1 b6 07 2d 91 bc 91 24 \
3a 5b 84 5f 7f d1 71 b0 2e dc 5a 0a 84 cf 28 dd \
24 11 46 bc 37 6e 3f 48 df 5e 7f ee 1d 11 04 8c \
19 0a 3d 3d eb 0f eb 64 b4 2d 9c 6f de ee 29 0f \
a0 e6 ae 2c 26 c0 24 9e a8 c1 81 f7 e2 ff d1 00 \
cb e5 fd 3c 4f 82 71 d6 2b 15 33 0c b8 fd cf 00 \
b3 df 50 7c a8 c9 24 f7 01 7b 7e 71 2d 15 a2 eb \
5c 50 48 44 51 e5 4e 1b 4b 99 5b d8 fd d9 45 97 \
bb 94 d7 af 0b 2c 04 df 10 ba 08 90 89 9e d9 29 \
3a 0f 55 b8 ba fa 99 92 64 03 5f 1d 4f be 7f e0 \
aa fa 10 9a 62 37 20 27 e5 0e 10 cd fe cc a1 27
Test: Encrypt
#
Comment: A.2. Example and Test Vector for XChaCha20
Key: 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f \
90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
IV: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f \
50 51 52 53 54 55 56 58
Plaintext: 54 68 65 20 64 68 6f 6c 65 20 28 70 72 6f 6e 6f \
75 6e 63 65 64 20 22 64 6f 6c 65 22 29 20 69 73 \
20 61 6c 73 6f 20 6b 6e 6f 77 6e 20 61 73 20 74 \
68 65 20 41 73 69 61 74 69 63 20 77 69 6c 64 20 \
64 6f 67 2c 20 72 65 64 20 64 6f 67 2c 20 61 6e \
64 20 77 68 69 73 74 6c 69 6e 67 20 64 6f 67 2e \
20 49 74 20 69 73 20 61 62 6f 75 74 20 74 68 65 \
20 73 69 7a 65 20 6f 66 20 61 20 47 65 72 6d 61 \
6e 20 73 68 65 70 68 65 72 64 20 62 75 74 20 6c \
6f 6f 6b 73 20 6d 6f 72 65 20 6c 69 6b 65 20 61 \
20 6c 6f 6e 67 2d 6c 65 67 67 65 64 20 66 6f 78 \
2e 20 54 68 69 73 20 68 69 67 68 6c 79 20 65 6c \
75 73 69 76 65 20 61 6e 64 20 73 6b 69 6c 6c 65 \
64 20 6a 75 6d 70 65 72 20 69 73 20 63 6c 61 73 \
73 69 66 69 65 64 20 77 69 74 68 20 77 6f 6c 76 \
65 73 2c 20 63 6f 79 6f 74 65 73 2c 20 6a 61 63 \
6b 61 6c 73 2c 20 61 6e 64 20 66 6f 78 65 73 20 \
69 6e 20 74 68 65 20 74 61 78 6f 6e 6f 6d 69 63 \
20 66 61 6d 69 6c 79 20 43 61 6e 69 64 61 65 2e
Ciphertext: 7d 0a 2e 6b 7f 7c 65 a2 36 54 26 30 29 4e 06 3b \
7a b9 b5 55 a5 d5 14 9a a2 1e 4a e1 e4 fb ce 87 \
ec c8 e0 8a 8b 5e 35 0a be 62 2b 2f fa 61 7b 20 \
2c fa d7 20 32 a3 03 7e 76 ff dc dc 43 76 ee 05 \
3a 19 0d 7e 46 ca 1d e0 41 44 85 03 81 b9 cb 29 \
f0 51 91 53 86 b8 a7 10 b8 ac 4d 02 7b 8b 05 0f \
7c ba 58 54 e0 28 d5 64 e4 53 b8 a9 68 82 41 73 \
fc 16 48 8b 89 70 ca c8 28 f1 1a e5 3c ab d2 01 \
12 f8 71 07 df 24 ee 61 83 d2 27 4f e4 c8 b1 48 \
55 34 ef 2c 5f bc 1e c2 4b fc 36 63 ef aa 08 bc \
04 7d 29 d2 50 43 53 2d b8 39 1a 8a 3d 77 6b f4 \
37 2a 69 55 82 7c cb 0c dd 4a f4 03 a7 ce 4c 63 \
d5 95 c7 5a 43 e0 45 f0 cc e1 f2 9c 8b 93 bd 65 \
af c5 97 49 22 f2 14 a4 0b 7c 40 2c db 91 ae 73 \
c0 b6 36 15 cd ad 04 80 68 0f 16 51 5a 7a ce 9d \
39 23 64 64 32 8a 37 74 3f fc 28 f4 dd b3 24 f4 \
d0 f5 bb dc 27 0c 65 b1 74 9a 6e ff f1 fb aa 09 \
53 61 75 cc d2 9f b9 e6 05 7b 30 73 20 d3 16 83 \
8a 9c 71 f7 0b 5b 59 07 a6 6f 7e a4 9a ad c4 09
Test: Encrypt

View File

@ -49,7 +49,8 @@
#include "misc.h"
#include "stdcpp.h"
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
@ -112,14 +113,10 @@ inline size_t AdvancedProcessBlocks64_6x2_NEON(F2 func2, F6 func6,
CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 8);
#if (CRYPTOPP_LITTLE_ENDIAN)
const uint32x4_t s_one = {0, 0, 0, 1<<24};
const uint32x4_t s_two = {0, 2<<24, 0, 2<<24};
#else
// TODO: verify these constants on ARM-BE
const uint32x4_t s_one = {0, 0, 0, 1};
const uint32x4_t s_two = {0, 2, 0, 2};
#endif
const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
const uint32x4_t s_one = vld1q_u32(w_one);
const uint32x4_t s_two = vld1q_u32(w_two);
const size_t blockSize = 8;
const size_t neonBlockSize = 16;
@ -357,14 +354,10 @@ inline size_t AdvancedProcessBlocks128_6x1_NEON(F1 func1, F6 func6,
CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 16);
#if (CRYPTOPP_LITTLE_ENDIAN)
const uint32x4_t s_one = {0, 0, 0, 1<<24};
//const uint32x4_t s_two = {0, 2<<24, 0, 2<<24};
#else
// TODO: verify these constants on ARM-BE
const uint32x4_t s_one = {0, 0, 0, 1};
//const uint32x4_t s_two = {0, 2, 0, 2};
#endif
const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
const uint32x4_t s_one = vld1q_u32(w_one);
const uint32x4_t s_two = vld1q_u32(w_two);
const size_t blockSize = 16;
// const size_t neonBlockSize = 16;
@ -502,32 +495,25 @@ inline size_t AdvancedProcessBlocks128_6x1_NEON(F1 func1, F6 func6,
/// \tparam F1 function to process 1 128-bit block
/// \tparam F4 function to process 4 128-bit blocks
/// \tparam W word type of the subkey table
/// \tparam V vector type of the NEON datatype
/// \details AdvancedProcessBlocks128_4x1_NEON processes 4 and 1 NEON SIMD words
/// at a time.
/// \details The subkey type is usually word32 or word64. V is the vector type and it is
/// usually uint32x4_t or uint64x2_t. F1, F4, W and V must use the same word and
/// vector type. The V parameter is used to avoid template argument
/// deduction/substitution failures.
template <typename F1, typename F4, typename W, typename V>
/// usually uint32x4_t or uint32x4_t. F1, F4, and W must use the same word and
/// vector type.
template <typename F1, typename F4, typename W>
inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4,
const V& unused, const W *subKeys, size_t rounds, const byte *inBlocks,
const W *subKeys, size_t rounds, const byte *inBlocks,
const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
{
CRYPTOPP_ASSERT(subKeys);
CRYPTOPP_ASSERT(inBlocks);
CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 16);
CRYPTOPP_UNUSED(unused);
#if (CRYPTOPP_LITTLE_ENDIAN)
const uint32x4_t s_one = {0, 0, 0, 1<<24};
//const uint32x4_t s_two = {0, 2<<24, 0, 2<<24};
#else
// TODO: verify these constants on ARM-BE
const uint32x4_t s_one = {0, 0, 0, 1};
//const uint32x4_t s_two = {0, 2, 0, 2};
#endif
const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
const uint32x4_t s_one = vld1q_u32(w_one);
const uint32x4_t s_two = vld1q_u32(w_two);
const size_t blockSize = 16;
// const size_t neonBlockSize = 16;
@ -554,62 +540,62 @@ inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4,
{
while (length >= 4*blockSize)
{
uint64x2_t block0, block1, block2, block3;
uint32x4_t block0, block1, block2, block3;
if (flags & BT_InBlockIsCounter)
{
const uint64x2_t one = vreinterpretq_u64_u32(s_one);
block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
block1 = vaddq_u64(block0, one);
block2 = vaddq_u64(block1, one);
block3 = vaddq_u64(block2, one);
vst1q_u8(const_cast<byte*>(inBlocks),
vreinterpretq_u8_u64(vaddq_u64(block3, one)));
const uint32x4_t one = s_one;
block0 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
block1 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block0), vreinterpretq_u64_u32(one)));
block2 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block1), vreinterpretq_u64_u32(one)));
block3 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block2), vreinterpretq_u64_u32(one)));
vst1q_u8(const_cast<byte*>(inBlocks), vreinterpretq_u8_u64(vaddq_u64(
vreinterpretq_u64_u32(block3), vreinterpretq_u64_u32(one))));
}
else
{
block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
block0 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement);
block1 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
block1 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement);
block2 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
block2 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement);
block3 = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
block3 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement);
}
if (xorInput)
{
block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block0 = veorq_u32(block0, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block1 = veorq_u32(block1, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
block2 = veorq_u64(block2, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block2 = veorq_u32(block2, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
block3 = veorq_u64(block3, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block3 = veorq_u32(block3, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
}
func4((V&)block0, (V&)block1, (V&)block2, (V&)block3, subKeys, static_cast<unsigned int>(rounds));
func4(block0, block1, block2, block3, subKeys, static_cast<unsigned int>(rounds));
if (xorOutput)
{
block0 = veorq_u64(block0, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block0 = veorq_u32(block0, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
block1 = veorq_u64(block1, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block1 = veorq_u32(block1, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
block2 = veorq_u64(block2, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block2 = veorq_u32(block2, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
block3 = veorq_u64(block3, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block3 = veorq_u32(block3, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
xorBlocks = PtrAdd(xorBlocks, xorIncrement);
}
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block0));
vst1q_u8(outBlocks, vreinterpretq_u8_u32(block0));
outBlocks = PtrAdd(outBlocks, outIncrement);
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block1));
vst1q_u8(outBlocks, vreinterpretq_u8_u32(block1));
outBlocks = PtrAdd(outBlocks, outIncrement);
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block2));
vst1q_u8(outBlocks, vreinterpretq_u8_u32(block2));
outBlocks = PtrAdd(outBlocks, outIncrement);
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block3));
vst1q_u8(outBlocks, vreinterpretq_u8_u32(block3));
outBlocks = PtrAdd(outBlocks, outIncrement);
length -= 4*blockSize;
@ -618,20 +604,20 @@ inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4,
while (length >= blockSize)
{
uint64x2_t block = vreinterpretq_u64_u8(vld1q_u8(inBlocks));
uint32x4_t block = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
if (xorInput)
block = veorq_u64(block, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block = veorq_u32(block, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
if (flags & BT_InBlockIsCounter)
const_cast<byte *>(inBlocks)[15]++;
func1( (V&)block, subKeys, static_cast<unsigned int>(rounds));
func1(block, subKeys, static_cast<unsigned int>(rounds));
if (xorOutput)
block = veorq_u64(block, vreinterpretq_u64_u8(vld1q_u8(xorBlocks)));
block = veorq_u32(block, vreinterpretq_u32_u8(vld1q_u8(xorBlocks)));
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block));
vst1q_u8(outBlocks, vreinterpretq_u8_u32(block));
inBlocks = PtrAdd(inBlocks, inIncrement);
outBlocks = PtrAdd(outBlocks, outIncrement);
@ -660,14 +646,10 @@ inline size_t AdvancedProcessBlocks128_6x2_NEON(F2 func2, F6 func6,
CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 16);
#if (CRYPTOPP_LITTLE_ENDIAN)
const uint32x4_t s_one = {0, 0, 0, 1<<24};
//const uint32x4_t s_two = {0, 2<<24, 0, 2<<24};
#else
// TODO: verify these constants on ARM-BE
const uint32x4_t s_one = {0, 0, 0, 1};
//const uint32x4_t s_two = {0, 2, 0, 2};
#endif
const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
const uint32x4_t s_one = vld1q_u32(w_one);
const uint32x4_t s_two = vld1q_u32(w_two);
const size_t blockSize = 16;
// const size_t neonBlockSize = 16;

View File

@ -14,12 +14,11 @@
# include <tmmintrin.h>
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
// Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
// compilers don't follow ACLE conventions for the include.
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>
@ -47,7 +46,7 @@ using CryptoPP::byte;
using CryptoPP::word32;
inline byte ARIA_BRF(const word32 x, const int y) {
return GETBYTE(x, y);
return static_cast<byte>(GETBYTE(x, y));
}
ANONYMOUS_NAMESPACE_END

View File

@ -0,0 +1,189 @@
// arm_simd.h - written and placed in public domain by Jeffrey Walton
/// \file arm_simd.h
/// \brief Support functions for ARM and vector operations
#ifndef CRYPTOPP_ARM_SIMD_H
#define CRYPTOPP_ARM_SIMD_H
#include "config.h"
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>
#endif
#if (CRYPTOPP_ARM_PMULL_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details PMULL_00() performs polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x00)</tt>.
/// The <tt>0x00</tt> indicates the low 64-bits of <tt>a</tt> and <tt>b</tt>
/// are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and
/// numbered 0.
/// \since Crypto++ 8.0
inline uint64x2_t PMULL_00(const uint64x2_t a, const uint64x2_t b)
{
#if defined(_MSC_VER)
const __n64 x = { vgetq_lane_u64(a, 0) };
const __n64 y = { vgetq_lane_u64(b, 0) };
return vmull_p64(x, y);
#elif defined(__GNUC__)
uint64x2_t r;
__asm __volatile("pmull %0.1q, %1.1d, %2.1d \n\t"
:"=w" (r) : "w" (a), "w" (b) );
return r;
#else
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details PMULL_01 performs() polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x01)</tt>.
/// The <tt>0x01</tt> indicates the low 64-bits of <tt>a</tt> and high
/// 64-bits of <tt>b</tt> are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and
/// numbered 0.
/// \since Crypto++ 8.0
inline uint64x2_t PMULL_01(const uint64x2_t a, const uint64x2_t b)
{
#if defined(_MSC_VER)
const __n64 x = { vgetq_lane_u64(a, 0) };
const __n64 y = { vgetq_lane_u64(b, 1) };
return vmull_p64(x, y);
#elif defined(__GNUC__)
uint64x2_t r;
__asm __volatile("pmull %0.1q, %1.1d, %2.1d \n\t"
:"=w" (r) : "w" (a), "w" (vget_high_u64(b)) );
return r;
#else
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
vgetq_lane_u64(vreinterpretq_u64_u8(b),1)));
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details PMULL_10() performs polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x10)</tt>.
/// The <tt>0x10</tt> indicates the high 64-bits of <tt>a</tt> and low
/// 64-bits of <tt>b</tt> are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and
/// numbered 0.
/// \since Crypto++ 8.0
inline uint64x2_t PMULL_10(const uint64x2_t a, const uint64x2_t b)
{
#if defined(_MSC_VER)
const __n64 x = { vgetq_lane_u64(a, 1) };
const __n64 y = { vgetq_lane_u64(b, 0) };
return vmull_p64(x, y);
#elif defined(__GNUC__)
uint64x2_t r;
__asm __volatile("pmull %0.1q, %1.1d, %2.1d \n\t"
:"=w" (r) : "w" (vget_high_u64(a)), "w" (b) );
return r;
#else
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details PMULL_11() performs polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x11)</tt>.
/// The <tt>0x11</tt> indicates the high 64-bits of <tt>a</tt> and <tt>b</tt>
/// are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and
/// numbered 0.
/// \since Crypto++ 8.0
inline uint64x2_t PMULL_11(const uint64x2_t a, const uint64x2_t b)
{
#if defined(_MSC_VER)
const __n64 x = { vgetq_lane_u64(a, 1) };
const __n64 y = { vgetq_lane_u64(b, 1) };
return vmull_p64(x, y);
#elif defined(__GNUC__)
uint64x2_t r;
__asm __volatile("pmull2 %0.1q, %1.2d, %2.2d \n\t"
:"=w" (r) : "w" (a), "w" (b) );
return r;
#else
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
vgetq_lane_u64(vreinterpretq_u64_u8(b),1)));
#endif
}
/// \brief Vector extraction
/// \param a the first term
/// \param b the second term
/// \param c the byte count
/// \returns vector
/// \details VEXT_U8() extracts the first <tt>c</tt> bytes of vector
/// <tt>a</tt> and the remaining bytes in <tt>b</tt>.
/// \since Crypto++ 8.0
inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b, unsigned int c)
{
#if defined(_MSC_VER)
return (uint64x2_t)vextq_u8(
vreinterpretq_u8_u64(a), vreinterpretq_u8_u64(b), c);
#else
uint64x2_t r;
__asm __volatile("ext %0.16b, %1.16b, %2.16b, %3 \n\t"
:"=w" (r) : "w" (a), "w" (b), "I" (c) );
return r;
#endif
}
/// \brief Vector extraction
/// \tparam C the byte count
/// \param a the first term
/// \param b the second term
/// \returns vector
/// \details VEXT_U8() extracts the first <tt>C</tt> bytes of vector
/// <tt>a</tt> and the remaining bytes in <tt>b</tt>.
/// \since Crypto++ 8.0
template <unsigned int C>
inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b)
{
// https://github.com/weidai11/cryptopp/issues/366
#if defined(_MSC_VER)
return (uint64x2_t)vextq_u8(
vreinterpretq_u8_u64(a), vreinterpretq_u8_u64(b), C);
#else
uint64x2_t r;
__asm __volatile("ext %0.16b, %1.16b, %2.16b, %3 \n\t"
:"=w" (r) : "w" (a), "w" (b), "I" (C) );
return r;
#endif
}
#endif // CRYPTOPP_ARM_PMULL_AVAILABLE
#endif // CRYPTOPP_ARM_SIMD_H

View File

@ -10,11 +10,15 @@ NAMESPACE_BEGIN(CryptoPP)
void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
{
// UBsan finding with -std=c++03 using memcpy
CRYPTOPP_ASSERT(input && len);
if(!input || !len) return;
unsigned int blockSize = AuthenticationBlockSize();
unsigned int &num = m_bufferedDataLength;
byte* data = m_buffer.begin();
if (num != 0) // process left over data
if (data && num) // process left over data
{
if (num+len >= blockSize)
{
@ -41,7 +45,8 @@ void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_
len = leftOver;
}
memcpy(data, input, len);
if (data && len)
memcpy(data, input, len);
num = (unsigned int)len;
}
@ -74,6 +79,7 @@ void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
{
// Part of original authenc.cpp code. Don't remove it.
if (length == 0) {return;}
switch (m_state)
@ -102,9 +108,9 @@ void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
{
m_totalMessageLength += length;
if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
if (m_state >= State_IVSet && length > MaxMessageLength()-m_totalMessageLength)
throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
m_totalMessageLength += length;
reswitch:
switch (m_state)

View File

@ -60,7 +60,7 @@ protected:
void AuthenticateData(const byte *data, size_t len);
const SymmetricCipher & GetSymmetricCipher() const
{return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
{return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();}
virtual SymmetricCipher & AccessSymmetricCipher() =0;
virtual bool AuthenticationIsOnPlaintext() const =0;

View File

@ -434,17 +434,17 @@ void Benchmark1(double t, double hertz)
BenchMarkByNameKeyLess<RandomNumberGenerator>("AutoSeededX917RNG(AES)");
#endif
BenchMarkByNameKeyLess<RandomNumberGenerator>("MT19937");
#if (CRYPTOPP_BOOL_X86)
#if (CRYPTOPP_BOOL_X86) && !defined(CRYPTOPP_DISABLE_ASM)
if (HasPadlockRNG())
BenchMarkByNameKeyLess<RandomNumberGenerator>("PadlockRNG");
#endif
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) && !defined(CRYPTOPP_DISABLE_ASM)
if (HasRDRAND())
BenchMarkByNameKeyLess<RandomNumberGenerator>("RDRAND");
if (HasRDSEED())
BenchMarkByNameKeyLess<RandomNumberGenerator>("RDSEED");
#endif
#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) && !defined(CRYPTOPP_DISABLE_ASM)
if (HasDARN())
BenchMarkByNameKeyLess<RandomNumberGenerator>("DARN");
#endif

View File

@ -125,6 +125,7 @@ void Benchmark2(double t, double hertz)
BenchMarkByName<MessageAuthenticationCode>("CMAC(AES)");
BenchMarkByName<MessageAuthenticationCode>("DMAC(AES)");
BenchMarkByName<MessageAuthenticationCode>("Poly1305(AES)");
BenchMarkByName<MessageAuthenticationCode>("Poly1305TLS");
BenchMarkByName<MessageAuthenticationCode>("BLAKE2s");
BenchMarkByName<MessageAuthenticationCode>("BLAKE2b");
BenchMarkByName<MessageAuthenticationCode>("SipHash-2-4");
@ -141,6 +142,7 @@ void Benchmark2(double t, double hertz)
BenchMarkByName<SymmetricCipher>("ChaCha", 0, "ChaCha20");
BenchMarkByName<SymmetricCipher>("ChaCha", 0, "ChaCha12", MakeParameters(Name::Rounds(), 12));
BenchMarkByName<SymmetricCipher>("ChaCha", 0, "ChaCha8", MakeParameters(Name::Rounds(), 8));
BenchMarkByName<SymmetricCipher>("ChaChaTLS");
BenchMarkByName<SymmetricCipher>("Sosemanuk");
BenchMarkByName<SymmetricCipher>("Rabbit");
BenchMarkByName<SymmetricCipher>("RabbitWithIV");
@ -245,6 +247,8 @@ void Benchmark2(double t, double hertz)
}
BenchMarkByName2<AuthenticatedSymmetricCipher, AuthenticatedSymmetricCipher>("AES/CCM");
BenchMarkByName2<AuthenticatedSymmetricCipher, AuthenticatedSymmetricCipher>("AES/EAX");
BenchMarkByName2<AuthenticatedSymmetricCipher, AuthenticatedSymmetricCipher>("ChaCha20/Poly1305");
BenchMarkByName2<AuthenticatedSymmetricCipher, AuthenticatedSymmetricCipher>("XChaCha20/Poly1305");
}
std::cout << "\n</TABLE>" << std::endl;

View File

@ -38,12 +38,11 @@
# include <smmintrin.h>
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
// Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
// compilers don't follow ACLE conventions for the include.
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>

View File

@ -49,12 +49,11 @@
# include <smmintrin.h>
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
// Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
// compilers don't follow ACLE conventions for the include.
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>
@ -849,6 +848,7 @@ uint32x4_p VectorSet32<2,0,2,0>(const uint32x4_p a, const uint32x4_p b,
const uint32x4_p c, const uint32x4_p d)
{
// a=b, c=d, mask is {2,0, 2,0}
CRYPTOPP_UNUSED(b); CRYPTOPP_UNUSED(d);
const uint8x16_p mask = {16,17,18,19, 24,25,26,27, 0,1,2,3, 8,9,10,11};
return VecPermute(a, c, mask);
}
@ -858,6 +858,7 @@ uint32x4_p VectorSet32<3,1,3,1>(const uint32x4_p a, const uint32x4_p b,
const uint32x4_p c, const uint32x4_p d)
{
// a=b, c=d, mask is {3,1, 3,1}
CRYPTOPP_UNUSED(b); CRYPTOPP_UNUSED(d);
const uint8x16_p mask = {20,21,22,23, 28,29,30,31, 4,5,6,7, 12,13,14,15};
return VecPermute(a, c, mask);
}

View File

@ -73,7 +73,7 @@ protected:
virtual BlockCipher & AccessBlockCipher() =0;
virtual int DefaultDigestSize() const =0;
const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();}
byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
enum {REQUIRED_BLOCKSIZE = 16};

View File

@ -10,19 +10,23 @@
#include "misc.h"
#include "cpu.h"
// Internal compiler error in GCC 3.3 and below
#if defined(__GNUC__) && (__GNUC__ < 4)
# undef CRYPTOPP_SSE2_INTRIN_AVAILABLE
#endif
NAMESPACE_BEGIN(CryptoPP)
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
extern void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
extern void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif
#if (CRYPTOPP_AVX2_AVAILABLE)
extern void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
extern void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif
#if (CRYPTOPP_POWER7_AVAILABLE)
extern void ChaCha_OperateKeystream_POWER7(const word32 *state, const byte* input, byte *output, unsigned int rounds);
@ -30,6 +34,19 @@ extern void ChaCha_OperateKeystream_POWER7(const word32 *state, const byte* inpu
extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
void ChaCha_TestInstantiations()
{
ChaCha::Encryption x;
ChaChaTLS::Encryption y;
XChaCha20::Encryption z;
}
#endif
NAMESPACE_END // CryptoPP
////////////////////////////// ChaCha Core //////////////////////////////
#define CHACHA_QUARTER_ROUND(a,b,c,d) \
a += b; d ^= a; d = rotlConstant<16,word32>(d); \
c += d; b ^= c; b = rotlConstant<12,word32>(b); \
@ -37,43 +54,210 @@ extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* inp
c += d; b ^= c; b = rotlConstant<7,word32>(b);
#define CHACHA_OUTPUT(x){\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + m_state[0]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + m_state[1]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + m_state[2]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + m_state[3]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + m_state[4]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + m_state[5]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + m_state[6]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + m_state[7]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + m_state[8]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + m_state[9]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + m_state[10]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + m_state[11]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + m_state[12]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + m_state[13]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + m_state[14]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + m_state[15]);}
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + state[0]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + state[1]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + state[2]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + state[3]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + state[4]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + state[5]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + state[6]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + state[7]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + state[8]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + state[9]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + state[10]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + state[11]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + state[12]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + state[13]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + state[14]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + state[15]);}
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
void ChaCha_TestInstantiations()
ANONYMOUS_NAMESPACE_BEGIN
// Hacks... Bring in all symbols, and supply
// the stuff the templates normally provide.
using namespace CryptoPP;
typedef word32 WordType;
enum {BYTES_PER_ITERATION=64};
// MultiBlockSafe detects a condition that can arise in the SIMD
// implementations where we overflow one of the 32-bit state words during
// addition in an intermediate result. Preconditions for the issue include
// a user seeks to around 2^32 blocks (256 GB of data) for ChaCha; or a
// user specifies an arbitrarily large initial counter block for ChaChaTLS.
// Also see https://github.com/weidai11/cryptopp/issues/732.
inline bool MultiBlockSafe(unsigned int ctrLow, unsigned int blocks)
{
ChaCha::Encryption x;
return 0xffffffff - ctrLow > blocks;
}
// OperateKeystream always produces a key stream. The key stream is written
// to output. Optionally a message may be supplied to xor with the key stream.
// The message is input, and output = output ^ input.
void ChaCha_OperateKeystream(KeystreamOperation operation,
word32 state[16], word32& ctrLow, word32& ctrHigh, word32 rounds,
byte *output, const byte *input, size_t iterationCount)
{
do
{
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
{
while (iterationCount >= 8 && MultiBlockSafe(state[12], 8))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_AVX2(state, xorInput ? input : NULLPTR, output, rounds);
// MultiBlockSafe avoids overflow on the counter words
state[12] += 8;
input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
output += 8 * BYTES_PER_ITERATION;
iterationCount -= 8;
}
}
#endif
std::string ChaCha_Policy::AlgorithmName() const
{
return std::string("ChaCha")+IntToString(m_rounds);
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2())
{
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_SSE2(state, xorInput ? input : NULLPTR, output, rounds);
// MultiBlockSafe avoids overflow on the counter words
state[12] += 4;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
{
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_NEON(state, xorInput ? input : NULLPTR, output, rounds);
// MultiBlockSafe avoids overflow on the counter words
state[12] += 4;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
#if (CRYPTOPP_POWER7_AVAILABLE)
if (HasPower7())
{
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_POWER7(state, xorInput ? input : NULLPTR, output, rounds);
// MultiBlockSafe avoids overflow on the counter words
state[12] += 4;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#elif (CRYPTOPP_ALTIVEC_AVAILABLE)
if (HasAltivec())
{
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_ALTIVEC(state, xorInput ? input : NULLPTR, output, rounds);
// MultiBlockSafe avoids overflow on the counter words
state[12] += 4;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
if (iterationCount)
{
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3];
x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7];
x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11];
x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15];
for (int i = static_cast<int>(rounds); i > 0; i -= 2)
{
CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
}
CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION);
// This is state[12] and state[13] from ChaCha. In the case of
// ChaChaTLS ctrHigh is a reference to a discard value.
if (++ctrLow == 0)
ctrHigh++;
}
// We may re-enter a SIMD keystream operation from here.
} while (iterationCount--);
}
std::string ChaCha_Policy::AlgorithmProvider() const
// XChaCha key derivation
void HChaCha_OperateKeystream(const word32 state[16], word32 output[8])
{
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3];
x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7];
x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11];
x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15];
for (int i = 20; i > 0; i -= 2)
{
CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
}
output[0] = x0; output[1] = x1;
output[2] = x2; output[3] = x3;
output[4] = x12; output[5] = x13;
output[6] = x14; output[7] = x15;
}
std::string ChaCha_AlgorithmProvider()
{
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
return "AVX2";
else
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2())
return "SSE2";
else
@ -95,52 +279,14 @@ std::string ChaCha_Policy::AlgorithmProvider() const
return "C++";
}
void ChaCha_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
CRYPTOPP_UNUSED(params);
CRYPTOPP_ASSERT(length == 16 || length == 32);
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
throw InvalidRounds(ChaCha::StaticAlgorithmName(), m_rounds);
// "expand 16-byte k" or "expand 32-byte k"
m_state[0] = 0x61707865;
m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e;
m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32;
m_state[3] = 0x6b206574;
GetBlock<word32, LittleEndian> get1(key);
get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
}
void ChaCha_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
{
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(length==8);
GetBlock<word32, LittleEndian> get(IV);
m_state[12] = m_state[13] = 0;
get(m_state[14])(m_state[15]);
}
void ChaCha_Policy::SeekToIteration(lword iterationCount)
{
m_state[12] = (word32)iterationCount; // low word
m_state[13] = (word32)SafeRightShift<32>(iterationCount);
}
unsigned int ChaCha_Policy::GetAlignment() const
unsigned int ChaCha_GetAlignment()
{
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
return 16;
else
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2())
return 16;
else
@ -153,14 +299,14 @@ unsigned int ChaCha_Policy::GetAlignment() const
return GetAlignmentOf<word32>();
}
unsigned int ChaCha_Policy::GetOptimalBlockSize() const
unsigned int ChaCha_GetOptimalBlockSize()
{
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
return 8 * BYTES_PER_ITERATION;
else
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2())
return 4*BYTES_PER_ITERATION;
else
@ -178,147 +324,267 @@ unsigned int ChaCha_Policy::GetOptimalBlockSize() const
return BYTES_PER_ITERATION;
}
bool ChaCha_Policy::MultiBlockSafe(unsigned int blocks) const
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Bernstein ChaCha //////////////////////////////
std::string ChaCha_Policy::AlgorithmName() const
{
return 0xffffffff - m_state[12] > blocks;
return std::string("ChaCha")+IntToString(m_rounds);
}
std::string ChaCha_Policy::AlgorithmProvider() const
{
return ChaCha_AlgorithmProvider();
}
void ChaCha_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
// Use previous rounds as the default value
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
if (rounds != 20 && rounds != 12 && rounds != 8)
throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
// Latch a good value
m_rounds = rounds;
// "expand 16-byte k" or "expand 32-byte k"
m_state[0] = 0x61707865;
m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e;
m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32;
m_state[3] = 0x6b206574;
GetBlock<word32, LittleEndian> get1(key);
get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
}
void ChaCha_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
{
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(length==8); CRYPTOPP_UNUSED(length);
GetBlock<word32, LittleEndian> get(IV);
m_state[12] = m_state[13] = 0;
get(m_state[14])(m_state[15]);
}
void ChaCha_Policy::SeekToIteration(lword iterationCount)
{
m_state[12] = (word32)iterationCount; // low word
m_state[13] = (word32)SafeRightShift<32>(iterationCount);
}
unsigned int ChaCha_Policy::GetAlignment() const
{
return ChaCha_GetAlignment();
}
unsigned int ChaCha_Policy::GetOptimalBlockSize() const
{
return ChaCha_GetOptimalBlockSize();
}
// OperateKeystream always produces a key stream. The key stream is written
// to output. Optionally a message may be supplied to xor with the key stream.
// The message is input, and output = output ^ input.
void ChaCha_Policy::OperateKeystream(KeystreamOperation operation,
byte *output, const byte *input, size_t iterationCount)
{
do
{
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
{
while (iterationCount >= 8 && MultiBlockSafe(8))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_AVX2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
m_rounds, output, input, iterationCount);
}
// MultiBlockSafe avoids overflow on the counter words
m_state[12] += 8;
//if (m_state[12] < 8)
// m_state[13]++;
////////////////////////////// IETF ChaChaTLS //////////////////////////////
input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
output += 8 * BYTES_PER_ITERATION;
iterationCount -= 8;
}
}
#endif
std::string ChaChaTLS_Policy::AlgorithmName() const
{
return std::string("ChaChaTLS");
}
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
if (HasSSE2())
{
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_SSE2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
std::string ChaChaTLS_Policy::AlgorithmProvider() const
{
return ChaCha_AlgorithmProvider();
}
// MultiBlockSafe avoids overflow on the counter words
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
CRYPTOPP_UNUSED(length);
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
// ChaChaTLS is always 20 rounds. Fetch Rounds() to avoid a spurious failure.
int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS);
if (rounds != 20)
throw InvalidRounds(ChaChaTLS::StaticAlgorithmName(), rounds);
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
{
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_NEON(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// RFC 8439 test vectors use an initial block counter. However, the counter
// can be an arbitrary value per RFC 8439 Section 2.4. We stash the counter
// away in state[16] and use it for a Resynchronize() operation. I think
// the initial counter is used more like a Tweak when non-0, and it should
// be provided in Resynchronize() (light-weight re-keying). However,
// Resynchronize() does not have an overload that allows us to pass it into
// the function, so we have to use the heavier-weight SetKey to change it.
word64 block;
if (params.GetValue("InitialBlock", block))
m_counter = static_cast<word32>(block);
else
m_counter = 0;
// MultiBlockSafe avoids overflow on the counter words
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
// State words are defined in RFC 8439, Section 2.3. Key is 32-bytes.
GetBlock<word32, LittleEndian> get(key);
get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
(m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
}
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
{
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(length==12);
#if (CRYPTOPP_POWER7_AVAILABLE)
if (HasPower7())
{
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_POWER7(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// State words are defined in RFC 8439, Section 2.3.
m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
// MultiBlockSafe avoids overflow on the counter words
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
// Copy saved key into state
std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#elif (CRYPTOPP_ALTIVEC_AVAILABLE)
if (HasAltivec())
{
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_ALTIVEC(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// State words are defined in RFC 8439, Section 2.3
GetBlock<word32, LittleEndian> get(IV);
m_state[12] = m_counter;
get(m_state[13])(m_state[14])(m_state[15]);
}
// MultiBlockSafe avoids overflow on the counter words
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
{
// Should we throw here??? If the initial block counter is
// large then we can wrap and process more data as long as
// data processed in the security context does not exceed
// 2^32 blocks or approximately 256 GB of data.
CRYPTOPP_ASSERT(iterationCount <= std::numeric_limits<word32>::max());
m_state[12] = (word32)iterationCount; // low word
}
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
unsigned int ChaChaTLS_Policy::GetAlignment() const
{
return ChaCha_GetAlignment();
}
if (iterationCount)
{
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
{
return ChaCha_GetOptimalBlockSize();
}
x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3];
x4 = m_state[4]; x5 = m_state[5]; x6 = m_state[6]; x7 = m_state[7];
x8 = m_state[8]; x9 = m_state[9]; x10 = m_state[10]; x11 = m_state[11];
x12 = m_state[12]; x13 = m_state[13]; x14 = m_state[14]; x15 = m_state[15];
void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
byte *output, const byte *input, size_t iterationCount)
{
word32 discard=0;
ChaCha_OperateKeystream(operation, m_state, m_state[12], discard,
ROUNDS, output, input, iterationCount);
for (int i = static_cast<int>(m_rounds); i > 0; i -= 2)
{
CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
// If this fires it means ChaCha_OperateKeystream generated a counter
// block carry that was discarded. The problem is, the RFC does not
// specify what should happen when the counter block wraps. All we can
// do is inform the user that something bad may happen because we don't
// know what we should do.
// Also see https://github.com/weidai11/cryptopp/issues/790 and
// https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU
// CRYPTOPP_ASSERT(discard==0);
}
CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
}
////////////////////////////// IETF XChaCha20 //////////////////////////////
CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION);
std::string XChaCha20_Policy::AlgorithmName() const
{
return std::string("XChaCha20");
}
if (++m_state[12] == 0)
m_state[13]++;
}
std::string XChaCha20_Policy::AlgorithmProvider() const
{
return ChaCha_AlgorithmProvider();
}
// We may re-enter a SIMD keystream operation from here.
} while (iterationCount--);
void XChaCha20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
CRYPTOPP_UNUSED(length);
// Use previous rounds as the default value
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
if (rounds != 20 && rounds != 12)
throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
// Latch a good value
m_rounds = rounds;
word64 block;
if (params.GetValue("InitialBlock", block))
m_counter = static_cast<word32>(block);
else
m_counter = 1;
// Stash key away for use in CipherResynchronize
GetBlock<word32, LittleEndian> get(key);
get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
(m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
}
void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
{
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(length==24);
// HChaCha derivation
m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
// Copy saved key into state
std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
GetBlock<word32, LittleEndian> get(iv);
get(m_state[12])(m_state[13])(m_state[14])(m_state[15]);
// Operate the keystream without adding state back in.
// This function also gathers the key words into a
// contiguous 8-word block.
HChaCha_OperateKeystream(m_state, m_state+4);
// XChaCha state
m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
// Setup new IV
m_state[12] = m_counter;
m_state[13] = 0;
m_state[14] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+16);
m_state[15] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+20);
}
void XChaCha20_Policy::SeekToIteration(lword iterationCount)
{
// Should we throw here??? XChaCha does not have a block
// counter, so I'm not sure how to seek on it.
CRYPTOPP_ASSERT(0); CRYPTOPP_UNUSED(iterationCount);
}
unsigned int XChaCha20_Policy::GetAlignment() const
{
return ChaCha_GetAlignment();
}
unsigned int XChaCha20_Policy::GetOptimalBlockSize() const
{
return ChaCha_GetOptimalBlockSize();
}
void XChaCha20_Policy::OperateKeystream(KeystreamOperation operation,
byte *output, const byte *input, size_t iterationCount)
{
ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
m_rounds, output, input, iterationCount);
}
NAMESPACE_END

View File

@ -3,13 +3,28 @@
// and Bernstein's reference ChaCha family implementation at
// http://cr.yp.to/chacha.html.
// The library added Bernstein's ChaCha classses at Crypto++ 5.6.4. The IETF
// uses a slightly different implementation than Bernstein, and the IETF
// ChaCha and XChaCha classes were added at Crypto++ 8.1. We wanted to maintain
// ABI compatibility at the 8.1 release so the original ChaCha classes were not
// disturbed. Instead new classes were added for IETF ChaCha. The back-end
// implementation shares code as expected, however.
/// \file chacha.h
/// \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers
/// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha,
/// a variant of Salsa20</a> (2008.01.28). Bernstein's implementation is _slightly_ different from the TLS working group's
/// implementation for cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
/// \since Crypto++ 5.6.4
/// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a
/// href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a
/// variant of Salsa20</a> (2008.01.28). Crypto++ also provides the
/// IETF implementation of ChaCha using the ChaChaTLS name. Bernstein's
/// implementation is _slightly_ different from the TLS working group's
/// implementation for cipher suites
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
/// and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>. Finally,
/// the library provides <a
/// href="https://tools.ietf.org/html/draft-arciszewski-xchacha">XChaCha:
/// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03)</a>.
/// \since ChaCha since Crypto++ 5.6.4, ChaChaTLS and XChaCha20 since Crypto++ 8.1
#ifndef CRYPTOPP_CHACHA_H
#define CRYPTOPP_CHACHA_H
@ -19,6 +34,8 @@
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Bernstein ChaCha //////////////////////////////
/// \brief ChaCha stream cipher information
/// \since Crypto++ 5.6.4
struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>
@ -40,8 +57,8 @@ struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterf
class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{
public:
~ChaCha_Policy() {}
ChaCha_Policy() : m_rounds(0) {}
virtual ~ChaCha_Policy() {}
ChaCha_Policy() : m_rounds(ROUNDS) {}
protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
@ -55,28 +72,149 @@ protected:
std::string AlgorithmName() const;
std::string AlgorithmProvider() const;
// MultiBlockSafe detects a condition that can arise in the SIMD
// implementations where we overflow one of the 32-bit state words
// during addition in an intermediate result. Conditions to trigger
// issue include a user seeks to around 2^32 blocks (256 GB of data).
// https://github.com/weidai11/cryptopp/issues/732
inline bool MultiBlockSafe(unsigned int blocks) const;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
FixedSizeAlignedSecBlock<word32, 16> m_state;
unsigned int m_rounds;
};
/// \brief ChaCha stream cipher
/// \details Bernstein and ECRYPT's ChaCha is _slightly_ different from the TLS working
/// group's implementation for cipher suites
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and
/// <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
/// \sa <a href="http://cr.yp.to/chacha/chacha-20080208.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
/// \details This is Bernstein and ECRYPT's ChaCha. It is _slightly_ different
/// from the IETF's version of ChaCha called ChaChaTLS.
/// \sa <a href="http://cr.yp.to/chacha/chacha-20080208.pdf">ChaCha, a variant
/// of Salsa20</a> (2008.01.28).
/// \since Crypto++ 5.6.4
struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation
{
/// \brief ChaCha Encryption
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy, AdditiveCipherTemplate<> >, ChaCha_Info > Encryption;
/// \brief ChaCha Decryption
typedef Encryption Decryption;
};
////////////////////////////// IETF ChaChaTLS //////////////////////////////
/// \brief ChaCha-TLS stream cipher information
/// \since Crypto++ 8.1
struct ChaChaTLS_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 12>, FixedRounds<20>
{
/// \brief The algorithm name
/// \returns the algorithm name
/// \details StaticAlgorithmName returns the algorithm's name as a static
/// member function.
/// \details This is the IETF's variant of Bernstein's ChaCha from RFC
/// 8439. IETF ChaCha is called ChaChaTLS in the Crypto++ library. It
/// is _slightly_ different from Bernstein's implementation.
static const char* StaticAlgorithmName() {
return "ChaChaTLS";
}
};
/// \brief ChaCha-TLS stream cipher implementation
/// \since Crypto++ 8.1
class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{
public:
virtual ~ChaChaTLS_Policy() {}
ChaChaTLS_Policy() : m_counter(0) {}
protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
bool CipherIsRandomAccess() const {return true;}
void SeekToIteration(lword iterationCount);
unsigned int GetAlignment() const;
unsigned int GetOptimalBlockSize() const;
std::string AlgorithmName() const;
std::string AlgorithmProvider() const;
FixedSizeAlignedSecBlock<word32, 16+8> m_state;
unsigned int m_counter;
CRYPTOPP_CONSTANT(ROUNDS = ChaChaTLS_Info::ROUNDS)
CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state
CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state
};
/// \brief ChaCha-TLS stream cipher
/// \details This is the IETF's variant of Bernstein's ChaCha from RFC 8439.
/// IETF ChaCha is called ChaChaTLS in the Crypto++ library. It is
/// _slightly_ different from the Bernstein implementation. ChaCha-TLS
/// can be used for cipher suites
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and
/// <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
/// \sa <a href="https://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and
/// Poly1305 for IETF Protocols</a>, <A
/// HREF="https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU">How
/// to handle block counter wrap in IETF's ChaCha algorithm?</A> and
/// <A HREF="https://github.com/weidai11/cryptopp/issues/790">Issue
/// 790, ChaChaTLS results when counter block wraps</A>.
/// \since Crypto++ 8.1
struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation
{
/// \brief ChaCha-TLS Encryption
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaChaTLS_Policy, AdditiveCipherTemplate<> >, ChaChaTLS_Info > Encryption;
/// \brief ChaCha-TLS Decryption
typedef Encryption Decryption;
};
////////////////////////////// IETF XChaCha20 draft //////////////////////////////
/// \brief XChaCha stream cipher information
/// \since Crypto++ 8.1
struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24>
{
/// \brief The algorithm name
/// \returns the algorithm name
/// \details StaticAlgorithmName returns the algorithm's name as a static
/// member function.
/// \details This is the IETF's XChaCha from draft-arciszewski-xchacha.
static const char* StaticAlgorithmName() {
return "XChaCha20";
}
};
/// \brief XChaCha stream cipher implementation
/// \since Crypto++ 8.1
class CRYPTOPP_NO_VTABLE XChaCha20_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{
public:
virtual ~XChaCha20_Policy() {}
XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {}
protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
bool CipherIsRandomAccess() const {return false;}
void SeekToIteration(lword iterationCount);
unsigned int GetAlignment() const;
unsigned int GetOptimalBlockSize() const;
std::string AlgorithmName() const;
std::string AlgorithmProvider() const;
FixedSizeAlignedSecBlock<word32, 16+8> m_state;
unsigned int m_counter, m_rounds;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state
};
/// \brief XChaCha stream cipher
/// \details This is the IETF's XChaCha from draft-arciszewski-xchacha.
/// \sa <a href="https://tools.ietf.org/html/draft-arciszewski-xchacha">XChaCha:
/// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03)</a>, <A
/// HREF="https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU">How
/// to handle block counter wrap in IETF's ChaCha algorithm?</A> and
/// <A HREF="https://github.com/weidai11/cryptopp/issues/790">Issue
/// 790, ChaCha20 results when counter block wraps</A>.
/// \since Crypto++ 8.1
struct XChaCha20 : public XChaCha20_Info, public SymmetricCipherDocumentation
{
/// \brief XChaCha Encryption
typedef SymmetricCipherFinal<ConcretePolicyHolder<XChaCha20_Policy, AdditiveCipherTemplate<> >, XChaCha20_Info > Encryption;
/// \brief XChaCha Decryption
typedef Encryption Decryption;
};

View File

@ -30,7 +30,12 @@
#include "chacha.h"
#include "misc.h"
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
// Internal compiler error in GCC 3.3 and below
#if defined(__GNUC__) && (__GNUC__ < 4)
# undef CRYPTOPP_SSE2_INTRIN_AVAILABLE
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
# include <xmmintrin.h>
# include <emmintrin.h>
#endif
@ -43,12 +48,11 @@
# include <ammintrin.h>
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
// Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
// compilers don't follow ACLE conventions for the include.
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>
@ -161,7 +165,7 @@ inline uint32x4_t Add64(const uint32x4_t& a, const uint32x4_t& b)
// ***************************** SSE2 ***************************** //
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
template <unsigned int R>
inline __m128i RotateLeft(const __m128i val)
@ -199,7 +203,7 @@ inline __m128i RotateLeft<16>(const __m128i val)
#endif
}
#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE
#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE
// **************************** Altivec **************************** //
@ -297,8 +301,9 @@ void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *
const uint32x4_t state2 = vld1q_u32(state + 2*4);
const uint32x4_t state3 = vld1q_u32(state + 3*4);
const unsigned int w[] = {1,0,0,0, 2,0,0,0, 3,0,0,0};
const uint32x4_t CTRS[3] = {
{1,0,0,0}, {2,0,0,0}, {3,0,0,0}
vld1q_u32(w+0), vld1q_u32(w+4), vld1q_u32(w+8)
};
uint32x4_t r0_0 = state0;
@ -556,7 +561,7 @@ void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *
// ***************************** SSE2 ***************************** //
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE)
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *output, unsigned int rounds)
{
@ -820,7 +825,7 @@ void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *
_mm_storeu_si128(output_mm + 15, r3_3);
}
#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE
#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE
#if (CRYPTOPP_POWER7_AVAILABLE || CRYPTOPP_ALTIVEC_AVAILABLE)

View File

@ -0,0 +1,207 @@
// chachapoly.cpp - written and placed in the public domain by Jeffrey Walton
// RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439
#include "pch.h"
#include "chachapoly.h"
#include "algparam.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// IETF ChaChaTLS //////////////////////////////
// RekeyCipherAndMac is heavier-weight than we like. The Authenc framework was
// predicated on BlockCiphers, where the key and key schedule could be
// calculated independent of the IV being used. However, the ChaCha and
// ChaCha20Poly1305 construction combines key setup and IV. That is, both are
// needed to key or rekey the cipher. Even a simple Resync() requires us to
// regenerate the initial state for both ChaCha20 and Poly1305.
void ChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs &params)
{
// Derive MAC key
AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true);
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0));
// Only the first 256-bits are used to key the MAC
SecByteBlock derived(NULLPTR, 32);
AccessSymmetricCipher().ProcessString(derived, derived.size());
// Key the Poly1305 MAC
AccessMAC().SetKey(derived, derived.size(), params);
// Key the ChaCha20 cipher
AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true);
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1));
}
void ChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(userKey && userKeyLength == 32);
m_userKey.Assign(userKey, userKeyLength);
// ChaCha/Poly1305 initial state depends on both the key and IV. The
// IV may or may not be present during the call to SetKeyWithoutResync.
// If the IV is present, the framework will call SetKeyWithoutResync
// followed by Resynchronize which calls Resync. In this case we defer
// calculating the initial state until the call to Resynchronize.
// If the IV is not present, it avoids calling ChaCha's SetKey without
// an IV, which results in an exception. In this case the user will need
// to call Resynchronize to key ChaCha and Poly1305.
// RekeyCipherAndMac(userKey, userKeyLength, params);
CRYPTOPP_UNUSED(params);
}
void ChaCha20Poly1305_Base::Resync(const byte *iv, size_t len)
{
CRYPTOPP_ASSERT(iv && len == 12);
RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(),
MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len)));
}
size_t ChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len)
{
AccessMAC().Update(data, len);
return 0;
}
void ChaCha20Poly1305_Base::AuthenticateLastHeaderBlock()
{
// Pad to a multiple of 16 or 0
const byte zero[16] = {0};
size_t pad = (16 - (m_totalHeaderLength % 16)) % 16;
AccessMAC().Update(zero, pad);
}
void ChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock()
{
// Pad to a multiple of 16 or 0
const byte zero[16] = {0};
size_t pad = (16 - (m_totalMessageLength % 16)) % 16;
AccessMAC().Update(zero, pad);
}
void ChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
{
CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)];
PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength);
PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength);
AccessMAC().Update(length, sizeof(length));
AccessMAC().TruncatedFinal(mac, macSize);
m_state = State_KeySet;
}
void ChaCha20Poly1305_Base::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength)
{
Resynchronize(iv, ivLength);
Update(aad, aadLength);
ProcessString(ciphertext, message, messageLength);
TruncatedFinal(mac, macSize);
}
bool ChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength)
{
Resynchronize(iv, ivLength);
Update(aad, aadLength);
ProcessString(message, ciphertext, ciphertextLength);
return TruncatedVerify(mac, macLength);
}
////////////////////////////// IETF XChaCha20 draft //////////////////////////////
// RekeyCipherAndMac is heavier-weight than we like. The Authenc framework was
// predicated on BlockCiphers, where the key and key schedule could be
// calculated independent of the IV being used. However, the ChaCha and
// ChaCha20Poly1305 construction combines key setup and IV. That is, both are
// needed to key or rekey the cipher. Even a simple Resync() requires us to
// regenerate the initial state for both ChaCha20 and Poly1305.
void XChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs &params)
{
// Derive MAC key
AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true);
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0));
// Only the first 256-bits are used to key the MAC
SecByteBlock derived(NULLPTR, 32);
AccessSymmetricCipher().ProcessString(derived, derived.size());
// Key the Poly1305 MAC
AccessMAC().SetKey(derived, derived.size(), params);
// Key the ChaCha20 cipher
AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true);
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1));
}
void XChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(userKey && userKeyLength == 32);
m_userKey.Assign(userKey, userKeyLength);
// XChaCha20/Poly1305 initial state depends on both the key and IV. The
// IV may or may not be present during the call to SetKeyWithoutResync.
// If the IV is present, the framework will call SetKeyWithoutResync
// followed by Resynchronize which calls Resync. In this case we defer
// calculating the initial state until the call to Resynchronize.
// If the IV is not present, it avoids calling ChaCha's SetKey without
// an IV, which results in an exception. In this case the user will need
// to call Resynchronize to key ChaCha and Poly1305.
// RekeyCipherAndMac(userKey, userKeyLength, params);
CRYPTOPP_UNUSED(params);
}
void XChaCha20Poly1305_Base::Resync(const byte *iv, size_t len)
{
CRYPTOPP_ASSERT(iv && len == 24);
RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(),
MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len)));
}
size_t XChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len)
{
AccessMAC().Update(data, len);
return 0;
}
void XChaCha20Poly1305_Base::AuthenticateLastHeaderBlock()
{
// Pad to a multiple of 16 or 0
const byte zero[16] = {0};
size_t pad = (16 - (m_totalHeaderLength % 16)) % 16;
AccessMAC().Update(zero, pad);
}
void XChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock()
{
// Pad to a multiple of 16 or 0
const byte zero[16] = {0};
size_t pad = (16 - (m_totalMessageLength % 16)) % 16;
AccessMAC().Update(zero, pad);
}
void XChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
{
CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)];
PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength);
PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength);
AccessMAC().Update(length, sizeof(length));
AccessMAC().TruncatedFinal(mac, macSize);
m_state = State_KeySet;
}
void XChaCha20Poly1305_Base::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength)
{
Resynchronize(iv, ivLength);
Update(aad, aadLength);
ProcessString(ciphertext, message, messageLength);
TruncatedFinal(mac, macSize);
}
bool XChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength)
{
Resynchronize(iv, ivLength);
Update(aad, aadLength);
ProcessString(message, ciphertext, ciphertextLength);
return TruncatedVerify(mac, macLength);
}
NAMESPACE_END

View File

@ -0,0 +1,320 @@
// chachapoly.h - written and placed in the public domain by Jeffrey Walton
// RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439
/// \file chachapoly.h
/// \brief ChaCha20/Poly1305-TLS AEAD scheme
/// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
/// ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
/// AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha
/// and Poly1305.
/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
/// for IETF Protocols</A>.
/// \since Crypto++ 8.1
#ifndef CRYPTOPP_CHACHA_POLY1305_H
#define CRYPTOPP_CHACHA_POLY1305_H
#include "cryptlib.h"
#include "authenc.h"
#include "chacha.h"
#include "poly1305.h"
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// IETF ChaChaTLS //////////////////////////////
/// \brief ChaCha20Poly1305 cipher base implementation
/// \details Base implementation of the AuthenticatedSymmetricCipher interface
/// \since Crypto++ 8.1
class ChaCha20Poly1305_Base : public AuthenticatedSymmetricCipherBase
{
public:
virtual ~ChaCha20Poly1305_Base() {}
virtual const MessageAuthenticationCode & GetMAC() const = 0;
virtual MessageAuthenticationCode & AccessMAC() = 0;
public:
// AuthenticatedSymmetricCipher
std::string AlgorithmName() const
{return std::string("ChaCha20/Poly1305");}
std::string AlgorithmProvider() const
{return GetSymmetricCipher().AlgorithmProvider();}
size_t MinKeyLength() const
{return 32;}
size_t MaxKeyLength() const
{return 32;}
size_t DefaultKeyLength() const
{return 32;}
size_t GetValidKeyLength(size_t n) const
{CRYPTOPP_UNUSED(n); return 32;}
bool IsValidKeyLength(size_t n) const
{return n==32;}
unsigned int OptimalDataAlignment() const
{return GetSymmetricCipher().OptimalDataAlignment();}
IV_Requirement IVRequirement() const
{return UNIQUE_IV;}
unsigned int IVSize() const
{return 12;}
unsigned int MinIVLength() const
{return 12;}
unsigned int MaxIVLength() const
{return 12;}
unsigned int DigestSize() const
{return 16;}
lword MaxHeaderLength() const
{return LWORD_MAX;} // 2^64-1 bytes
lword MaxMessageLength() const
{return W64LIT(274877906880);} // 2^38-1 blocks
lword MaxFooterLength() const
{return 0;}
/// \brief Encrypts and calculates a MAC in one call
/// \param ciphertext the encryption buffer
/// \param mac the mac buffer
/// \param macSize the size of the MAC buffer, in bytes
/// \param iv the iv buffer
/// \param ivLength the size of the IV buffer, in bytes
/// \param aad the AAD buffer
/// \param aadLength the size of the AAD buffer, in bytes
/// \param message the message buffer
/// \param messageLength the size of the messagetext buffer, in bytes
/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
/// truncates the MAC if <tt>macSize < TagSize()</tt>.
virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength);
/// \brief Decrypts and verifies a MAC in one call
/// \param message the decryption buffer
/// \param mac the mac buffer
/// \param macSize the size of the MAC buffer, in bytes
/// \param iv the iv buffer
/// \param ivLength the size of the IV buffer, in bytes
/// \param aad the AAD buffer
/// \param aadLength the size of the AAD buffer, in bytes
/// \param ciphertext the cipher buffer
/// \param ciphertextLength the size of the ciphertext buffer, in bytes
/// \return true if the MAC is valid and the decoding succeeded, false otherwise
/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
/// is truncated if <tt>macLength < TagSize()</tt>.
virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength);
protected:
// AuthenticatedSymmetricCipherBase
bool AuthenticationIsOnPlaintext() const {return false;}
unsigned int AuthenticationBlockSize() const {return 1;}
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Resync(const byte *iv, size_t len);
size_t AuthenticateBlocks(const byte *data, size_t len);
void AuthenticateLastHeaderBlock();
void AuthenticateLastConfidentialBlock();
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
protected:
// See comments in chachapoly.cpp
void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs &params);
SecByteBlock m_userKey;
};
/// \brief ChaCha20Poly1305 cipher final implementation
/// \tparam T_IsEncryption flag indicating cipher direction
/// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
/// ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
/// AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha
/// and Poly1305.
/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
/// for IETF Protocols</A>.
/// \since Crypto++ 8.1
template <bool T_IsEncryption>
class ChaCha20Poly1305_Final : public ChaCha20Poly1305_Base
{
public:
static std::string StaticAlgorithmName()
{return std::string("ChaCha20/Poly1305");}
protected:
const SymmetricCipher & GetSymmetricCipher()
{return const_cast<ChaCha20Poly1305_Final *>(this)->AccessSymmetricCipher();}
SymmetricCipher & AccessSymmetricCipher()
{return m_cipher;}
bool IsForwardTransformation() const
{return T_IsEncryption;}
const MessageAuthenticationCode & GetMAC() const
{return const_cast<ChaCha20Poly1305_Final *>(this)->AccessMAC();}
MessageAuthenticationCode & AccessMAC()
{return m_mac;}
private:
ChaChaTLS::Encryption m_cipher;
Poly1305TLS m_mac;
};
/// \brief ChaCha20/Poly1305-TLS AEAD scheme
/// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
/// ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
/// AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha
/// and Poly1305.
/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
/// for IETF Protocols</A>.
/// \since Crypto++ 8.1
struct ChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation
{
/// \brief ChaCha20Poly1305 encryption
typedef ChaCha20Poly1305_Final<true> Encryption;
/// \brief ChaCha20Poly1305 decryption
typedef ChaCha20Poly1305_Final<false> Decryption;
};
////////////////////////////// IETF XChaCha20 draft //////////////////////////////
/// \brief XChaCha20Poly1305 cipher base implementation
/// \details Base implementation of the AuthenticatedSymmetricCipher interface
/// \since Crypto++ 8.1
class XChaCha20Poly1305_Base : public AuthenticatedSymmetricCipherBase
{
public:
virtual ~XChaCha20Poly1305_Base() {}
virtual const MessageAuthenticationCode & GetMAC() const = 0;
virtual MessageAuthenticationCode & AccessMAC() = 0;
public:
// AuthenticatedSymmetricCipher
std::string AlgorithmName() const
{return std::string("XChaCha20/Poly1305");}
std::string AlgorithmProvider() const
{return GetSymmetricCipher().AlgorithmProvider();}
size_t MinKeyLength() const
{return 32;}
size_t MaxKeyLength() const
{return 32;}
size_t DefaultKeyLength() const
{return 32;}
size_t GetValidKeyLength(size_t n) const
{CRYPTOPP_UNUSED(n); return 32;}
bool IsValidKeyLength(size_t n) const
{return n==32;}
unsigned int OptimalDataAlignment() const
{return GetSymmetricCipher().OptimalDataAlignment();}
IV_Requirement IVRequirement() const
{return UNIQUE_IV;}
unsigned int IVSize() const
{return 24;}
unsigned int MinIVLength() const
{return 24;}
unsigned int MaxIVLength() const
{return 24;}
unsigned int DigestSize() const
{return 16;}
lword MaxHeaderLength() const
{return LWORD_MAX;} // 2^64-1 bytes
lword MaxMessageLength() const
{return W64LIT(274877906880);} // 2^38-1 blocks
lword MaxFooterLength() const
{return 0;}
/// \brief Encrypts and calculates a MAC in one call
/// \param ciphertext the encryption buffer
/// \param mac the mac buffer
/// \param macSize the size of the MAC buffer, in bytes
/// \param iv the iv buffer
/// \param ivLength the size of the IV buffer, in bytes
/// \param aad the AAD buffer
/// \param aadLength the size of the AAD buffer, in bytes
/// \param message the message buffer
/// \param messageLength the size of the messagetext buffer, in bytes
/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
/// truncates the MAC if <tt>macSize < TagSize()</tt>.
virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength);
/// \brief Decrypts and verifies a MAC in one call
/// \param message the decryption buffer
/// \param mac the mac buffer
/// \param macSize the size of the MAC buffer, in bytes
/// \param iv the iv buffer
/// \param ivLength the size of the IV buffer, in bytes
/// \param aad the AAD buffer
/// \param aadLength the size of the AAD buffer, in bytes
/// \param ciphertext the cipher buffer
/// \param ciphertextLength the size of the ciphertext buffer, in bytes
/// \return true if the MAC is valid and the decoding succeeded, false otherwise
/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
/// is truncated if <tt>macLength < TagSize()</tt>.
virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength);
protected:
// AuthenticatedSymmetricCipherBase
bool AuthenticationIsOnPlaintext() const {return false;}
unsigned int AuthenticationBlockSize() const {return 1;}
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
void Resync(const byte *iv, size_t len);
size_t AuthenticateBlocks(const byte *data, size_t len);
void AuthenticateLastHeaderBlock();
void AuthenticateLastConfidentialBlock();
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
protected:
// See comments in chachapoly.cpp
void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs &params);
SecByteBlock m_userKey;
};
/// \brief XChaCha20Poly1305 cipher final implementation
/// \tparam T_IsEncryption flag indicating cipher direction
/// \details XChaCha20Poly1305 is an authenticated encryption scheme that combines
/// XChaCha20 and Poly1305-TLS. The scheme is defined in RFC 8439, section 2.8,
/// AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha
/// and Poly1305.
/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
/// for IETF Protocols</A>.
/// \since Crypto++ 8.1
template <bool T_IsEncryption>
class XChaCha20Poly1305_Final : public XChaCha20Poly1305_Base
{
public:
static std::string StaticAlgorithmName()
{return std::string("XChaCha20/Poly1305");}
protected:
const SymmetricCipher & GetSymmetricCipher()
{return const_cast<XChaCha20Poly1305_Final *>(this)->AccessSymmetricCipher();}
SymmetricCipher & AccessSymmetricCipher()
{return m_cipher;}
bool IsForwardTransformation() const
{return T_IsEncryption;}
const MessageAuthenticationCode & GetMAC() const
{return const_cast<XChaCha20Poly1305_Final *>(this)->AccessMAC();}
MessageAuthenticationCode & AccessMAC()
{return m_mac;}
private:
XChaCha20::Encryption m_cipher;
Poly1305TLS m_mac;
};
/// \brief XChaCha20/Poly1305-TLS AEAD scheme
/// \details XChaCha20Poly1305 is an authenticated encryption scheme that combines
/// XChaCha20 and Poly1305-TLS. The scheme is defined in RFC 8439, section 2.8,
/// AEAD_XCHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha
/// and Poly1305.
/// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
/// for IETF Protocols</A>.
/// \since Crypto++ 8.1
struct XChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation
{
/// \brief XChaCha20Poly1305 encryption
typedef XChaCha20Poly1305_Final<true> Encryption;
/// \brief XChaCha20Poly1305 decryption
typedef XChaCha20Poly1305_Final<false> Decryption;
};
NAMESPACE_END
#endif // CRYPTOPP_CHACHA_POLY1305_H

View File

@ -95,7 +95,7 @@ public:
#endif
};
/// \brief Encryption transformation
/// \brief Decryption transformation
/// \details Dec provides implementation for decryption transformation. All key and block
/// sizes are supported.
/// \since Crypto++ 8.0
@ -109,11 +109,15 @@ public:
#endif
};
/// \brief CHAM64 encryption
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
/// \brief CHAM64 decryption
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
/// \brief CHAM64 encryption
typedef CHAM64::Encryption CHAM64Encryption;
/// \brief CHAM64 decryption
typedef CHAM64::Decryption CHAM64Decryption;
/// \brief CHAM 128-bit block cipher
@ -154,7 +158,7 @@ public:
#endif
};
/// \brief Encryption transformation
/// \brief Decryption transformation
/// \details Dec provides implementation for decryption transformation. All key and block
/// sizes are supported.
/// \since Crypto++ 8.0
@ -168,11 +172,15 @@ public:
#endif
};
/// \brief CHAM128 encryption
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
/// \brief CHAM128 decryption
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
/// \brief CHAM128 encryption
typedef CHAM128::Encryption CHAM128Encryption;
/// \brief CHAM128 decryption
typedef CHAM128::Decryption CHAM128Decryption;
NAMESPACE_END

View File

@ -10,20 +10,14 @@
#include "cham.h"
#include "misc.h"
#include "adv_simd.h"
// Uncomment for benchmarking C++ against SSE or NEON.
// Do so in both simon.cpp and simon-simd.cpp.
// #undef CRYPTOPP_SSSE3_AVAILABLE
// #undef CRYPTOPP_ARM_NEON_AVAILABLE
#if defined(CRYPTOPP_SSE2_AVAILABLE)
# define CRYPTOPP_AVX512_ROTATE 1
# include <xmmintrin.h>
# include <emmintrin.h>
#endif
#if (CRYPTOPP_SSSE3_AVAILABLE)
#include "adv_simd.h"
# include <pmmintrin.h>
# include <tmmintrin.h>
#endif
@ -32,6 +26,11 @@
# include <ammintrin.h>
#endif
#if defined(__AVX512F__)
# define CRYPTOPP_AVX512_ROTATE 1
# include <immintrin.h>
#endif
// Squash MS LNK4221 and libtool warnings
extern const char CHAM_SIMD_FNAME[] = __FILE__;
@ -68,7 +67,6 @@ inline __m128i RotateRight16(const __m128i& val)
#endif
}
// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks.
template <>
inline __m128i RotateLeft16<8>(const __m128i& val)
{
@ -80,7 +78,6 @@ inline __m128i RotateLeft16<8>(const __m128i& val)
#endif
}
// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks.
template <>
inline __m128i RotateRight16<8>(const __m128i& val)
{

View File

@ -68,6 +68,30 @@
# define CRYPTOPP_DISABLE_ASM 1
#endif
// Some Clang and SunCC cannot handle mixed asm with positional arguments,
// where the body is Intel style with no prefix and the templates are
// AT&T style. Define this is the Makefile misdetects the configuration.
// Also see https://bugs.llvm.org/show_bug.cgi?id=39895 .
// #define CRYPTOPP_DISABLE_MIXED_ASM 1
// Several compilers discard SIMD code that loads unaligned data. The symptom
// is often self test failures and UBsan findings for unaligned loads. For
// example, Power7 can load unaligned data using vec_vsx_ld but some versions
// of GCC and Clang require 16-byte aligned data when using the builtin.
// It is not limited to SSE and PowerPC code. Define this to disable
// Crypto++ code that uses potentially problematic builtins or intrinsics.
// Also see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88234 and
// https://bugs.llvm.org/show_bug.cgi?id=39704
// #define CRYPTOPP_BUGGY_SIMD_LOAD_AND_STORE 1
// This list will probably grow over time as more compilers are identified.
#if defined(CRYPTOPP_BUGGY_SIMD_LOAD_AND_STORE)
# define CRYPTOPP_DISABLE_LEA_SIMD 1
# define CRYPTOPP_DISABLE_SIMON_SIMD 1
# define CRYPTOPP_DISABLE_SPECK_SIMD 1
# define CRYPTOPP_DISABLE_SM4_SIMD 1
#endif
// Define CRYPTOPP_NO_CXX11 to avoid C++11 related features shown at the
// end of this file. Some compilers and standard C++ headers advertise C++11
// but they are really just C++03 with some additional C++11 headers and
@ -92,7 +116,7 @@
// the version of the library the headers came from. It is not
// necessarily the version of the library built as a shared object if
// versions are inadvertently mixed and matched.
#define CRYPTOPP_VERSION 800
#define CRYPTOPP_VERSION 810
// Define this if you want to set a prefix for TestData/ and TestVectors/
// Be sure to add the trailing slash since its simple concatenation.
@ -291,12 +315,6 @@ const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
#define CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE 1
#endif
// Some Clang cannot handle mixed asm with positional arguments, where the
// body is Intel style with no prefix and the templates are AT&T style.
// Define this is the Makefile misdetects the configuration.
// Also see https://bugs.llvm.org/show_bug.cgi?id=39895 .
// #define CRYPTOPP_DISABLE_MIXED_ASM 1
// define hword, word, and dword. these are used for multiprecision integer arithmetic
// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
@ -573,7 +591,7 @@ NAMESPACE_END
// Requires Binutils 2.24
#if !defined(CRYPTOPP_DISABLE_AVX2) && defined(CRYPTOPP_AVX_AVAILABLE) && \
(defined(__AVX2__) || (CRYPTOPP_MSC_VERSION >= 1800) || (__SUNPRO_CC >= 0x5130) || \
(CRYPTOPP_GCC_VERSION >= 40700) || (__INTEL_COMPILER >= 1400) || \
(CRYPTOPP_GCC_VERSION >= 40900) || (__INTEL_COMPILER >= 1400) || \
(CRYPTOPP_LLVM_CLANG_VERSION >= 30100) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40600))
#define CRYPTOPP_AVX2_AVAILABLE 1
#endif
@ -645,7 +663,7 @@ NAMESPACE_END
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_NEON) || defined(__ARM_FEATURE_NEON) || defined(__ARM_FEATURE_ASIMD) || \
(CRYPTOPP_GCC_VERSION >= 40800) || (CRYPTOPP_CLANG_VERSION >= 30300) || \
(CRYPTOPP_MSC_VERSION >= 1910)
(CRYPTOPP_MSC_VERSION >= 1916)
# define CRYPTOPP_ARM_NEON_AVAILABLE 1
# define CRYPTOPP_ARM_ASIMD_AVAILABLE 1
# endif // Compilers
@ -658,7 +676,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_CRC32_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_CRC32) || (CRYPTOPP_GCC_VERSION >= 40800) || \
(CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_MSC_VERSION >= 1910)
(CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_MSC_VERSION >= 1916)
# define CRYPTOPP_ARM_CRC32_AVAILABLE 1
# endif // Compilers
# endif // Platforms
@ -670,7 +688,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_PMULL_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \
(CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_MSC_VERSION >= 1910)
(CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_MSC_VERSION >= 1916)
# define CRYPTOPP_ARM_PMULL_AVAILABLE 1
# endif // Compilers
# endif // Platforms
@ -694,7 +712,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \
(CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_MSC_VERSION >= 1910)
(CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_MSC_VERSION >= 1916)
# define CRYPTOPP_ARM_SHA1_AVAILABLE 1
# define CRYPTOPP_ARM_SHA2_AVAILABLE 1
# endif // Compilers
@ -707,7 +725,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_SHA3) || (CRYPTOPP_GCC_VERSION >= 80000) || \
(CRYPTOPP_MSC_VERSION >= 2100)
(CRYPTOPP_MSC_VERSION >= 5000)
# define CRYPTOPP_ARM_SHA512_AVAILABLE 1
# define CRYPTOPP_ARM_SHA3_AVAILABLE 1
# endif // Compilers
@ -720,7 +738,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_SM3_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_SM3) || (CRYPTOPP_GCC_VERSION >= 80000) || \
(CRYPTOPP_MSC_VERSION >= 2100)
(CRYPTOPP_MSC_VERSION >= 5000)
# define CRYPTOPP_ARM_SM3_AVAILABLE 1
# define CRYPTOPP_ARM_SM4_AVAILABLE 1
# endif // Compilers
@ -921,7 +939,7 @@ NAMESPACE_END
#ifndef NO_OS_DEPENDENCE
#if defined(_WIN32) || defined(__CYGWIN__)
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#define CRYPTOPP_WIN32_AVAILABLE
#endif

View File

@ -322,8 +322,13 @@ void DetectX86Features()
CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27))
if ((cpuid1[2] & AVX_FLAG) == AVX_FLAG)
{
// Unable to perform the necessary tests
#if defined(CRYPTOPP_DISABLE_ASM)
g_hasAVX = false;
// GCC 4.1/Binutils 2.17 cannot consume xgetbv
#if defined(__GNUC__) || (__SUNPRO_CC >= 0x5100) || defined(__BORLANDC__)
#elif defined(__GNUC__) || (__SUNPRO_CC >= 0x5100) || defined(__BORLANDC__)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and
// http://www.agner.org/optimize/vectorclass/read.php?i=65
word32 a=0, d=0;
@ -331,7 +336,7 @@ void DetectX86Features()
(
// "xgetbv" : "=a"(a), "=d"(d) : "c"(0) :
".byte 0x0f, 0x01, 0xd0" "\n\t"
: "=a"(a), "=d"(d) : "c"(0) :
: "=a"(a), "=d"(d) : "c"(0) : "cc"
);
word64 xcr0 = a | static_cast<word64>(d) << 32;
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
@ -360,8 +365,12 @@ void DetectX86Features()
#elif defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
word64 xcr0 = ExtendedControlRegister(0);
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
#elif defined(__SUNPRO_CC) // fall into
// Downlevel SunCC
#elif defined(__SUNPRO_CC)
g_hasAVX = false;
// _xgetbv is available
#else
word64 xcr0 = _xgetbv(0);
g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;

View File

@ -14,7 +14,8 @@
# include <nmmintrin.h>
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif

View File

@ -16,12 +16,17 @@
# You must also add /DCRYPTOPP_DEBUG or /DDEBUG if you want a debug build with
# the library's assert. The library moved from Posix NDEBUG and assert() to
# CRYPTOPP_ASSERT at 5.6.5 due to CVE-2016-7420. CRYPTOPP_ASSERT has the
# additional benefit of using DebugBreak(), and the program does not crash
# additional benefit of using DebugBreak(), and the program does not crash
# while you are debugging it like would happen with Posix assert().
# There is mention of cryptopp.dll, CRYPTOPP_IMPORTS and CRYPTOPP_EXPORTS
# below. They are for testing only. Attempting to produce a working DLL on
# Windows fails. Too many missing symbols because cryptest.exe exercises
# about 80% of the library, but CRYPTOPP_DLL is only used for FIPS algos.
# The list of LIB_SRCS and TEST_SRCS was generated under Linux with
# "make sources | fold -w74 -s". The list of LIB_OBJS and TEST_OBJS was
# generated with "make sources | fold -w74 -s | sed 's|.cpp|.obj|g'". The
# "make sources | fold -w73 -s". The list of LIB_OBJS and TEST_OBJS was
# generated with "make sources | fold -w73 -s | sed 's|.cpp|.obj|g'". The
# order of the first three object files are significant. See C++ Static
# Initialization Order Fisaco on the Crypto++ wiki for details.
@ -56,29 +61,29 @@ LIB_SRCS = \
authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2.cpp \
blake2b_simd.cpp blake2s_simd.cpp blowfish.cpp blumshub.cpp camellia.cpp \
cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp chacha_avx.cpp \
chacha_simd.cpp cham.cpp cham_simd.cpp channels.cpp cmac.cpp crc.cpp \
crc_simd.cpp darn.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp \
dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp dsa.cpp eax.cpp ec2n.cpp \
eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp \
filters.cpp fips140.cpp fipstest.cpp gcm.cpp gcm_simd.cpp gf256.cpp \
gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hc128.cpp hc256.cpp \
hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp \
kalyna.cpp kalynatab.cpp keccak.cpp keccakc.cpp lea.cpp lea_simd.cpp \
luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp \
mqueue.cpp mqv.cpp nbtheory.cpp neon_simd.cpp oaep.cpp osrng.cpp \
padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp \
ppc_power7.cpp ppc_power8.cpp ppc_power9.cpp ppc_simd.cpp pssr.cpp \
pubkey.cpp queue.cpp rabbit.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp \
rc6.cpp rdrand.cpp rdtables.cpp rijndael.cpp rijndael_simd.cpp ripemd.cpp \
rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp \
serpent.cpp sha.cpp sha3.cpp sha_simd.cpp shacal2.cpp shacal2_simd.cpp \
shark.cpp sharkbox.cpp simeck.cpp simeck_simd.cpp simon.cpp \
simon128_simd.cpp simon64_simd.cpp skipjack.cpp sm3.cpp sm4.cpp \
sm4_simd.cpp sosemanuk.cpp speck.cpp speck128_simd.cpp speck64_simd.cpp \
square.cpp squaretb.cpp sse_simd.cpp strciphr.cpp tea.cpp tftables.cpp \
threefish.cpp tiger.cpp tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp \
vmac.cpp wake.cpp whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp \
zdeflate.cpp zinflate.cpp zlib.cpp
chacha_simd.cpp chachapoly.cpp cham.cpp cham_simd.cpp channels.cpp \
cmac.cpp crc.cpp crc_simd.cpp darn.cpp default.cpp des.cpp dessp.cpp \
dh.cpp dh2.cpp dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp dsa.cpp \
eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp \
esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm.cpp \
gcm_simd.cpp gf256.cpp gf2_32.cpp gf2n.cpp gf2n_simd.cpp gfpcrypt.cpp \
gost.cpp gzip.cpp hc128.cpp hc256.cpp hex.cpp hight.cpp hmac.cpp \
hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp \
keccak.cpp keccakc.cpp lea.cpp lea_simd.cpp luc.cpp mars.cpp marss.cpp \
md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp \
nbtheory.cpp neon_simd.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp \
pkcspad.cpp poly1305.cpp polynomi.cpp ppc_power7.cpp ppc_power8.cpp \
ppc_power9.cpp ppc_simd.cpp pssr.cpp pubkey.cpp queue.cpp rabbit.cpp \
rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp \
rijndael.cpp rijndael_simd.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp \
safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha.cpp \
sha3.cpp sha_simd.cpp shacal2.cpp shacal2_simd.cpp shark.cpp sharkbox.cpp \
simeck.cpp simeck_simd.cpp simon.cpp simon128_simd.cpp simon64_simd.cpp \
skipjack.cpp sm3.cpp sm4.cpp sm4_simd.cpp sosemanuk.cpp speck.cpp \
speck128_simd.cpp speck64_simd.cpp square.cpp squaretb.cpp sse_simd.cpp \
strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp \
ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wake.cpp whrlpool.cpp \
xed25519.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
LIB_OBJS = \
cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj \
@ -86,29 +91,32 @@ LIB_OBJS = \
authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2.obj \
blake2b_simd.obj blake2s_simd.obj blowfish.obj blumshub.obj camellia.obj \
cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj chacha_avx.obj \
chacha_simd.obj cham.obj cham_simd.obj channels.obj cmac.obj crc.obj \
crc_simd.obj darn.obj default.obj des.obj dessp.obj dh.obj dh2.obj \
dll.obj donna_32.obj donna_64.obj donna_sse.obj dsa.obj eax.obj ec2n.obj \
eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj \
filters.obj fips140.obj fipstest.obj gcm.obj gcm_simd.obj gf256.obj \
gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hc128.obj hc256.obj \
hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj \
kalyna.obj kalynatab.obj keccak.obj keccakc.obj lea.obj lea_simd.obj \
luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj \
mqueue.obj mqv.obj nbtheory.obj neon_simd.obj oaep.obj osrng.obj \
padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj \
ppc_power7.obj ppc_power8.obj ppc_power9.obj ppc_simd.obj pssr.obj \
pubkey.obj queue.obj rabbit.obj rabin.obj randpool.obj rc2.obj rc5.obj \
rc6.obj rdrand.obj rdtables.obj rijndael.obj rijndael_simd.obj ripemd.obj \
rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj \
serpent.obj sha.obj sha3.obj sha_simd.obj shacal2.obj shacal2_simd.obj \
shark.obj sharkbox.obj simeck.obj simeck_simd.obj simon.obj \
simon128_simd.obj simon64_simd.obj skipjack.obj sm3.obj sm4.obj \
sm4_simd.obj sosemanuk.obj speck.obj speck128_simd.obj speck64_simd.obj \
square.obj squaretb.obj sse_simd.obj strciphr.obj tea.obj tftables.obj \
threefish.obj tiger.obj tigertab.obj ttmac.obj tweetnacl.obj twofish.obj \
vmac.obj wake.obj whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj \
zdeflate.obj zinflate.obj zlib.obj
chacha_simd.obj chachapoly.obj cham.obj cham_simd.obj channels.obj \
cmac.obj crc.obj crc_simd.obj darn.obj default.obj des.obj dessp.obj \
dh.obj dh2.obj dll.obj donna_32.obj donna_64.obj donna_sse.obj dsa.obj \
eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj \
esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm.obj \
gcm_simd.obj gf256.obj gf2_32.obj gf2n.obj gf2n_simd.obj gfpcrypt.obj \
gost.obj gzip.obj hc128.obj hc256.obj hex.obj hight.obj hmac.obj \
hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj \
keccak.obj keccakc.obj lea.obj lea_simd.obj luc.obj mars.obj marss.obj \
md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj \
nbtheory.obj neon_simd.obj oaep.obj osrng.obj padlkrng.obj panama.obj \
pkcspad.obj poly1305.obj polynomi.obj ppc_power7.obj ppc_power8.obj \
ppc_power9.obj ppc_simd.obj pssr.obj pubkey.obj queue.obj rabbit.obj \
rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj \
rijndael.obj rijndael_simd.obj ripemd.obj rng.obj rsa.obj rw.obj \
safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha.obj \
sha3.obj sha_simd.obj shacal2.obj shacal2_simd.obj shark.obj sharkbox.obj \
simeck.obj simeck_simd.obj simon.obj simon128_simd.obj simon64_simd.obj \
skipjack.obj sm3.obj sm4.obj sm4_simd.obj sosemanuk.obj speck.obj \
speck128_simd.obj speck64_simd.obj square.obj squaretb.obj sse_simd.obj \
strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj \
ttmac.obj tweetnacl.obj twofish.obj vmac.obj wake.obj whrlpool.obj \
xed25519.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
ASM_OBJS = \
rdrand-x86.obj rdrand-x64.obj x64masm.obj x64dll.obj
TEST_SRCS = \
test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \
@ -127,7 +135,15 @@ TEST_OBJS = \
CXX = cl.exe
LD = link.exe
AR = lib.exe
RM = del.exe
RM = del
RMDIR = rd
# We may misdetect the environment on VS2005 or so. Uncomment as
# needed to match the Developer Prompt environment.
# PLATFORM = x86
# PLATFORM = x64
# PLATFORM = arm
# PLATFORM = arm64
# C4231 is needed for VS2008 and below. Lots of noise...
CXXFLAGS = /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc
@ -195,7 +211,6 @@ LDFLAGS = $(LDFLAGS) /MACHINE:X64
LDLIBS = $(LDLIBS) kernel32.lib
!ENDIF
# We still don't know what we need for ARM64 on Windows. ARM64 and arm64 may be incorrect
!IF "$(PLATFORM)" == "ARM" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "ARM64" || "$(PLATFORM)" == "arm64"
# CXXFLAGS = $(CXXFLAGS) /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
@ -207,14 +222,57 @@ LIB_OBJS = $(LIB_OBJS) neon_simd.obj
all: cryptest.exe
# For testing cryptopp.dll and CRYPTOPP_IMPORTS
#cryptest.exe: pch.pch cryptopp.lib $(TEST_OBJS)
# $(LD) $(LDFLAGS) $(TEST_OBJS) cryptopp.lib $(LDLIBS) /out:$@
cryptest.exe: pch.pch cryptlib.lib $(TEST_OBJS)
$(LD) $(LDFLAGS) $(TEST_OBJS) cryptlib.lib $(LDLIBS) /out:$@
cryptlib.lib: $(LIB_OBJS)
$(AR) $(ARFLAGS) $(LIB_OBJS) /out:$@
clean:
$(RM) /F /Q pch.pch $(LIB_OBJS) pch.obj rdrand-x86.obj rdrand-x64.obj x64masm.obj x64dll.obj cryptlib.lib $(TEST_OBJS) cryptest.exe *.pdb
cryptopp.dump: cryptlib.lib
dumpbin.exe /LINKERMEMBER cryptlib.lib /OUT:$@
cryptopp.map: $(LIB_OBJS)
$(LD) $(LDFLAGS) /DLL /MAP /MAPINFO:EXPORTS $(LIB_OBJS)
mv cryptlib.map cryptopp.map
cryptopp.def: cryptopp.dump
dump2def.exe cryptopp.dump cryptopp.def
# LD produces 3 output artifacts for cryptopp.dll
cryptopp.dll cryptopp.lib cryptopp.exp: $(LIB_OBJS) cryptopp.def
$(LD) $(LDFLAGS) /DLL /DEF:cryptopp.def /IGNORE:4102 $(LIB_OBJS) $(LDLIBS) /out:cryptopp.dll
clean ::
$(RM) /F /Q cryptest.exe cryptest.lib cryptest.exp pch.pch 2>nul
clean ::
$(RM) /F /Q cryptlib.lib cryptlib.exp cryptlib.dll 2>nul
clean ::
$(RM) /F /Q cryptopp.dll cryptopp.lib cryptopp.exp cryptopp.def 2>nul
clean ::
$(RM) /F /Q pch.obj $(LIB_OBJS) $(ASM_OBJS) $(TEST_OBJS) *.pdb 2>nul
distclean :: clean
!IF EXIST ($(USERNAME).sdf)
attrib -r -a -s -h $(USERNAME).sdf 2>nul
$(RM) /F /Q $(USERNAME).sdf 2>nul
!ENDIF
!IF EXIST ($(USERNAME).suo)
attrib -r -a -s -h $(USERNAME).suo 2>nul
$(RM) /F /Q $(USERNAME).suo 2>nul
!ENDIF
!IF EXIST (Win32\)
$(RMDIR) Win32\ /q /s 2>nul
!ENDIF
!IF EXIST (x64\)
$(RMDIR) x64\ /q /s 2>nul
!ENDIF
!IF EXIST (ipch\)
$(RMDIR) ipch\ /q /s 2>nul
!ENDIF
# Precompiled header
pch.pch: pch.h pch.cpp
@ -245,6 +303,54 @@ chacha_avx.obj:
$(CXX) $(CXXFLAGS) /arch:AVX /c chacha_avx.cpp
!endif
# For testing cryptopp.dll and CRYPTOPP_IMPORTS
#CXXFLAGS_IMPORTS = /wd4275 /wd4251 /DCRYPTOPP_IMPORTS
#test.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#datatest.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#fipstest.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#bench1.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#bench2.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#bench3.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#regtest1.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#regtest2.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#regtest3.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#regtest4.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat1.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat2.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat3.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat4.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat5.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat6.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat7.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat8.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat9.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
#validat10.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_IMPORTS) /c $?
# For testing cryptopp.dll and CRYPTOPP_EXPORTS
#CXXFLAGS_EXPORTS = /wd4275 /wd4251 /DCXXFLAGS_EXPORTS
#.cpp.obj:
# $(CXX) $(CXXFLAGS) $(CXXFLAGS_EXPORTS) /c $<
.cpp.obj:
$(CXX) $(CXXFLAGS) /c $<

View File

@ -108,6 +108,7 @@ fi
THIS_SYSTEM=$(uname -s 2>&1)
IS_AIX=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c aix)
IS_DARWIN=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c darwin)
IS_HURD=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c gnu)
IS_LINUX=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c linux)
IS_CYGWIN=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c cygwin)
IS_MINGW=$(echo -n "$THIS_SYSTEM" | "$GREP" -i -c mingw)
@ -155,6 +156,8 @@ if [[ ("$IS_X86" -ne "0" || "$IS_X64" -ne "0") ]]; then
X86_CPU_FLAGS=$(grep Features /var/run/dmesg.boot)
elif [[ ("$IS_DRAGONFLY" -ne "0") ]]; then
X86_CPU_FLAGS=$(dmesg | grep Features)
elif [[ ("$IS_HURD" -ne "0") ]]; then
: # Do nothing... cpuid is not helpful at the moment
else
X86_CPU_FLAGS="$($AWK '{IGNORECASE=1}{if ($1 == "flags"){print;exit}}' < /proc/cpuinfo | cut -f 2 -d ':')"
fi

View File

@ -3,7 +3,7 @@
/// \file cryptlib.h
/// \brief Abstract base classes that provide a uniform interface to this library.
/*! \mainpage Crypto++ Library 8.0 API Reference
/*! \mainpage Crypto++ Library 8.1 API Reference
<dl>
<dt>Abstract Base Classes<dd>
cryptlib.h
@ -500,9 +500,9 @@ const std::string AAD_CHANNEL;
const NameValuePairs& g_nullNameValuePairs;
#else
extern const std::string DEFAULT_CHANNEL;
extern const std::string AAD_CHANNEL;
extern const NameValuePairs& g_nullNameValuePairs;
extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
extern CRYPTOPP_DLL const NameValuePairs& g_nullNameValuePairs;
#endif
// Document additional name spaces which show up elsewhere in the sources.
@ -1129,9 +1129,11 @@ public:
unsigned int TagSize() const {return DigestSize();}
/// \brief Provides the block size of the compression function
/// \return the block size of the compression function, in bytes
/// \details BlockSize() will return 0 if the hash is not block based. For example,
/// SHA3 is a recursive hash (not an iterative hash), and it does not have a block size.
/// \return block size of the compression function, in bytes
/// \details BlockSize() will return 0 if the hash is not block based
/// or does not have an equivalent block size. For example, Keccak
/// and SHA-3 do not have a block size, but they do have an equivalent
/// block size called rate expressed as <tt>r</tt>.
virtual unsigned int BlockSize() const {return 0;}
/// \brief Provides the input block size most efficient for this hash.
@ -1301,31 +1303,63 @@ public:
/// \brief Provides the maximum length of AAD that can be input
/// \return the maximum length of AAD that can be input before the encrypted data
virtual lword MaxHeaderLength() const =0;
/// \brief Provides the maximum length of encrypted data
/// \return the maximum length of encrypted data
virtual lword MaxMessageLength() const =0;
/// \brief Provides the the maximum length of AAD
/// \return the maximum length of AAD that can be input after the encrypted data
virtual lword MaxFooterLength() const {return 0;}
/// \brief Determines if data lengths must be specified prior to inputting data
/// \return true if the data lengths are required before inputting data, false otherwise
/// \details if this function returns true, SpecifyDataLengths() must be called before attempting to input data.
/// This is the case for some schemes, such as CCM.
/// \sa SpecifyDataLengths()
virtual bool NeedsPrespecifiedDataLengths() const {return false;}
/// \brief Prespecifies the data lengths
/// \details this function only needs to be called if NeedsPrespecifiedDataLengths() returns true
/// \brief Prescribes the data lengths
/// \param headerLength size of data before message is input, in bytes
/// \param messageLength size of the message, in bytes
/// \param footerLength size of data after message is input, in bytes
/// \details SpecifyDataLengths() only needs to be called if NeedsPrespecifiedDataLengths() returns <tt>true</tt>.
/// If <tt>true</tt>, then <tt>headerLength</tt> will be validated against <tt>MaxHeaderLength()</tt>,
/// <tt>messageLength</tt> will be validated against <tt>MaxMessageLength()</tt>, and
/// <tt>footerLength</tt> will be validated against <tt>MaxFooterLength()</tt>.
/// \sa NeedsPrespecifiedDataLengths()
void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0);
/// \brief Encrypts and calculates a MAC in one call
/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function will truncate MAC if
/// <tt>macSize < TagSize()</tt>.
/// \param ciphertext the encryption buffer
/// \param mac the mac buffer
/// \param macSize the size of the MAC buffer, in bytes
/// \param iv the iv buffer
/// \param ivLength the size of the IV buffer, in bytes
/// \param header the AAD buffer
/// \param headerLength the size of the AAD buffer, in bytes
/// \param message the message buffer
/// \param messageLength the size of the messagetext buffer, in bytes
/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
/// truncates the MAC if <tt>macSize < TagSize()</tt>.
virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength);
/// \brief Decrypts and verifies a MAC in one call
/// \param message the decryption buffer
/// \param mac the mac buffer
/// \param macSize the size of the MAC buffer, in bytes
/// \param iv the iv buffer
/// \param ivLength the size of the IV buffer, in bytes
/// \param header the AAD buffer
/// \param headerLength the size of the AAD buffer, in bytes
/// \param ciphertext the ciphertext buffer
/// \param ciphertextLength the size of the ciphertext buffer, in bytes
/// \return true if the MAC is valid and the decoding succeeded, false otherwise
/// \details DecryptAndVerify() decrypts and verifies the MAC in one call. The function returns true iff MAC is valid.
/// DecryptAndVerify() will assume MAC is truncated if <tt>macLength < TagSize()</tt>.
virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength);
/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
/// is truncated if <tt>macLength < TagSize()</tt>.
virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength);
/// \brief Provides the name of this algorithm
/// \return the standard algorithm name

View File

@ -198,6 +198,7 @@
<ExcludedFromBuild Condition=" '$(PlatformToolset)' == 'v100' Or '$(PlatformToolset)' == 'v110' ">true</ExcludedFromBuild>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
<ClCompile Include="chachapoly.cpp" />
<ClCompile Include="cham.cpp" />
<ClCompile Include="cham_simd.cpp" />
<ClCompile Include="channels.cpp" />
@ -238,6 +239,7 @@
<ClCompile Include="gf256.cpp" />
<ClCompile Include="gf2_32.cpp" />
<ClCompile Include="gf2n.cpp" />
<ClCompile Include="gf2n_simd.cpp" />
<ClCompile Include="gfpcrypt.cpp" />
<ClCompile Include="gost.cpp" />
<ClCompile Include="gzip.cpp" />
@ -255,7 +257,8 @@
<ClCompile Include="kalyna.cpp" />
<ClCompile Include="kalynatab.cpp" />
<ClCompile Include="keccak.cpp" />
<ClCompile Include="keccakc.cpp" />
<ClCompile Include="keccak_core.cpp" />
<ClCompile Include="keccak_simd.cpp" />
<ClCompile Include="lea.cpp" />
<ClCompile Include="lea_simd.cpp" />
<ClCompile Include="luc.cpp" />
@ -307,6 +310,7 @@
<ClCompile Include="sha3.cpp" />
<ClCompile Include="shacal2.cpp" />
<ClCompile Include="shacal2_simd.cpp" />
<ClCompile Include="shake.cpp" />
<ClCompile Include="shark.cpp" />
<ClCompile Include="sharkbox.cpp" />
<ClCompile Include="simeck.cpp" />
@ -403,6 +407,7 @@
<ClInclude Include="cbcmac.h" />
<ClInclude Include="ccm.h" />
<ClInclude Include="chacha.h" />
<ClInclude Include="chachapoly.h" />
<ClInclude Include="cham.h" />
<ClInclude Include="channels.h" />
<ClInclude Include="cmac.h" />
@ -457,7 +462,6 @@
<ClInclude Include="iterhash.h" />
<ClInclude Include="kalyna.h" />
<ClInclude Include="keccak.h" />
<ClInclude Include="keccakc.h" />
<ClInclude Include="lubyrack.h" />
<ClInclude Include="lea.h" />
<ClInclude Include="luc.h" />
@ -511,6 +515,7 @@
<ClInclude Include="sha.h" />
<ClInclude Include="sha3.h" />
<ClInclude Include="shacal2.h" />
<ClInclude Include="shake.h" />
<ClInclude Include="shark.h" />
<ClInclude Include="simple.h" />
<ClInclude Include="simeck.h" />

View File

@ -95,6 +95,9 @@
<ClCompile Include="chacha_avx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="chachapoly.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cham.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -203,6 +206,9 @@
<ClCompile Include="gf2n.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gf2n_simd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gfpcrypt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -251,7 +257,10 @@
<ClCompile Include="keccak.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="keccakc.cpp">
<ClCompile Include="keccak_core.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="keccak_simd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="lea.cpp">
@ -401,6 +410,9 @@
<ClCompile Include="shacal2_simd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shake.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shark.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -753,9 +765,6 @@
<ClInclude Include="keccak.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="keccakc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="lubyrack.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -915,6 +924,9 @@
<ClInclude Include="shacal2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shake.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shark.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -1014,11 +1026,20 @@
<ClInclude Include="chacha.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="chachapoly.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="rdrand.asm">
<Filter>Source Files</Filter>
</CustomBuild>
<CustomBuild Include="x64dll.asm">
<Filter>Source Files</Filter>
</CustomBuild>
<CustomBuild Include="x64masm.asm">
<Filter>Source Files</Filter>
</CustomBuild>
<CustomBuild Include="adhoc.cpp.proto">
<Filter>Miscellaneous</Filter>
</CustomBuild>

View File

@ -1 +1 @@
include("${CMAKE_CURRENT_LIST_DIR}/cryptopp-targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cryptopp-targets.cmake")

View File

@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 8,0,0,0
PRODUCTVERSION 8,0,0,0
FILEVERSION 8,1,0,0
PRODUCTVERSION 8,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -46,13 +46,13 @@ BEGIN
VALUE "Comments", "Free crypto library, more information available at www.cryptopp.com"
VALUE "CompanyName", "Wei Dai"
VALUE "FileDescription", "Crypto++® Library DLL"
VALUE "FileVersion", "8, 0, 0, 0"
VALUE "FileVersion", "8, 1, 0, 0"
VALUE "InternalName", "cryptopp"
VALUE "LegalCopyright", "Copyright© 1995-2018 by Wei Dai"
VALUE "LegalTrademarks", "Crypto++®"
VALUE "OriginalFilename", "cryptopp.dll"
VALUE "ProductName", "Crypto++® Library"
VALUE "ProductVersion", "8, 0, 0, 0"
VALUE "ProductVersion", "8, 1, 0, 0"
END
END
BLOCK "VarFileInfo"

View File

@ -527,7 +527,7 @@ void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
// been processed. Also note we only unlatch from testDataPairs. If
// overrideParameters are specified, the caller is responsible for
// managing the parameter.
v.erase("Tweak"); v.erase("BlockSize"); v.erase("BlockPaddingScheme");
v.erase("Tweak"); v.erase("InitialBlock"); v.erase("BlockSize"); v.erase("BlockPaddingScheme");
std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
if (test == "EncryptionMCT" || test == "DecryptionMCT")

View File

@ -81,6 +81,23 @@ int ed25519_publickey(byte publicKey[32], const byte secretKey[32]);
/// SHA512.
int ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], const byte publicKey[32], byte signature[64]);
/// \brief Creates a signature on a message
/// \param stream std::istream derived class
/// \param publicKey byte array with the public key
/// \param secretKey byte array with the private key
/// \param signature byte array for the signature
/// \returns 0 on success, non-0 otherwise
/// \details ed25519_sign() generates a signature on a message using
/// the public and private keys. The various buffers can be exact
/// sizes, and do not require extra space like when using the
/// NaCl library functions.
/// \details This ed25519_sign() overload handles large streams. It
/// was added for signing and verifying files that are too large
/// for a memory allocation.
/// \details At the moment the hash function for signing is fixed at
/// SHA512.
int ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32], byte signature[64]);
/// \brief Verifies a signature on a message
/// \param message byte array with the message
/// \param messageLength size of the message, in bytes
@ -88,13 +105,29 @@ int ed25519_sign(const byte* message, size_t messageLength, const byte secretKey
/// \param signature byte array with the signature
/// \returns 0 on success, non-0 otherwise
/// \details ed25519_sign_open() verifies a signature on a message using
/// the public. The various buffers can be exact sizes, and do not
/// the public key. The various buffers can be exact sizes, and do not
/// require extra space like when using the NaCl library functions.
/// \details At the moment the hash function for signing is fixed at
/// SHA512.
int
ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]);
/// \brief Verifies a signature on a message
/// \param stream std::istream derived class
/// \param publicKey byte array with the public key
/// \param signature byte array with the signature
/// \returns 0 on success, non-0 otherwise
/// \details ed25519_sign_open() verifies a signature on a message using
/// the public key. The various buffers can be exact sizes, and do not
/// require extra space like when using the NaCl library functions.
/// \details This ed25519_sign_open() overload handles large streams. It
/// was added for signing and verifying files that are too large
/// for a memory allocation.
/// \details At the moment the hash function for signing is fixed at
/// SHA512.
int
ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64]);
//****************************** Internal ******************************//
#ifndef CRYPTOPP_DOXYGEN_PROCESSING

View File

@ -27,6 +27,13 @@
#include "misc.h"
#include "cpu.h"
#include <istream>
#include <sstream>
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic ignored "-Wunused-function"
#endif
// Squash MS LNK4221 and libtool warnings
extern const char DONNA32_FNAME[] = __FILE__;
@ -1029,7 +1036,21 @@ ed25519_extsk(hash_512bits extsk, const byte sk[32]) {
}
void
ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const unsigned char *m, size_t mlen) {
UpdateFromStream(HashTransformation& hash, std::istream& stream)
{
SecByteBlock block(4096);
while (stream.read((char*)block.begin(), block.size()))
hash.Update(block, block.size());
std::streamsize rem = stream.gcount();
if (rem)
hash.Update(block, (size_t)rem);
block.SetMark(0);
}
void
ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const byte *m, size_t mlen) {
SHA512 hash;
hash.Update(RS, 32);
hash.Update(pk, 32);
@ -1037,6 +1058,15 @@ ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const unsi
hash.Final(hram);
}
void
ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], std::istream& stream) {
SHA512 hash;
hash.Update(RS, 32);
hash.Update(pk, 32);
UpdateFromStream(hash, stream);
hash.Final(hram);
}
inline bignum256modm_element_t
lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
return (a - b) >> 31;
@ -1552,7 +1582,7 @@ ge25519_pack(byte r[32], const ge25519 *p) {
}
int
ed25519_verify(const unsigned char *x, const unsigned char *y, size_t len) {
ed25519_verify(const byte *x, const byte *y, size_t len) {
size_t differentbits = 0;
while (len--)
differentbits |= (*x++ ^ *y++);
@ -1735,7 +1765,7 @@ int curve25519_mult_CXX(byte sharedKey[32], const byte secretKey[32], const byte
using namespace CryptoPP::Donna::X25519;
FixedSizeSecBlock<byte, 32> e;
for (size_t i = 0;i < 32;++i)
for (size_t i = 0; i < 32; ++i)
e[i] = secretKey[i];
e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40;
@ -1853,6 +1883,55 @@ ed25519_publickey(byte publicKey[32], const byte secretKey[32])
return ed25519_publickey_CXX(publicKey, secretKey);
}
int
ed25519_sign_CXX(std::istream& stream, const byte sk[32], const byte pk[32], byte RS[64])
{
using namespace CryptoPP::Donna::Ed25519;
bignum256modm r, S, a;
ALIGN(16) ge25519 R;
hash_512bits extsk, hashr, hram;
// Unfortunately we need to read the stream twice. The fisrt time calculates
// 'r = H(aExt[32..64], m)'. The second time calculates 'S = H(R,A,m)'. There
// is a data dependency due to hashing 'RS' with 'R = [r]B' that does not
// allow us to read the stream once.
std::streampos where = stream.tellg();
ed25519_extsk(extsk, sk);
/* r = H(aExt[32..64], m) */
SHA512 hash;
hash.Update(extsk + 32, 32);
UpdateFromStream(hash, stream);
hash.Final(hashr);
expand256_modm(r, hashr, 64);
/* R = rB */
ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
ge25519_pack(RS, &R);
// Reset stream for the second digest
stream.clear();
stream.seekg(where);
/* S = H(R,A,m).. */
ed25519_hram(hram, RS, pk, stream);
expand256_modm(S, hram, 64);
/* S = H(R,A,m)a */
expand256_modm(a, extsk, 32);
mul256_modm(S, S, a);
/* S = (r + H(R,A,m)a) */
add256_modm(S, S, r);
/* S = (r + H(R,A,m)a) mod L */
contract256_modm(RS + 32, S);
return 0;
}
int
ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32], byte RS[64])
{
@ -1892,6 +1971,13 @@ ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32
return 0;
}
int
ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32],
byte signature[64])
{
return ed25519_sign_CXX(stream, secretKey, publicKey, signature);
}
int
ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32],
const byte publicKey[32], byte signature[64])
@ -1899,6 +1985,34 @@ ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32]
return ed25519_sign_CXX(message, messageLength, secretKey, publicKey, signature);
}
int
ed25519_sign_open_CXX(std::istream& stream, const byte pk[32], const byte RS[64]) {
using namespace CryptoPP::Donna::Ed25519;
ALIGN(16) ge25519 R, A;
hash_512bits hash;
bignum256modm hram, S;
byte checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1;
/* hram = H(R,A,m) */
ed25519_hram(hash, RS, pk, stream);
expand256_modm(hram, hash, 64);
/* S */
expand256_modm(S, RS + 32, 32);
/* SB - H(R,A,m)A */
ge25519_double_scalarmult_vartime(&R, &A, hram, S);
ge25519_pack(checkR, &R);
/* check that R = SB - H(R,A,m)A */
return ed25519_verify(RS, checkR, 32) ? 0 : -1;
}
int
ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte RS[64]) {
@ -1907,7 +2021,7 @@ ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte
ALIGN(16) ge25519 R, A;
hash_512bits hash;
bignum256modm hram, S;
unsigned char checkR[32];
byte checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1;
@ -1933,6 +2047,12 @@ ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKe
return ed25519_sign_open_CXX(message, messageLength, publicKey, signature);
}
int
ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64])
{
return ed25519_sign_open_CXX(stream, publicKey, signature);
}
NAMESPACE_END // Donna
NAMESPACE_END // CryptoPP

View File

@ -27,6 +27,13 @@
#include "misc.h"
#include "cpu.h"
#include <istream>
#include <sstream>
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic ignored "-Wunused-function"
#endif
// Squash MS LNK4221 and libtool warnings
extern const char DONNA64_FNAME[] = __FILE__;
@ -728,7 +735,7 @@ curve25519_contract(byte *out, const bignum25519 input) {
/* out = (flag) ? in : out */
inline void
curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], word64 flag) {
curve25519_move_conditional_bytes(byte out[96], const byte in[96], word64 flag) {
const word64 nb = flag - 1, b = ~nb;
const word64 *inq = (const word64 *)in;
word64 *outq = (word64 *)out;
@ -749,7 +756,7 @@ curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], word64
/* if (iswap) swap(a, b) */
inline void
curve25519_swap_conditional(bignum25519 a, bignum25519 b, word64 iswap) {
const word64 swap = (word64)(-(int64_t)iswap);
const word64 swap = (word64)(-(sword64)iswap);
word64 x0,x1,x2,x3,x4;
x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0;
@ -777,7 +784,21 @@ ed25519_extsk(hash_512bits extsk, const byte sk[32]) {
}
void
ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const unsigned char *m, size_t mlen) {
UpdateFromStream(HashTransformation& hash, std::istream& stream)
{
SecByteBlock block(4096);
while (stream.read((char*)block.begin(), block.size()))
hash.Update(block, block.size());
std::streamsize rem = stream.gcount();
if (rem)
hash.Update(block, rem);
block.SetMark(0);
}
void
ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const byte *m, size_t mlen) {
SHA512 hash;
hash.Update(RS, 32);
hash.Update(pk, 32);
@ -785,6 +806,15 @@ ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], const unsi
hash.Final(hram);
}
void
ed25519_hram(hash_512bits hram, const byte RS[64], const byte pk[32], std::istream& stream) {
SHA512 hash;
hash.Update(RS, 32);
hash.Update(pk, 32);
UpdateFromStream(hash, stream);
hash.Final(hram);
}
bignum256modm_element_t
lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
return (a - b) >> 63;
@ -857,7 +887,6 @@ barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256m
reduce256_modm(r);
}
void
add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
bignum256modm_element_t c;
@ -1268,7 +1297,7 @@ ge25519_pack(byte r[32], const ge25519 *p) {
}
int
ed25519_verify(const unsigned char *x, const unsigned char *y, size_t len) {
ed25519_verify(const byte *x, const byte *y, size_t len) {
size_t differentbits = 0;
while (len--)
differentbits |= (*x++ ^ *y++);
@ -1376,7 +1405,7 @@ ge25519_windowb_equal(word32 b, word32 c) {
}
void
ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], word32 pos, signed char b) {
ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const byte table[256][96], word32 pos, signed char b) {
bignum25519 neg;
word32 sign = (word32)((byte)b >> 7);
word32 mask = ~(sign - 1);
@ -1384,7 +1413,7 @@ ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][
word32 i;
/* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */
uint8_t packed[96] = {0};
byte packed[96] = {0};
packed[0] = 1;
packed[32] = 1;
@ -1406,7 +1435,7 @@ ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][
/* computes [s]basepoint */
void
ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t basepoint_table[256][96], const bignum256modm s) {
ge25519_scalarmult_base_niels(ge25519 *r, const byte basepoint_table[256][96], const bignum256modm s) {
signed char b[64];
word32 i;
ge25519_niels t;
@ -1569,6 +1598,54 @@ ed25519_publickey(byte publicKey[32], const byte secretKey[32])
return ed25519_publickey_CXX(publicKey, secretKey);
}
int
ed25519_sign_CXX(std::istream& stream, const byte sk[32], const byte pk[32], byte RS[64])
{
using namespace CryptoPP::Donna::Ed25519;
bignum256modm r, S, a;
ALIGN(16) ge25519 R;
hash_512bits extsk, hashr, hram;
// Unfortunately we need to read the stream twice. The fisrt time calculates
// 'r = H(aExt[32..64], m)'. The second time calculates 'S = H(R,A,m)'. There
// is a data dependency due to hashing 'RS' with 'R = [r]B' that does not
// allow us to read the stream once.
std::streampos where = stream.tellg();
ed25519_extsk(extsk, sk);
/* r = H(aExt[32..64], m) */
SHA512 hash;
hash.Update(extsk + 32, 32);
UpdateFromStream(hash, stream);
hash.Final(hashr);
expand256_modm(r, hashr, 64);
/* R = rB */
ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
ge25519_pack(RS, &R);
// Reset stream for the second digest
stream.clear();
stream.seekg(where);
/* S = H(R,A,m).. */
ed25519_hram(hram, RS, pk, stream);
expand256_modm(S, hram, 64);
/* S = H(R,A,m)a */
expand256_modm(a, extsk, 32);
mul256_modm(S, S, a);
/* S = (r + H(R,A,m)a) */
add256_modm(S, S, r);
/* S = (r + H(R,A,m)a) mod L */
contract256_modm(RS + 32, S);
return 0;
}
int
ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32], byte RS[64])
{
@ -1607,6 +1684,13 @@ ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32
return 0;
}
int
ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32],
byte signature[64])
{
return ed25519_sign_CXX(stream, secretKey, publicKey, signature);
}
int
ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32],
const byte publicKey[32], byte signature[64])
@ -1622,7 +1706,7 @@ ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte
ALIGN(16) ge25519 R, A;
hash_512bits hash;
bignum256modm hram, S;
unsigned char checkR[32];
byte checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1;
@ -1642,6 +1726,40 @@ ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte
return ed25519_verify(RS, checkR, 32) ? 0 : -1;
}
int
ed25519_sign_open_CXX(std::istream& stream, const byte pk[32], const byte RS[64]) {
using namespace CryptoPP::Donna::Ed25519;
ALIGN(16) ge25519 R, A;
hash_512bits hash;
bignum256modm hram, S;
byte checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1;
/* hram = H(R,A,m) */
ed25519_hram(hash, RS, pk, stream);
expand256_modm(hram, hash, 64);
/* S */
expand256_modm(S, RS + 32, 32);
/* SB - H(R,A,m)A */
ge25519_double_scalarmult_vartime(&R, &A, hram, S);
ge25519_pack(checkR, &R);
/* check that R = SB - H(R,A,m)A */
return ed25519_verify(RS, checkR, 32) ? 0 : -1;
}
int
ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64])
{
return ed25519_sign_open_CXX(stream, publicKey, signature);
}
int
ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64])
{

View File

@ -24,6 +24,7 @@
// and not the actual alignment of the variable and data.
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic ignored "-Wcast-align"
# pragma GCC diagnostic ignored "-Wunused-function"
#endif
// Squash MS LNK4221 and libtool warnings

View File

@ -99,7 +99,12 @@ template<> struct EcRecommendedParameters<EC2N>
StringSource ssA(a, true, new HexDecoder);
StringSource ssB(b, true, new HexDecoder);
if (t0 == 0)
return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
{
if (t2 == 233 && t3 == 74 && t4 == 0)
return new EC2N(GF2NT233(233, 74, 0), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
else
return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
}
else
return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
};

View File

@ -135,6 +135,7 @@ public:
try
{
this->GetMaterial().DoQuickSanityCheck();
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer)

View File

@ -30,18 +30,18 @@
#include <windows.h>
#if defined(_MSC_VER) && _MSC_VER >= 1400
#ifdef _M_IX86
#define _CRT_DEBUGGER_HOOK _crt_debugger_hook
#else
#define _CRT_DEBUGGER_HOOK __crt_debugger_hook
#endif
#if _MSC_VER < 1900
# ifdef _M_IX86
# define _CRT_DEBUGGER_HOOK _crt_debugger_hook
# else
# define _CRT_DEBUGGER_HOOK __crt_debugger_hook
# endif
# if _MSC_VER < 1900
extern "C" {_CRTIMP void __cdecl _CRT_DEBUGGER_HOOK(int);}
#else
# else
extern "C" {void __cdecl _CRT_DEBUGGER_HOOK(int); }
# endif
#endif
#endif
#endif
#endif // CRYPTOPP_WIN32_AVAILABLE
#include <sstream>
#include <iostream>
@ -401,7 +401,7 @@ bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModule
}
}
#if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(_M_ARM)
#if defined(_MSC_VER) && _MSC_VER >= 1400 && !(defined(_M_ARM) || defined(_M_ARM64))
// first byte of _CRT_DEBUGGER_HOOK gets modified in memory by the debugger invisibly, so read it from file
if (IsDebuggerPresent())
{

View File

@ -80,7 +80,7 @@ protected:
virtual BlockCipher & AccessBlockCipher() =0;
virtual GCM_TablesOption GetTablesOption() const =0;
const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();};
const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();}
byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;}
byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;}

View File

@ -29,7 +29,8 @@
# include <wmmintrin.h>
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
@ -38,6 +39,10 @@
# include <arm_acle.h>
#endif
#if defined(CRYPTOPP_ARM_PMULL_AVAILABLE)
# include "arm_simd.h"
#endif
#if defined(CRYPTOPP_ALTIVEC_AVAILABLE)
# include "ppc_simd.h"
#endif
@ -62,205 +67,6 @@
// Squash MS LNK4221 and libtool warnings
extern const char GCM_SIMD_FNAME[] = __FILE__;
ANONYMOUS_NAMESPACE_BEGIN
// *************************** ARM NEON *************************** //
#if CRYPTOPP_ARM_PMULL_AVAILABLE
#if defined(__GNUC__)
// Schneiders, Hovsmith and O'Rourke used this trick.
// It results in much better code generation in production code
// by avoiding D-register spills when using vgetq_lane_u64. The
// problem does not surface under minimal test cases.
inline uint64x2_t PMULL_00(const uint64x2_t a, const uint64x2_t b)
{
uint64x2_t r;
__asm __volatile("pmull %0.1q, %1.1d, %2.1d \n\t"
:"=w" (r) : "w" (a), "w" (b) );
return r;
}
inline uint64x2_t PMULL_01(const uint64x2_t a, const uint64x2_t b)
{
uint64x2_t r;
__asm __volatile("pmull %0.1q, %1.1d, %2.1d \n\t"
:"=w" (r) : "w" (a), "w" (vget_high_u64(b)) );
return r;
}
inline uint64x2_t PMULL_10(const uint64x2_t a, const uint64x2_t b)
{
uint64x2_t r;
__asm __volatile("pmull %0.1q, %1.1d, %2.1d \n\t"
:"=w" (r) : "w" (vget_high_u64(a)), "w" (b) );
return r;
}
inline uint64x2_t PMULL_11(const uint64x2_t a, const uint64x2_t b)
{
uint64x2_t r;
__asm __volatile("pmull2 %0.1q, %1.2d, %2.2d \n\t"
:"=w" (r) : "w" (a), "w" (b) );
return r;
}
inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b, unsigned int c)
{
uint64x2_t r;
__asm __volatile("ext %0.16b, %1.16b, %2.16b, %3 \n\t"
:"=w" (r) : "w" (a), "w" (b), "I" (c) );
return r;
}
// https://github.com/weidai11/cryptopp/issues/366
template <unsigned int C>
inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b)
{
uint64x2_t r;
__asm __volatile("ext %0.16b, %1.16b, %2.16b, %3 \n\t"
:"=w" (r) : "w" (a), "w" (b), "I" (C) );
return r;
}
#endif // GCC and compatibles
#if defined(_MSC_VER)
inline uint64x2_t PMULL_00(const uint64x2_t a, const uint64x2_t b)
{
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
}
inline uint64x2_t PMULL_01(const uint64x2_t a, const uint64x2_t b)
{
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),0),
vgetq_lane_u64(vreinterpretq_u64_u8(b),1)));
}
inline uint64x2_t PMULL_10(const uint64x2_t a, const uint64x2_t b)
{
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
vgetq_lane_u64(vreinterpretq_u64_u8(b),0)));
}
inline uint64x2_t PMULL_11(const uint64x2_t a, const uint64x2_t b)
{
return (uint64x2_t)(vmull_p64(
vgetq_lane_u64(vreinterpretq_u64_u8(a),1),
vgetq_lane_u64(vreinterpretq_u64_u8(b),1)));
}
inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b, unsigned int c)
{
return (uint64x2_t)vextq_u8(
vreinterpretq_u8_u64(a), vreinterpretq_u8_u64(b), c);
}
// https://github.com/weidai11/cryptopp/issues/366
template <unsigned int C>
inline uint64x2_t VEXT_U8(uint64x2_t a, uint64x2_t b)
{
return (uint64x2_t)vextq_u8(
vreinterpretq_u8_u64(a), vreinterpretq_u8_u64(b), C);
}
#endif // Microsoft and compatibles
#endif // CRYPTOPP_ARM_PMULL_AVAILABLE
// ************************** Power 8 Crypto ************************** //
#if CRYPTOPP_POWER8_VMULL_AVAILABLE
using CryptoPP::uint32x4_p;
using CryptoPP::uint64x2_p;
using CryptoPP::VecGetLow;
using CryptoPP::VecGetHigh;
using CryptoPP::VecRotateLeftOctet;
// POWER8 GCM mode is confusing. The algorithm is reflected so
// nearly everything we do is reversed for a little-endian system,
// including on big-endian machines. VMULL2LE swaps dwords for a
// little endian machine; VMULL_00LE, VMULL_01LE, VMULL_10LE and
// VMULL_11LE are backwards and (1) read low words with
// VecGetHigh, (2) read high words with VecGetLow, and
// (3) yields a product that is endian swapped. The steps ensures
// GCM parameters are presented in the correct order for the
// algorithm on both big and little-endian systems, but it is
// awful to try to follow the logic because it is so backwards.
// Because functions like VMULL_NN are so backwards we can't put
// them in ppc_simd.h. They simply don't work the way a typical
// user expects them to work.
inline uint64x2_p VMULL2LE(const uint64x2_p& val)
{
#if (CRYPTOPP_BIG_ENDIAN)
return VecRotateLeftOctet<8>(val);
#else
return val;
#endif
}
// _mm_clmulepi64_si128(a, b, 0x00)
inline uint64x2_p VMULL_00LE(const uint64x2_p& a, const uint64x2_p& b)
{
#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
return VMULL2LE(__vpmsumd (VecGetHigh(a), VecGetHigh(b)));
#elif defined(__clang__)
return VMULL2LE(__builtin_altivec_crypto_vpmsumd (VecGetHigh(a), VecGetHigh(b)));
#else
return VMULL2LE(__builtin_crypto_vpmsumd (VecGetHigh(a), VecGetHigh(b)));
#endif
}
// _mm_clmulepi64_si128(a, b, 0x01)
inline uint64x2_p VMULL_01LE(const uint64x2_p& a, const uint64x2_p& b)
{
// Small speedup. VecGetHigh(b) ensures the high dword of 'b' is 0.
// The 0 used in the vmull yields 0 for the high product, so the high
// dword of 'a' is "don't care".
#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
return VMULL2LE(__vpmsumd (a, VecGetHigh(b)));
#elif defined(__clang__)
return VMULL2LE(__builtin_altivec_crypto_vpmsumd (a, VecGetHigh(b)));
#else
return VMULL2LE(__builtin_crypto_vpmsumd (a, VecGetHigh(b)));
#endif
}
// _mm_clmulepi64_si128(a, b, 0x10)
inline uint64x2_p VMULL_10LE(const uint64x2_p& a, const uint64x2_p& b)
{
// Small speedup. VecGetHigh(a) ensures the high dword of 'a' is 0.
// The 0 used in the vmull yields 0 for the high product, so the high
// dword of 'b' is "don't care".
#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
return VMULL2LE(__vpmsumd (VecGetHigh(a), b));
#elif defined(__clang__)
return VMULL2LE(__builtin_altivec_crypto_vpmsumd (VecGetHigh(a), b));
#else
return VMULL2LE(__builtin_crypto_vpmsumd (VecGetHigh(a), b));
#endif
}
// _mm_clmulepi64_si128(a, b, 0x11)
inline uint64x2_p VMULL_11LE(const uint64x2_p& a, const uint64x2_p& b)
{
// Small speedup. VecGetLow(a) ensures the high dword of 'a' is 0.
// The 0 used in the vmull yields 0 for the high product, so the high
// dword of 'b' is "don't care".
#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
return VMULL2LE(__vpmsumd (VecGetLow(a), b));
#elif defined(__clang__)
return VMULL2LE(__builtin_altivec_crypto_vpmsumd (VecGetLow(a), b));
#else
return VMULL2LE(__builtin_crypto_vpmsumd (VecGetLow(a), b));
#endif
}
#endif // CRYPTOPP_POWER8_VMULL_AVAILABLE
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
// ************************* Feature Probes ************************* //
@ -287,23 +93,24 @@ bool CPU_ProbePMULL()
volatile bool result = true;
__try
{
const poly64_t a1={0x9090909090909090}, b1={0xb0b0b0b0b0b0b0b0};
const poly8x16_t a2={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0},
b2={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0};
const poly128_t r1 = pmull_p64(a1, b1);
const poly128_t r2 = pmull_high_p64((poly64x2_t)(a2), (poly64x2_t)(b2));
// Linaro is missing a lot of pmull gear. Also see http://github.com/weidai11/cryptopp/issues/233.
const uint64x2_t t1 = (uint64x2_t)(r1); // {bignum,bignum}
const uint64x2_t t2 = (uint64x2_t)(r2); // {bignum,bignum}
const uint64_t wa1[]={0,0x9090909090909090}, wb1[]={0,0xb0b0b0b0b0b0b0b0};
const uint64x2_t a1=vld1q_u64(wa1), b1=vld1q_u64(wb1);
result = !!(vgetq_lane_u64(t1,0) == 0x5300530053005300 &&
vgetq_lane_u64(t1,1) == 0x5300530053005300 &&
vgetq_lane_u64(t2,0) == 0x6c006c006c006c00 &&
vgetq_lane_u64(t2,1) == 0x6c006c006c006c00);
const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0},
wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0};
const uint8x16_t a2=vld1q_u8(wa2), b2=vld1q_u8(wb2);
const uint64x2_t r1 = PMULL_00(a1, b1);
const uint64x2_t r2 = PMULL_11(vreinterpretq_u64_u8(a2),
vreinterpretq_u64_u8(b2));
result = !!(vgetq_lane_u64(r1,0) == 0x5300530053005300 &&
vgetq_lane_u64(r1,1) == 0x5300530053005300 &&
vgetq_lane_u64(r2,0) == 0x6c006c006c006c00 &&
vgetq_lane_u64(r2,1) == 0x6c006c006c006c00);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
@ -328,14 +135,18 @@ bool CPU_ProbePMULL()
else
{
// Linaro is missing a lot of pmull gear. Also see http://github.com/weidai11/cryptopp/issues/233.
const uint64x2_t a1={0,0x9090909090909090}, b1={0,0xb0b0b0b0b0b0b0b0};
const uint8x16_t a2={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
const uint64_t wa1[]={0,0x9090909090909090}, wb1[]={0,0xb0b0b0b0b0b0b0b0};
const uint64x2_t a1=vld1q_u64(wa1), b1=vld1q_u64(wb1);
const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0},
b2={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0};
const uint8x16_t a2=vld1q_u8(wa2), b2=vld1q_u8(wb2);
const uint64x2_t r1 = PMULL_00(a1, b1);
const uint64x2_t r2 = PMULL_11((uint64x2_t)a2, (uint64x2_t)b2);
const uint64x2_t r2 = PMULL_11(vreinterpretq_u64_u8(a2),
vreinterpretq_u64_u8(b2));
result = !!(vgetq_lane_u64(r1,0) == 0x5300530053005300 &&
vgetq_lane_u64(r1,1) == 0x5300530053005300 &&
@ -374,17 +185,24 @@ bool CPU_ProbePMULL()
result = false;
else
{
const uint8x16_p a={0x0f,0x08,0x08,0x08, 0x80,0x80,0x80,0x80,
0x00,0x0a,0x0a,0x0a, 0xa0,0xa0,0xa0,0xa0},
b={0x0f,0xc0,0xc0,0xc0, 0x0c,0x0c,0x0c,0x0c,
0x00,0xe0,0xe0,0xe0, 0x0e,0x0e,0x0e,0x0e};
const uint64_t wa1[]={0,W64LIT(0x9090909090909090)},
wb1[]={0,W64LIT(0xb0b0b0b0b0b0b0b0)};
const uint64x2_p a1=VecLoad(wa1), b1=VecLoad(wb1);
const uint64x2_p r1 = VMULL_00LE((uint64x2_p)(a), (uint64x2_p)(b));
const uint64x2_p r2 = VMULL_01LE((uint64x2_p)(a), (uint64x2_p)(b));
const uint64x2_p r3 = VMULL_10LE((uint64x2_p)(a), (uint64x2_p)(b));
const uint64x2_p r4 = VMULL_11LE((uint64x2_p)(a), (uint64x2_p)(b));
const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0},
wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0};
const uint32x4_p a2=VecLoad(wa2), b2=VecLoad(wb2);
result = VecNotEqual(r1, r2) && VecNotEqual(r3, r4);
const uint64x2_p r1 = VecPolyMultiply00LE(a1, b1);
const uint64x2_p r2 = VecPolyMultiply11LE((uint64x2_p)a2, (uint64x2_p)b2);
const uint64_t wc1[]={W64LIT(0x5300530053005300), W64LIT(0x5300530053005300)},
wc2[]={W64LIT(0x6c006c006c006c00), W64LIT(0x6c006c006c006c00)};
const uint64x2_p c1=VecLoad(wc1), c2=VecLoad(wc2);
result = !!(VecEqual(r1, c1) && VecEqual(r2, c2));
}
sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
@ -765,9 +583,9 @@ uint64x2_p GCM_Reduce_VMULL(uint64x2_p c0, uint64x2_p c1, uint64x2_p c2, uint64x
const uint64x2_p m1 = {1,1}, m63 = {63,63};
c1 = VecXor(c1, VecShiftRightOctet<8>(c0));
c1 = VecXor(c1, VMULL_10LE(c0, r));
c1 = VecXor(c1, VecPolyMultiply10LE(c0, r));
c0 = VecXor(c1, VecShiftLeftOctet<8>(c0));
c0 = VMULL_00LE(vec_sl(c0, m1), r);
c0 = VecPolyMultiply00LE(vec_sl(c0, m1), r);
c2 = VecXor(c2, c0);
c2 = VecXor(c2, VecShiftLeftOctet<8>(c1));
c1 = vec_sr(vec_mergeh(c1, c2), m63);
@ -778,9 +596,9 @@ uint64x2_p GCM_Reduce_VMULL(uint64x2_p c0, uint64x2_p c1, uint64x2_p c2, uint64x
inline uint64x2_p GCM_Multiply_VMULL(uint64x2_p x, uint64x2_p h, uint64x2_p r)
{
const uint64x2_p c0 = VMULL_00LE(x, h);
const uint64x2_p c1 = VecXor(VMULL_01LE(x, h), VMULL_10LE(x, h));
const uint64x2_p c2 = VMULL_11LE(x, h);
const uint64x2_p c0 = VecPolyMultiply00LE(x, h);
const uint64x2_p c1 = VecXor(VecPolyMultiply01LE(x, h), VecPolyMultiply10LE(x, h));
const uint64x2_p c2 = VecPolyMultiply11LE(x, h);
return GCM_Reduce_VMULL(c0, c1, c2, r);
}
@ -875,35 +693,35 @@ size_t GCM_AuthenticateBlocks_VMULL(const byte *data, size_t len, const byte *mt
{
d1 = LoadBuffer2(data);
d1 = VecXor(d1, x);
c0 = VecXor(c0, VMULL_00LE(d1, h0));
c2 = VecXor(c2, VMULL_01LE(d1, h1));
c0 = VecXor(c0, VecPolyMultiply00LE(d1, h0));
c2 = VecXor(c2, VecPolyMultiply01LE(d1, h1));
d1 = VecXor(d1, SwapWords(d1));
c1 = VecXor(c1, VMULL_00LE(d1, h2));
c1 = VecXor(c1, VecPolyMultiply00LE(d1, h2));
break;
}
d1 = LoadBuffer1(data+(s-i)*16-8);
c0 = VecXor(c0, VMULL_01LE(d2, h0));
c2 = VecXor(c2, VMULL_01LE(d1, h1));
c0 = VecXor(c0, VecPolyMultiply01LE(d2, h0));
c2 = VecXor(c2, VecPolyMultiply01LE(d1, h1));
d2 = VecXor(d2, d1);
c1 = VecXor(c1, VMULL_01LE(d2, h2));
c1 = VecXor(c1, VecPolyMultiply01LE(d2, h2));
if (++i == s)
{
d1 = LoadBuffer2(data);
d1 = VecXor(d1, x);
c0 = VecXor(c0, VMULL_10LE(d1, h0));
c2 = VecXor(c2, VMULL_11LE(d1, h1));
c0 = VecXor(c0, VecPolyMultiply10LE(d1, h0));
c2 = VecXor(c2, VecPolyMultiply11LE(d1, h1));
d1 = VecXor(d1, SwapWords(d1));
c1 = VecXor(c1, VMULL_10LE(d1, h2));
c1 = VecXor(c1, VecPolyMultiply10LE(d1, h2));
break;
}
d2 = LoadBuffer2(data+(s-i)*16-8);
c0 = VecXor(c0, VMULL_10LE(d1, h0));
c2 = VecXor(c2, VMULL_10LE(d2, h1));
c0 = VecXor(c0, VecPolyMultiply10LE(d1, h0));
c2 = VecXor(c2, VecPolyMultiply10LE(d2, h1));
d1 = VecXor(d1, d2);
c1 = VecXor(c1, VMULL_10LE(d1, h2));
c1 = VecXor(c1, VecPolyMultiply10LE(d1, h2));
}
data += s*16;
len -= s*16;

View File

@ -13,8 +13,9 @@
#include "words.h"
#include "misc.h"
#include "gf2n.h"
#include "asn.h"
#include "oids.h"
#include "asn.h"
#include "cpu.h"
#include <iostream>
@ -41,6 +42,21 @@ ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
#if (CRYPTOPP_CLMUL_AVAILABLE)
extern CRYPTOPP_DLL void GF2NT_233_Multiply_Reduce_CLMUL(const word* pA, const word* pB, word* pC);
extern CRYPTOPP_DLL void GF2NT_233_Square_Reduce_CLMUL(const word* pA, word* pC);
#endif
#if (CRYPTOPP_ARM_PMULL_AVAILABLE)
extern void GF2NT_233_Multiply_Reduce_ARMv8(const word* pA, const word* pB, word* pC);
extern void GF2NT_233_Square_Reduce_ARMv8(const word* pA, word* pC);
#endif
#if (CRYPTOPP_POWER8_VMULL_AVAILABLE)
extern void GF2NT_233_Multiply_Reduce_POWER8(const word* pA, const word* pB, word* pC);
extern void GF2NT_233_Square_Reduce_POWER8(const word* pA, word* pC);
#endif
PolynomialMod2::PolynomialMod2()
{
}
@ -75,7 +91,7 @@ void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits)
PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength)
{
PolynomialMod2 result((word)0, bitLength);
SetWords(result.reg, word(SIZE_MAX), result.reg.size());
SetWords(result.reg, ~(word(0)), result.reg.size());
if (bitLength%WORD_BITS)
result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS);
return result;
@ -943,6 +959,112 @@ GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
return result.release();
}
// ********************************************************
GF2NT233::GF2NT233(unsigned int c0, unsigned int c1, unsigned int c2)
: GF2NT(c0, c1, c2)
{
CRYPTOPP_ASSERT(c0 > c1 && c1 > c2 && c2==0);
}
const GF2NT::Element& GF2NT233::Multiply(const Element &a, const Element &b) const
{
#if (CRYPTOPP_CLMUL_AVAILABLE)
if (HasCLMUL())
{
CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(b.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256);
const word* pA = a.reg.begin();
const word* pB = b.reg.begin();
word* pR = result.reg.begin();
GF2NT_233_Multiply_Reduce_CLMUL(pA, pB, pR);
return result;
}
else
#elif (CRYPTOPP_ARM_PMULL_AVAILABLE)
if (HasPMULL())
{
CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(b.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256);
const word* pA = a.reg.begin();
const word* pB = b.reg.begin();
word* pR = result.reg.begin();
GF2NT_233_Multiply_Reduce_ARMv8(pA, pB, pR);
return result;
}
else
#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE)
if (HasPMULL())
{
CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(b.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256);
const word* pA = a.reg.begin();
const word* pB = b.reg.begin();
word* pR = result.reg.begin();
GF2NT_233_Multiply_Reduce_POWER8(pA, pB, pR);
return result;
}
else
#endif
return GF2NT::Multiply(a, b);
}
const GF2NT::Element& GF2NT233::Square(const Element &a) const
{
#if (CRYPTOPP_CLMUL_AVAILABLE)
if (HasCLMUL())
{
CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256);
const word* pA = a.reg.begin();
word* pR = result.reg.begin();
GF2NT_233_Square_Reduce_CLMUL(pA, pR);
return result;
}
else
#elif (CRYPTOPP_ARM_PMULL_AVAILABLE)
if (HasPMULL())
{
CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256);
const word* pA = a.reg.begin();
word* pR = result.reg.begin();
GF2NT_233_Square_Reduce_ARMv8(pA, pR);
return result;
}
else
#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE)
if (HasPMULL())
{
CRYPTOPP_ASSERT(a.reg.size()*WORD_BITS == 256);
CRYPTOPP_ASSERT(result.reg.size()*WORD_BITS == 256);
const word* pA = a.reg.begin();
word* pR = result.reg.begin();
GF2NT_233_Square_Reduce_POWER8(pA, pR);
return result;
}
else
#endif
return GF2NT::Square(a);
}
NAMESPACE_END
#endif

View File

@ -246,6 +246,7 @@ public:
private:
friend class GF2NT;
friend class GF2NT233;
SecWordBlock reg;
};
@ -344,13 +345,29 @@ public:
const Element& MultiplicativeInverse(const Element &a) const;
private:
protected:
const Element& Reduced(const Element &a) const;
unsigned int t0, t1;
mutable PolynomialMod2 result;
};
/// \brief GF(2^n) for b233 and k233
/// \details GF2NT233 is a specialization of GF2NT that provides Multiply()
/// and Square() operations when carryless multiplies is available.
class CRYPTOPP_DLL GF2NT233 : public GF2NT
{
public:
// polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
GF2NT233(unsigned int t0, unsigned int t1, unsigned int t2);
GF2NP * Clone() const {return new GF2NT233(*this);}
const Element& Multiply(const Element &a, const Element &b) const;
const Element& Square(const Element &a) const;
};
/// \brief GF(2^n) with Pentanomial Basis
class CRYPTOPP_DLL GF2NPP : public GF2NP
{

View File

@ -0,0 +1,610 @@
// gf2n_simd.cpp - written and placed in the public domain by Jeffrey Walton
// Also based on PCLMULQDQ code by Jankowski, Laurent and
// O'Mahony from Intel (see reference below).
//
// This source file uses intrinsics and built-ins to gain access to
// CLMUL, ARMv8a, and Power8 instructions. A separate source file is
// needed because additional CXXFLAGS are required to enable the
// appropriate instructions sets in some build configurations.
//
// Several speedups were taken from Intel Polynomial Multiplication
// Instruction and its Usage for Elliptic Curve Cryptography, by
// Krzysztof Jankowski, Pierre Laurent and Aidan O'Mahony,
// https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/polynomial-multiplication-instructions-paper.pdf
// There may be more speedups available, see https://eprint.iacr.org/2011/589.pdf.
// The IACR paper performs some optimizations that the compiler is
// expected to perform, like Common Subexpression Elimination to save
// on variables (among others). Note that the compiler may miss the
// optimization so the IACR paper is useful. However, the code is GPL3
// and toxic for some users of the library...
#include "pch.h"
#include "config.h"
#include "gf2n.h"
#if (CRYPTOPP_CLMUL_AVAILABLE)
# include <emmintrin.h>
# include <wmmintrin.h>
#endif
#if (CRYPTOPP_ARM_PMULL_AVAILABLE)
# include "arm_simd.h"
#endif
#if defined(CRYPTOPP_ALTIVEC_AVAILABLE)
# include "ppc_simd.h"
#endif
ANONYMOUS_NAMESPACE_BEGIN
// ************************** ARMv8 ************************** //
using CryptoPP::word;
#if (CRYPTOPP_ARM_PMULL_AVAILABLE)
// c1c0 = a * b
inline void
F2N_Multiply_128x128_ARMv8(uint64x2_t& c1, uint64x2_t& c0, const uint64x2_t& a, const uint64x2_t& b)
{
uint64x2_t t1, t2, z0={0};
c0 = PMULL_00(a, b);
c1 = PMULL_11(a, b);
t1 = vmovq_n_u64(vgetq_lane_u64(a, 1));
t1 = veorq_u64(a, t1);
t2 = vmovq_n_u64(vgetq_lane_u64(b, 1));
t2 = veorq_u64(b, t2);
t1 = PMULL_00(t1, t2);
t1 = veorq_u64(c0, t1);
t1 = veorq_u64(c1, t1);
t2 = t1;
t1 = vextq_u64(z0, t1, 1);
t2 = vextq_u64(t2, z0, 1);
c0 = veorq_u64(c0, t1);
c1 = veorq_u64(c1, t2);
}
// c3c2c1c0 = a1a0 * b1b0
inline void
F2N_Multiply_256x256_ARMv8(uint64x2_t& c3, uint64x2_t& c2, uint64x2_t& c1, uint64x2_t& c0,
const uint64x2_t& b1, const uint64x2_t& b0, const uint64x2_t& a1, const uint64x2_t& a0)
{
uint64x2_t c4, c5;
uint64x2_t x0=a0, x1=a1, y0=b0, y1=b1;
F2N_Multiply_128x128_ARMv8(c1, c0, x0, y0);
F2N_Multiply_128x128_ARMv8(c3, c2, x1, y1);
x0 = veorq_u64(x0, x1);
y0 = veorq_u64(y0, y1);
F2N_Multiply_128x128_ARMv8(c5, c4, x0, y0);
c4 = veorq_u64(c4, c0);
c4 = veorq_u64(c4, c2);
c5 = veorq_u64(c5, c1);
c5 = veorq_u64(c5, c3);
c1 = veorq_u64(c1, c4);
c2 = veorq_u64(c2, c5);
}
// c3c2c1c0 = a1a0 * a1a0
inline void
F2N_Square_256_ARMv8(uint64x2_t& c3, uint64x2_t& c2, uint64x2_t& c1,
uint64x2_t& c0, const uint64x2_t& a1, const uint64x2_t& a0)
{
c0 = PMULL_00(a0, a0);
c1 = PMULL_11(a0, a0);
c2 = PMULL_00(a1, a1);
c3 = PMULL_11(a1, a1);
}
// x = (x << n), z = 0
template <unsigned int N>
inline uint64x2_t ShiftLeft128_ARMv8(uint64x2_t x)
{
uint64x2_t u=x, v, z={0};
x = vshlq_n_u64(x, N);
u = vshrq_n_u64(u, (64-N));
v = vcombine_u64(vget_low_u64(z), vget_low_u64(u));
x = vorrq_u64(x, v);
return x;
}
// c1c0 = c3c2c1c0 MOD p. This is a Barrett reduction. Reading at
// Intel paper or https://github.com/antonblanchard/crc32-vpmsum.
inline void
GF2NT_233_Reduce_ARMv8(uint64x2_t& c3, uint64x2_t& c2, uint64x2_t& c1, uint64x2_t& c0)
{
const unsigned int mask[4] = {
0xffffffff, 0xffffffff, 0xffffffff, 0x000001ff,
};
uint64x2_t b3, b2, b1, /*b0,*/ a1, a0, m0, z0={0};
m0 = vreinterpretq_u64_u32(vld1q_u32(mask));
b1 = c1; a1 = c1;
a0 = vcombine_u64(vget_low_u64(c1), vget_low_u64(z0));
a1 = vshlq_n_u64(a1, 23);
a1 = vshrq_n_u64(a1, 23);
c1 = vorrq_u64(a1, a0);
b2 = vshrq_n_u64(c2, (64-23));
c3 = ShiftLeft128_ARMv8<23>(c3);
a0 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0));
c3 = vorrq_u64(c3, a0);
b1 = vshrq_n_u64(b1, (64-23));
c2 = ShiftLeft128_ARMv8<23>(c2);
a0 = vcombine_u64(vget_high_u64(b1), vget_high_u64(z0));
c2 = vorrq_u64(c2, a0);
b3 = c3;
b2 = vshrq_n_u64(c2, (64-10));
b3 = ShiftLeft128_ARMv8<10>(b3);
a0 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0));
b3 = vorrq_u64(b3, a0);
a0 = vcombine_u64(vget_high_u64(c3), vget_high_u64(z0));
b3 = veorq_u64(b3, a0);
b1 = vshrq_n_u64(b3, (64-23));
b3 = ShiftLeft128_ARMv8<23>(b3);
b3 = vcombine_u64(vget_high_u64(b3), vget_high_u64(z0));
b3 = vorrq_u64(b3, b1);
c2 = veorq_u64(c2, b3);
b3 = c3;
b2 = vshrq_n_u64(c2, (64-10));
b3 = ShiftLeft128_ARMv8<10>(b3);
b2 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0));
b3 = vorrq_u64(b3, b2);
b2 = c2;
b2 = ShiftLeft128_ARMv8<10>(b2);
a0 = vcombine_u64(vget_low_u64(z0), vget_low_u64(b2));
c2 = veorq_u64(c2, a0);
a0 = vcombine_u64(vget_low_u64(z0), vget_low_u64(b3));
a1 = vcombine_u64(vget_high_u64(b2), vget_high_u64(z0));
a0 = vorrq_u64(a0, a1);
c3 = veorq_u64(c3, a0);
c0 = veorq_u64(c0, c2);
c1 = veorq_u64(c1, c3);
c1 = vandq_u64(c1, m0);
}
#endif
// ************************** SSE ************************** //
#if (CRYPTOPP_CLMUL_AVAILABLE)
using CryptoPP::word;
// c1c0 = a * b
inline void
F2N_Multiply_128x128_CLMUL(__m128i& c1, __m128i& c0, const __m128i& a, const __m128i& b)
{
__m128i t1, t2;
c0 = _mm_clmulepi64_si128(a, b, 0x00);
c1 = _mm_clmulepi64_si128(a, b, 0x11);
t1 = _mm_shuffle_epi32(a, 0xEE);
t1 = _mm_xor_si128(a, t1);
t2 = _mm_shuffle_epi32(b, 0xEE);
t2 = _mm_xor_si128(b, t2);
t1 = _mm_clmulepi64_si128(t1, t2, 0x00);
t1 = _mm_xor_si128(c0, t1);
t1 = _mm_xor_si128(c1, t1);
t2 = t1;
t1 = _mm_slli_si128(t1, 8);
t2 = _mm_srli_si128(t2, 8);
c0 = _mm_xor_si128(c0, t1);
c1 = _mm_xor_si128(c1, t2);
}
// c3c2c1c0 = a1a0 * b1b0
inline void
F2N_Multiply_256x256_CLMUL(__m128i& c3, __m128i& c2, __m128i& c1, __m128i& c0,
const __m128i& b1, const __m128i& b0, const __m128i& a1, const __m128i& a0)
{
__m128i c4, c5;
__m128i x0=a0, x1=a1, y0=b0, y1=b1;
F2N_Multiply_128x128_CLMUL(c1, c0, x0, y0);
F2N_Multiply_128x128_CLMUL(c3, c2, x1, y1);
x0 = _mm_xor_si128(x0, x1);
y0 = _mm_xor_si128(y0, y1);
F2N_Multiply_128x128_CLMUL(c5, c4, x0, y0);
c4 = _mm_xor_si128(c4, c0);
c4 = _mm_xor_si128(c4, c2);
c5 = _mm_xor_si128(c5, c1);
c5 = _mm_xor_si128(c5, c3);
c1 = _mm_xor_si128(c1, c4);
c2 = _mm_xor_si128(c2, c5);
}
// c3c2c1c0 = a1a0 * a1a0
inline void
F2N_Square_256_CLMUL(__m128i& c3, __m128i& c2, __m128i& c1,
__m128i& c0, const __m128i& a1, const __m128i& a0)
{
c0 = _mm_clmulepi64_si128(a0, a0, 0x00);
c1 = _mm_clmulepi64_si128(a0, a0, 0x11);
c2 = _mm_clmulepi64_si128(a1, a1, 0x00);
c3 = _mm_clmulepi64_si128(a1, a1, 0x11);
}
// x = (x << n), z = 0
template <unsigned int N>
inline __m128i ShiftLeft128_SSE(__m128i x, const __m128i& z)
{
__m128i u=x, v;
x = _mm_slli_epi64(x, N);
u = _mm_srli_epi64(u, (64-N));
v = _mm_unpacklo_epi64(z, u);
x = _mm_or_si128(x, v);
return x;
}
// c1c0 = c3c2c1c0 MOD p. This is a Barrett reduction. Reading at
// Intel paper or https://github.com/antonblanchard/crc32-vpmsum.
inline void
GF2NT_233_Reduce_CLMUL(__m128i& c3, __m128i& c2, __m128i& c1, __m128i& c0)
{
const unsigned int m[4] = {
0xffffffff, 0xffffffff, 0xffffffff, 0x000001ff
};
__m128i b3, b2, b1, /*b0,*/ a1, a0, m0, z0;
m0 = _mm_set_epi32(m[3], m[2], m[1], m[0]);
z0 = _mm_setzero_si128();
b1 = c1; a1 = c1;
a0 = _mm_move_epi64(c1);
a1 = _mm_slli_epi64(a1, 23);
a1 = _mm_srli_epi64(a1, 23);
c1 = _mm_or_si128(a1, a0);
b2 = _mm_srli_epi64(c2, (64-23));
c3 = ShiftLeft128_SSE<23>(c3, z0);
a0 = _mm_unpackhi_epi64(b2, z0);
c3 = _mm_or_si128(c3, a0);
b1 = _mm_srli_epi64(b1, (64-23));
c2 = ShiftLeft128_SSE<23>(c2, z0);
a0 = _mm_unpackhi_epi64(b1, z0);
c2 = _mm_or_si128(c2, a0);
b3 = c3;
b2 = _mm_srli_epi64(c2, (64-10));
b3 = ShiftLeft128_SSE<10>(b3, z0);
a0 = _mm_unpackhi_epi64(b2, z0);
b3 = _mm_or_si128(b3, a0);
a0 = _mm_unpackhi_epi64(c3, z0);
b3 = _mm_xor_si128(b3, a0);
b1 = _mm_srli_epi64(b3, (64-23));
b3 = ShiftLeft128_SSE<23>(b3, z0);
b3 = _mm_unpackhi_epi64(b3, z0);
b3 = _mm_or_si128(b3, b1);
c2 = _mm_xor_si128(c2, b3);
b3 = c3;
b2 = _mm_srli_epi64(c2, (64-10));
b3 = ShiftLeft128_SSE<10>(b3, z0);
b2 = _mm_unpackhi_epi64(b2, z0);
b3 = _mm_or_si128(b3, b2);
b2 = c2;
b2 = ShiftLeft128_SSE<10>(b2, z0);
a0 = _mm_unpacklo_epi64(z0, b2);
c2 = _mm_xor_si128(c2, a0);
a0 = _mm_unpacklo_epi64(z0, b3);
a1 = _mm_unpackhi_epi64(b2, z0);
a0 = _mm_or_si128(a0, a1);
c3 = _mm_xor_si128(c3, a0);
c0 = _mm_xor_si128(c0, c2);
c1 = _mm_xor_si128(c1, c3);
c1 = _mm_and_si128(c1, m0);
}
#endif
// ************************* Power8 ************************* //
#if (CRYPTOPP_POWER8_VMULL_AVAILABLE)
using CryptoPP::byte;
using CryptoPP::word;
using CryptoPP::uint8x16_p;
using CryptoPP::uint64x2_p;
using CryptoPP::VecLoad;
using CryptoPP::VecStore;
using CryptoPP::VecOr;
using CryptoPP::VecXor;
using CryptoPP::VecAnd;
using CryptoPP::VecPermute;
using CryptoPP::VecMergeLow;
using CryptoPP::VecMergeHigh;
using CryptoPP::VecShiftLeft;
using CryptoPP::VecShiftRight;
using CryptoPP::VecPolyMultiply00LE;
using CryptoPP::VecPolyMultiply11LE;
// c1c0 = a * b
inline void
F2N_Multiply_128x128_POWER8(uint64x2_p& c1, uint64x2_p& c0, const uint64x2_p& a, const uint64x2_p& b)
{
uint64x2_p t1, t2;
const uint64x2_p z0={0};
c0 = VecPolyMultiply00LE(a, b);
c1 = VecPolyMultiply11LE(a, b);
t1 = VecMergeLow(a, a);
t1 = VecXor(a, t1);
t2 = VecMergeLow(b, b);
t2 = VecXor(b, t2);
t1 = VecPolyMultiply00LE(t1, t2);
t1 = VecXor(c0, t1);
t1 = VecXor(c1, t1);
t2 = t1;
t1 = VecMergeHigh(z0, t1);
t2 = VecMergeLow(t2, z0);
c0 = VecXor(c0, t1);
c1 = VecXor(c1, t2);
}
// c3c2c1c0 = a1a0 * b1b0
inline void
F2N_Multiply_256x256_POWER8(uint64x2_p& c3, uint64x2_p& c2, uint64x2_p& c1, uint64x2_p& c0,
const uint64x2_p& b1, const uint64x2_p& b0, const uint64x2_p& a1, const uint64x2_p& a0)
{
uint64x2_p c4, c5;
uint64x2_p x0=a0, x1=a1, y0=b0, y1=b1;
F2N_Multiply_128x128_POWER8(c1, c0, x0, y0);
F2N_Multiply_128x128_POWER8(c3, c2, x1, y1);
x0 = VecXor(x0, x1);
y0 = VecXor(y0, y1);
F2N_Multiply_128x128_POWER8(c5, c4, x0, y0);
c4 = VecXor(c4, c0);
c4 = VecXor(c4, c2);
c5 = VecXor(c5, c1);
c5 = VecXor(c5, c3);
c1 = VecXor(c1, c4);
c2 = VecXor(c2, c5);
}
// c3c2c1c0 = a1a0 * a1a0
inline void
F2N_Square_256_POWER8(uint64x2_p& c3, uint64x2_p& c2, uint64x2_p& c1,
uint64x2_p& c0, const uint64x2_p& a1, const uint64x2_p& a0)
{
c0 = VecPolyMultiply00LE(a0, a0);
c1 = VecPolyMultiply11LE(a0, a0);
c2 = VecPolyMultiply00LE(a1, a1);
c3 = VecPolyMultiply11LE(a1, a1);
}
// x = (x << n), z = 0
template <unsigned int N>
inline uint64x2_p ShiftLeft128_POWER8(uint64x2_p x)
{
uint64x2_p u=x, v;
const uint64x2_p z={0};
x = VecShiftLeft<N>(x);
u = VecShiftRight<64-N>(u);
v = VecMergeHigh(z, u);
x = VecOr(x, v);
return x;
}
// c1c0 = c3c2c1c0 MOD p. This is a Barrett reduction. Reading at
// Intel paper or https://github.com/antonblanchard/crc32-vpmsum.
inline void
GF2NT_233_Reduce_POWER8(uint64x2_p& c3, uint64x2_p& c2, uint64x2_p& c1, uint64x2_p& c0)
{
const uint64_t mod[] = {W64LIT(0xffffffffffffffff), W64LIT(0x01ffffffffff)};
const uint64x2_p m0 = (uint64x2_p)VecLoad(mod);
uint64x2_p b3, b2, b1, /*b0,*/ a1, a0;
const uint64x2_p z0={0};
b1 = c1; a1 = c1;
a0 = VecMergeHigh(c1, z0);
a1 = VecShiftLeft<23>(a1);
a1 = VecShiftRight<23>(a1);
c1 = VecOr(a1, a0);
b2 = VecShiftRight<64-23>(c2);
c3 = ShiftLeft128_POWER8<23>(c3);
a0 = VecMergeLow(b2, z0);
c3 = VecOr(c3, a0);
b1 = VecShiftRight<64-23>(b1);
c2 = ShiftLeft128_POWER8<23>(c2);
a0 = VecMergeLow(b1, z0);
c2 = VecOr(c2, a0);
b3 = c3;
b2 = VecShiftRight<64-10>(c2);
b3 = ShiftLeft128_POWER8<10>(b3);
a0 = VecMergeLow(b2, z0);
b3 = VecOr(b3, a0);
a0 = VecMergeLow(c3, z0);
b3 = VecXor(b3, a0);
b1 = VecShiftRight<64-23>(b3);
b3 = ShiftLeft128_POWER8<23>(b3);
b3 = VecMergeLow(b3, z0);
b3 = VecOr(b3, b1);
c2 = VecXor(c2, b3);
b3 = c3;
b2 = VecShiftRight<64-10>(c2);
b3 = ShiftLeft128_POWER8<10>(b3);
b2 = VecMergeLow(b2, z0);
b3 = VecOr(b3, b2);
b2 = c2;
b2 = ShiftLeft128_POWER8<10>(b2);
a0 = VecMergeHigh(z0, b2);
c2 = VecXor(c2, a0);
a0 = VecMergeHigh(z0, b3);
a1 = VecMergeLow(b2, z0);
a0 = VecOr(a0, a1);
c3 = VecXor(c3, a0);
c0 = VecXor(c0, c2);
c1 = VecXor(c1, c3);
c1 = VecAnd(c1, m0);
}
#endif
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
#if (CRYPTOPP_CLMUL_AVAILABLE)
void
GF2NT_233_Multiply_Reduce_CLMUL(const word* pA, const word* pB, word* pC)
{
const __m128i* pAA = reinterpret_cast<const __m128i*>(pA);
const __m128i* pBB = reinterpret_cast<const __m128i*>(pB);
__m128i a0 = _mm_loadu_si128(pAA+0);
__m128i a1 = _mm_loadu_si128(pAA+1);
__m128i b0 = _mm_loadu_si128(pBB+0);
__m128i b1 = _mm_loadu_si128(pBB+1);
__m128i c0, c1, c2, c3;
F2N_Multiply_256x256_CLMUL(c3, c2, c1, c0, a1, a0, b1, b0);
GF2NT_233_Reduce_CLMUL(c3, c2, c1, c0);
__m128i* pCC = reinterpret_cast<__m128i*>(pC);
_mm_storeu_si128(pCC+0, c0);
_mm_storeu_si128(pCC+1, c1);
}
void
GF2NT_233_Square_Reduce_CLMUL(const word* pA, word* pC)
{
const __m128i* pAA = reinterpret_cast<const __m128i*>(pA);
__m128i a0 = _mm_loadu_si128(pAA+0);
__m128i a1 = _mm_loadu_si128(pAA+1);
__m128i c0, c1, c2, c3;
F2N_Square_256_CLMUL(c3, c2, c1, c0, a1, a0);
GF2NT_233_Reduce_CLMUL(c3, c2, c1, c0);
__m128i* pCC = reinterpret_cast<__m128i*>(pC);
_mm_storeu_si128(pCC+0, c0);
_mm_storeu_si128(pCC+1, c1);
}
#elif (CRYPTOPP_ARM_PMULL_AVAILABLE)
void
GF2NT_233_Multiply_Reduce_ARMv8(const word* pA, const word* pB, word* pC)
{
// word is either 32-bit or 64-bit, depending on the platform.
// Load using a 32-bit pointer to avoid possible alignment issues.
const uint32_t* pAA = reinterpret_cast<const uint32_t*>(pA);
const uint32_t* pBB = reinterpret_cast<const uint32_t*>(pB);
uint64x2_t a0 = vreinterpretq_u64_u32(vld1q_u32(pAA+0));
uint64x2_t a1 = vreinterpretq_u64_u32(vld1q_u32(pAA+4));
uint64x2_t b0 = vreinterpretq_u64_u32(vld1q_u32(pBB+0));
uint64x2_t b1 = vreinterpretq_u64_u32(vld1q_u32(pBB+4));
uint64x2_t c0, c1, c2, c3;
F2N_Multiply_256x256_ARMv8(c3, c2, c1, c0, a1, a0, b1, b0);
GF2NT_233_Reduce_ARMv8(c3, c2, c1, c0);
uint32_t* pCC = reinterpret_cast<uint32_t*>(pC);
vst1q_u32(pCC+0, vreinterpretq_u32_u64(c0));
vst1q_u32(pCC+4, vreinterpretq_u32_u64(c1));
}
void
GF2NT_233_Square_Reduce_ARMv8(const word* pA, word* pC)
{
// word is either 32-bit or 64-bit, depending on the platform.
// Load using a 32-bit pointer to avoid possible alignment issues.
const uint32_t* pAA = reinterpret_cast<const uint32_t*>(pA);
uint64x2_t a0 = vreinterpretq_u64_u32(vld1q_u32(pAA+0));
uint64x2_t a1 = vreinterpretq_u64_u32(vld1q_u32(pAA+4));
uint64x2_t c0, c1, c2, c3;
F2N_Square_256_ARMv8(c3, c2, c1, c0, a1, a0);
GF2NT_233_Reduce_ARMv8(c3, c2, c1, c0);
uint32_t* pCC = reinterpret_cast<uint32_t*>(pC);
vst1q_u32(pCC+0, vreinterpretq_u32_u64(c0));
vst1q_u32(pCC+4, vreinterpretq_u32_u64(c1));
}
#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE)
void
GF2NT_233_Multiply_Reduce_POWER8(const word* pA, const word* pB, word* pC)
{
// word is either 32-bit or 64-bit, depending on the platform.
// Load using a byte pointer to avoid possible alignment issues.
const byte* pAA = reinterpret_cast<const byte*>(pA);
const byte* pBB = reinterpret_cast<const byte*>(pB);
uint64x2_p a0 = (uint64x2_p)VecLoad(pAA+0);
uint64x2_p a1 = (uint64x2_p)VecLoad(pAA+16);
uint64x2_p b0 = (uint64x2_p)VecLoad(pBB+0);
uint64x2_p b1 = (uint64x2_p)VecLoad(pBB+16);
#if (CRYPTOPP_BIG_ENDIAN)
const uint8_t mb[] = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
const uint8x16_p m = (uint8x16_p)VecLoad(mb);
a0 = VecPermute(a0, m);
a1 = VecPermute(a1, m);
b0 = VecPermute(b0, m);
b1 = VecPermute(b1, m);
#endif
uint64x2_p c0, c1, c2, c3;
F2N_Multiply_256x256_POWER8(c3, c2, c1, c0, a1, a0, b1, b0);
GF2NT_233_Reduce_POWER8(c3, c2, c1, c0);
#if (CRYPTOPP_BIG_ENDIAN)
c0 = VecPermute(c0, m);
c1 = VecPermute(c1, m);
#endif
byte* pCC = reinterpret_cast<byte*>(pC);
VecStore(c0, pCC+0);
VecStore(c1, pCC+16);
}
void
GF2NT_233_Square_Reduce_POWER8(const word* pA, word* pC)
{
// word is either 32-bit or 64-bit, depending on the platform.
// Load using a byte pointer to avoid possible alignment issues.
const byte* pAA = reinterpret_cast<const byte*>(pA);
uint64x2_p a0 = (uint64x2_p)VecLoad(pAA+0);
uint64x2_p a1 = (uint64x2_p)VecLoad(pAA+16);
#if (CRYPTOPP_BIG_ENDIAN)
const uint8_t mb[] = {4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11};
const uint8x16_p m = (uint8x16_p)VecLoad(mb);
a0 = VecPermute(a0, m);
a1 = VecPermute(a1, m);
#endif
uint64x2_p c0, c1, c2, c3;
F2N_Square_256_POWER8(c3, c2, c1, c0, a1, a0);
GF2NT_233_Reduce_POWER8(c3, c2, c1, c0);
#if (CRYPTOPP_BIG_ENDIAN)
c0 = VecPermute(c0, m);
c1 = VecPermute(c1, m);
#endif
byte* pCC = reinterpret_cast<byte*>(pC);
VecStore(c0, pCC+0);
VecStore(c1, pCC+16);
}
#endif
NAMESPACE_END

View File

@ -20,6 +20,9 @@ class SHA3_256;
class SHA3_384;
class SHA3_512;
class SHAKE128;
class SHAKE256;
class Tiger;
class RIPEMD128;
class RIPEMD160;

View File

@ -134,6 +134,7 @@ public:
try
{
this->GetMaterial().DoQuickSanityCheck();
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer)

View File

@ -233,7 +233,7 @@ static word AtomicInverseModPower2(word A)
#define GetBorrow(u) u##1
#else
#define Declare2Words(x) dword x;
#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && !defined(_M_ARM)
#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64))
#define MultiplyWords(p, a, b) p = __emulu(a, b);
#else
#define MultiplyWords(p, a, b) p = (dword)a*b;
@ -503,8 +503,9 @@ S DivideThreeWordsByTwo(S *A, S B0, S B1, D *dummy=NULLPTR)
template <class S, class D>
inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B)
{
// Profiling tells us the original second case was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original second case was dominant, so it was
// promoted to the first If statement. The code change occurred at
// Commit dc99266599a0e72d.
if (!!B)
{
@ -2437,8 +2438,9 @@ void AsymmetricMultiply(word *R, word *T, const word *A, size_t NA, const word *
if (NA==2 && !A[1])
{
// Profiling tells us the original Default case was dominant, so it was promoted to the first Case statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Default case was dominant, so it was
// promoted to the first Case statement. The code change occurred at
// Commit dc99266599a0e72d.
switch (A[0])
{
default:
@ -2484,8 +2486,9 @@ void AsymmetricMultiply(word *R, word *T, const word *A, size_t NA, const word *
void RecursiveInverseModPower2(word *R, word *T, const word *A, size_t N)
{
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Else was dominant, so it was
// promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if (N!=2)
{
const size_t N2 = N/2;
@ -3099,8 +3102,9 @@ Integer& Integer::operator=(const Integer& t)
bool Integer::GetBit(size_t n) const
{
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Else was dominant, so it was
// promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if (n/WORD_BITS < reg.size())
return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
else
@ -3123,8 +3127,9 @@ void Integer::SetBit(size_t n, bool value)
byte Integer::GetByte(size_t n) const
{
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Else was dominant, so it was
// promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if (n/WORD_SIZE < reg.size())
return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
else
@ -3227,7 +3232,7 @@ static Integer StringToInteger(const T *str, ByteOrder order)
{
int digit, ch = static_cast<int>(str[i]);
// Profiling showd the second and third Else needed to be swapped
// Profiling showd the second and third Else needed to be swapped
// The code change occurred at Commit dc99266599a0e72d.
if (ch >= '0' && ch <= '9')
digit = ch - '0';
@ -3387,8 +3392,9 @@ void Integer::Decode(BufferedTransformation &bt, size_t inputLen, Signedness s)
size_t Integer::MinEncodedSize(Signedness signedness) const
{
// Profiling tells us the original second If was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original second If was dominant, so it
// was promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
unsigned int outputLen = STDMAX(1U, ByteCount());
const bool pre = (signedness == UNSIGNED);
if (!pre && NotNegative() && (GetByte(outputLen-1) & 0x80))
@ -3523,7 +3529,8 @@ void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const In
bool Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod)
{
return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max)("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod));
return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max)
("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod));
}
class KDF2_RNG : public RandomNumberGenerator
@ -3842,8 +3849,9 @@ Integer Integer::Xor(const Integer& t) const
void PositiveAdd(Integer &sum, const Integer &a, const Integer& b)
{
// Profiling tells us the original second Else If was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original second Else If was dominant, so it
// was promoted to the first If statement. The code change occurred at
// Commit dc99266599a0e72d.
int carry; const bool pre = (a.reg.size() == b.reg.size());
if (!pre && a.reg.size() > b.reg.size())
{
@ -3877,8 +3885,9 @@ void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b)
unsigned bSize = b.WordCount();
bSize += bSize%2;
// Profiling tells us the original second Else If was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original second Else If was dominant, so it
// was promoted to the first If statement. The code change occurred at
// Commit dc99266599a0e72d.
if (aSize > bSize)
{
word borrow = Subtract(diff.reg, a.reg, b.reg, bSize);
@ -4235,7 +4244,9 @@ void Integer::Divide(word &remainder, Integer &quotient, const Integer &dividend
if (!divisor)
throw Integer::DivideByZero();
if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
// IsPowerOf2 uses BMI on x86 if available. There is a small
// but measurable improvement during decryption and signing.
if (IsPowerOf2(divisor))
{
quotient = dividend >> (BitPrecision(divisor)-1);
remainder = dividend.reg[0] & (divisor-1);
@ -4279,12 +4290,14 @@ word Integer::Modulo(word divisor) const
word remainder;
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Else was dominant, so it was
// promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if ((divisor & (divisor-1)) != 0) // divisor is not a power of 2
{
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Else was dominant, so it
// was promoted to the first If statement. The code change
// occurred at Commit dc99266599a0e72d.
unsigned int i = WordCount();
if (divisor > 5)
{
@ -4319,8 +4332,9 @@ void Integer::Negate()
int Integer::PositiveCompare(const Integer& t) const
{
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement.
// The code change occurred at Commit dc99266599a0e72d.
// Profiling tells us the original Else was dominant, so it
// was promoted to the first If statement. The code change
// occurred at Commit dc99266599a0e72d.
const unsigned size = WordCount(), tSize = t.WordCount();
if (size != tSize)
return size > tSize ? 1 : -1;

View File

@ -19,10 +19,12 @@ http://creativecommons.org/publicdomain/zero/1.0/
#include "pch.h"
#include "keccak.h"
#include "keccakc.h"
NAMESPACE_BEGIN(CryptoPP)
// The Keccak core function
extern void KeccakF1600(word64 *state);
void Keccak::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0));
@ -52,13 +54,13 @@ void Keccak::Restart()
void Keccak::TruncatedFinal(byte *hash, size_t size)
{
CRYPTOPP_ASSERT(hash != NULLPTR);
CRYPTOPP_ASSERT(hash != NULLPTR);
ThrowIfInvalidTruncatedSize(size);
m_state.BytePtr()[m_counter] ^= 1;
m_state.BytePtr()[m_counter] ^= 0x01;
m_state.BytePtr()[r()-1] ^= 0x80;
KeccakF1600(m_state);
memcpy(hash, m_state, size);
std::memcpy(hash, m_state, size);
Restart();
}

View File

@ -39,30 +39,30 @@ NAMESPACE_BEGIN(CryptoPP)
/// \since Crypto++ 5.6.4
class Keccak : public HashTransformation
{
protected:
/// \brief Construct a Keccak
/// \param digestSize the digest size, in bytes
/// \details Keccak is the base class for Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
/// Library users should instantiate a derived class, and only use Keccak
/// as a base class reference or pointer.
/// \details This constructor was moved to protected at Crypto++ 8.1
/// because users were attempting to create Keccak objects with it.
/// \since Crypto++ 5.6.4
Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
public:
/// \brief Construct a Keccak
/// \param digestSize the digest size, in bytes
/// \details Keccak is the base class for Keccak_224, Keccak_256, Keccak_384 and Keccak_512.
/// Library users should instantiate a derived class, and only use Keccak
/// as a base class reference or pointer.
/// \since Crypto++ 5.6.4
Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
unsigned int DigestSize() const {return m_digestSize;}
std::string AlgorithmName() const {return "Keccak-" + IntToString(m_digestSize*8);}
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "Keccak"; }
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
unsigned int DigestSize() const {return m_digestSize;}
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
void Update(const byte *input, size_t length);
void Restart();
void TruncatedFinal(byte *hash, size_t size);
//unsigned int BlockSize() const { return r(); } // that's the idea behind it
void Update(const byte *input, size_t length);
void Restart();
void TruncatedFinal(byte *hash, size_t size);
protected:
inline unsigned int r() const {return 200 - 2 * m_digestSize;}
inline unsigned int r() const {return BlockSize();}
FixedSizeSecBlock<word64, 25> m_state;
unsigned int m_digestSize, m_counter;
FixedSizeSecBlock<word64, 25> m_state;
unsigned int m_digestSize, m_counter;
};
/// \brief Keccak message digest template
@ -72,33 +72,48 @@ template<unsigned int T_DigestSize>
class Keccak_Final : public Keccak
{
public:
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE)
static std::string StaticAlgorithmName()
{ return "Keccak-" + IntToString(DIGESTSIZE * 8); }
/// \brief Construct a Keccak-X message digest
Keccak_Final() : Keccak(DIGESTSIZE) {}
/// \brief Provides the block size of the compression function
/// \return block size of the compression function, in bytes
/// \details BlockSize() will return 0 if the hash is not block based
/// or does not have an equivalent block size. For example, Keccak
/// and SHA-3 do not have a block size, but they do have an equivalent
/// block size called rate expressed as <tt>r</tt>.
unsigned int BlockSize() const { return BLOCKSIZE; }
std::string AlgorithmName() const { return StaticAlgorithmName(); }
/// \brief Construct a Keccak-X message digest
Keccak_Final() : Keccak(DIGESTSIZE) {}
static std::string StaticAlgorithmName() { return "Keccak-" + IntToString(DIGESTSIZE * 8); }
unsigned int BlockSize() const { return BLOCKSIZE; }
private:
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC
#if !defined(__BORLANDC__)
// ensure there was no underflow in the math
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200);
// this is a general expectation by HMAC
CRYPTOPP_COMPILE_ASSERT((int)BLOCKSIZE > (int)DIGESTSIZE);
#endif
};
/// \brief Keccak-224 message digest
/// \since Crypto++ 5.6.4
typedef Keccak_Final<28> Keccak_224;
DOCUMENTED_TYPEDEF(Keccak_Final<28>, Keccak_224);
/// \brief Keccak-256 message digest
/// \since Crypto++ 5.6.4
typedef Keccak_Final<32> Keccak_256;
DOCUMENTED_TYPEDEF(Keccak_Final<32>, Keccak_256);
/// \brief Keccak-384 message digest
/// \since Crypto++ 5.6.4
typedef Keccak_Final<48> Keccak_384;
DOCUMENTED_TYPEDEF(Keccak_Final<48>, Keccak_384);
/// \brief Keccak-512 message digest
/// \since Crypto++ 5.6.4
typedef Keccak_Final<64> Keccak_512;
DOCUMENTED_TYPEDEF(Keccak_Final<64>, Keccak_512);
NAMESPACE_END

View File

@ -0,0 +1,261 @@
// keccakc.cpp - Keccak core functions shared between SHA3 and Keccak.
// written and placed in the public domain by JW.
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michael Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by Ronny Van Keer, hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "pch.h"
#include "keccak.h"
NAMESPACE_BEGIN(CryptoPP)
// The Keccak core function
extern void KeccakF1600(word64 *state);
// The F1600 round constants
extern const word64 KeccakF1600Constants[24];
NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_ALIGN_DATA(8)
const word64 KeccakF1600Constants[24] =
{
W64LIT(0x0000000000000001), W64LIT(0x0000000000008082),
W64LIT(0x800000000000808a), W64LIT(0x8000000080008000),
W64LIT(0x000000000000808b), W64LIT(0x0000000080000001),
W64LIT(0x8000000080008081), W64LIT(0x8000000000008009),
W64LIT(0x000000000000008a), W64LIT(0x0000000000000088),
W64LIT(0x0000000080008009), W64LIT(0x000000008000000a),
W64LIT(0x000000008000808b), W64LIT(0x800000000000008b),
W64LIT(0x8000000000008089), W64LIT(0x8000000000008003),
W64LIT(0x8000000000008002), W64LIT(0x8000000000000080),
W64LIT(0x000000000000800a), W64LIT(0x800000008000000a),
W64LIT(0x8000000080008081), W64LIT(0x8000000000008080),
W64LIT(0x0000000080000001), W64LIT(0x8000000080008008)
};
void KeccakF1600(word64 *state)
{
word64 Aba, Abe, Abi, Abo, Abu;
word64 Aga, Age, Agi, Ago, Agu;
word64 Aka, Ake, Aki, Ako, Aku;
word64 Ama, Ame, Ami, Amo, Amu;
word64 Asa, Ase, Asi, Aso, Asu;
word64 BCa, BCe, BCi, BCo, BCu;
word64 Da, De, Di, Do, Du;
word64 Eba, Ebe, Ebi, Ebo, Ebu;
word64 Ega, Ege, Egi, Ego, Egu;
word64 Eka, Eke, Eki, Eko, Eku;
word64 Ema, Eme, Emi, Emo, Emu;
word64 Esa, Ese, Esi, Eso, Esu;
typedef BlockGetAndPut<word64, LittleEndian, true, true> Block;
Block::Get(state)(Aba)(Abe)(Abi)(Abo)(Abu)(Aga)(Age)(Agi)(Ago)(Agu)(Aka)(Ake)(Aki)(Ako)(Aku)(Ama)(Ame)(Ami)(Amo)(Amu)(Asa)(Ase)(Asi)(Aso)(Asu);
for( unsigned int round = 0; round < 24; round += 2 )
{
// prepareTheta
BCa = Aba^Aga^Aka^Ama^Asa;
BCe = Abe^Age^Ake^Ame^Ase;
BCi = Abi^Agi^Aki^Ami^Asi;
BCo = Abo^Ago^Ako^Amo^Aso;
BCu = Abu^Agu^Aku^Amu^Asu;
//thetaRhoPiChiIotaPrepareTheta(round , A, E)
Da = BCu^rotlConstant<1>(BCe);
De = BCa^rotlConstant<1>(BCi);
Di = BCe^rotlConstant<1>(BCo);
Do = BCi^rotlConstant<1>(BCu);
Du = BCo^rotlConstant<1>(BCa);
Aba ^= Da;
BCa = Aba;
Age ^= De;
BCe = rotlConstant<44>(Age);
Aki ^= Di;
BCi = rotlConstant<43>(Aki);
Amo ^= Do;
BCo = rotlConstant<21>(Amo);
Asu ^= Du;
BCu = rotlConstant<14>(Asu);
Eba = BCa ^((~BCe)& BCi );
Eba ^= KeccakF1600Constants[round];
Ebe = BCe ^((~BCi)& BCo );
Ebi = BCi ^((~BCo)& BCu );
Ebo = BCo ^((~BCu)& BCa );
Ebu = BCu ^((~BCa)& BCe );
Abo ^= Do;
BCa = rotlConstant<28>(Abo);
Agu ^= Du;
BCe = rotlConstant<20>(Agu);
Aka ^= Da;
BCi = rotlConstant<3>(Aka);
Ame ^= De;
BCo = rotlConstant<45>(Ame);
Asi ^= Di;
BCu = rotlConstant<61>(Asi);
Ega = BCa ^((~BCe)& BCi );
Ege = BCe ^((~BCi)& BCo );
Egi = BCi ^((~BCo)& BCu );
Ego = BCo ^((~BCu)& BCa );
Egu = BCu ^((~BCa)& BCe );
Abe ^= De;
BCa = rotlConstant<1>(Abe);
Agi ^= Di;
BCe = rotlConstant<6>(Agi);
Ako ^= Do;
BCi = rotlConstant<25>(Ako);
Amu ^= Du;
BCo = rotlConstant<8>(Amu);
Asa ^= Da;
BCu = rotlConstant<18>(Asa);
Eka = BCa ^((~BCe)& BCi );
Eke = BCe ^((~BCi)& BCo );
Eki = BCi ^((~BCo)& BCu );
Eko = BCo ^((~BCu)& BCa );
Eku = BCu ^((~BCa)& BCe );
Abu ^= Du;
BCa = rotlConstant<27>(Abu);
Aga ^= Da;
BCe = rotlConstant<36>(Aga);
Ake ^= De;
BCi = rotlConstant<10>(Ake);
Ami ^= Di;
BCo = rotlConstant<15>(Ami);
Aso ^= Do;
BCu = rotlConstant<56>(Aso);
Ema = BCa ^((~BCe)& BCi );
Eme = BCe ^((~BCi)& BCo );
Emi = BCi ^((~BCo)& BCu );
Emo = BCo ^((~BCu)& BCa );
Emu = BCu ^((~BCa)& BCe );
Abi ^= Di;
BCa = rotlConstant<62>(Abi);
Ago ^= Do;
BCe = rotlConstant<55>(Ago);
Aku ^= Du;
BCi = rotlConstant<39>(Aku);
Ama ^= Da;
BCo = rotlConstant<41>(Ama);
Ase ^= De;
BCu = rotlConstant<2>(Ase);
Esa = BCa ^((~BCe)& BCi );
Ese = BCe ^((~BCi)& BCo );
Esi = BCi ^((~BCo)& BCu );
Eso = BCo ^((~BCu)& BCa );
Esu = BCu ^((~BCa)& BCe );
// prepareTheta
BCa = Eba^Ega^Eka^Ema^Esa;
BCe = Ebe^Ege^Eke^Eme^Ese;
BCi = Ebi^Egi^Eki^Emi^Esi;
BCo = Ebo^Ego^Eko^Emo^Eso;
BCu = Ebu^Egu^Eku^Emu^Esu;
//thetaRhoPiChiIotaPrepareTheta(round+1, E, A)
Da = BCu^rotlConstant<1>(BCe);
De = BCa^rotlConstant<1>(BCi);
Di = BCe^rotlConstant<1>(BCo);
Do = BCi^rotlConstant<1>(BCu);
Du = BCo^rotlConstant<1>(BCa);
Eba ^= Da;
BCa = Eba;
Ege ^= De;
BCe = rotlConstant<44>(Ege);
Eki ^= Di;
BCi = rotlConstant<43>(Eki);
Emo ^= Do;
BCo = rotlConstant<21>(Emo);
Esu ^= Du;
BCu = rotlConstant<14>(Esu);
Aba = BCa ^((~BCe)& BCi );
Aba ^= KeccakF1600Constants[round+1];
Abe = BCe ^((~BCi)& BCo );
Abi = BCi ^((~BCo)& BCu );
Abo = BCo ^((~BCu)& BCa );
Abu = BCu ^((~BCa)& BCe );
Ebo ^= Do;
BCa = rotlConstant<28>(Ebo);
Egu ^= Du;
BCe = rotlConstant<20>(Egu);
Eka ^= Da;
BCi = rotlConstant<3>(Eka);
Eme ^= De;
BCo = rotlConstant<45>(Eme);
Esi ^= Di;
BCu = rotlConstant<61>(Esi);
Aga = BCa ^((~BCe)& BCi );
Age = BCe ^((~BCi)& BCo );
Agi = BCi ^((~BCo)& BCu );
Ago = BCo ^((~BCu)& BCa );
Agu = BCu ^((~BCa)& BCe );
Ebe ^= De;
BCa = rotlConstant<1>(Ebe);
Egi ^= Di;
BCe = rotlConstant<6>(Egi);
Eko ^= Do;
BCi = rotlConstant<25>(Eko);
Emu ^= Du;
BCo = rotlConstant<8>(Emu);
Esa ^= Da;
BCu = rotlConstant<18>(Esa);
Aka = BCa ^((~BCe)& BCi );
Ake = BCe ^((~BCi)& BCo );
Aki = BCi ^((~BCo)& BCu );
Ako = BCo ^((~BCu)& BCa );
Aku = BCu ^((~BCa)& BCe );
Ebu ^= Du;
BCa = rotlConstant<27>(Ebu);
Ega ^= Da;
BCe = rotlConstant<36>(Ega);
Eke ^= De;
BCi = rotlConstant<10>(Eke);
Emi ^= Di;
BCo = rotlConstant<15>(Emi);
Eso ^= Do;
BCu = rotlConstant<56>(Eso);
Ama = BCa ^((~BCe)& BCi );
Ame = BCe ^((~BCi)& BCo );
Ami = BCi ^((~BCo)& BCu );
Amo = BCo ^((~BCu)& BCa );
Amu = BCu ^((~BCa)& BCe );
Ebi ^= Di;
BCa = rotlConstant<62>(Ebi);
Ego ^= Do;
BCe = rotlConstant<55>(Ego);
Eku ^= Du;
BCi = rotlConstant<39>(Eku);
Ema ^= Da;
BCo = rotlConstant<41>(Ema);
Ese ^= De;
BCu = rotlConstant<2>(Ese);
Asa = BCa ^((~BCe)& BCi );
Ase = BCe ^((~BCi)& BCo );
Asi = BCi ^((~BCo)& BCu );
Aso = BCo ^((~BCu)& BCa );
Asu = BCu ^((~BCa)& BCe );
}
Block::Put(NULLPTR, state)(Aba)(Abe)(Abi)(Abo)(Abu)(Aga)(Age)(Agi)(Ago)(Agu)(Aka)(Ake)(Aki)(Ako)(Aku)(Ama)(Ame)(Ami)(Amo)(Amu)(Asa)(Ase)(Asi)(Aso)(Asu);
}
NAMESPACE_END

File diff suppressed because it is too large Load Diff

View File

@ -1,258 +0,0 @@
// keccakc.cpp - Keccak core functions shared between SHA3 and Keccak.
// written and placed in the public domain by JW.
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michael Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by Ronny Van Keer, hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "pch.h"
#include "keccak.h"
#include "keccakc.h"
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word64;
const word64 KeccakF_RoundConstants[24] =
{
W64LIT(0x0000000000000001), W64LIT(0x0000000000008082), W64LIT(0x800000000000808a),
W64LIT(0x8000000080008000), W64LIT(0x000000000000808b), W64LIT(0x0000000080000001),
W64LIT(0x8000000080008081), W64LIT(0x8000000000008009), W64LIT(0x000000000000008a),
W64LIT(0x0000000000000088), W64LIT(0x0000000080008009), W64LIT(0x000000008000000a),
W64LIT(0x000000008000808b), W64LIT(0x800000000000008b), W64LIT(0x8000000000008089),
W64LIT(0x8000000000008003), W64LIT(0x8000000000008002), W64LIT(0x8000000000000080),
W64LIT(0x000000000000800a), W64LIT(0x800000008000000a), W64LIT(0x8000000080008081),
W64LIT(0x8000000000008080), W64LIT(0x0000000080000001), W64LIT(0x8000000080008008)
};
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
void KeccakF1600(word64 *state)
{
{
word64 Aba, Abe, Abi, Abo, Abu;
word64 Aga, Age, Agi, Ago, Agu;
word64 Aka, Ake, Aki, Ako, Aku;
word64 Ama, Ame, Ami, Amo, Amu;
word64 Asa, Ase, Asi, Aso, Asu;
word64 BCa, BCe, BCi, BCo, BCu;
word64 Da, De, Di, Do, Du;
word64 Eba, Ebe, Ebi, Ebo, Ebu;
word64 Ega, Ege, Egi, Ego, Egu;
word64 Eka, Eke, Eki, Eko, Eku;
word64 Ema, Eme, Emi, Emo, Emu;
word64 Esa, Ese, Esi, Eso, Esu;
//copyFromState(A, state)
typedef BlockGetAndPut<word64, LittleEndian, true, true> Block;
Block::Get(state)(Aba)(Abe)(Abi)(Abo)(Abu)(Aga)(Age)(Agi)(Ago)(Agu)(Aka)(Ake)(Aki)(Ako)(Aku)(Ama)(Ame)(Ami)(Amo)(Amu)(Asa)(Ase)(Asi)(Aso)(Asu);
for( unsigned int round = 0; round < 24; round += 2 )
{
// prepareTheta
BCa = Aba^Aga^Aka^Ama^Asa;
BCe = Abe^Age^Ake^Ame^Ase;
BCi = Abi^Agi^Aki^Ami^Asi;
BCo = Abo^Ago^Ako^Amo^Aso;
BCu = Abu^Agu^Aku^Amu^Asu;
//thetaRhoPiChiIotaPrepareTheta(round , A, E)
Da = BCu^rotlConstant<1>(BCe);
De = BCa^rotlConstant<1>(BCi);
Di = BCe^rotlConstant<1>(BCo);
Do = BCi^rotlConstant<1>(BCu);
Du = BCo^rotlConstant<1>(BCa);
Aba ^= Da;
BCa = Aba;
Age ^= De;
BCe = rotlConstant<44>(Age);
Aki ^= Di;
BCi = rotlConstant<43>(Aki);
Amo ^= Do;
BCo = rotlConstant<21>(Amo);
Asu ^= Du;
BCu = rotlConstant<14>(Asu);
Eba = BCa ^((~BCe)& BCi );
Eba ^= (word64)KeccakF_RoundConstants[round];
Ebe = BCe ^((~BCi)& BCo );
Ebi = BCi ^((~BCo)& BCu );
Ebo = BCo ^((~BCu)& BCa );
Ebu = BCu ^((~BCa)& BCe );
Abo ^= Do;
BCa = rotlConstant<28>(Abo);
Agu ^= Du;
BCe = rotlConstant<20>(Agu);
Aka ^= Da;
BCi = rotlConstant<3>(Aka);
Ame ^= De;
BCo = rotlConstant<45>(Ame);
Asi ^= Di;
BCu = rotlConstant<61>(Asi);
Ega = BCa ^((~BCe)& BCi );
Ege = BCe ^((~BCi)& BCo );
Egi = BCi ^((~BCo)& BCu );
Ego = BCo ^((~BCu)& BCa );
Egu = BCu ^((~BCa)& BCe );
Abe ^= De;
BCa = rotlConstant<1>(Abe);
Agi ^= Di;
BCe = rotlConstant<6>(Agi);
Ako ^= Do;
BCi = rotlConstant<25>(Ako);
Amu ^= Du;
BCo = rotlConstant<8>(Amu);
Asa ^= Da;
BCu = rotlConstant<18>(Asa);
Eka = BCa ^((~BCe)& BCi );
Eke = BCe ^((~BCi)& BCo );
Eki = BCi ^((~BCo)& BCu );
Eko = BCo ^((~BCu)& BCa );
Eku = BCu ^((~BCa)& BCe );
Abu ^= Du;
BCa = rotlConstant<27>(Abu);
Aga ^= Da;
BCe = rotlConstant<36>(Aga);
Ake ^= De;
BCi = rotlConstant<10>(Ake);
Ami ^= Di;
BCo = rotlConstant<15>(Ami);
Aso ^= Do;
BCu = rotlConstant<56>(Aso);
Ema = BCa ^((~BCe)& BCi );
Eme = BCe ^((~BCi)& BCo );
Emi = BCi ^((~BCo)& BCu );
Emo = BCo ^((~BCu)& BCa );
Emu = BCu ^((~BCa)& BCe );
Abi ^= Di;
BCa = rotlConstant<62>(Abi);
Ago ^= Do;
BCe = rotlConstant<55>(Ago);
Aku ^= Du;
BCi = rotlConstant<39>(Aku);
Ama ^= Da;
BCo = rotlConstant<41>(Ama);
Ase ^= De;
BCu = rotlConstant<2>(Ase);
Esa = BCa ^((~BCe)& BCi );
Ese = BCe ^((~BCi)& BCo );
Esi = BCi ^((~BCo)& BCu );
Eso = BCo ^((~BCu)& BCa );
Esu = BCu ^((~BCa)& BCe );
// prepareTheta
BCa = Eba^Ega^Eka^Ema^Esa;
BCe = Ebe^Ege^Eke^Eme^Ese;
BCi = Ebi^Egi^Eki^Emi^Esi;
BCo = Ebo^Ego^Eko^Emo^Eso;
BCu = Ebu^Egu^Eku^Emu^Esu;
//thetaRhoPiChiIotaPrepareTheta(round+1, E, A)
Da = BCu^rotlConstant<1>(BCe);
De = BCa^rotlConstant<1>(BCi);
Di = BCe^rotlConstant<1>(BCo);
Do = BCi^rotlConstant<1>(BCu);
Du = BCo^rotlConstant<1>(BCa);
Eba ^= Da;
BCa = Eba;
Ege ^= De;
BCe = rotlConstant<44>(Ege);
Eki ^= Di;
BCi = rotlConstant<43>(Eki);
Emo ^= Do;
BCo = rotlConstant<21>(Emo);
Esu ^= Du;
BCu = rotlConstant<14>(Esu);
Aba = BCa ^((~BCe)& BCi );
Aba ^= (word64)KeccakF_RoundConstants[round+1];
Abe = BCe ^((~BCi)& BCo );
Abi = BCi ^((~BCo)& BCu );
Abo = BCo ^((~BCu)& BCa );
Abu = BCu ^((~BCa)& BCe );
Ebo ^= Do;
BCa = rotlConstant<28>(Ebo);
Egu ^= Du;
BCe = rotlConstant<20>(Egu);
Eka ^= Da;
BCi = rotlConstant<3>(Eka);
Eme ^= De;
BCo = rotlConstant<45>(Eme);
Esi ^= Di;
BCu = rotlConstant<61>(Esi);
Aga = BCa ^((~BCe)& BCi );
Age = BCe ^((~BCi)& BCo );
Agi = BCi ^((~BCo)& BCu );
Ago = BCo ^((~BCu)& BCa );
Agu = BCu ^((~BCa)& BCe );
Ebe ^= De;
BCa = rotlConstant<1>(Ebe);
Egi ^= Di;
BCe = rotlConstant<6>(Egi);
Eko ^= Do;
BCi = rotlConstant<25>(Eko);
Emu ^= Du;
BCo = rotlConstant<8>(Emu);
Esa ^= Da;
BCu = rotlConstant<18>(Esa);
Aka = BCa ^((~BCe)& BCi );
Ake = BCe ^((~BCi)& BCo );
Aki = BCi ^((~BCo)& BCu );
Ako = BCo ^((~BCu)& BCa );
Aku = BCu ^((~BCa)& BCe );
Ebu ^= Du;
BCa = rotlConstant<27>(Ebu);
Ega ^= Da;
BCe = rotlConstant<36>(Ega);
Eke ^= De;
BCi = rotlConstant<10>(Eke);
Emi ^= Di;
BCo = rotlConstant<15>(Emi);
Eso ^= Do;
BCu = rotlConstant<56>(Eso);
Ama = BCa ^((~BCe)& BCi );
Ame = BCe ^((~BCi)& BCo );
Ami = BCi ^((~BCo)& BCu );
Amo = BCo ^((~BCu)& BCa );
Amu = BCu ^((~BCa)& BCe );
Ebi ^= Di;
BCa = rotlConstant<62>(Ebi);
Ego ^= Do;
BCe = rotlConstant<55>(Ego);
Eku ^= Du;
BCi = rotlConstant<39>(Eku);
Ema ^= Da;
BCo = rotlConstant<41>(Ema);
Ese ^= De;
BCu = rotlConstant<2>(Ese);
Asa = BCa ^((~BCe)& BCi );
Ase = BCe ^((~BCi)& BCo );
Asi = BCi ^((~BCo)& BCu );
Aso = BCo ^((~BCu)& BCa );
Asu = BCu ^((~BCa)& BCe );
}
//copyToState(state, A)
Block::Put(NULLPTR, state)(Aba)(Abe)(Abi)(Abo)(Abu)(Aga)(Age)(Agi)(Ago)(Agu)(Aka)(Ake)(Aki)(Ako)(Aku)(Ama)(Ame)(Ami)(Amo)(Amu)(Asa)(Ase)(Asi)(Aso)(Asu);
}
}
NAMESPACE_END

View File

@ -1,13 +0,0 @@
// keccakc.h - Keccak core functions shared between SHA3 and Keccak.
// written and placed in the public domain by JW.
#ifndef CRYPTOPP_KECCAK_CORE
#define CRYPTOPP_KECCAK_CORE
NAMESPACE_BEGIN(CryptoPP)
void KeccakF1600(word64 *state);
NAMESPACE_END
#endif // CRYPTOPP_KECCAK_CORE

View File

@ -16,7 +16,9 @@
#include "algparam.h"
#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
# define CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS 1
# ifndef CRYPTOPP_DISABLE_LEA_SIMD
# define CRYPTOPP_LEA_ADVANCED_PROCESS_BLOCKS 1
# endif
#endif
// Yet another SunStudio/SunCC workaround. Failed self tests

View File

@ -10,7 +10,6 @@
#include "lea.h"
#include "misc.h"
#include "adv_simd.h"
// Uncomment for benchmarking C++ against SSE or NEON.
// Do so in both simon.cpp and simon-simd.cpp.
@ -18,6 +17,7 @@
// #undef CRYPTOPP_ARM_NEON_AVAILABLE
#if (CRYPTOPP_SSSE3_AVAILABLE)
# include "adv_simd.h"
# include <pmmintrin.h>
# include <tmmintrin.h>
#endif
@ -26,38 +26,41 @@
# include <ammintrin.h>
#endif
#if defined(__AVX512F__) && defined(__AVX512VL__)
#if defined(__AVX512F__)
# define CRYPTOPP_AVX512_ROTATE 1
# include <immintrin.h>
#endif
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
# include <arm_neon.h>
# include "adv_simd.h"
# ifndef _M_ARM64
# include <arm_neon.h>
# endif
#endif
// Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
// compilers don't follow ACLE conventions for the include.
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>
#endif
// Do not port this to POWER architecture. Naively we hoped
// for a 2x to 3x speedup. The result was a 5x slow down
// because of the rotates and scattered loads.
// for a 2x to 3x speedup. The result was a 5x slow down.
// The table below shows MiB/s and cpb.
//
// C++:
// <TD>LEA-128(128)/CTR (128-bit key)<TD>C++<TD>207<TD>15.64<TD>0.593<TD>2015
// <TD>LEA-128(192)/CTR (192-bit key)<TD>C++<TD>186<TD>17.48<TD>0.699<TD>2378
// <TD>LEA-128(256)/CTR (256-bit key)<TD>C++<TD>124<TD>26.2<TD>0.842<TD>2861
// <TD>LEA-128(128)/CTR (128-bit key)<TD>C++<TD>207<TD>15.64
// <TD>LEA-128(192)/CTR (192-bit key)<TD>C++<TD>186<TD>17.48
// <TD>LEA-128(256)/CTR (256-bit key)<TD>C++<TD>124<TD>26.2
//
// Power8:
// <TD>LEA-128(128)/CTR (128-bit key)<TD>Power8<TD>37<TD>88.7<TD>0.595<TD>2023
// <TD>LEA-128(192)/CTR (192-bit key)<TD>Power8<TD>40<TD>82.1<TD>0.699<TD>2375
// <TD>LEA-128(256)/CTR (256-bit key)<TD>Power8<TD>28<TD>116.0<TD>1.006<TD>3419
// <TD>LEA-128(128)/CTR (128-bit key)<TD>Power8<TD>37<TD>88.7
// <TD>LEA-128(192)/CTR (192-bit key)<TD>Power8<TD>40<TD>82.1
// <TD>LEA-128(256)/CTR (256-bit key)<TD>Power8<TD>28<TD>116.0
#undef CRYPTOPP_POWER8_AVAILABLE
#if defined(CRYPTOPP_POWER8_AVAILABLE)
# include "adv_simd.h"
# include "ppc_simd.h"
#endif
@ -1034,17 +1037,15 @@ size_t LEA_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
size_t LEA_Enc_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
{
uint32x4_t unused; // Avoid template argument deduction/substitution failures
return AdvancedProcessBlocks128_4x1_NEON(LEA_Enc_Block, LEA_Enc_4_Blocks,
unused, subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags);
subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags);
}
size_t LEA_Dec_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
{
uint32x4_t unused; // Avoid template argument deduction/substitution failures
return AdvancedProcessBlocks128_4x1_NEON(LEA_Dec_Block, LEA_Dec_4_Blocks,
unused, subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags);
subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags);
}
#endif // CRYPTOPP_ARM_NEON_AVAILABLE

View File

@ -280,8 +280,6 @@ void CallNewHandler()
throw std::bad_alloc();
}
#if CRYPTOPP_BOOL_ALIGN16
void * AlignedAllocate(size_t size)
{
byte *p;
@ -300,10 +298,13 @@ void * AlignedAllocate(size_t size)
#ifdef CRYPTOPP_NO_ALIGNED_ALLOC
size_t adjustment = 16-((size_t)p%16);
CRYPTOPP_ASSERT(adjustment > 0);
p += adjustment;
p[-1] = (byte)adjustment;
#endif
// If this assert fires then there are problems that need
// to be fixed. Please open a bug report.
CRYPTOPP_ASSERT(IsAlignedOn(p, 16));
return p;
}
@ -320,8 +321,6 @@ void AlignedDeallocate(void *p)
#endif
}
#endif // CRYPTOPP_BOOL_ALIGN16
void * UnalignedAllocate(size_t size)
{
void *p;

View File

@ -18,11 +18,12 @@
# endif
#endif
// Issue 340
// Issue 340 and Issue 793
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wconversion"
# pragma GCC diagnostic ignored "-Wsign-conversion"
# pragma GCC diagnostic ignored "-Wunused-function"
#endif
#include "cryptlib.h"
@ -101,35 +102,6 @@
#endif // CRYPTOPP_DOXYGEN_PROCESSING
// NumericLimitsMin and NumericLimitsMax added for word128 types,
// see http://github.com/weidai11/cryptopp/issues/364
ANONYMOUS_NAMESPACE_BEGIN
template<class T>
T NumericLimitsMin()
{
CRYPTOPP_ASSERT(std::numeric_limits<T>::is_specialized);
return (std::numeric_limits<T>::min)();
}
template<class T>
T NumericLimitsMax()
{
CRYPTOPP_ASSERT(std::numeric_limits<T>::is_specialized);
return (std::numeric_limits<T>::max)();
}
#if defined(CRYPTOPP_WORD128_AVAILABLE)
template<>
CryptoPP::word128 NumericLimitsMin()
{
return 0;
}
template<>
CryptoPP::word128 NumericLimitsMax()
{
return (((CryptoPP::word128)W64LIT(0xffffffffffffffff)) << 64U) | (CryptoPP::word128)W64LIT(0xffffffffffffffff);
}
#endif
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
// Forward declaration for IntToString specialization
@ -617,7 +589,7 @@ template <class T1, class T2> inline const T1 UnsignedMin(const T1& a, const T2&
template <class T1, class T2>
inline bool SafeConvert(T1 from, T2 &to)
{
to = (T2)from;
to = static_cast<T2>(from);
if (from != to || (from > 0) != (to > 0))
return false;
return true;
@ -632,7 +604,7 @@ template <class T>
std::string IntToString(T value, unsigned int base = 10)
{
// Hack... set the high bit for uppercase.
static const unsigned int HIGH_BIT = (1U << 31);
const unsigned int HIGH_BIT = (1U << 31);
const char CH = !!(base & HIGH_BIT) ? 'A' : 'a';
base &= ~HIGH_BIT;
@ -899,18 +871,20 @@ CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byt
/// \param buf1 the first buffer
/// \param buf2 the second buffer
/// \param count the size of the buffers, in bytes
/// \details The function effectively performs an XOR of the elements in two equally sized buffers
/// and retruns a result based on the XOR operation. The function is near constant-time because
/// CPU micro-code timings could affect the "constant-ness". Calling code is responsible for
/// mitigating timing attacks if the buffers are not equally sized.
/// \details The function effectively performs an XOR of the elements in two equally sized
/// buffers and retruns a result based on the XOR operation. The function is near
/// constant-time because CPU micro-code timings could affect the "constant-ness".
/// Calling code is responsible for mitigating timing attacks if the buffers are not
/// equally sized.
/// \sa ModPowerOf2
CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
/// \brief Tests whether a value is a power of 2
/// \param value the value to test
/// \returns true if value is a power of 2, false otherwise
/// \details The function creates a mask of <tt>value - 1</tt> and returns the result of
/// an AND operation compared to 0. If value is 0 or less than 0, then the function returns false.
/// \details The function creates a mask of <tt>value - 1</tt> and returns the result
/// of an AND operation compared to 0. If value is 0 or less than 0, then the function
/// returns false.
template <class T>
inline bool IsPowerOf2(const T &value)
{
@ -933,13 +907,65 @@ inline bool IsPowerOf2<word64>(const word64 &value)
# endif // __x86_64__
#endif // __BMI__
/// \brief Provide the minimum value for a type
/// \tparam T type of class
/// \returns the minimum value of the type or class
/// \details NumericLimitsMin() was introduced for Clang at <A
/// HREF="http://github.com/weidai11/cryptopp/issues/364">Issue 364,
/// Apple Clang 6.0 and numeric_limits<word128>::max() returns 0</A>.
/// \details NumericLimitsMin() requires a specialization for <tt>T</tt>,
/// meaning <tt>std::numeric_limits<T>::is_specialized</tt> must return
/// <tt>true</tt>. In the case of <tt>word128</tt> Clang did not specialize
/// <tt>numeric_limits</tt> for the type.
/// \since Crypto++ 8.1
template<class T>
inline T NumericLimitsMin()
{
CRYPTOPP_ASSERT(std::numeric_limits<T>::is_specialized);
return (std::numeric_limits<T>::min)();
}
/// \brief Provide the maximum value for a type
/// \tparam T type of class
/// \returns the maximum value of the type or class
/// \details NumericLimitsMax() was introduced for Clang at <A
/// HREF="http://github.com/weidai11/cryptopp/issues/364">Issue 364,
/// Apple Clang 6.0 and numeric_limits<word128>::max() returns 0</A>.
/// \details NumericLimitsMax() requires a specialization for <tt>T</tt>,
/// meaning <tt>std::numeric_limits<T>::is_specialized</tt> must return
/// <tt>true</tt>. In the case of <tt>word128</tt> Clang did not specialize
/// <tt>numeric_limits</tt> for the type.
/// \since Crypto++ 8.1
template<class T>
inline T NumericLimitsMax()
{
CRYPTOPP_ASSERT(std::numeric_limits<T>::is_specialized);
return (std::numeric_limits<T>::max)();
}
// NumericLimitsMin and NumericLimitsMax added for word128 types,
// see http://github.com/weidai11/cryptopp/issues/364
#if defined(CRYPTOPP_WORD128_AVAILABLE)
template<>
inline word128 NumericLimitsMin()
{
return 0;
}
template<>
inline word128 NumericLimitsMax()
{
return (static_cast<word128>(LWORD_MAX) << 64U) | LWORD_MAX;
}
#endif
/// \brief Performs a saturating subtract clamped at 0
/// \tparam T1 class or type
/// \tparam T2 class or type
/// \param a the minuend
/// \param b the subtrahend
/// \returns the difference produced by the saturating subtract
/// \details Saturating arithmetic restricts results to a fixed range. Results that are less than 0 are clamped at 0.
/// \details Saturating arithmetic restricts results to a fixed range. Results that are
/// less than 0 are clamped at 0.
/// \details Use of saturating arithmetic in places can be advantageous because it can
/// avoid a branch by using an instruction like a conditional move (<tt>CMOVE</tt>).
template <class T1, class T2>
@ -955,8 +981,8 @@ inline T1 SaturatingSubtract(const T1 &a, const T2 &b)
/// \param a the minuend
/// \param b the subtrahend
/// \returns the difference produced by the saturating subtract
/// \details Saturating arithmetic restricts results to a fixed range. Results that are less than
/// 1 are clamped at 1.
/// \details Saturating arithmetic restricts results to a fixed range. Results that are
/// less than 1 are clamped at 1.
/// \details Use of saturating arithmetic in places can be advantageous because it can
/// avoid a branch by using an instruction like a conditional move (<tt>CMOVE</tt>).
template <class T1, class T2>
@ -1156,6 +1182,7 @@ inline CipherDir GetCipherDir(const T &obj)
/// to free memory. There is no guarantee CallNewHandler will be able to procure more memory so
/// an allocation succeeds. If the call to set_new_handler fails, then CallNewHandler throws
/// a bad_alloc exception.
/// \sa AlignedAllocate, AlignedDeallocate, UnalignedAllocate, UnalignedDeallocate
CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
/// \brief Performs an addition with carry on a block of bytes
@ -1380,37 +1407,44 @@ std::string StringNarrow(const wchar_t *str, bool throwOnError = true);
/// then a 0x21 error is returned on Windows which eventually results in an InvalidArgument() exception.
std::wstring StringWiden(const char *str, bool throwOnError = true);
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
/// \brief Allocates a buffer on 16-byte boundary
/// \param size the size of the buffer
/// \details AlignedAllocate is primarily used when the data will be proccessed by MMX, SSE2 and NEON
/// instructions. The assembly language routines rely on the alignment. If the alignment is not
/// \details AlignedAllocate is primarily used when the data will be
/// proccessed by SSE, NEON, ARMv8 or PowerPC instructions. The assembly
/// language routines rely on the alignment. If the alignment is not
/// respected, then a SIGBUS could be generated on Unix and Linux, and an
/// EXCEPTION_DATATYPE_MISALIGNMENT could be generated on Windows.
/// \note AlignedAllocate and AlignedDeallocate are available when CRYPTOPP_BOOL_ALIGN16 is
/// defined. CRYPTOPP_BOOL_ALIGN16 is defined in config.h
/// \details Formerly, AlignedAllocate and AlignedDeallocate were only
/// available on certain platforms when CRYTPOPP_DISABLE_ASM was not in
/// effect. However, Android and iOS debug simulator builds got into a
/// state where the aligned allocator was not available and caused link
/// failures.
/// \since AlignedAllocate for SIMD since Crypto++ 1.0, AlignedAllocate
/// for all builds since Crypto++ 8.1
/// \sa AlignedDeallocate, UnalignedAllocate, UnalignedDeallocate, CallNewHandler,
/// <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
CRYPTOPP_DLL void* CRYPTOPP_API AlignedAllocate(size_t size);
/// \brief Frees a buffer allocated with AlignedAllocate
/// \param ptr the buffer to free
/// \note AlignedAllocate and AlignedDeallocate are available when CRYPTOPP_BOOL_ALIGN16 is
/// defined. CRYPTOPP_BOOL_ALIGN16 is defined in config.h
/// \since AlignedDeallocate for SIMD since Crypto++ 1.0, AlignedAllocate
/// for all builds since Crypto++ 8.1
/// \sa AlignedAllocate, UnalignedAllocate, UnalignedDeallocate, CallNewHandler,
/// <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
CRYPTOPP_DLL void CRYPTOPP_API AlignedDeallocate(void *ptr);
#endif // CRYPTOPP_DOXYGEN_PROCESSING
#if CRYPTOPP_BOOL_ALIGN16
CRYPTOPP_DLL void* CRYPTOPP_API AlignedAllocate(size_t size);
CRYPTOPP_DLL void CRYPTOPP_API AlignedDeallocate(void *ptr);
#endif // CRYPTOPP_BOOL_ALIGN16
/// \brief Allocates a buffer
/// \param size the size of the buffer
/// \since Crypto++ 1.0
/// \sa AlignedAllocate, AlignedDeallocate, UnalignedDeallocate, CallNewHandler,
/// <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
CRYPTOPP_DLL void * CRYPTOPP_API UnalignedAllocate(size_t size);
/// \brief Frees a buffer allocated with UnalignedAllocate
/// \param ptr the buffer to free
/// \since Crypto++ 1.0
/// \sa AlignedAllocate, AlignedDeallocate, UnalignedAllocate, CallNewHandler,
/// <A HREF="http://github.com/weidai11/cryptopp/issues/779">Issue 779</A>
CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *ptr);
// ************** rotate functions ***************
@ -1436,8 +1470,8 @@ template <unsigned int R, class T> inline T rotlConstant(T x)
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(R < THIS_SIZE);
return T((x<<R)|(x>>(-R&MASK)));
}
@ -1462,8 +1496,8 @@ template <unsigned int R, class T> inline T rotrConstant(T x)
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(R < THIS_SIZE);
return T((x >> R)|(x<<(-R&MASK)));
}
@ -1487,8 +1521,8 @@ template <class T> inline T rotlFixed(T x, unsigned int y)
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x<<y)|(x>>(-y&MASK)));
}
@ -1512,8 +1546,8 @@ template <class T> inline T rotrFixed(T x, unsigned int y)
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x >> y)|(x<<(-y&MASK)));
}
@ -1532,8 +1566,8 @@ template <class T> inline T rotrFixed(T x, unsigned int y)
/// \since Crypto++ 3.0
template <class T> inline T rotlVariable(T x, unsigned int y)
{
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x<<y)|(x>>(-y&MASK)));
}
@ -1552,8 +1586,8 @@ template <class T> inline T rotlVariable(T x, unsigned int y)
/// \since Crypto++ 3.0
template <class T> inline T rotrVariable(T x, unsigned int y)
{
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x>>y)|(x<<(-y&MASK)));
}
@ -1569,8 +1603,8 @@ template <class T> inline T rotrVariable(T x, unsigned int y)
/// \since Crypto++ 3.0
template <class T> inline T rotlMod(T x, unsigned int y)
{
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
return T((x<<(y&MASK))|(x>>(-y&MASK)));
}
@ -1585,8 +1619,8 @@ template <class T> inline T rotlMod(T x, unsigned int y)
/// \since Crypto++ 3.0
template <class T> inline T rotrMod(T x, unsigned int y)
{
static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1;
CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
return T((x>>(y&MASK))|(x<<(-y&MASK)));
}

View File

@ -53,7 +53,7 @@
#include "config.h"
#include "stdcpp.h"
#if defined(NO_OS_DEPENDENCE)
#if defined(NO_OS_DEPENDENCE) || !defined(OS_RNG_AVAILABLE)
# define CRYPTOPP_DISABLE_NACL 1
#endif

View File

@ -11,12 +11,11 @@
#include "config.h"
#include "stdcpp.h"
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) && !defined(_M_ARM64)
# include <arm_neon.h>
#endif
// Can't use CRYPTOPP_ARM_XXX_AVAILABLE because too many
// compilers don't follow ACLE conventions for the include.
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h>
# include <arm_acle.h>

View File

@ -8,8 +8,10 @@
#ifndef CRYPTOPP_IMPORTS
// Win32 has CryptoAPI and <wincrypt.h>. Windows 10 and Windows Store 10 have CNG and <bcrypt.h>.
// There's a hole for Windows Phone 8 and Windows Store 8. There is no userland crypto available.
// Also see http://stackoverflow.com/questions/36974545/random-numbers-for-windows-phone-8-and-windows-store-8
// There's a hole for Windows Phone 8 and Windows Store 8. There is no userland RNG available.
// Also see http://www.drdobbs.com/windows/using-c-and-com-with-winrt/240168150 and
// http://stackoverflow.com/questions/36974545/random-numbers-for-windows-phone-8-and-windows-store-8 and
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/25b83e13-c85f-4aa1-a057-88a279ea3fd6/what-crypto-random-generator-c-code-could-use-on-wp81
#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(OS_RNG_AVAILABLE)
# pragma message("WARNING: Compiling for Windows but an OS RNG is not available. This is likely a Windows Phone 8 or Windows Store 8 app.")
#endif

View File

@ -50,6 +50,7 @@ public:
unsigned int DigestSize() const {return DIGESTSIZE;}
void TruncatedFinal(byte *hash, size_t size);
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == BIG_ENDIAN_ORDER ? "Panama-BE" : "Panama-LE";}
std::string AlgorithmProvider() const {return Panama<B>::AlgorithmProvider();} // Fix https://github.com/weidai11/cryptopp/issues/801
protected:
void Init() {Panama<B>::Reset();}

View File

@ -1,120 +1,59 @@
// poly1305.cpp - written and placed in the public domain by Jeffrey Walton and Jean-Pierre Munch
// Based on Andy Polyakov's Base-2^26 scalar multiplication implementation for OpenSSL.
// Based on Andy Polyakov's Base-2^26 scalar multiplication implementation.
// For more information, see https://www.openssl.org/~appro/cryptogams/.
// Copyright (c) 2006-2017, CRYPTOGAMS by <appro@openssl.org>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain copyright notices,
// this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of the CRYPTOGAMS nor the names of its copyright
// holder and contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
#include "pch.h"
#include "cryptlib.h"
#include "poly1305.h"
#include "aes.h"
#include "cpu.h"
#include "poly1305.h"
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Common Poly1305 //////////////////////////////
#define CONSTANT_TIME_CARRY(a,b) ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1))
ANONYMOUS_NAMESPACE_BEGIN
template <class T>
std::string Poly1305_Base<T>::AlgorithmProvider() const
using namespace CryptoPP;
inline word32 CONSTANT_TIME_CARRY(word32 a, word32 b)
{
return m_cipher.AlgorithmProvider();
return ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1));
}
template <class T>
void Poly1305_Base<T>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
if (key && length)
{
// key is {k,r} pair, r is 16 bytes
length = SaturatingSubtract(length, (unsigned)BLOCKSIZE);
m_cipher.SetKey(key, length);
key += length;
// Rbar is clamped and little endian
m_r[0] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 0) & 0x0fffffff;
m_r[1] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 4) & 0x0ffffffc;
m_r[2] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 8) & 0x0ffffffc;
m_r[3] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 12) & 0x0ffffffc;
m_used = false;
}
ConstByteArrayParameter t;
if (params.GetValue(Name::IV(), t) && t.begin() && t.size())
{
// Nonce key is a class member to avoid the zeroizer on a temporary
CRYPTOPP_ASSERT(t.size() == m_nk.size());
std::memcpy(m_nk.begin(), t.begin(), m_nk.size());
m_cipher.ProcessBlock(m_nk.begin());
m_n[0] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 0);
m_n[1] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 4);
m_n[2] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 8);
m_n[3] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 12);
m_used = false;
}
Restart();
}
template <class T>
void Poly1305_Base<T>::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT((input && length) || !length);
if (!length) return;
size_t rem, num = m_idx;
if (num)
{
rem = BLOCKSIZE - num;
if (length >= rem)
{
// Process
memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem);
HashBlocks(m_acc, BLOCKSIZE, 1);
input += rem;
length -= rem;
}
else
{
// Accumulate
memcpy_s(m_acc + num, BLOCKSIZE - num, input, length);
m_idx = num + length;
return;
}
}
rem = length % BLOCKSIZE;
length -= rem;
if (length >= BLOCKSIZE) {
HashBlocks(input, length, 1);
input += length;
}
if (rem)
memcpy(m_acc, input, rem);
m_idx = rem;
}
template <class T>
void Poly1305_Base<T>::HashBlocks(const byte *input, size_t length, word32 padbit)
void Poly1305_HashBlocks(word32 h[5], word32 r[4], const byte *input, size_t length, word32 padbit)
{
word32 r0, r1, r2, r3;
word32 s1, s2, s3;
word32 h0, h1, h2, h3, h4, c;
word64 d0, d1, d2, d3;
r0 = m_r[0]; r1 = m_r[1];
r2 = m_r[2]; r3 = m_r[3];
r0 = r[0]; r1 = r[1];
r2 = r[2]; r3 = r[3];
s1 = r1 + (r1 >> 2);
s2 = r2 + (r2 >> 2);
s3 = r3 + (r3 >> 2);
h0 = m_h[0]; h1 = m_h[1]; h2 = m_h[2];
h3 = m_h[3]; h4 = m_h[4];
h0 = h[0]; h1 = h[1]; h2 = h[2];
h3 = h[3]; h4 = h[4];
while (length >= BLOCKSIZE)
while (length >= 16)
{
// h += m[i]
h0 = (word32)(d0 = (word64)h0 + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 0));
@ -161,51 +100,26 @@ void Poly1305_Base<T>::HashBlocks(const byte *input, size_t length, word32 padbi
h3 += (c = CONSTANT_TIME_CARRY(h2,c));
h4 += CONSTANT_TIME_CARRY(h3,c);
input += BLOCKSIZE;
length -= BLOCKSIZE;
input += 16;
length -= 16;
}
m_h[0] = h0; m_h[1] = h1; m_h[2] = h2;
m_h[3] = h3; m_h[4] = h4;
h[0] = h0; h[1] = h1; h[2] = h2;
h[3] = h3; h[4] = h4;
}
template <class T>
void Poly1305_Base<T>::TruncatedFinal(byte *mac, size_t size)
{
CRYPTOPP_ASSERT(mac); // Pointer is valid
CRYPTOPP_ASSERT(!m_used); // Nonce is fresh
ThrowIfInvalidTruncatedSize(size);
size_t num = m_idx;
if (num)
{
m_acc[num++] = 1; /* pad bit */
while (num < BLOCKSIZE)
m_acc[num++] = 0;
HashBlocks(m_acc, BLOCKSIZE, 0);
}
HashFinal(mac, size);
// Restart
m_used = true;
Restart();
}
template <class T>
void Poly1305_Base<T>::HashFinal(byte *mac, size_t size)
void Poly1305_HashFinal(word32 h[5], word32 n[4], byte *mac, size_t size)
{
word32 h0, h1, h2, h3, h4;
word32 g0, g1, g2, g3, g4;
word32 mask;
word64 t;
h0 = m_h[0];
h1 = m_h[1];
h2 = m_h[2];
h3 = m_h[3];
h4 = m_h[4];
h0 = h[0];
h1 = h[1];
h2 = h[2];
h3 = h[3];
h4 = h[4];
// compare to modulus by computing h + -p
g0 = (word32)(t = (word64)h0 + 5);
@ -223,12 +137,12 @@ void Poly1305_Base<T>::HashFinal(byte *mac, size_t size)
h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3;
// mac = (h + nonce) % (2^128)
h0 = (word32)(t = (word64)h0 + m_n[0]);
h1 = (word32)(t = (word64)h1 + (t >> 32) + m_n[1]);
h2 = (word32)(t = (word64)h2 + (t >> 32) + m_n[2]);
h3 = (word32)(t = (word64)h3 + (t >> 32) + m_n[3]);
h0 = (word32)(t = (word64)h0 + n[0]);
h1 = (word32)(t = (word64)h1 + (t >> 32) + n[1]);
h2 = (word32)(t = (word64)h2 + (t >> 32) + n[2]);
h3 = (word32)(t = (word64)h3 + (t >> 32) + n[3]);
if (size >= BLOCKSIZE)
if (size >= 16)
{
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 0, h0);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 4, h1);
@ -237,21 +151,150 @@ void Poly1305_Base<T>::HashFinal(byte *mac, size_t size)
}
else
{
FixedSizeAlignedSecBlock<byte, BLOCKSIZE> m;
FixedSizeAlignedSecBlock<byte, 16> m;
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, m + 0, h0);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, m + 4, h1);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, m + 8, h2);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, m + 12, h3);
memcpy(mac, m, size);
std::memcpy(mac, m, size);
}
}
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Bernstein Poly1305 //////////////////////////////
// TODO: No longer needed. Remove at next major version bump
template <class T>
void Poly1305_Base<T>::HashBlocks(const byte *input, size_t length, word32 padbit) {
CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length); CRYPTOPP_UNUSED(padbit);
CRYPTOPP_ASSERT(0);
}
// TODO: No longer needed. Remove at next major version bump
template <class T>
void Poly1305_Base<T>::HashFinal(byte *mac, size_t length) {
CRYPTOPP_UNUSED(mac); CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(0);
}
template <class T>
std::string Poly1305_Base<T>::AlgorithmProvider() const
{
return m_cipher.AlgorithmProvider();
}
template <class T>
void Poly1305_Base<T>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(key && length >= 32);
// key is {k,r} pair. k is AES key, r is the additional key that gets clamped
length = SaturatingSubtract(length, (unsigned)BLOCKSIZE);
m_cipher.SetKey(key, length);
key += length;
// Rbar is clamped and little endian
m_r[0] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 0) & 0x0fffffff;
m_r[1] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 4) & 0x0ffffffc;
m_r[2] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 8) & 0x0ffffffc;
m_r[3] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 12) & 0x0ffffffc;
// Mark the nonce as dirty, meaning we need a new one
m_used = true;
ConstByteArrayParameter t;
if (params.GetValue(Name::IV(), t) && t.begin() && t.size())
{
CRYPTOPP_ASSERT(t.size() == m_nk.size());
Resynchronize(t.begin(), (int)t.size());
}
Restart();
}
template <class T>
void Poly1305_Base<T>::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT((input && length) || !length);
if (!length) return;
size_t rem, num = m_idx;
if (num)
{
rem = BLOCKSIZE - num;
if (length >= rem)
{
// Process
memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem);
Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 1);
input += rem; length -= rem;
}
else
{
// Accumulate
memcpy_s(m_acc + num, BLOCKSIZE - num, input, length);
m_idx = num + length;
return;
}
}
rem = length % BLOCKSIZE;
length -= rem;
if (length >= BLOCKSIZE) {
Poly1305_HashBlocks(m_h, m_r, input, length, 1);
input += length;
}
if (rem)
memcpy(m_acc, input, rem);
m_idx = rem;
}
template <class T>
void Poly1305_Base<T>::TruncatedFinal(byte *mac, size_t size)
{
CRYPTOPP_ASSERT(mac); // Pointer is valid
CRYPTOPP_ASSERT(!m_used); // Nonce is fresh
ThrowIfInvalidTruncatedSize(size);
size_t num = m_idx;
if (num)
{
m_acc[num++] = 1; /* pad bit */
while (num < BLOCKSIZE)
m_acc[num++] = 0;
Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 0);
}
Poly1305_HashFinal(m_h, m_n, mac, size);
// Restart
m_used = true;
Restart();
}
template <class T>
void Poly1305_Base<T>::Resynchronize(const byte *nonce, int nonceLength)
{
CRYPTOPP_ASSERT(nonceLength == -1 || nonceLength == (int)BLOCKSIZE);
nonceLength == -1 ? nonceLength = BLOCKSIZE : nonceLength;
this->UncheckedSetKey(NULLPTR, 0, MakeParameters(Name::IV(), ConstByteArrayParameter(nonce, nonceLength)));
// Encrypt the nonce, stash in m_nk
m_cipher.ProcessBlock(nonce, m_nk.begin());
m_n[0] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 0);
m_n[1] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 4);
m_n[2] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 8);
m_n[3] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, m_nk + 12);
// Mark nonce as unused, meaning it is fresh
m_used = false;
}
template <class T>
@ -264,7 +307,93 @@ template <class T>
void Poly1305_Base<T>::Restart()
{
m_h[0] = m_h[1] = m_h[2] = m_h[3] = m_h[4] = 0;
// m_r[0] = m_r[1] = m_r[2] = m_r[3] = 0;
m_idx = 0;
}
////////////////////////////// IETF Poly1305 //////////////////////////////
void Poly1305TLS_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(key && length >= 32);
// key is {r,s} pair. r is the additional key that gets clamped, s is the nonce.
m_r[0] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 0) & 0x0fffffff;
m_r[1] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 4) & 0x0ffffffc;
m_r[2] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 8) & 0x0ffffffc;
m_r[3] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 12) & 0x0ffffffc;
key += 16;
m_n[0] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 0);
m_n[1] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 4);
m_n[2] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 8);
m_n[3] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, key + 12);
Restart();
}
void Poly1305TLS_Base::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT((input && length) || !length);
if (!length) return;
size_t rem, num = m_idx;
if (num)
{
rem = BLOCKSIZE - num;
if (length >= rem)
{
// Process
memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem);
Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 1);
input += rem; length -= rem;
}
else
{
// Accumulate
memcpy_s(m_acc + num, BLOCKSIZE - num, input, length);
m_idx = num + length;
return;
}
}
rem = length % BLOCKSIZE;
length -= rem;
if (length >= BLOCKSIZE) {
Poly1305_HashBlocks(m_h, m_r, input, length, 1);
input += length;
}
if (rem)
memcpy(m_acc, input, rem);
m_idx = rem;
}
void Poly1305TLS_Base::TruncatedFinal(byte *mac, size_t size)
{
CRYPTOPP_ASSERT(mac); // Pointer is valid
ThrowIfInvalidTruncatedSize(size);
size_t num = m_idx;
if (num)
{
m_acc[num++] = 1; /* pad bit */
while (num < BLOCKSIZE)
m_acc[num++] = 0;
Poly1305_HashBlocks(m_h, m_r, m_acc, BLOCKSIZE, 0);
}
Poly1305_HashFinal(m_h, m_n, mac, size);
Restart();
}
void Poly1305TLS_Base::Restart()
{
m_h[0] = m_h[1] = m_h[2] = m_h[3] = m_h[4] = 0;
m_idx = 0;
}

View File

@ -1,45 +1,26 @@
// poly1305.h - written and placed in the public domain by Jeffrey Walton and Jean-Pierre Munch
// Based on Andy Polyakov's Base-2^26 scalar multiplication implementation for OpenSSL.
// Based on Andy Polyakov's Base-2^26 scalar multiplication implementation.
// For more information, see https://www.openssl.org/~appro/cryptogams/.
// The library added Bernstein's Poly1305 classses at Crypto++ 6.0. The IETF
// uses a slightly different implementation than Bernstein, and the IETF
// classes were added at Crypto++ 8.1. We wanted to maintain ABI compatibility
// at the 8.1 release so the original Poly1305 classes were not disturbed.
// Instead new classes were added for IETF Poly1305. The back-end implementation
// shares code as expected, however.
/// \file poly1305.h
/// \brief Classes for Poly1305 message authentication code
/// \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide
/// variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length
/// message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce.
/// \details Each message must use a unique security context, which means either the key or nonce
/// must be changed after each message. It can be accomplished in one of two ways. First, you
/// can create a new Poly1305 object with a key and nonce each time its needed.
/// <pre> SecByteBlock key(32), nonce(16);
/// prng.GenerateBlock(key, key.size());
/// prng.GenerateBlock(nonce, nonce.size());
///
/// Poly1305<AES> poly1305(key, key.size(), nonce, nonce.size());
/// poly1305.Update(...);
/// poly1305.Final(...);</pre>
///
/// \details Second, you can create a Poly1305 object, reuse the key, and set a fresh nonce
/// for each message. The second and subsequent nonces can be generated directly using a
/// RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
/// <pre> SecByteBlock key(32), nonce(16);
/// prng.GenerateBlock(key, key.size());
/// prng.GenerateBlock(nonce, nonce.size());
///
/// // First message
/// Poly1305<AES> poly1305(key, key.size());
/// poly1305.Resynchronize(nonce);
/// poly1305.Update(...);
/// poly1305.Final(...);
///
/// // Second message
/// poly1305.GetNextIV(prng, nonce);
/// poly1305.Resynchronize(nonce);
/// poly1305.Update(...);
/// poly1305.Final(...);
/// ...</pre>
/// \details Crypto++ also supplies the IETF's version of Poly1305. It is a slightly different
/// algorithm than Bernstein's version.
/// \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES
/// Message-Authentication Code (20050329)</A> and Andy Polyakov <A
/// Message-Authentication Code (20050329)</A>, <a href="http://tools.ietf.org/html/rfc8439">RFC
/// 8439, ChaCha20 and Poly1305 for IETF Protocols</a> and Andy Polyakov <A
/// HREF="http://www.openssl.org/blog/blog/2016/02/15/poly1305-revised/">Poly1305 Revised</A>
/// \since Crypto++ 6.0
/// \since Poly1305 since Crypto++ 6.0, Poly1305TLS since Crypto++ 8.1
#ifndef CRYPTOPP_POLY1305_H
#define CRYPTOPP_POLY1305_H
@ -52,8 +33,11 @@
NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Bernstein Poly1305 //////////////////////////////
/// \brief Poly1305 message authentication code base class
/// \tparam T class derived from BlockCipherDocumentation with 16-byte key and 16-byte blocksize
/// \tparam T BlockCipherDocumentation derived class with 16-byte key and 16-byte blocksize
/// \details Poly1305_Base is the base class of Bernstein's Poly1305 algorithm.
/// \since Crypto++ 6.0
template <class T>
class CRYPTOPP_NO_VTABLE Poly1305_Base : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 16>, public MessageAuthenticationCode
@ -67,6 +51,7 @@ public:
CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
virtual ~Poly1305_Base() {}
Poly1305_Base() : m_idx(0), m_used(true) {}
void Resynchronize (const byte *iv, int ivLength=-1);
@ -83,6 +68,7 @@ public:
std::string AlgorithmProvider() const;
protected:
// TODO: No longer needed. Remove at next major version bump
void HashBlocks(const byte *input, size_t length, word32 padbit);
void HashFinal(byte *mac, size_t length);
@ -106,9 +92,13 @@ protected:
/// \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide
/// variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length
/// message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce.
/// \details Each message must use a unique security context, which means either the key or nonce
/// \details The key is 32 bytes and a concatenation <tt>key = {k,s}</tt>, where
/// <tt>k</tt> is the AES key and <tt>r</tt> is additional key that gets clamped.
/// The key is clamped internally so there is no need to perform the operation
/// before setting the key.
/// \details Each message must have a unique security context, which means either the key or nonce
/// must be changed after each message. It can be accomplished in one of two ways. First, you
/// can create a new Poly1305 object with a key and nonce each time its needed.
/// can create a new Poly1305 object each time its needed.
/// <pre> SecByteBlock key(32), nonce(16);
/// prng.GenerateBlock(key, key.size());
/// prng.GenerateBlock(nonce, nonce.size());
@ -118,8 +108,7 @@ protected:
/// poly1305.Final(...);</pre>
///
/// \details Second, you can create a Poly1305 object, reuse the key, and set a fresh nonce
/// for each message. The second and subsequent nonces can be generated directly using a
/// RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
/// for each message. The second and subsequent nonces can be generated using GetNextIV().
/// <pre> SecByteBlock key(32), nonce(16);
/// prng.GenerateBlock(key, key.size());
/// prng.GenerateBlock(nonce, nonce.size());
@ -136,8 +125,9 @@ protected:
/// poly1305.Update(...);
/// poly1305.Final(...);
/// ...</pre>
/// \warning The Poly1305 class does not enforce a fresh nonce for each message. The source code
/// will assert in debug builds to alert of nonce reuse. No action is taken in release builds.
/// \warning Each message must have a unique security context. The Poly1305 class does not
/// enforce a fresh key or nonce for each message. The source code will assert in debug
/// builds to alert of nonce reuse. No action is taken in release builds.
/// \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES
/// Message-Authentication Code (20050329)</A> and Andy Polyakov <A
/// HREF="http://www.openssl.org/blog/blog/2016/02/15/poly1305-revised/">Poly1305 Revised</A>
@ -156,14 +146,96 @@ public:
/// \param keyLength the size of the byte array, in bytes
/// \param nonce a byte array used to key the cipher
/// \param nonceLength the size of the byte array, in bytes
/// \details key is the 32-byte key composed of the 16-byte AES key and the 16 additional key
/// bytes used for <tt>r</tt>.
/// \details Each message requires a unique security context. You can use GetNextIV() and
/// Resynchronize() to set a new nonce under a key for a message.
/// \details The key is 32 bytes and a concatenation <tt>key = {k,s}</tt>, where
/// <tt>k</tt> is the AES key and <tt>r</tt> is additional key that gets clamped.
/// The key is clamped internally so there is no need to perform the operation
/// before setting the key.
/// \details Each message requires a unique security context. You can use GetNextIV()
/// and Resynchronize() to set a new nonce under a key for a message.
Poly1305(const byte *key, size_t keyLength=DEFAULT_KEYLENGTH, const byte *nonce=NULLPTR, size_t nonceLength=0)
{this->SetKey(key, keyLength, MakeParameters(Name::IV(), ConstByteArrayParameter(nonce, nonceLength)));}
};
////////////////////////////// IETF Poly1305 //////////////////////////////
/// \brief Poly1305-TLS message authentication code base class
/// \details Poly1305TLS_Base is the base class of the IETF's Poly1305 algorithm.
/// \since Crypto++ 8.1
class Poly1305TLS_Base : public FixedKeyLength<32>, public MessageAuthenticationCode
{
public:
static std::string StaticAlgorithmName() {return std::string("Poly1305TLS");}
CRYPTOPP_CONSTANT(DIGESTSIZE=16)
CRYPTOPP_CONSTANT(BLOCKSIZE=16)
virtual ~Poly1305TLS_Base() {}
Poly1305TLS_Base() {}
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
void Update(const byte *input, size_t length);
void TruncatedFinal(byte *mac, size_t size);
void Restart();
unsigned int BlockSize() const {return BLOCKSIZE;}
unsigned int DigestSize() const {return DIGESTSIZE;}
protected:
// Accumulated hash, clamped r-key, and encrypted nonce
FixedSizeAlignedSecBlock<word32, 5> m_h;
FixedSizeAlignedSecBlock<word32, 4> m_r;
FixedSizeAlignedSecBlock<word32, 4> m_n;
// Accumulated message bytes and index
FixedSizeAlignedSecBlock<byte, BLOCKSIZE> m_acc;
size_t m_idx;
};
/// \brief Poly1305-TLS message authentication code
/// \details This is the IETF's variant of Bernstein's Poly1305 from RFC 8439.
/// IETF Poly1305 is called Poly1305TLS in the Crypto++ library. It is
/// _slightly_ different from the Bernstein implementation. Poly1305-TLS
/// can be used for cipher suites
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and
/// <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
/// \details The key is 32 bytes and a concatenation <tt>key = {r,s}</tt>, where
/// <tt>r</tt> is additional key that gets clamped and <tt>s</tt> is the nonce.
/// The key is clamped internally so there is no need to perform the operation
/// before setting the key.
/// \details Each message must have a unique security context, which means the key
/// must be changed after each message. It can be accomplished in one of two ways.
/// First, you can create a new Poly1305 object with a new key each time its needed.
/// <pre> SecByteBlock key(32);
/// prng.GenerateBlock(key, key.size());
///
/// Poly1305TLS poly1305(key, key.size());
/// poly1305.Update(...);
/// poly1305.Final(...);</pre>
///
/// \details Second, you can create a Poly1305 object, and use a new key for each
/// message. The keys can be generated directly using a RandomNumberGenerator()
/// derived class.
/// <pre> SecByteBlock key(32);
/// prng.GenerateBlock(key, key.size());
///
/// // First message
/// Poly1305TLS poly1305(key, key.size());
/// poly1305.Update(...);
/// poly1305.Final(...);
///
/// // Second message
/// prng.GenerateBlock(key, key.size());
/// poly1305.SetKey(key, key.size());
/// poly1305.Update(...);
/// poly1305.Final(...);
/// ...</pre>
/// \warning Each message must have a unique security context. The Poly1305-TLS class
/// does not enforce a fresh key or nonce for each message.
/// \since Crypto++ 8.1
/// \sa MessageAuthenticationCode(), <a href="http://tools.ietf.org/html/rfc8439">RFC
/// 8439, ChaCha20 and Poly1305 for IETF Protocols</a>
DOCUMENTED_TYPEDEF(MessageAuthenticationCodeFinal<Poly1305TLS_Base>, Poly1305TLS)
NAMESPACE_END
#endif // CRYPTOPP_POLY1305_H

View File

@ -39,9 +39,10 @@
/// builtins. When using XLC with -qxlcompatmacros the compiler pretends to
/// be GCC, Clang and XLC all at once but it can only consume it's variety
/// of builtins.
/// \details At Crypto++ 8.0 the various VectorFunc{Name} were renamed to
/// VecFunc{Name}. For example, VectorAnd was changed to VecAnd. The name
/// change helped consolidate two slightly different implementations.
/// \details At Crypto++ 8.0 the various <tt>Vector{FuncName}</tt> were
/// renamed to <tt>Vec{FuncName}</tt>. For example, <tt>VectorAnd</tt> was
/// changed to <tt>VecAnd</tt>. The name change helped consolidate two
/// slightly different implementations.
/// \since Crypto++ 6.0, LLVM Clang compiler support since Crypto++ 8.0
// Use __ALTIVEC__, _ARCH_PWR7 and _ARCH_PWR8 when detecting actual
@ -175,7 +176,8 @@ inline T VecReverse(const T data)
#endif
}
//////////////////////// Loads ////////////////////////
/// \name LOAD OPERATIONS
//@{
/// \brief Loads a vector from a byte array
/// \param src the byte array
@ -503,7 +505,10 @@ inline uint32x4_p VecLoadBE(int off, const byte src[16])
#endif // _ARCH_PWR7
}
//////////////////////// Stores ////////////////////////
//@}
/// \name STORE OPERATIONS
//@{
/// \brief Stores a vector to a byte array
/// \tparam T vector type
@ -857,44 +862,10 @@ inline void VecStoreBE(const T data, int off, word32 dest[4])
return VecStoreBE((uint8x16_p)data, off, (byte*)dest);
}
//////////////////////// Miscellaneous ////////////////////////
//@}
/// \brief Permutes a vector
/// \tparam T1 vector type
/// \tparam T2 vector type
/// \param vec the vector
/// \param mask vector mask
/// \returns vector
/// \details VecPermute() returns a new vector from vec based on
/// mask. mask is an uint8x16_p type vector. The return
/// vector is the same type as vec.
/// \par Wraps
/// vec_perm
/// \since Crypto++ 6.0
template <class T1, class T2>
inline T1 VecPermute(const T1 vec, const T2 mask)
{
return (T1)vec_perm(vec, vec, (uint8x16_p)mask);
}
/// \brief Permutes two vectors
/// \tparam T1 vector type
/// \tparam T2 vector type
/// \param vec1 the first vector
/// \param vec2 the second vector
/// \param mask vector mask
/// \returns vector
/// \details VecPermute() returns a new vector from vec1 and vec2
/// based on mask. mask is an uint8x16_p type vector. The return
/// vector is the same type as vec1.
/// \par Wraps
/// vec_perm
/// \since Crypto++ 6.0
template <class T1, class T2>
inline T1 VecPermute(const T1 vec1, const T1 vec2, const T2 mask)
{
return (T1)vec_perm(vec1, (T1)vec2, (uint8x16_p)mask);
}
/// \name LOGICAL OPERATIONS
//@{
/// \brief AND two vectors
/// \tparam T1 vector type
@ -947,6 +918,11 @@ inline T1 VecXor(const T1 vec1, const T2 vec2)
return (T1)vec_xor(vec1, (T1)vec2);
}
//@}
/// \name ARITHMETIC OPERATIONS
//@{
/// \brief Add two vectors
/// \tparam T1 vector type
/// \tparam T2 vector type
@ -1013,6 +989,48 @@ inline uint32x4_p VecAdd64(const uint32x4_p& vec1, const uint32x4_p& vec2)
#endif
}
//@}
/// \name OTHER OPERATIONS
//@{
/// \brief Permutes a vector
/// \tparam T1 vector type
/// \tparam T2 vector type
/// \param vec the vector
/// \param mask vector mask
/// \returns vector
/// \details VecPermute() returns a new vector from vec based on
/// mask. mask is an uint8x16_p type vector. The return
/// vector is the same type as vec.
/// \par Wraps
/// vec_perm
/// \since Crypto++ 6.0
template <class T1, class T2>
inline T1 VecPermute(const T1 vec, const T2 mask)
{
return (T1)vec_perm(vec, vec, (uint8x16_p)mask);
}
/// \brief Permutes two vectors
/// \tparam T1 vector type
/// \tparam T2 vector type
/// \param vec1 the first vector
/// \param vec2 the second vector
/// \param mask vector mask
/// \returns vector
/// \details VecPermute() returns a new vector from vec1 and vec2
/// based on mask. mask is an uint8x16_p type vector. The return
/// vector is the same type as vec1.
/// \par Wraps
/// vec_perm
/// \since Crypto++ 6.0
template <class T1, class T2>
inline T1 VecPermute(const T1 vec1, const T1 vec2, const T2 mask)
{
return (T1)vec_perm(vec1, (T1)vec2, (uint8x16_p)mask);
}
/// \brief Shift a vector left
/// \tparam C shift byte count
/// \tparam T vector type
@ -1172,6 +1190,49 @@ inline uint32x4_p VecRotateLeft(const uint32x4_p vec)
return vec_rl(vec, m);
}
/// \brief Shift a packed vector left
/// \tparam C shift bit count
/// \param vec the vector
/// \returns vector
/// \details VecShiftLeft() rotates each element in a packed vector by bit count.
/// \par Wraps
/// vec_sl
/// \since Crypto++ 8.1
template<unsigned int C>
inline uint32x4_p VecShiftLeft(const uint32x4_p vec)
{
const uint32x4_p m = {C, C, C, C};
return vec_sl(vec, m);
}
/// \brief Merge two vectors
/// \tparam T vector type
/// \param vec1 the first vector
/// \param vec2 the second vector
/// \returns vector
/// \par Wraps
/// vec_mergeh
/// \since Crypto++ 8.1
template <class T>
inline T VecMergeHigh(const T vec1, const T vec2)
{
return vec_mergeh(vec1, vec2);
}
/// \brief Merge two vectors
/// \tparam T vector type
/// \param vec1 the first vector
/// \param vec2 the second vector
/// \returns vector
/// \par Wraps
/// vec_mergel
/// \since Crypto++ 8.1
template <class T>
inline T VecMergeLow(const T vec1, const T vec2)
{
return vec_mergel(vec1, vec2);
}
#if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief Rotate a packed vector left
@ -1190,6 +1251,22 @@ inline uint64x2_p VecRotateLeft(const uint64x2_p vec)
return vec_rl(vec, m);
}
/// \brief Shift a packed vector left
/// \tparam C shift bit count
/// \param vec the vector
/// \returns vector
/// \details VecShiftLeft() rotates each element in a packed vector by bit count.
/// \details VecShiftLeft() with 64-bit elements is available on POWER8 and above.
/// \par Wraps
/// vec_sl
/// \since Crypto++ 8.1
template<unsigned int C>
inline uint64x2_p VecShiftLeft(const uint64x2_p vec)
{
const uint64x2_p m = {C, C};
return vec_sl(vec, m);
}
#endif
/// \brief Rotate a packed vector right
@ -1207,6 +1284,21 @@ inline uint32x4_p VecRotateRight(const uint32x4_p vec)
return vec_rl(vec, m);
}
/// \brief Shift a packed vector right
/// \tparam C shift bit count
/// \param vec the vector
/// \returns vector
/// \details VecShiftRight() rotates each element in a packed vector by bit count.
/// \par Wraps
/// vec_rl
/// \since Crypto++ 8.1
template<unsigned int C>
inline uint32x4_p VecShiftRight(const uint32x4_p vec)
{
const uint32x4_p m = {C, C, C, C};
return vec_sr(vec, m);
}
#if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief Rotate a packed vector right
@ -1225,6 +1317,22 @@ inline uint64x2_p VecRotateRight(const uint64x2_p vec)
return vec_rl(vec, m);
}
/// \brief Shift a packed vector right
/// \tparam C shift bit count
/// \param vec the vector
/// \returns vector
/// \details VecShiftRight() rotates each element in a packed vector by bit count.
/// \details VecShiftRight() with 64-bit elements is available on POWER8 and above.
/// \par Wraps
/// vec_sr
/// \since Crypto++ 8.1
template<unsigned int C>
inline uint64x2_p VecShiftRight(const uint64x2_p vec)
{
const uint64x2_p m = {C, C};
return vec_sr(vec, m);
}
#endif
/// \brief Exchange high and low double words
@ -1254,10 +1362,12 @@ inline T VecSwapWords(const T vec)
template <class T>
inline T VecGetLow(const T val)
{
//const T zero = {0};
//const uint8x16_p mask = {16,16,16,16, 16,16,16,16, 8,9,10,11, 12,13,14,15 };
//return (T)vec_perm(zero, val, mask);
#if (CRYPTOPP_BIG_ENDIAN) && (_ARCH_PWR8)
const T zero = {0};
return (T)VecMergeLow((uint64x2_p)zero, (uint64x2_p)val);
#else
return VecShiftRightOctet<8>(VecShiftLeftOctet<8>(val));
#endif
}
/// \brief Extract a dword from a vector
@ -1274,10 +1384,12 @@ inline T VecGetLow(const T val)
template <class T>
inline T VecGetHigh(const T val)
{
//const T zero = {0};
//const uint8x16_p mask = {16,16,16,16, 16,16,16,16, 0,1,2,3, 4,5,6,7 };
//return (T)vec_perm(zero, val, mask);
#if (CRYPTOPP_BIG_ENDIAN) && (_ARCH_PWR8)
const T zero = {0};
return (T)VecMergeHigh((uint64x2_p)zero, (uint64x2_p)val);
#else
return VecShiftRightOctet<8>(val);
#endif
}
/// \brief Compare two vectors
@ -1314,10 +1426,158 @@ inline bool VecNotEqual(const T1 vec1, const T2 vec2)
return 0 == vec_all_eq((uint32x4_p)vec1, (uint32x4_p)vec2);
}
//@}
//////////////////////// Power8 Crypto ////////////////////////
#if defined(__CRYPTO__) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \name POLYNOMIAL MULTIPLICATION
//@{
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details VecPolyMultiply() performs polynomial multiplication. POWER8
/// polynomial multiplication multiplies the high and low terms, and then
/// XOR's the high and low products. That is, the result is <tt>ah*bh XOR
/// al*bl</tt>. It is different behavior than Intel polynomial
/// multiplication. To obtain a single product without the XOR, then set
/// one of the high or low terms to 0. For example, setting <tt>ah=0</tt>
/// results in <tt>0*bh XOR al*bl = al*bl</tt>.
/// \par Wraps
/// __vpmsumw, __builtin_altivec_crypto_vpmsumw and __builtin_crypto_vpmsumw.
/// \since Crypto++ 8.1
inline uint32x4_p VecPolyMultiply(const uint32x4_p& a, const uint32x4_p& b)
{
#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
return __vpmsumw (a, b);
#elif defined(__clang__)
return __builtin_altivec_crypto_vpmsumw (a, b);
#else
return __builtin_crypto_vpmsumw (a, b);
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details VecPolyMultiply() performs polynomial multiplication. POWER8
/// polynomial multiplication multiplies the high and low terms, and then
/// XOR's the high and low products. That is, the result is <tt>ah*bh XOR
/// al*bl</tt>. It is different behavior than Intel polynomial
/// multiplication. To obtain a single product without the XOR, then set
/// one of the high or low terms to 0. For example, setting <tt>ah=0</tt>
/// results in <tt>0*bh XOR al*bl = al*bl</tt>.
/// \par Wraps
/// __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
/// \since Crypto++ 8.1
inline uint64x2_p VecPolyMultiply(const uint64x2_p& a, const uint64x2_p& b)
{
#if defined(__ibmxl__) || (defined(_AIX) && defined(__xlC__))
return __vpmsumd (a, b);
#elif defined(__clang__)
return __builtin_altivec_crypto_vpmsumd (a, b);
#else
return __builtin_crypto_vpmsumd (a, b);
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details VecPolyMultiply00LE() performs polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x00)</tt>.
/// The <tt>0x00</tt> indicates the low 64-bits of <tt>a</tt> and <tt>b</tt>
/// are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and numbered 0.
/// \par Wraps
/// __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
/// \since Crypto++ 8.0
inline uint64x2_p VecPolyMultiply00LE(const uint64x2_p& a, const uint64x2_p& b)
{
#if (CRYPTOPP_BIG_ENDIAN)
return VecSwapWords(VecPolyMultiply(VecGetHigh(a), VecGetHigh(b)));
#else
return VecPolyMultiply(VecGetHigh(a), VecGetHigh(b));
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details VecPolyMultiply01LE performs() polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x01)</tt>.
/// The <tt>0x01</tt> indicates the low 64-bits of <tt>a</tt> and high
/// 64-bits of <tt>b</tt> are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and numbered 0.
/// \par Wraps
/// __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
/// \since Crypto++ 8.0
inline uint64x2_p VecPolyMultiply01LE(const uint64x2_p& a, const uint64x2_p& b)
{
#if (CRYPTOPP_BIG_ENDIAN)
return VecSwapWords(VecPolyMultiply(a, VecGetHigh(b)));
#else
return VecPolyMultiply(a, VecGetHigh(b));
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details VecPolyMultiply10LE() performs polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x10)</tt>.
/// The <tt>0x10</tt> indicates the high 64-bits of <tt>a</tt> and low
/// 64-bits of <tt>b</tt> are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and numbered 0.
/// \par Wraps
/// __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
/// \since Crypto++ 8.0
inline uint64x2_p VecPolyMultiply10LE(const uint64x2_p& a, const uint64x2_p& b)
{
#if (CRYPTOPP_BIG_ENDIAN)
return VecSwapWords(VecPolyMultiply(VecGetHigh(a), b));
#else
return VecPolyMultiply(VecGetHigh(a), b);
#endif
}
/// \brief Polynomial multiplication
/// \param a the first term
/// \param b the second term
/// \returns vector product
/// \details VecPolyMultiply11LE() performs polynomial multiplication and presents
/// the result like Intel's <tt>c = _mm_clmulepi64_si128(a, b, 0x11)</tt>.
/// The <tt>0x11</tt> indicates the high 64-bits of <tt>a</tt> and <tt>b</tt>
/// are multiplied.
/// \note An Intel XMM register is composed of 128-bits. The leftmost bit
/// is MSB and numbered 127, while the the rightmost bit is LSB and numbered 0.
/// \par Wraps
/// __vpmsumd, __builtin_altivec_crypto_vpmsumd and __builtin_crypto_vpmsumd.
/// \since Crypto++ 8.0
inline uint64x2_p VecPolyMultiply11LE(const uint64x2_p& a, const uint64x2_p& b)
{
#if (CRYPTOPP_BIG_ENDIAN)
return VecSwapWords(VecPolyMultiply(VecGetLow(a), b));
#else
return VecPolyMultiply(VecGetLow(a), b);
#endif
}
//@}
/// \name AES ENCRYPTION
//@{
/// \brief One round of AES encryption
/// \tparam T1 vector type
/// \tparam T2 vector type
@ -1418,6 +1678,11 @@ inline T1 VecDecryptLast(const T1 state, const T2 key)
#endif
}
//@}
/// \name SHA DIGESTS
//@{
/// \brief SHA256 Sigma functions
/// \tparam func function
/// \tparam fmask function mask
@ -1468,6 +1733,8 @@ inline T VecSHA512(const T vec)
#endif
}
//@}
#endif // __CRYPTO__
#endif // _ALTIVEC_

View File

@ -379,7 +379,7 @@ public:
{
static HashIdentifier CRYPTOPP_API Lookup()
{
return HashIdentifier((const byte *)NULLPTR, 0);
return HashIdentifier(static_cast<const byte *>(NULLPTR), 0);
}
};
};

View File

@ -24,7 +24,7 @@
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
#if defined(CRYPTOPP_CPUID_AVAILABLE)
#if defined(CRYPTOPP_CPUID_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(CRYPTOPP_MSC_VERSION)
# define MASM_RDRAND_ASM_AVAILABLE 1
@ -54,7 +54,7 @@ extern "C" void CRYPTOPP_FASTCALL MASM_RDSEED_GenerateBlock(byte*, size_t);
NAMESPACE_BEGIN(CryptoPP)
#if defined(CRYPTOPP_CPUID_AVAILABLE)
#if defined(CRYPTOPP_CPUID_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
// Fills 4 bytes
inline void RDRAND32(void* output)

View File

@ -15,6 +15,7 @@
#include "md5.h"
#include "keccak.h"
#include "sha3.h"
#include "shake.h"
#include "blake2.h"
#include "sha.h"
#include "sha3.h"
@ -109,6 +110,8 @@ void RegisterFactories1()
RegisterDefaultFactoryFor<HashTransformation, SHA3_256>();
RegisterDefaultFactoryFor<HashTransformation, SHA3_384>();
RegisterDefaultFactoryFor<HashTransformation, SHA3_512>();
RegisterDefaultFactoryFor<HashTransformation, SHAKE128>();
RegisterDefaultFactoryFor<HashTransformation, SHAKE256>();
RegisterDefaultFactoryFor<HashTransformation, SM3>();
RegisterDefaultFactoryFor<HashTransformation, BLAKE2s>();
RegisterDefaultFactoryFor<HashTransformation, BLAKE2b>();

View File

@ -23,6 +23,7 @@
#include "sha3.h"
#include "blake2.h"
#include "ripemd.h"
#include "chacha.h"
#include "poly1305.h"
#include "siphash.h"
#include "panama.h"
@ -72,6 +73,7 @@ void RegisterFactories2()
RegisterDefaultFactoryFor<MessageAuthenticationCode, CMAC<AES> >();
RegisterDefaultFactoryFor<MessageAuthenticationCode, DMAC<AES> >();
RegisterDefaultFactoryFor<MessageAuthenticationCode, Poly1305<AES> >();
RegisterDefaultFactoryFor<MessageAuthenticationCode, Poly1305TLS>();
RegisterDefaultFactoryFor<MessageAuthenticationCode, CMAC<DES_EDE3> >();
RegisterDefaultFactoryFor<MessageAuthenticationCode, BLAKE2s>();
RegisterDefaultFactoryFor<MessageAuthenticationCode, BLAKE2b>();
@ -93,6 +95,8 @@ void RegisterFactories3()
RegisterSymmetricCipherDefaultFactories<Salsa20>();
RegisterSymmetricCipherDefaultFactories<XSalsa20>();
RegisterSymmetricCipherDefaultFactories<ChaCha>();
RegisterSymmetricCipherDefaultFactories<ChaChaTLS>();
RegisterSymmetricCipherDefaultFactories<XChaCha20>();
RegisterSymmetricCipherDefaultFactories<Sosemanuk>();
RegisterSymmetricCipherDefaultFactories<Rabbit>();
RegisterSymmetricCipherDefaultFactories<RabbitWithIV>();

View File

@ -39,6 +39,7 @@
#include "rc5.h"
#include "skipjack.h"
#include "blowfish.h"
#include "chachapoly.h"
// Aggressive stack checking with VS2005 SP1 and above.
#if (_MSC_FULL_VER >= 140050727)
@ -70,6 +71,9 @@ void RegisterFactories4()
RegisterAuthenticatedSymmetricCipherDefaultFactories<CCM<AES> >();
RegisterAuthenticatedSymmetricCipherDefaultFactories<GCM<AES> >();
RegisterAuthenticatedSymmetricCipherDefaultFactories<EAX<AES> >();
RegisterAuthenticatedSymmetricCipherDefaultFactories<ChaCha20Poly1305>();
RegisterAuthenticatedSymmetricCipherDefaultFactories<XChaCha20Poly1305>();
RegisterSymmetricCipherDefaultFactories<CBC_Mode<ARIA> >(); // For test vectors
RegisterSymmetricCipherDefaultFactories<CTR_Mode<ARIA> >();
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Camellia> >();

View File

@ -23,15 +23,20 @@
#include "pch.h"
#include "config.h"
#include "misc.h"
#include "adv_simd.h"
#if (CRYPTOPP_AESNI_AVAILABLE)
# include "adv_simd.h"
# include <emmintrin.h>
# include <smmintrin.h>
# include <wmmintrin.h>
#endif
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
# include <arm_neon.h>
# include "adv_simd.h"
# ifndef _M_ARM64
# include <arm_neon.h>
# endif
#endif
#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
@ -40,6 +45,7 @@
#endif
#if defined(CRYPTOPP_POWER8_AES_AVAILABLE)
# include "adv_simd.h"
# include "ppc_simd.h"
#endif
@ -191,7 +197,7 @@ static inline void ARMV8_Enc_6_Blocks(uint64x2_t &data0, uint64x2_t &data1,
uint8x16_t key;
for (unsigned int i=0; i<rounds-1; ++i)
{
uint8x16_t key = vld1q_u8(keys+i*16);
key = vld1q_u8(keys+i*16);
// AES single round encryption
block0 = vaeseq_u8(block0, key);
// AES mix columns

View File

@ -90,11 +90,12 @@ void Salsa20_Core(word32* data, unsigned int rounds)
x[15] ^= rotlConstant<18>(x[14]+x[13]);
}
#ifdef _MSC_VER
// OpenMP 4.0 released July 2013.
#if _OPENMP >= 201307
#pragma omp simd
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#else
#pragma omp simd
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#endif
@ -111,10 +112,13 @@ std::string Salsa20_Policy::AlgorithmProvider() const
void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
// Use previous rounds as the default value
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
if (rounds != 20 && rounds != 12 && rounds != 8)
throw InvalidRounds(Salsa20::StaticAlgorithmName(), rounds);
if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
throw InvalidRounds(Salsa20::StaticAlgorithmName(), m_rounds);
// Latch a good value
m_rounds = rounds;
// m_state is reordered for SSE2
GetBlock<word32, LittleEndian> get1(key);
@ -691,8 +695,7 @@ Salsa20_OperateKeystream ENDP
void XSalsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds);

View File

@ -36,6 +36,7 @@ struct Salsa20_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInter
class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{
protected:
Salsa20_Policy() : m_rounds(ROUNDS) {}
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
@ -49,6 +50,7 @@ protected:
std::string AlgorithmProvider() const;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
FixedSizeAlignedSecBlock<word32, 16> m_state;
int m_rounds;
};

Some files were not shown because too many files have changed in this diff Show More