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: 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. * 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. * 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 Version 0.10.0

View File

@ -52,15 +52,34 @@ namespace cpputils {
void ThreadSystem::_stopAllThreadsForRestart() { void ThreadSystem::_stopAllThreadsForRestart() {
_mutex.lock(); // Is unlocked in the after-fork handler. This way, the whole fork() is protected. _mutex.lock(); // Is unlocked in the after-fork handler. This way, the whole fork() is protected.
for (RunningThread &thread : _runningThreads) { 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(); thread.thread.interrupt();
} }
for (RunningThread &thread : _runningThreads) { 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(); thread.thread.join();
} }
} }
void ThreadSystem::_restartAllThreads() { void ThreadSystem::_restartAllThreads() {
for (RunningThread &thread : _runningThreads) { 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); thread.thread = _startThread(thread.loopIteration, thread.threadName);
} }
_mutex.unlock(); // Was locked in the before-fork handler _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?"); ASSERT(_device != none, "File system not ready to be initialized. Was it already initialized before?");
//TODO Test auto unmounting after idle timeout //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) { if (_idleUnmounter != none) {
(*_device)->onFsAction(std::bind(&CallAfterTimeout::resetTimer, _idleUnmounter->get())); (*_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) { 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 // 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>())); bf::path::imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16<wchar_t>()));
#endif
_mountdir = mountdir; _mountdir = mountdir;

View File

@ -1,6 +1,8 @@
#include <cpp-utils/process/subprocess.h> #include <cpp-utils/process/subprocess.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <cpp-utils/lock/ConditionBarrier.h>
using cpputils::Subprocess; using cpputils::Subprocess;
using cpputils::SubprocessError; using cpputils::SubprocessError;
@ -98,3 +100,25 @@ TEST(SubprocessTest, Call_error5withoutput_output) {
TEST(SubprocessTest, Call_error5withoutput_exitcode) { TEST(SubprocessTest, Call_error5withoutput_exitcode) {
EXPECT_EQ(5, Subprocess::call(exit_with_message_and_status("hello", 5)).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(); 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); string name = get_thread_name(&child);
EXPECT_EQ("my_thread_name", name); 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: This directory contains external projects, taken from the following locations:
googletest: https://github.com/google/googletest/tree/release-1.8.1 googletest: https://github.com/google/googletest/tree/release-1.8.1
spdlog: https://github.com/gabime/spdlog/tree/v0.16.3/include/spdlog spdlog: https://github.com/gabime/spdlog/tree/v0.16.3/include/spdlog
cryptopp: https://github.com/weidai11/cryptopp/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/CRYPTOPP_8_0_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 - 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 ## 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 # could be handy for archiving the generated documentation or if some version
# control system is used. # 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 # 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 # 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_simd.cpp
aria.h aria.h
argnames.h argnames.h
arm_simd.h
asn.cpp asn.cpp
asn.h asn.h
authenc.cpp authenc.cpp
@ -55,6 +56,8 @@ chacha.cpp
chacha_avx.cpp chacha_avx.cpp
chacha_simd.cpp chacha_simd.cpp
chacha.h chacha.h
chachapoly.cpp
chachapoly.h
cham.cpp cham.cpp
cham_simd.cpp cham_simd.cpp
cham.h cham.h
@ -146,6 +149,7 @@ gf256.cpp
gf256.h gf256.h
gf2_32.cpp gf2_32.cpp
gf2_32.h gf2_32.h
gf2n_simd.cpp
gf2n.cpp gf2n.cpp
gf2n.h gf2n.h
gfpcrypt.cpp gfpcrypt.cpp
@ -182,9 +186,9 @@ kalynatab.cpp
kalyna.cpp kalyna.cpp
kalyna.h kalyna.h
keccak.cpp keccak.cpp
keccak_core.cpp
keccak_simd.cpp
keccak.h keccak.h
keccakc.cpp
keccakc.h
lubyrack.h lubyrack.h
lea.cpp lea.cpp
lea_simd.cpp lea_simd.cpp
@ -305,6 +309,8 @@ sha3.h
shacal2.cpp shacal2.cpp
shacal2_simd.cpp shacal2_simd.cpp
shacal2.h shacal2.h
shake.cpp
shake.h
shark.cpp shark.cpp
shark.h shark.h
sharkbox.cpp sharkbox.cpp
@ -473,6 +479,7 @@ TestData/x25519v0.dat
TestData/x25519v1.dat TestData/x25519v1.dat
TestData/xtrdh171.dat TestData/xtrdh171.dat
TestData/xtrdh342.dat TestData/xtrdh342.dat
TestVectors/aead.txt
TestVectors/aes.txt TestVectors/aes.txt
TestVectors/all.txt TestVectors/all.txt
TestVectors/aria.txt TestVectors/aria.txt
@ -483,6 +490,7 @@ TestVectors/camellia.txt
TestVectors/ccm.txt TestVectors/ccm.txt
TestVectors/chacha.txt TestVectors/chacha.txt
TestVectors/chacha_tls.txt TestVectors/chacha_tls.txt
TestVectors/chacha20poly1305.txt
TestVectors/cham.txt TestVectors/cham.txt
TestVectors/cmac.txt TestVectors/cmac.txt
TestVectors/dlies.txt TestVectors/dlies.txt
@ -502,8 +510,9 @@ TestVectors/keccak.txt
TestVectors/lea.txt TestVectors/lea.txt
TestVectors/mars.txt TestVectors/mars.txt
TestVectors/nr.txt TestVectors/nr.txt
TestVectors/ocb.txt
TestVectors/panama.txt TestVectors/panama.txt
TestVectors/poly1305aes.txt
TestVectors/poly1305_tls.txt
TestVectors/rabbit.txt TestVectors/rabbit.txt
TestVectors/Readme.txt TestVectors/Readme.txt
TestVectors/rsa_oaep.txt TestVectors/rsa_oaep.txt
@ -528,6 +537,7 @@ TestVectors/sha3_256_fips_202.txt
TestVectors/sha3_384_fips_202.txt TestVectors/sha3_384_fips_202.txt
TestVectors/sha3_512_fips_202.txt TestVectors/sha3_512_fips_202.txt
TestVectors/sha3_fips_202.txt TestVectors/sha3_fips_202.txt
TestVectors/shake.txt
TestVectors/shacal2.txt TestVectors/shacal2.txt
TestVectors/simeck.txt TestVectors/simeck.txt
TestVectors/simon.txt TestVectors/simon.txt
@ -542,6 +552,7 @@ TestVectors/ttmac.txt
TestVectors/vmac.txt TestVectors/vmac.txt
TestVectors/wake.txt TestVectors/wake.txt
TestVectors/whrlpool.txt TestVectors/whrlpool.txt
TestVectors/xchacha.txt
TestPrograms/test_32bit.cxx TestPrograms/test_32bit.cxx
TestPrograms/test_64bit.cxx TestPrograms/test_64bit.cxx
TestPrograms/test_arm_acle.cxx TestPrograms/test_arm_acle.cxx

View File

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

View File

@ -26,10 +26,6 @@ EGREP ?= egrep
LN ?= ln -sf LN ?= ln -sf
LDCONF ?= /sbin/ldconfig -n LDCONF ?= /sbin/ldconfig -n
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
IS_IOS ?= 0 IS_IOS ?= 0
IS_ANDROID ?= 0 IS_ANDROID ?= 0
IS_ARM_EMBEDDED ?= 0 IS_ARM_EMBEDDED ?= 0
@ -188,6 +184,9 @@ ifeq ($(DETECT_FEATURES),1)
ifneq ($(strip $(TCXXFLAGS)),) ifneq ($(strip $(TCXXFLAGS)),)
$(info Using testing flags: $(TCXXFLAGS)) $(info Using testing flags: $(TCXXFLAGS))
endif endif
#TPROG = TestPrograms/test_cxx.cxx
#$(info Testing compile... )
#$(info $(shell $(CXX) $(TCXXFLAGS) $(ZOPT) $(TOPT) $(TPROG) -o $(TOUT) 1>/dev/null))
endif endif
# For the previous messages # For the previous messages
@ -335,6 +334,13 @@ ifeq ($(DETECT_FEATURES),1)
endif endif
endif endif
# Drop to SSE2 if available
ifeq ($(GCM_FLAG),)
ifneq ($(SSE2_FLAG),)
GCM_FLAG = $(SSE2_FLAG)
endif
endif
# DETECT_FEATURES # DETECT_FEATURES
endif endif
@ -693,34 +699,47 @@ distclean: clean autotools-clean cmake-clean
.PHONY: install .PHONY: install
install: cryptest.exe install-lib install: cryptest.exe install-lib
@-$(MKDIR) $(DESTDIR)$(BINDIR) @-$(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/TestData
@-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestVectors @-$(MKDIR) $(DESTDIR)$(DATADIR)/cryptopp/TestVectors
$(INSTALL_DATA) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData $(CP) TestData/*.dat $(DESTDIR)$(DATADIR)/cryptopp/TestData
$(INSTALL_DATA) TestVectors/*.txt $(DESTDIR)$(DATADIR)/cryptopp/TestVectors $(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 # A recipe to install only the library, and not cryptest.exe. Also
# see https://github.com/weidai11/cryptopp/issues/653. # see https://github.com/weidai11/cryptopp/issues/653.
.PHONY: install-lib .PHONY: install-lib
install-lib: install-lib:
@-$(MKDIR) $(DESTDIR)$(INCLUDEDIR)/cryptopp @-$(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),) ifneq ($(wildcard libcryptopp.a),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR) @-$(MKDIR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libcryptopp.a $(DESTDIR)$(LIBDIR) $(CP) libcryptopp.a $(DESTDIR)$(LIBDIR)
$(CHMOD) 0644 $(DESTDIR)$(LIBDIR)/libcryptopp.a
endif endif
ifneq ($(wildcard libcryptopp.dylib),) ifneq ($(wildcard libcryptopp.dylib),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR) @-$(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 endif
ifneq ($(wildcard libcryptopp.so$(SOLIB_VERSION_SUFFIX)),) ifneq ($(wildcard libcryptopp.so$(SOLIB_VERSION_SUFFIX)),)
@-$(MKDIR) $(DESTDIR)$(LIBDIR) @-$(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) ifeq ($(HAS_SOLIB_VERSION),1)
-$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)/libcryptopp.so -$(LN) libcryptopp.so$(SOLIB_VERSION_SUFFIX) $(DESTDIR)$(LIBDIR)/libcryptopp.so
$(LDCONF) $(DESTDIR)$(LIBDIR) $(LDCONF) $(DESTDIR)$(LIBDIR)
endif endif
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 .PHONY: remove uninstall
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 MacPorts GCC 7.0, Clang 4.0, Intel C++ 17.00, IBM XL C/C++ 13.1
8.0.0 - December 28, 2018 8.0.0 - December 28, 2018
- major release, recompile of programs required - major release, recompile of programs required
- expanded community input and support - expanded community input and support
* 54 unique contributors as of this release * 54 unique contributors as of this release
@ -452,3 +451,19 @@ last several releases.
- fix SPARC alignment problems due to GetAlignmentOf<T>() on word64 - fix SPARC alignment problems due to GetAlignmentOf<T>() on word64
- add ARM AES asm implementation from Cryptogams - 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 This copyright applies only to this software distribution package
as a compilation, and does not imply a copyright on any particular as a compilation, and does not imply a copyright on any particular
file in the package. file in the package.
@ -22,6 +22,18 @@ Richard De Moliner - safer.cpp
Matthew Skala - twofish.cpp Matthew Skala - twofish.cpp
Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp
Ronny Van Keer - sha3.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 The Crypto++ Library (as a compilation) is currently licensed under the Boost
Software License 1.0 (http://www.boost.org/users/license.html). 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, 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 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. 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 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, high speed stream ciphers ChaCha (8/12/20), ChaCha (IETF), Panama, Salsa20,
XSalsa20 Sosemanuk, XSalsa20, XChaCha20
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent, AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
CAST-256 CAST-256
ARIA, IDEA, Blowfish, Triple-DES (DES-EDE2 and ARIA, Blowfish, Camellia, CHAM, HIGHT, IDEA,
DES-EDE3), Camellia, SEED, Kalyna (128/256/512), Kalyna (128/256/512), LEA, SEED, RC5, SHACAL-2,
other block ciphers RC5, SIMON-64, SIMON-128, SPECK-64, SPECK-128, other block ciphers SIMON (64/128), Skipjack, SPECK (64/128),
Skipjack, SHACAL-2, SM4, Threefish (256/512/1024), Simeck, SM4, Threefish (256/512/1024),
TEA, XTEA Triple-DES (DES-EDE2 and DES-EDE3), TEA, XTEA
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS), block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
CFB, OFB, counter mode (CTR) CFB, OFB, counter mode (CTR)
message authentication codes BLAKE2s, BLAKE2b, CMAC, CBC-MAC, DMAC, GMAC, HMAC, 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, BLAKE2s, BLAKE2b, Keccack (F1600), SHA-1,
hash functions SHA-2 (224/256/384/512), SHA-3 (224/256/384/512), hash functions SHA-2 (224/256/384/512), SHA-3 (224/256/384/512),
SipHash, SM3, Tiger, RIPEMD-128, RIPEMD-160, SHAKE (128/256), SipHash, SM3, Tiger,
RIPEMD-256, RIPEMD-320, WHIRLPOOL RIPEMD (128/160/256/320), WHIRLPOOL
RSA, DSA, Determinsitic DSA, ElGamal, RSA, DSA, Determinsitic DSA, ElGamal,
public-key cryptography Nyberg-Rueppel (NR), Rabin-Williams (RW), LUC, 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 + 32-bit CRC, CRC-C and Adler32 checksum
* class wrappers for these platform and operating system features (optional): * class wrappers for these platform and operating system features (optional):
+ high resolution timers on Windows, Unix, and Mac OS + high resolution timers on Windows, Unix, and Mac OS
+ Berkeley and Windows style sockets
+ Windows named pipes
+ /dev/random, /dev/urandom, /dev/srandom + /dev/random, /dev/urandom, /dev/srandom
+ Microsoft's CryptGenRandom or BCryptGenRandom on Windows + Microsoft's CryptGenRandom or BCryptGenRandom on Windows
* A high level interface for most of the above, using a filter/pipeline * 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 *** *** Side Channel Attacks ***
Crypto++ attempts to resist side channel attacks using various remediations. We Crypto++ attempts to resist side channel attacks using various remediations. We
believe the library is hardened but the remdiations may be incomplete. The first believe the library is mostly hardened but the remdiations may be incomplete. The
line of defense uses hardware instructions when possible. The library also uses first line of defense uses hardware instructions when possible for block ciphers,
cache-aware algoirthms and access patterns to minimize leakage. If you suspect hashes and other primitives. Hardware acceleration remediates many timing attacks.
or find an information leak then please report it. 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 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 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 uses them during testing. If you want the Specter workarounds then add the GCC
options to your CXXFLAGS when building the library. options to your CXXFLAGS when building the library.
If you suspect or find an information leak then please report it.
*** Documentation and Support *** *** Documentation and Support ***
Crypto++ is documented through inline comments in header files, which are 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 [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi fi
if ! ./cryptestcwd v; then if ! ./cryptest v; then
echo "cryptestcwd v failed." echo "cryptest v failed."
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi fi
if ! ./cryptestcwd tv all; then if ! ./cryptest tv all; then
echo "cryptestcwd tv all failed." echo "cryptest tv all failed."
[[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
fi fi

View File

@ -1,10 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# cryptest.sh - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. # cryptest.sh - written and placed in public domain by Jeffrey Walton and Uri
# Copyright assigned to Crypto++ project. # Blumenthal.
# This is a test script that can be used on some Linux/Unix/Apple machines to automate testing # This is a test script that can be used on some Linux/Unix/Apple machines to
# of the shared object to ensure linking and symbols don't go missing from release to release. # automate testing of the shared object to ensure linking and symbols don't go
# missing from release to release.
# Fixup ancient Bash # Fixup ancient Bash
# https://unix.stackexchange.com/q/468579/56041 # https://unix.stackexchange.com/q/468579/56041
@ -12,10 +13,20 @@ if [[ -z "$BASH_SOURCE" ]]; then
BASH_SOURCE="$0" BASH_SOURCE="$0"
fi 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 # Tags to test
OLD_VERSION_TAG=CRYPTOPP_7_0_0 OLD_VERSION_TAG=CRYPTOPP_8_0_0
NEW_VERSION_TAG=master NEW_VERSION_TAG=master
############################################ ############################################

View File

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

View File

@ -63,26 +63,31 @@ do
# ARMv5 # ARMv5
if [ "$CL" == "armv5" ]; then if [ "$CL" == "armv5" ]; then
BACK_ARCH=armv5 BACK_ARCH=armv5
APPLE_SDK=iPhoneOS
fi fi
# ARMv6 # ARMv6
if [ "$CL" == "armv6" ]; then if [ "$CL" == "armv6" ]; then
BACK_ARCH=armv6 BACK_ARCH=armv6
APPLE_SDK=iPhoneOS
fi fi
# ARMv7 # ARMv7
if [ "$CL" == "armv7" ]; then if [ "$CL" == "armv7" ]; then
BACK_ARCH=armv7 BACK_ARCH=armv7
APPLE_SDK=iPhoneOS
fi fi
# ARMv7s # ARMv7s
if [ "$CL" == "armv7s" ]; then if [ "$CL" == "armv7s" ]; then
BACK_ARCH=armv7s BACK_ARCH=armv7s
APPLE_SDK=iPhoneOS
fi fi
# ARM64 # ARM64
if [[ ("$CL" == "arm64" || "$CL" == "armv8" || "$CL" == "aarch64") ]]; then if [[ ("$CL" == "arm64" || "$CL" == "armv8" || "$CL" == "aarch64") ]]; then
BACK_ARCH=arm64 BACK_ARCH=arm64
APPLE_SDK=iPhoneOS
fi fi
# iPhone # iPhone
@ -201,7 +206,7 @@ fi
# Simulator fixup. LD fails to link dylib. # Simulator fixup. LD fails to link dylib.
if [ "$APPLE_SDK" == "iPhoneSimulator" ] && [ "$IOS_ARCH" == "i386" ]; then 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 fi
# ARMv7s fixup. Xcode 4/iOS 6 # ARMv7s fixup. Xcode 4/iOS 6
@ -219,12 +224,6 @@ if [ "$APPLE_SDK" == "AppleTVOS" ]; then
IOS_FLAGS="" IOS_FLAGS=""
fi 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. # 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 # We may need to link against crt1.o for simulator builds. Also see
# https://stackoverflow.com/q/24841283/608639 # 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 AlgorithmType: FileList
Name: all.txt collection Name: all.txt collection
Test: TestVectors/tea.txt Test: TestVectors/aes.txt
Test: TestVectors/wake.txt Test: TestVectors/aria.txt
Test: TestVectors/blake2b.txt
Test: TestVectors/blake2s.txt
Test: TestVectors/camellia.txt Test: TestVectors/camellia.txt
Test: TestVectors/shacal2.txt Test: TestVectors/ccm.txt
Test: TestVectors/ttmac.txt Test: TestVectors/chacha_tls.txt
Test: TestVectors/whrlpool.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/dlies.txt
Test: TestVectors/dsa.txt
Test: TestVectors/dsa_1363.txt Test: TestVectors/dsa_1363.txt
Test: TestVectors/dsa_rfc6979.txt Test: TestVectors/dsa_rfc6979.txt
Test: TestVectors/dsa.txt
Test: TestVectors/eax.txt
Test: TestVectors/esign.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/hmac.txt
Test: TestVectors/kalyna.txt
Test: TestVectors/keccak.txt
Test: TestVectors/lea.txt
Test: TestVectors/mars.txt
Test: TestVectors/nr.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_oaep.txt
Test: TestVectors/rsa_pkcs1_1_5.txt Test: TestVectors/rsa_pkcs1_1_5.txt
Test: TestVectors/rsa_pss.txt Test: TestVectors/rsa_pss.txt
Test: TestVectors/rw.txt Test: TestVectors/rw.txt
Test: TestVectors/salsa.txt
Test: TestVectors/seal.txt Test: TestVectors/seal.txt
Test: TestVectors/sha.txt Test: TestVectors/seed.txt
Test: TestVectors/keccak.txt
Test: TestVectors/sha1_fips_180.txt Test: TestVectors/sha1_fips_180.txt
Test: TestVectors/sha2_fips_180.txt Test: TestVectors/sha2_fips_180.txt
Test: TestVectors/sha3_fips_202.txt Test: TestVectors/sha3_fips_202.txt
Test: TestVectors/panama.txt Test: TestVectors/shake.txt
Test: TestVectors/sm3.txt Test: TestVectors/shacal2.txt
Test: TestVectors/aes.txt Test: TestVectors/sha.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/simeck.txt Test: TestVectors/simeck.txt
Test: TestVectors/simon.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/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 AlgorithmType: SymmetricCipher
Name: ChaCha20 Name: ChaChaTLS
Source: http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305 Source: http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305
Comment: Section 7, Test 1 #
Key: 0000000000000000000000000000000000000000000000000000000000000000 Comment: Section A.1, ChaCha20 Block Function, Test 1
IV: 0000000000000000 Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
Plaintext: IV: 00 00 00 00 00 00 00 00 00 00 00 00
Ciphertext: 76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669 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 Test: Encrypt
Comment: Section 7, Test 2 #
Key: 0000000000000000000000000000000000000000000000000000000000000001 Comment: Section A.1, ChaCha20 Block Function, Test 2
IV: 0000000000000000 Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
Plaintext: IV: 00 00 00 00 00 00 00 00 00 00 00 00
Ciphertext: 4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275 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 Test: Encrypt
Comment: Section 7, Test 3 #
Key: 0000000000000000000000000000000000000000000000000000000000000000 Comment: Section A.1, ChaCha20 Block Function, Test 3
IV: 0000000000000001 Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
Plaintext: IV: 00 00 00 00 00 00 00 00 00 00 00 00
Ciphertext: de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3 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 Test: Encrypt
Comment: Section 7, Test 4 #
Key: 0000000000000000000000000000000000000000000000000000000000000000 Comment: Section A.1, ChaCha20 Block Function, Test 4
IV: 0100000000000000 Key: 00ff000000000000 0000000000000000 0000000000000000 0000000000000000
Plaintext: IV: 00 00 00 00 00 00 00 00 00 00 00 00
Ciphertext: ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb004 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 Test: Encrypt
Comment: Section 7, Test 5 #
Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f Comment: Section A.1, ChaCha20 Block Function, Test 5
IV: 0001020304050607 Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
Plaintext: IV: 00 00 00 00 00 00 00 00 00 00 00 02
Ciphertext: f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1 \ Plaintext: r64 00
5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e \ Ciphertext: c2 c6 4d 37 8c d5 36 37 4a e2 04 b9 ef 93 3f cd \
09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5 \ 1a 8b 22 88 b3 df a4 96 72 ab 76 5b 54 ee 27 c7 \
07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2 \ 8a 97 0e 0e 95 5c 14 f3 a8 8e 74 1b 97 c2 86 f7 \
ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb 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 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 "misc.h"
#include "stdcpp.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> # include <arm_neon.h>
#endif #endif
@ -112,14 +113,10 @@ inline size_t AdvancedProcessBlocks64_6x2_NEON(F2 func2, F6 func6,
CRYPTOPP_ASSERT(outBlocks); CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 8); CRYPTOPP_ASSERT(length >= 8);
#if (CRYPTOPP_LITTLE_ENDIAN) const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const uint32x4_t s_one = {0, 0, 0, 1<<24}; const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
const uint32x4_t s_two = {0, 2<<24, 0, 2<<24}; const uint32x4_t s_one = vld1q_u32(w_one);
#else const uint32x4_t s_two = vld1q_u32(w_two);
// 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 size_t blockSize = 8; const size_t blockSize = 8;
const size_t neonBlockSize = 16; const size_t neonBlockSize = 16;
@ -357,14 +354,10 @@ inline size_t AdvancedProcessBlocks128_6x1_NEON(F1 func1, F6 func6,
CRYPTOPP_ASSERT(outBlocks); CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 16); CRYPTOPP_ASSERT(length >= 16);
#if (CRYPTOPP_LITTLE_ENDIAN) const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const uint32x4_t s_one = {0, 0, 0, 1<<24}; const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
//const uint32x4_t s_two = {0, 2<<24, 0, 2<<24}; const uint32x4_t s_one = vld1q_u32(w_one);
#else const uint32x4_t s_two = vld1q_u32(w_two);
// 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 size_t blockSize = 16; const size_t blockSize = 16;
// const size_t neonBlockSize = 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 F1 function to process 1 128-bit block
/// \tparam F4 function to process 4 128-bit blocks /// \tparam F4 function to process 4 128-bit blocks
/// \tparam W word type of the subkey table /// \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 /// \details AdvancedProcessBlocks128_4x1_NEON processes 4 and 1 NEON SIMD words
/// at a time. /// at a time.
/// \details The subkey type is usually word32 or word64. V is the vector type and it is /// \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 /// usually uint32x4_t or uint32x4_t. F1, F4, and W must use the same word and
/// vector type. The V parameter is used to avoid template argument /// vector type.
/// deduction/substitution failures. template <typename F1, typename F4, typename W>
template <typename F1, typename F4, typename W, typename V>
inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4, 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) const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
{ {
CRYPTOPP_ASSERT(subKeys); CRYPTOPP_ASSERT(subKeys);
CRYPTOPP_ASSERT(inBlocks); CRYPTOPP_ASSERT(inBlocks);
CRYPTOPP_ASSERT(outBlocks); CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 16); CRYPTOPP_ASSERT(length >= 16);
CRYPTOPP_UNUSED(unused);
#if (CRYPTOPP_LITTLE_ENDIAN) const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const uint32x4_t s_one = {0, 0, 0, 1<<24}; const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
//const uint32x4_t s_two = {0, 2<<24, 0, 2<<24}; const uint32x4_t s_one = vld1q_u32(w_one);
#else const uint32x4_t s_two = vld1q_u32(w_two);
// 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 size_t blockSize = 16; const size_t blockSize = 16;
// const size_t neonBlockSize = 16; // const size_t neonBlockSize = 16;
@ -554,62 +540,62 @@ inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4,
{ {
while (length >= 4*blockSize) while (length >= 4*blockSize)
{ {
uint64x2_t block0, block1, block2, block3; uint32x4_t block0, block1, block2, block3;
if (flags & BT_InBlockIsCounter) if (flags & BT_InBlockIsCounter)
{ {
const uint64x2_t one = vreinterpretq_u64_u32(s_one); const uint32x4_t one = s_one;
block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks)); block0 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
block1 = vaddq_u64(block0, one); block1 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block0), vreinterpretq_u64_u32(one)));
block2 = vaddq_u64(block1, one); block2 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block1), vreinterpretq_u64_u32(one)));
block3 = vaddq_u64(block2, one); block3 = vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(block2), vreinterpretq_u64_u32(one)));
vst1q_u8(const_cast<byte*>(inBlocks), vst1q_u8(const_cast<byte*>(inBlocks), vreinterpretq_u8_u64(vaddq_u64(
vreinterpretq_u8_u64(vaddq_u64(block3, one))); vreinterpretq_u64_u32(block3), vreinterpretq_u64_u32(one))));
} }
else else
{ {
block0 = vreinterpretq_u64_u8(vld1q_u8(inBlocks)); block0 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement); inBlocks = PtrAdd(inBlocks, inIncrement);
block1 = vreinterpretq_u64_u8(vld1q_u8(inBlocks)); block1 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement); inBlocks = PtrAdd(inBlocks, inIncrement);
block2 = vreinterpretq_u64_u8(vld1q_u8(inBlocks)); block2 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement); inBlocks = PtrAdd(inBlocks, inIncrement);
block3 = vreinterpretq_u64_u8(vld1q_u8(inBlocks)); block3 = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
inBlocks = PtrAdd(inBlocks, inIncrement); inBlocks = PtrAdd(inBlocks, inIncrement);
} }
if (xorInput) 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); 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); 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); 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); 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) 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); 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); 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); 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); xorBlocks = PtrAdd(xorBlocks, xorIncrement);
} }
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block0)); vst1q_u8(outBlocks, vreinterpretq_u8_u32(block0));
outBlocks = PtrAdd(outBlocks, outIncrement); outBlocks = PtrAdd(outBlocks, outIncrement);
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block1)); vst1q_u8(outBlocks, vreinterpretq_u8_u32(block1));
outBlocks = PtrAdd(outBlocks, outIncrement); outBlocks = PtrAdd(outBlocks, outIncrement);
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block2)); vst1q_u8(outBlocks, vreinterpretq_u8_u32(block2));
outBlocks = PtrAdd(outBlocks, outIncrement); outBlocks = PtrAdd(outBlocks, outIncrement);
vst1q_u8(outBlocks, vreinterpretq_u8_u64(block3)); vst1q_u8(outBlocks, vreinterpretq_u8_u32(block3));
outBlocks = PtrAdd(outBlocks, outIncrement); outBlocks = PtrAdd(outBlocks, outIncrement);
length -= 4*blockSize; length -= 4*blockSize;
@ -618,20 +604,20 @@ inline size_t AdvancedProcessBlocks128_4x1_NEON(F1 func1, F4 func4,
while (length >= blockSize) while (length >= blockSize)
{ {
uint64x2_t block = vreinterpretq_u64_u8(vld1q_u8(inBlocks)); uint32x4_t block = vreinterpretq_u32_u8(vld1q_u8(inBlocks));
if (xorInput) 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) if (flags & BT_InBlockIsCounter)
const_cast<byte *>(inBlocks)[15]++; const_cast<byte *>(inBlocks)[15]++;
func1( (V&)block, subKeys, static_cast<unsigned int>(rounds)); func1(block, subKeys, static_cast<unsigned int>(rounds));
if (xorOutput) 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); inBlocks = PtrAdd(inBlocks, inIncrement);
outBlocks = PtrAdd(outBlocks, outIncrement); outBlocks = PtrAdd(outBlocks, outIncrement);
@ -660,14 +646,10 @@ inline size_t AdvancedProcessBlocks128_6x2_NEON(F2 func2, F6 func6,
CRYPTOPP_ASSERT(outBlocks); CRYPTOPP_ASSERT(outBlocks);
CRYPTOPP_ASSERT(length >= 16); CRYPTOPP_ASSERT(length >= 16);
#if (CRYPTOPP_LITTLE_ENDIAN) const unsigned int w_one[] = {0, 0<<24, 0, 1<<24};
const uint32x4_t s_one = {0, 0, 0, 1<<24}; const unsigned int w_two[] = {0, 2<<24, 0, 2<<24};
//const uint32x4_t s_two = {0, 2<<24, 0, 2<<24}; const uint32x4_t s_one = vld1q_u32(w_one);
#else const uint32x4_t s_two = vld1q_u32(w_two);
// 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 size_t blockSize = 16; const size_t blockSize = 16;
// const size_t neonBlockSize = 16; // const size_t neonBlockSize = 16;

View File

@ -14,12 +14,11 @@
# include <tmmintrin.h> # include <tmmintrin.h>
#endif #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> # 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) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h> # include <stdint.h>
# include <arm_acle.h> # include <arm_acle.h>
@ -47,7 +46,7 @@ using CryptoPP::byte;
using CryptoPP::word32; using CryptoPP::word32;
inline byte ARIA_BRF(const word32 x, const int y) { inline byte ARIA_BRF(const word32 x, const int y) {
return GETBYTE(x, y); return static_cast<byte>(GETBYTE(x, y));
} }
ANONYMOUS_NAMESPACE_END 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) 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 blockSize = AuthenticationBlockSize();
unsigned int &num = m_bufferedDataLength; unsigned int &num = m_bufferedDataLength;
byte* data = m_buffer.begin(); byte* data = m_buffer.begin();
if (num != 0) // process left over data if (data && num) // process left over data
{ {
if (num+len >= blockSize) if (num+len >= blockSize)
{ {
@ -41,7 +45,8 @@ void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_
len = leftOver; len = leftOver;
} }
memcpy(data, input, len); if (data && len)
memcpy(data, input, len);
num = (unsigned int)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) void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
{ {
// Part of original authenc.cpp code. Don't remove it.
if (length == 0) {return;} if (length == 0) {return;}
switch (m_state) 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) void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
{ {
m_totalMessageLength += length; if (m_state >= State_IVSet && length > MaxMessageLength()-m_totalMessageLength)
if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum"); throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
m_totalMessageLength += length;
reswitch: reswitch:
switch (m_state) switch (m_state)

View File

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

View File

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

View File

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

View File

@ -38,12 +38,11 @@
# include <smmintrin.h> # include <smmintrin.h>
#endif #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> # 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) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h> # include <stdint.h>
# include <arm_acle.h> # include <arm_acle.h>

View File

@ -49,12 +49,11 @@
# include <smmintrin.h> # include <smmintrin.h>
#endif #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> # 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) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h> # include <stdint.h>
# include <arm_acle.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) const uint32x4_p c, const uint32x4_p d)
{ {
// a=b, c=d, mask is {2,0, 2,0} // 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}; 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); 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) const uint32x4_p c, const uint32x4_p d)
{ {
// a=b, c=d, mask is {3,1, 3,1} // 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}; 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); return VecPermute(a, c, mask);
} }

View File

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

View File

@ -10,19 +10,23 @@
#include "misc.h" #include "misc.h"
#include "cpu.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) NAMESPACE_BEGIN(CryptoPP)
#if (CRYPTOPP_ARM_NEON_AVAILABLE) #if (CRYPTOPP_ARM_NEON_AVAILABLE)
extern void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *output, unsigned int rounds); extern void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif #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) #if (CRYPTOPP_AVX2_AVAILABLE)
extern void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, byte *output, unsigned int rounds); extern void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif #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) #if (CRYPTOPP_POWER7_AVAILABLE)
extern void ChaCha_OperateKeystream_POWER7(const word32 *state, const byte* input, byte *output, unsigned int rounds); 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); extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* input, byte *output, unsigned int rounds);
#endif #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) \ #define CHACHA_QUARTER_ROUND(a,b,c,d) \
a += b; d ^= a; d = rotlConstant<16,word32>(d); \ a += b; d ^= a; d = rotlConstant<16,word32>(d); \
c += d; b ^= c; b = rotlConstant<12,word32>(b); \ 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); c += d; b ^= c; b = rotlConstant<7,word32>(b);
#define CHACHA_OUTPUT(x){\ #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, 0, x0 + state[0]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + m_state[1]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + state[1]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + m_state[2]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + state[2]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + m_state[3]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + state[3]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + m_state[4]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + state[4]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + m_state[5]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + state[5]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + m_state[6]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + state[6]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + m_state[7]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + state[7]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + m_state[8]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + state[8]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + m_state[9]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + state[9]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + m_state[10]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + state[10]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + m_state[11]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + state[11]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + m_state[12]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + state[12]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + m_state[13]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + state[13]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + m_state[14]);\ CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + state[14]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + m_state[15]);} CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + state[15]);}
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) ANONYMOUS_NAMESPACE_BEGIN
void ChaCha_TestInstantiations()
// 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 #endif
std::string ChaCha_Policy::AlgorithmName() const #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
{ if (HasSSE2())
return std::string("ChaCha")+IntToString(m_rounds); {
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 (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2()) if (HasAVX2())
return "AVX2"; return "AVX2";
else else
#endif #endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE) #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2()) if (HasSSE2())
return "SSE2"; return "SSE2";
else else
@ -95,52 +279,14 @@ std::string ChaCha_Policy::AlgorithmProvider() const
return "C++"; return "C++";
} }
void ChaCha_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) unsigned int ChaCha_GetAlignment()
{
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
{ {
#if (CRYPTOPP_AVX2_AVAILABLE) #if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2()) if (HasAVX2())
return 16; return 16;
else else
#endif #endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE) #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2()) if (HasSSE2())
return 16; return 16;
else else
@ -153,14 +299,14 @@ unsigned int ChaCha_Policy::GetAlignment() const
return GetAlignmentOf<word32>(); return GetAlignmentOf<word32>();
} }
unsigned int ChaCha_Policy::GetOptimalBlockSize() const unsigned int ChaCha_GetOptimalBlockSize()
{ {
#if (CRYPTOPP_AVX2_AVAILABLE) #if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2()) if (HasAVX2())
return 8 * BYTES_PER_ITERATION; return 8 * BYTES_PER_ITERATION;
else else
#endif #endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE) #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2()) if (HasSSE2())
return 4*BYTES_PER_ITERATION; return 4*BYTES_PER_ITERATION;
else else
@ -178,147 +324,267 @@ unsigned int ChaCha_Policy::GetOptimalBlockSize() const
return BYTES_PER_ITERATION; 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, void ChaCha_Policy::OperateKeystream(KeystreamOperation operation,
byte *output, const byte *input, size_t iterationCount) byte *output, const byte *input, size_t iterationCount)
{ {
do ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
{ m_rounds, output, input, iterationCount);
#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);
// MultiBlockSafe avoids overflow on the counter words ////////////////////////////// IETF ChaChaTLS //////////////////////////////
m_state[12] += 8;
//if (m_state[12] < 8)
// m_state[13]++;
input += (!!xorInput) * 8 * BYTES_PER_ITERATION; std::string ChaChaTLS_Policy::AlgorithmName() const
output += 8 * BYTES_PER_ITERATION; {
iterationCount -= 8; return std::string("ChaChaTLS");
} }
}
#endif
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE) std::string ChaChaTLS_Policy::AlgorithmProvider() const
if (HasSSE2()) {
{ return ChaCha_AlgorithmProvider();
while (iterationCount >= 4 && MultiBlockSafe(4)) }
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_SSE2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
m_state[12] += 4; {
//if (m_state[12] < 4) CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
// m_state[13]++; CRYPTOPP_UNUSED(length);
input += (!!xorInput)*4*BYTES_PER_ITERATION; // ChaChaTLS is always 20 rounds. Fetch Rounds() to avoid a spurious failure.
output += 4*BYTES_PER_ITERATION; int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS);
iterationCount -= 4; if (rounds != 20)
} throw InvalidRounds(ChaChaTLS::StaticAlgorithmName(), rounds);
}
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE) // RFC 8439 test vectors use an initial block counter. However, the counter
if (HasNEON()) // 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
while (iterationCount >= 4 && MultiBlockSafe(4)) // the initial counter is used more like a Tweak when non-0, and it should
{ // be provided in Resynchronize() (light-weight re-keying). However,
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL; // Resynchronize() does not have an overload that allows us to pass it into
ChaCha_OperateKeystream_NEON(m_state, xorInput ? input : NULLPTR, output, m_rounds); // 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 // State words are defined in RFC 8439, Section 2.3. Key is 32-bytes.
m_state[12] += 4; GetBlock<word32, LittleEndian> get(key);
//if (m_state[12] < 4) get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
// m_state[13]++; (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
}
input += (!!xorInput)*4*BYTES_PER_ITERATION; void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
output += 4*BYTES_PER_ITERATION; {
iterationCount -= 4; CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
} CRYPTOPP_ASSERT(length==12);
}
#endif
#if (CRYPTOPP_POWER7_AVAILABLE) // State words are defined in RFC 8439, Section 2.3.
if (HasPower7()) m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
{ m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_POWER7(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words // Copy saved key into state
m_state[12] += 4; std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
//if (m_state[12] < 4)
// m_state[13]++;
input += (!!xorInput)*4*BYTES_PER_ITERATION; // State words are defined in RFC 8439, Section 2.3
output += 4*BYTES_PER_ITERATION; GetBlock<word32, LittleEndian> get(IV);
iterationCount -= 4; m_state[12] = m_counter;
} get(m_state[13])(m_state[14])(m_state[15]);
} }
#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);
// MultiBlockSafe avoids overflow on the counter words void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
m_state[12] += 4; {
//if (m_state[12] < 4) // Should we throw here??? If the initial block counter is
// m_state[13]++; // 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; unsigned int ChaChaTLS_Policy::GetAlignment() const
output += 4*BYTES_PER_ITERATION; {
iterationCount -= 4; return ChaCha_GetAlignment();
} }
}
#endif
if (iterationCount) unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
{ {
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; return ChaCha_GetOptimalBlockSize();
}
x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3]; void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
x4 = m_state[4]; x5 = m_state[5]; x6 = m_state[6]; x7 = m_state[7]; byte *output, const byte *input, size_t iterationCount)
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]; 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) // If this fires it means ChaCha_OperateKeystream generated a counter
{ // block carry that was discarded. The problem is, the RFC does not
CHACHA_QUARTER_ROUND(x0, x4, x8, x12); // specify what should happen when the counter block wraps. All we can
CHACHA_QUARTER_ROUND(x1, x5, x9, x13); // do is inform the user that something bad may happen because we don't
CHACHA_QUARTER_ROUND(x2, x6, x10, x14); // know what we should do.
CHACHA_QUARTER_ROUND(x3, x7, x11, x15); // 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); ////////////////////////////// IETF XChaCha20 //////////////////////////////
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); std::string XChaCha20_Policy::AlgorithmName() const
{
return std::string("XChaCha20");
}
if (++m_state[12] == 0) std::string XChaCha20_Policy::AlgorithmProvider() const
m_state[13]++; {
} return ChaCha_AlgorithmProvider();
}
// We may re-enter a SIMD keystream operation from here. void XChaCha20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
} while (iterationCount--); {
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 NAMESPACE_END

View File

@ -3,13 +3,28 @@
// and Bernstein's reference ChaCha family implementation at // and Bernstein's reference ChaCha family implementation at
// http://cr.yp.to/chacha.html. // 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 /// \file chacha.h
/// \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers /// \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, /// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a
/// a variant of Salsa20</a> (2008.01.28). Bernstein's implementation is _slightly_ different from the TLS working group's /// href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a
/// implementation for cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>, /// variant of Salsa20</a> (2008.01.28). Crypto++ also provides the
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>. /// IETF implementation of ChaCha using the ChaChaTLS name. Bernstein's
/// \since Crypto++ 5.6.4 /// 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 #ifndef CRYPTOPP_CHACHA_H
#define CRYPTOPP_CHACHA_H #define CRYPTOPP_CHACHA_H
@ -19,6 +34,8 @@
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Bernstein ChaCha //////////////////////////////
/// \brief ChaCha stream cipher information /// \brief ChaCha stream cipher information
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8> 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> class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{ {
public: public:
~ChaCha_Policy() {} virtual ~ChaCha_Policy() {}
ChaCha_Policy() : m_rounds(0) {} ChaCha_Policy() : m_rounds(ROUNDS) {}
protected: protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length); void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
@ -55,28 +72,149 @@ protected:
std::string AlgorithmName() const; std::string AlgorithmName() const;
std::string AlgorithmProvider() const; std::string AlgorithmProvider() const;
// MultiBlockSafe detects a condition that can arise in the SIMD CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
// 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;
FixedSizeAlignedSecBlock<word32, 16> m_state; FixedSizeAlignedSecBlock<word32, 16> m_state;
unsigned int m_rounds; unsigned int m_rounds;
}; };
/// \brief ChaCha stream cipher /// \brief ChaCha stream cipher
/// \details Bernstein and ECRYPT's ChaCha is _slightly_ different from the TLS working /// \details This is Bernstein and ECRYPT's ChaCha. It is _slightly_ different
/// group's implementation for cipher suites /// from the IETF's version of ChaCha called ChaChaTLS.
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>, /// \sa <a href="http://cr.yp.to/chacha/chacha-20080208.pdf">ChaCha, a variant
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and /// of Salsa20</a> (2008.01.28).
/// <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).
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation
{ {
/// \brief ChaCha Encryption
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy, AdditiveCipherTemplate<> >, ChaCha_Info > 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; typedef Encryption Decryption;
}; };

View File

@ -30,7 +30,12 @@
#include "chacha.h" #include "chacha.h"
#include "misc.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 <xmmintrin.h>
# include <emmintrin.h> # include <emmintrin.h>
#endif #endif
@ -43,12 +48,11 @@
# include <ammintrin.h> # include <ammintrin.h>
#endif #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> # 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) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h> # include <stdint.h>
# include <arm_acle.h> # include <arm_acle.h>
@ -161,7 +165,7 @@ inline uint32x4_t Add64(const uint32x4_t& a, const uint32x4_t& b)
// ***************************** SSE2 ***************************** // // ***************************** SSE2 ***************************** //
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE) #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
template <unsigned int R> template <unsigned int R>
inline __m128i RotateLeft(const __m128i val) inline __m128i RotateLeft(const __m128i val)
@ -199,7 +203,7 @@ inline __m128i RotateLeft<16>(const __m128i val)
#endif #endif
} }
#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE || CRYPTOPP_SSE2_ASM_AVAILABLE #endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE
// **************************** Altivec **************************** // // **************************** 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 state2 = vld1q_u32(state + 2*4);
const uint32x4_t state3 = vld1q_u32(state + 3*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] = { 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; uint32x4_t r0_0 = state0;
@ -556,7 +561,7 @@ void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *
// ***************************** SSE2 ***************************** // // ***************************** 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) 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); _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) #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 #endif
}; };
/// \brief Encryption transformation /// \brief Decryption transformation
/// \details Dec provides implementation for decryption transformation. All key and block /// \details Dec provides implementation for decryption transformation. All key and block
/// sizes are supported. /// sizes are supported.
/// \since Crypto++ 8.0 /// \since Crypto++ 8.0
@ -109,11 +109,15 @@ public:
#endif #endif
}; };
/// \brief CHAM64 encryption
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption; typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
/// \brief CHAM64 decryption
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption; typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
}; };
/// \brief CHAM64 encryption
typedef CHAM64::Encryption CHAM64Encryption; typedef CHAM64::Encryption CHAM64Encryption;
/// \brief CHAM64 decryption
typedef CHAM64::Decryption CHAM64Decryption; typedef CHAM64::Decryption CHAM64Decryption;
/// \brief CHAM 128-bit block cipher /// \brief CHAM 128-bit block cipher
@ -154,7 +158,7 @@ public:
#endif #endif
}; };
/// \brief Encryption transformation /// \brief Decryption transformation
/// \details Dec provides implementation for decryption transformation. All key and block /// \details Dec provides implementation for decryption transformation. All key and block
/// sizes are supported. /// sizes are supported.
/// \since Crypto++ 8.0 /// \since Crypto++ 8.0
@ -168,11 +172,15 @@ public:
#endif #endif
}; };
/// \brief CHAM128 encryption
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption; typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
/// \brief CHAM128 decryption
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption; typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
}; };
/// \brief CHAM128 encryption
typedef CHAM128::Encryption CHAM128Encryption; typedef CHAM128::Encryption CHAM128Encryption;
/// \brief CHAM128 decryption
typedef CHAM128::Decryption CHAM128Decryption; typedef CHAM128::Decryption CHAM128Decryption;
NAMESPACE_END NAMESPACE_END

View File

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

View File

@ -68,6 +68,30 @@
# define CRYPTOPP_DISABLE_ASM 1 # define CRYPTOPP_DISABLE_ASM 1
#endif #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 // 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 // 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 // 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 // the version of the library the headers came from. It is not
// necessarily the version of the library built as a shared object if // necessarily the version of the library built as a shared object if
// versions are inadvertently mixed and matched. // 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/ // Define this if you want to set a prefix for TestData/ and TestVectors/
// Be sure to add the trailing slash since its simple concatenation. // 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 #define CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE 1
#endif #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 // 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 // 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__)) #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 // Requires Binutils 2.24
#if !defined(CRYPTOPP_DISABLE_AVX2) && defined(CRYPTOPP_AVX_AVAILABLE) && \ #if !defined(CRYPTOPP_DISABLE_AVX2) && defined(CRYPTOPP_AVX_AVAILABLE) && \
(defined(__AVX2__) || (CRYPTOPP_MSC_VERSION >= 1800) || (__SUNPRO_CC >= 0x5130) || \ (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)) (CRYPTOPP_LLVM_CLANG_VERSION >= 30100) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40600))
#define CRYPTOPP_AVX2_AVAILABLE 1 #define CRYPTOPP_AVX2_AVAILABLE 1
#endif #endif
@ -645,7 +663,7 @@ NAMESPACE_END
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) # if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_NEON) || defined(__ARM_FEATURE_NEON) || defined(__ARM_FEATURE_ASIMD) || \ # if defined(__ARM_NEON) || defined(__ARM_FEATURE_NEON) || defined(__ARM_FEATURE_ASIMD) || \
(CRYPTOPP_GCC_VERSION >= 40800) || (CRYPTOPP_CLANG_VERSION >= 30300) || \ (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_NEON_AVAILABLE 1
# define CRYPTOPP_ARM_ASIMD_AVAILABLE 1 # define CRYPTOPP_ARM_ASIMD_AVAILABLE 1
# endif // Compilers # endif // Compilers
@ -658,7 +676,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_CRC32_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) #if !defined(CRYPTOPP_ARM_CRC32_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) # if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_CRC32) || (CRYPTOPP_GCC_VERSION >= 40800) || \ # 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 # define CRYPTOPP_ARM_CRC32_AVAILABLE 1
# endif // Compilers # endif // Compilers
# endif // Platforms # endif // Platforms
@ -670,7 +688,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_PMULL_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) #if !defined(CRYPTOPP_ARM_PMULL_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) # if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \ # 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 # define CRYPTOPP_ARM_PMULL_AVAILABLE 1
# endif // Compilers # endif // Compilers
# endif // Platforms # endif // Platforms
@ -694,7 +712,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) #if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) # if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_CRYPTO) || (CRYPTOPP_GCC_VERSION >= 40800) || \ # 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_SHA1_AVAILABLE 1
# define CRYPTOPP_ARM_SHA2_AVAILABLE 1 # define CRYPTOPP_ARM_SHA2_AVAILABLE 1
# endif // Compilers # endif // Compilers
@ -707,7 +725,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) #if !defined(CRYPTOPP_ARM_SHA_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) # if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_SHA3) || (CRYPTOPP_GCC_VERSION >= 80000) || \ # 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_SHA512_AVAILABLE 1
# define CRYPTOPP_ARM_SHA3_AVAILABLE 1 # define CRYPTOPP_ARM_SHA3_AVAILABLE 1
# endif // Compilers # endif // Compilers
@ -720,7 +738,7 @@ NAMESPACE_END
#if !defined(CRYPTOPP_ARM_SM3_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM) #if !defined(CRYPTOPP_ARM_SM3_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
# if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64) # if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
# if defined(__ARM_FEATURE_SM3) || (CRYPTOPP_GCC_VERSION >= 80000) || \ # 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_SM3_AVAILABLE 1
# define CRYPTOPP_ARM_SM4_AVAILABLE 1 # define CRYPTOPP_ARM_SM4_AVAILABLE 1
# endif // Compilers # endif // Compilers
@ -921,7 +939,7 @@ NAMESPACE_END
#ifndef NO_OS_DEPENDENCE #ifndef NO_OS_DEPENDENCE
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#define CRYPTOPP_WIN32_AVAILABLE #define CRYPTOPP_WIN32_AVAILABLE
#endif #endif

View File

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

View File

@ -14,7 +14,8 @@
# include <nmmintrin.h> # include <nmmintrin.h>
#endif #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> # include <arm_neon.h>
#endif #endif

View File

@ -16,12 +16,17 @@
# You must also add /DCRYPTOPP_DEBUG or /DDEBUG if you want a debug build with # 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 # 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 # 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(). # 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 # 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 # "make sources | fold -w73 -s". The list of LIB_OBJS and TEST_OBJS was
# generated with "make sources | fold -w74 -s | sed 's|.cpp|.obj|g'". The # 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 # order of the first three object files are significant. See C++ Static
# Initialization Order Fisaco on the Crypto++ wiki for details. # 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 \ authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2.cpp \
blake2b_simd.cpp blake2s_simd.cpp blowfish.cpp blumshub.cpp camellia.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 \ 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 \ chacha_simd.cpp chachapoly.cpp cham.cpp cham_simd.cpp channels.cpp \
crc_simd.cpp darn.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp \ cmac.cpp crc.cpp crc_simd.cpp darn.cpp default.cpp des.cpp dessp.cpp \
dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp dsa.cpp eax.cpp ec2n.cpp \ dh.cpp dh2.cpp dll.cpp donna_32.cpp donna_64.cpp donna_sse.cpp dsa.cpp \
eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp \ eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp \
filters.cpp fips140.cpp fipstest.cpp gcm.cpp gcm_simd.cpp gf256.cpp \ esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm.cpp \
gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hc128.cpp hc256.cpp \ gcm_simd.cpp gf256.cpp gf2_32.cpp gf2n.cpp gf2n_simd.cpp gfpcrypt.cpp \
hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp \ gost.cpp gzip.cpp hc128.cpp hc256.cpp hex.cpp hight.cpp hmac.cpp \
kalyna.cpp kalynatab.cpp keccak.cpp keccakc.cpp lea.cpp lea_simd.cpp \ hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp \
luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp \ keccak.cpp keccakc.cpp lea.cpp lea_simd.cpp luc.cpp mars.cpp marss.cpp \
mqueue.cpp mqv.cpp nbtheory.cpp neon_simd.cpp oaep.cpp osrng.cpp \ md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp \
padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp \ nbtheory.cpp neon_simd.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp \
ppc_power7.cpp ppc_power8.cpp ppc_power9.cpp ppc_simd.cpp pssr.cpp \ pkcspad.cpp poly1305.cpp polynomi.cpp ppc_power7.cpp ppc_power8.cpp \
pubkey.cpp queue.cpp rabbit.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp \ ppc_power9.cpp ppc_simd.cpp pssr.cpp pubkey.cpp queue.cpp rabbit.cpp \
rc6.cpp rdrand.cpp rdtables.cpp rijndael.cpp rijndael_simd.cpp ripemd.cpp \ rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp \
rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp \ rijndael.cpp rijndael_simd.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp \
serpent.cpp sha.cpp sha3.cpp sha_simd.cpp shacal2.cpp shacal2_simd.cpp \ safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha.cpp \
shark.cpp sharkbox.cpp simeck.cpp simeck_simd.cpp simon.cpp \ sha3.cpp sha_simd.cpp shacal2.cpp shacal2_simd.cpp shark.cpp sharkbox.cpp \
simon128_simd.cpp simon64_simd.cpp skipjack.cpp sm3.cpp sm4.cpp \ simeck.cpp simeck_simd.cpp simon.cpp simon128_simd.cpp simon64_simd.cpp \
sm4_simd.cpp sosemanuk.cpp speck.cpp speck128_simd.cpp speck64_simd.cpp \ skipjack.cpp sm3.cpp sm4.cpp sm4_simd.cpp sosemanuk.cpp speck.cpp \
square.cpp squaretb.cpp sse_simd.cpp strciphr.cpp tea.cpp tftables.cpp \ speck128_simd.cpp speck64_simd.cpp square.cpp squaretb.cpp sse_simd.cpp \
threefish.cpp tiger.cpp tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp \ strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp \
vmac.cpp wake.cpp whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp \ ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wake.cpp whrlpool.cpp \
zdeflate.cpp zinflate.cpp zlib.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
LIB_OBJS = \ LIB_OBJS = \
cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj \ 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 \ authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2.obj \
blake2b_simd.obj blake2s_simd.obj blowfish.obj blumshub.obj camellia.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 \ 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 \ chacha_simd.obj chachapoly.obj cham.obj cham_simd.obj channels.obj \
crc_simd.obj darn.obj default.obj des.obj dessp.obj dh.obj dh2.obj \ cmac.obj crc.obj crc_simd.obj darn.obj default.obj des.obj dessp.obj \
dll.obj donna_32.obj donna_64.obj donna_sse.obj dsa.obj eax.obj ec2n.obj \ dh.obj dh2.obj dll.obj donna_32.obj donna_64.obj donna_sse.obj dsa.obj \
eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj \ eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj \
filters.obj fips140.obj fipstest.obj gcm.obj gcm_simd.obj gf256.obj \ esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm.obj \
gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hc128.obj hc256.obj \ gcm_simd.obj gf256.obj gf2_32.obj gf2n.obj gf2n_simd.obj gfpcrypt.obj \
hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj \ gost.obj gzip.obj hc128.obj hc256.obj hex.obj hight.obj hmac.obj \
kalyna.obj kalynatab.obj keccak.obj keccakc.obj lea.obj lea_simd.obj \ hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj \
luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj \ keccak.obj keccakc.obj lea.obj lea_simd.obj luc.obj mars.obj marss.obj \
mqueue.obj mqv.obj nbtheory.obj neon_simd.obj oaep.obj osrng.obj \ md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj \
padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj \ nbtheory.obj neon_simd.obj oaep.obj osrng.obj padlkrng.obj panama.obj \
ppc_power7.obj ppc_power8.obj ppc_power9.obj ppc_simd.obj pssr.obj \ pkcspad.obj poly1305.obj polynomi.obj ppc_power7.obj ppc_power8.obj \
pubkey.obj queue.obj rabbit.obj rabin.obj randpool.obj rc2.obj rc5.obj \ ppc_power9.obj ppc_simd.obj pssr.obj pubkey.obj queue.obj rabbit.obj \
rc6.obj rdrand.obj rdtables.obj rijndael.obj rijndael_simd.obj ripemd.obj \ rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj \
rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj \ rijndael.obj rijndael_simd.obj ripemd.obj rng.obj rsa.obj rw.obj \
serpent.obj sha.obj sha3.obj sha_simd.obj shacal2.obj shacal2_simd.obj \ safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha.obj \
shark.obj sharkbox.obj simeck.obj simeck_simd.obj simon.obj \ sha3.obj sha_simd.obj shacal2.obj shacal2_simd.obj shark.obj sharkbox.obj \
simon128_simd.obj simon64_simd.obj skipjack.obj sm3.obj sm4.obj \ simeck.obj simeck_simd.obj simon.obj simon128_simd.obj simon64_simd.obj \
sm4_simd.obj sosemanuk.obj speck.obj speck128_simd.obj speck64_simd.obj \ skipjack.obj sm3.obj sm4.obj sm4_simd.obj sosemanuk.obj speck.obj \
square.obj squaretb.obj sse_simd.obj strciphr.obj tea.obj tftables.obj \ speck128_simd.obj speck64_simd.obj square.obj squaretb.obj sse_simd.obj \
threefish.obj tiger.obj tigertab.obj ttmac.obj tweetnacl.obj twofish.obj \ strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj \
vmac.obj wake.obj whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj \ ttmac.obj tweetnacl.obj twofish.obj vmac.obj wake.obj whrlpool.obj \
zdeflate.obj zinflate.obj zlib.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_SRCS = \
test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \ test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \
@ -127,7 +135,15 @@ TEST_OBJS = \
CXX = cl.exe CXX = cl.exe
LD = link.exe LD = link.exe
AR = lib.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... # C4231 is needed for VS2008 and below. Lots of noise...
CXXFLAGS = /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc CXXFLAGS = /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc
@ -195,7 +211,6 @@ LDFLAGS = $(LDFLAGS) /MACHINE:X64
LDLIBS = $(LDLIBS) kernel32.lib LDLIBS = $(LDLIBS) kernel32.lib
!ENDIF !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" !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) /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
@ -207,14 +222,57 @@ LIB_OBJS = $(LIB_OBJS) neon_simd.obj
all: cryptest.exe 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) cryptest.exe: pch.pch cryptlib.lib $(TEST_OBJS)
$(LD) $(LDFLAGS) $(TEST_OBJS) cryptlib.lib $(LDLIBS) /out:$@ $(LD) $(LDFLAGS) $(TEST_OBJS) cryptlib.lib $(LDLIBS) /out:$@
cryptlib.lib: $(LIB_OBJS) cryptlib.lib: $(LIB_OBJS)
$(AR) $(ARFLAGS) $(LIB_OBJS) /out:$@ $(AR) $(ARFLAGS) $(LIB_OBJS) /out:$@
clean: cryptopp.dump: cryptlib.lib
$(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 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 # Precompiled header
pch.pch: pch.h pch.cpp pch.pch: pch.h pch.cpp
@ -245,6 +303,54 @@ chacha_avx.obj:
$(CXX) $(CXXFLAGS) /arch:AVX /c chacha_avx.cpp $(CXX) $(CXXFLAGS) /arch:AVX /c chacha_avx.cpp
!endif !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: .cpp.obj:
$(CXX) $(CXXFLAGS) /c $< $(CXX) $(CXXFLAGS) /c $<

View File

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

View File

@ -3,7 +3,7 @@
/// \file cryptlib.h /// \file cryptlib.h
/// \brief Abstract base classes that provide a uniform interface to this library. /// \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> <dl>
<dt>Abstract Base Classes<dd> <dt>Abstract Base Classes<dd>
cryptlib.h cryptlib.h
@ -500,9 +500,9 @@ const std::string AAD_CHANNEL;
const NameValuePairs& g_nullNameValuePairs; const NameValuePairs& g_nullNameValuePairs;
#else #else
extern const std::string DEFAULT_CHANNEL; extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
extern const std::string AAD_CHANNEL; extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
extern const NameValuePairs& g_nullNameValuePairs; extern CRYPTOPP_DLL const NameValuePairs& g_nullNameValuePairs;
#endif #endif
// Document additional name spaces which show up elsewhere in the sources. // Document additional name spaces which show up elsewhere in the sources.
@ -1129,9 +1129,11 @@ public:
unsigned int TagSize() const {return DigestSize();} unsigned int TagSize() const {return DigestSize();}
/// \brief Provides the block size of the compression function /// \brief Provides the block size of the compression function
/// \return the block size of the compression function, in bytes /// \return block size of the compression function, in bytes
/// \details BlockSize() will return 0 if the hash is not block based. For example, /// \details BlockSize() will return 0 if the hash is not block based
/// SHA3 is a recursive hash (not an iterative hash), and it does not have a block size. /// 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;} virtual unsigned int BlockSize() const {return 0;}
/// \brief Provides the input block size most efficient for this hash. /// \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 /// \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 /// \return the maximum length of AAD that can be input before the encrypted data
virtual lword MaxHeaderLength() const =0; virtual lword MaxHeaderLength() const =0;
/// \brief Provides the maximum length of encrypted data /// \brief Provides the maximum length of encrypted data
/// \return the maximum length of encrypted data /// \return the maximum length of encrypted data
virtual lword MaxMessageLength() const =0; virtual lword MaxMessageLength() const =0;
/// \brief Provides the the maximum length of AAD /// \brief Provides the the maximum length of AAD
/// \return the maximum length of AAD that can be input after the encrypted data /// \return the maximum length of AAD that can be input after the encrypted data
virtual lword MaxFooterLength() const {return 0;} virtual lword MaxFooterLength() const {return 0;}
/// \brief Determines if data lengths must be specified prior to inputting data /// \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 /// \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. /// \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. /// This is the case for some schemes, such as CCM.
/// \sa SpecifyDataLengths() /// \sa SpecifyDataLengths()
virtual bool NeedsPrespecifiedDataLengths() const {return false;} 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() /// \sa NeedsPrespecifiedDataLengths()
void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0); void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0);
/// \brief Encrypts and calculates a MAC in one call /// \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 /// \param ciphertext the encryption buffer
/// <tt>macSize < TagSize()</tt>. /// \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); 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 /// \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 /// \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. /// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
/// DecryptAndVerify() will assume MAC is truncated if <tt>macLength < TagSize()</tt>. /// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
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 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 /// \brief Provides the name of this algorithm
/// \return the standard algorithm name /// \return the standard algorithm name

View File

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

View File

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

View File

@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 8,0,0,0 FILEVERSION 8,1,0,0
PRODUCTVERSION 8,0,0,0 PRODUCTVERSION 8,1,0,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -46,13 +46,13 @@ BEGIN
VALUE "Comments", "Free crypto library, more information available at www.cryptopp.com" VALUE "Comments", "Free crypto library, more information available at www.cryptopp.com"
VALUE "CompanyName", "Wei Dai" VALUE "CompanyName", "Wei Dai"
VALUE "FileDescription", "Crypto++® Library DLL" VALUE "FileDescription", "Crypto++® Library DLL"
VALUE "FileVersion", "8, 0, 0, 0" VALUE "FileVersion", "8, 1, 0, 0"
VALUE "InternalName", "cryptopp" VALUE "InternalName", "cryptopp"
VALUE "LegalCopyright", "Copyright© 1995-2018 by Wei Dai" VALUE "LegalCopyright", "Copyright© 1995-2018 by Wei Dai"
VALUE "LegalTrademarks", "Crypto++®" VALUE "LegalTrademarks", "Crypto++®"
VALUE "OriginalFilename", "cryptopp.dll" VALUE "OriginalFilename", "cryptopp.dll"
VALUE "ProductName", "Crypto++® Library" VALUE "ProductName", "Crypto++® Library"
VALUE "ProductVersion", "8, 0, 0, 0" VALUE "ProductVersion", "8, 1, 0, 0"
END END
END END
BLOCK "VarFileInfo" 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 // been processed. Also note we only unlatch from testDataPairs. If
// overrideParameters are specified, the caller is responsible for // overrideParameters are specified, the caller is responsible for
// managing the parameter. // 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; std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
if (test == "EncryptionMCT" || test == "DecryptionMCT") if (test == "EncryptionMCT" || test == "DecryptionMCT")

View File

@ -81,6 +81,23 @@ int ed25519_publickey(byte publicKey[32], const byte secretKey[32]);
/// SHA512. /// SHA512.
int ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], const byte publicKey[32], byte signature[64]); 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 /// \brief Verifies a signature on a message
/// \param message byte array with the message /// \param message byte array with the message
/// \param messageLength size of the message, in bytes /// \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 /// \param signature byte array with the signature
/// \returns 0 on success, non-0 otherwise /// \returns 0 on success, non-0 otherwise
/// \details ed25519_sign_open() verifies a signature on a message using /// \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. /// require extra space like when using the NaCl library functions.
/// \details At the moment the hash function for signing is fixed at /// \details At the moment the hash function for signing is fixed at
/// SHA512. /// SHA512.
int int
ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]); 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 ******************************// //****************************** Internal ******************************//
#ifndef CRYPTOPP_DOXYGEN_PROCESSING #ifndef CRYPTOPP_DOXYGEN_PROCESSING

View File

@ -27,6 +27,13 @@
#include "misc.h" #include "misc.h"
#include "cpu.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 // Squash MS LNK4221 and libtool warnings
extern const char DONNA32_FNAME[] = __FILE__; extern const char DONNA32_FNAME[] = __FILE__;
@ -1029,7 +1036,21 @@ ed25519_extsk(hash_512bits extsk, const byte sk[32]) {
} }
void 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; SHA512 hash;
hash.Update(RS, 32); hash.Update(RS, 32);
hash.Update(pk, 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); 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 inline bignum256modm_element_t
lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) { lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
return (a - b) >> 31; return (a - b) >> 31;
@ -1552,7 +1582,7 @@ ge25519_pack(byte r[32], const ge25519 *p) {
} }
int 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; size_t differentbits = 0;
while (len--) while (len--)
differentbits |= (*x++ ^ *y++); 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; using namespace CryptoPP::Donna::X25519;
FixedSizeSecBlock<byte, 32> e; 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[i] = secretKey[i];
e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40; 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); 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 int
ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32], byte RS[64]) 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; 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 int
ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32],
const byte publicKey[32], byte signature[64]) 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); 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 int
ed25519_sign_open_CXX(const byte *m, size_t mlen, const byte pk[32], const byte RS[64]) { 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; ALIGN(16) ge25519 R, A;
hash_512bits hash; hash_512bits hash;
bignum256modm hram, S; bignum256modm hram, S;
unsigned char checkR[32]; byte checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1; 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); 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 // Donna
NAMESPACE_END // CryptoPP NAMESPACE_END // CryptoPP

View File

@ -27,6 +27,13 @@
#include "misc.h" #include "misc.h"
#include "cpu.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 // Squash MS LNK4221 and libtool warnings
extern const char DONNA64_FNAME[] = __FILE__; extern const char DONNA64_FNAME[] = __FILE__;
@ -728,7 +735,7 @@ curve25519_contract(byte *out, const bignum25519 input) {
/* out = (flag) ? in : out */ /* out = (flag) ? in : out */
inline void 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 nb = flag - 1, b = ~nb;
const word64 *inq = (const word64 *)in; const word64 *inq = (const word64 *)in;
word64 *outq = (word64 *)out; 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) */ /* if (iswap) swap(a, b) */
inline void inline void
curve25519_swap_conditional(bignum25519 a, bignum25519 b, word64 iswap) { 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; word64 x0,x1,x2,x3,x4;
x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0; 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 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; SHA512 hash;
hash.Update(RS, 32); hash.Update(RS, 32);
hash.Update(pk, 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); 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 bignum256modm_element_t
lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) { lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
return (a - b) >> 63; return (a - b) >> 63;
@ -857,7 +887,6 @@ barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256m
reduce256_modm(r); reduce256_modm(r);
} }
void void
add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
bignum256modm_element_t c; bignum256modm_element_t c;
@ -1268,7 +1297,7 @@ ge25519_pack(byte r[32], const ge25519 *p) {
} }
int 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; size_t differentbits = 0;
while (len--) while (len--)
differentbits |= (*x++ ^ *y++); differentbits |= (*x++ ^ *y++);
@ -1376,7 +1405,7 @@ ge25519_windowb_equal(word32 b, word32 c) {
} }
void 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; bignum25519 neg;
word32 sign = (word32)((byte)b >> 7); word32 sign = (word32)((byte)b >> 7);
word32 mask = ~(sign - 1); word32 mask = ~(sign - 1);
@ -1384,7 +1413,7 @@ ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][
word32 i; word32 i;
/* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */ /* 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[0] = 1;
packed[32] = 1; packed[32] = 1;
@ -1406,7 +1435,7 @@ ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][
/* computes [s]basepoint */ /* computes [s]basepoint */
void 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]; signed char b[64];
word32 i; word32 i;
ge25519_niels t; ge25519_niels t;
@ -1569,6 +1598,54 @@ ed25519_publickey(byte publicKey[32], const byte secretKey[32])
return ed25519_publickey_CXX(publicKey, secretKey); 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 int
ed25519_sign_CXX(const byte *m, size_t mlen, const byte sk[32], const byte pk[32], byte RS[64]) 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; 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 int
ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32],
const byte publicKey[32], byte signature[64]) 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; ALIGN(16) ge25519 R, A;
hash_512bits hash; hash_512bits hash;
bignum256modm hram, S; bignum256modm hram, S;
unsigned char checkR[32]; byte checkR[32];
if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk))
return -1; 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; 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 int
ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]) 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. // and not the actual alignment of the variable and data.
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic ignored "-Wcast-align" # pragma GCC diagnostic ignored "-Wcast-align"
# pragma GCC diagnostic ignored "-Wunused-function"
#endif #endif
// Squash MS LNK4221 and libtool warnings // Squash MS LNK4221 and libtool warnings

View File

@ -99,7 +99,12 @@ template<> struct EcRecommendedParameters<EC2N>
StringSource ssA(a, true, new HexDecoder); StringSource ssA(a, true, new HexDecoder);
StringSource ssB(b, true, new HexDecoder); StringSource ssB(b, true, new HexDecoder);
if (t0 == 0) 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 else
return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); 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 try
{ {
this->GetMaterial().DoQuickSanityCheck();
const DL_GroupParameters<Element> &params = GetAbstractGroupParameters(); const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
if(m_role == RoleServer) if(m_role == RoleServer)

View File

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

View File

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

View File

@ -29,7 +29,8 @@
# include <wmmintrin.h> # include <wmmintrin.h>
#endif #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> # include <arm_neon.h>
#endif #endif
@ -38,6 +39,10 @@
# include <arm_acle.h> # include <arm_acle.h>
#endif #endif
#if defined(CRYPTOPP_ARM_PMULL_AVAILABLE)
# include "arm_simd.h"
#endif
#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) #if defined(CRYPTOPP_ALTIVEC_AVAILABLE)
# include "ppc_simd.h" # include "ppc_simd.h"
#endif #endif
@ -62,205 +67,6 @@
// Squash MS LNK4221 and libtool warnings // Squash MS LNK4221 and libtool warnings
extern const char GCM_SIMD_FNAME[] = __FILE__; 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) NAMESPACE_BEGIN(CryptoPP)
// ************************* Feature Probes ************************* // // ************************* Feature Probes ************************* //
@ -287,23 +93,24 @@ bool CPU_ProbePMULL()
volatile bool result = true; volatile bool result = true;
__try __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. // 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 uint64_t wa1[]={0,0x9090909090909090}, wb1[]={0,0xb0b0b0b0b0b0b0b0};
const uint64x2_t t2 = (uint64x2_t)(r2); // {bignum,bignum} const uint64x2_t a1=vld1q_u64(wa1), b1=vld1q_u64(wb1);
result = !!(vgetq_lane_u64(t1,0) == 0x5300530053005300 && const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
vgetq_lane_u64(t1,1) == 0x5300530053005300 && 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0},
vgetq_lane_u64(t2,0) == 0x6c006c006c006c00 && wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
vgetq_lane_u64(t2,1) == 0x6c006c006c006c00); 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) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
@ -328,14 +135,18 @@ bool CPU_ProbePMULL()
else else
{ {
// Linaro is missing a lot of pmull gear. Also see http://github.com/weidai11/cryptopp/issues/233. // 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 uint64_t wa1[]={0,0x9090909090909090}, wb1[]={0,0xb0b0b0b0b0b0b0b0};
const uint8x16_t a2={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 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}, 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}; 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 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 && result = !!(vgetq_lane_u64(r1,0) == 0x5300530053005300 &&
vgetq_lane_u64(r1,1) == 0x5300530053005300 && vgetq_lane_u64(r1,1) == 0x5300530053005300 &&
@ -374,17 +185,24 @@ bool CPU_ProbePMULL()
result = false; result = false;
else else
{ {
const uint8x16_p a={0x0f,0x08,0x08,0x08, 0x80,0x80,0x80,0x80, const uint64_t wa1[]={0,W64LIT(0x9090909090909090)},
0x00,0x0a,0x0a,0x0a, 0xa0,0xa0,0xa0,0xa0}, wb1[]={0,W64LIT(0xb0b0b0b0b0b0b0b0)};
b={0x0f,0xc0,0xc0,0xc0, 0x0c,0x0c,0x0c,0x0c, const uint64x2_p a1=VecLoad(wa1), b1=VecLoad(wb1);
0x00,0xe0,0xe0,0xe0, 0x0e,0x0e,0x0e,0x0e};
const uint64x2_p r1 = VMULL_00LE((uint64x2_p)(a), (uint64x2_p)(b)); const uint8_t wa2[]={0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
const uint64x2_p r2 = VMULL_01LE((uint64x2_p)(a), (uint64x2_p)(b)); 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0},
const uint64x2_p r3 = VMULL_10LE((uint64x2_p)(a), (uint64x2_p)(b)); wb2[]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
const uint64x2_p r4 = VMULL_11LE((uint64x2_p)(a), (uint64x2_p)(b)); 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); 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}; const uint64x2_p m1 = {1,1}, m63 = {63,63};
c1 = VecXor(c1, VecShiftRightOctet<8>(c0)); 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 = 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, c0);
c2 = VecXor(c2, VecShiftLeftOctet<8>(c1)); c2 = VecXor(c2, VecShiftLeftOctet<8>(c1));
c1 = vec_sr(vec_mergeh(c1, c2), m63); 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) 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 c0 = VecPolyMultiply00LE(x, h);
const uint64x2_p c1 = VecXor(VMULL_01LE(x, h), VMULL_10LE(x, h)); const uint64x2_p c1 = VecXor(VecPolyMultiply01LE(x, h), VecPolyMultiply10LE(x, h));
const uint64x2_p c2 = VMULL_11LE(x, h); const uint64x2_p c2 = VecPolyMultiply11LE(x, h);
return GCM_Reduce_VMULL(c0, c1, c2, r); 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 = LoadBuffer2(data);
d1 = VecXor(d1, x); d1 = VecXor(d1, x);
c0 = VecXor(c0, VMULL_00LE(d1, h0)); c0 = VecXor(c0, VecPolyMultiply00LE(d1, h0));
c2 = VecXor(c2, VMULL_01LE(d1, h1)); c2 = VecXor(c2, VecPolyMultiply01LE(d1, h1));
d1 = VecXor(d1, SwapWords(d1)); d1 = VecXor(d1, SwapWords(d1));
c1 = VecXor(c1, VMULL_00LE(d1, h2)); c1 = VecXor(c1, VecPolyMultiply00LE(d1, h2));
break; break;
} }
d1 = LoadBuffer1(data+(s-i)*16-8); d1 = LoadBuffer1(data+(s-i)*16-8);
c0 = VecXor(c0, VMULL_01LE(d2, h0)); c0 = VecXor(c0, VecPolyMultiply01LE(d2, h0));
c2 = VecXor(c2, VMULL_01LE(d1, h1)); c2 = VecXor(c2, VecPolyMultiply01LE(d1, h1));
d2 = VecXor(d2, d1); d2 = VecXor(d2, d1);
c1 = VecXor(c1, VMULL_01LE(d2, h2)); c1 = VecXor(c1, VecPolyMultiply01LE(d2, h2));
if (++i == s) if (++i == s)
{ {
d1 = LoadBuffer2(data); d1 = LoadBuffer2(data);
d1 = VecXor(d1, x); d1 = VecXor(d1, x);
c0 = VecXor(c0, VMULL_10LE(d1, h0)); c0 = VecXor(c0, VecPolyMultiply10LE(d1, h0));
c2 = VecXor(c2, VMULL_11LE(d1, h1)); c2 = VecXor(c2, VecPolyMultiply11LE(d1, h1));
d1 = VecXor(d1, SwapWords(d1)); d1 = VecXor(d1, SwapWords(d1));
c1 = VecXor(c1, VMULL_10LE(d1, h2)); c1 = VecXor(c1, VecPolyMultiply10LE(d1, h2));
break; break;
} }
d2 = LoadBuffer2(data+(s-i)*16-8); d2 = LoadBuffer2(data+(s-i)*16-8);
c0 = VecXor(c0, VMULL_10LE(d1, h0)); c0 = VecXor(c0, VecPolyMultiply10LE(d1, h0));
c2 = VecXor(c2, VMULL_10LE(d2, h1)); c2 = VecXor(c2, VecPolyMultiply10LE(d2, h1));
d1 = VecXor(d1, d2); d1 = VecXor(d1, d2);
c1 = VecXor(c1, VMULL_10LE(d1, h2)); c1 = VecXor(c1, VecPolyMultiply10LE(d1, h2));
} }
data += s*16; data += s*16;
len -= s*16; len -= s*16;

View File

@ -13,8 +13,9 @@
#include "words.h" #include "words.h"
#include "misc.h" #include "misc.h"
#include "gf2n.h" #include "gf2n.h"
#include "asn.h"
#include "oids.h" #include "oids.h"
#include "asn.h"
#include "cpu.h"
#include <iostream> #include <iostream>
@ -41,6 +42,21 @@ ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP) 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() PolynomialMod2::PolynomialMod2()
{ {
} }
@ -75,7 +91,7 @@ void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits)
PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength) PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength)
{ {
PolynomialMod2 result((word)0, 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) if (bitLength%WORD_BITS)
result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS); result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS);
return result; return result;
@ -943,6 +959,112 @@ GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
return result.release(); 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 NAMESPACE_END
#endif #endif

View File

@ -246,6 +246,7 @@ public:
private: private:
friend class GF2NT; friend class GF2NT;
friend class GF2NT233;
SecWordBlock reg; SecWordBlock reg;
}; };
@ -344,13 +345,29 @@ public:
const Element& MultiplicativeInverse(const Element &a) const; const Element& MultiplicativeInverse(const Element &a) const;
private: protected:
const Element& Reduced(const Element &a) const; const Element& Reduced(const Element &a) const;
unsigned int t0, t1; unsigned int t0, t1;
mutable PolynomialMod2 result; 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 /// \brief GF(2^n) with Pentanomial Basis
class CRYPTOPP_DLL GF2NPP : public GF2NP 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_384;
class SHA3_512; class SHA3_512;
class SHAKE128;
class SHAKE256;
class Tiger; class Tiger;
class RIPEMD128; class RIPEMD128;
class RIPEMD160; class RIPEMD160;

View File

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

View File

@ -233,7 +233,7 @@ static word AtomicInverseModPower2(word A)
#define GetBorrow(u) u##1 #define GetBorrow(u) u##1
#else #else
#define Declare2Words(x) dword x; #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); #define MultiplyWords(p, a, b) p = __emulu(a, b);
#else #else
#define MultiplyWords(p, a, b) p = (dword)a*b; #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> template <class S, class D>
inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B) 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. // Profiling tells us the original second case was dominant, so it was
// The code change occurred at Commit dc99266599a0e72d. // promoted to the first If statement. The code change occurred at
// Commit dc99266599a0e72d.
if (!!B) 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]) if (NA==2 && !A[1])
{ {
// Profiling tells us the original Default case was dominant, so it was promoted to the first Case statement. // Profiling tells us the original Default case was dominant, so it was
// The code change occurred at Commit dc99266599a0e72d. // promoted to the first Case statement. The code change occurred at
// Commit dc99266599a0e72d.
switch (A[0]) switch (A[0])
{ {
default: 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) 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. // Profiling tells us the original Else was dominant, so it was
// The code change occurred at Commit dc99266599a0e72d. // promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if (N!=2) if (N!=2)
{ {
const size_t N2 = 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 bool Integer::GetBit(size_t n) const
{ {
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement. // Profiling tells us the original Else was dominant, so it was
// The code change occurred at Commit dc99266599a0e72d. // promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if (n/WORD_BITS < reg.size()) if (n/WORD_BITS < reg.size())
return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1); return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
else else
@ -3123,8 +3127,9 @@ void Integer::SetBit(size_t n, bool value)
byte Integer::GetByte(size_t n) const byte Integer::GetByte(size_t n) const
{ {
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement. // Profiling tells us the original Else was dominant, so it was
// The code change occurred at Commit dc99266599a0e72d. // promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
if (n/WORD_SIZE < reg.size()) if (n/WORD_SIZE < reg.size())
return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
else else
@ -3227,7 +3232,7 @@ static Integer StringToInteger(const T *str, ByteOrder order)
{ {
int digit, ch = static_cast<int>(str[i]); 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. // The code change occurred at Commit dc99266599a0e72d.
if (ch >= '0' && ch <= '9') if (ch >= '0' && ch <= '9')
digit = ch - '0'; digit = ch - '0';
@ -3387,8 +3392,9 @@ void Integer::Decode(BufferedTransformation &bt, size_t inputLen, Signedness s)
size_t Integer::MinEncodedSize(Signedness signedness) const 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. // Profiling tells us the original second If was dominant, so it
// The code change occurred at Commit dc99266599a0e72d. // was promoted to the first If statement. The code change occurred
// at Commit dc99266599a0e72d.
unsigned int outputLen = STDMAX(1U, ByteCount()); unsigned int outputLen = STDMAX(1U, ByteCount());
const bool pre = (signedness == UNSIGNED); const bool pre = (signedness == UNSIGNED);
if (!pre && NotNegative() && (GetByte(outputLen-1) & 0x80)) 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) 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 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) 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. // Profiling tells us the original second Else If was dominant, so it
// The code change occurred at Commit dc99266599a0e72d. // 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()); int carry; const bool pre = (a.reg.size() == b.reg.size());
if (!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(); unsigned bSize = b.WordCount();
bSize += bSize%2; bSize += bSize%2;
// Profiling tells us the original second Else If was dominant, so it was promoted to the first If statement. // Profiling tells us the original second Else If was dominant, so it
// The code change occurred at Commit dc99266599a0e72d. // was promoted to the first If statement. The code change occurred at
// Commit dc99266599a0e72d.
if (aSize > bSize) if (aSize > bSize)
{ {
word borrow = Subtract(diff.reg, a.reg, b.reg, 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) if (!divisor)
throw Integer::DivideByZero(); 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); quotient = dividend >> (BitPrecision(divisor)-1);
remainder = dividend.reg[0] & (divisor-1); remainder = dividend.reg[0] & (divisor-1);
@ -4279,12 +4290,14 @@ word Integer::Modulo(word divisor) const
word remainder; word remainder;
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement. // Profiling tells us the original Else was dominant, so it was
// The code change occurred at Commit dc99266599a0e72d. // 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 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. // Profiling tells us the original Else was dominant, so it
// The code change occurred at Commit dc99266599a0e72d. // was promoted to the first If statement. The code change
// occurred at Commit dc99266599a0e72d.
unsigned int i = WordCount(); unsigned int i = WordCount();
if (divisor > 5) if (divisor > 5)
{ {
@ -4319,8 +4332,9 @@ void Integer::Negate()
int Integer::PositiveCompare(const Integer& t) const int Integer::PositiveCompare(const Integer& t) const
{ {
// Profiling tells us the original Else was dominant, so it was promoted to the first If statement. // Profiling tells us the original Else was dominant, so it
// The code change occurred at Commit dc99266599a0e72d. // was promoted to the first If statement. The code change
// occurred at Commit dc99266599a0e72d.
const unsigned size = WordCount(), tSize = t.WordCount(); const unsigned size = WordCount(), tSize = t.WordCount();
if (size != tSize) if (size != tSize)
return size > tSize ? 1 : -1; return size > tSize ? 1 : -1;

View File

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

View File

@ -39,30 +39,30 @@ NAMESPACE_BEGIN(CryptoPP)
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
class Keccak : public HashTransformation 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: public:
/// \brief Construct a Keccak unsigned int DigestSize() const {return m_digestSize;}
/// \param digestSize the digest size, in bytes unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
/// \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>();}
void Update(const byte *input, size_t length); void Update(const byte *input, size_t length);
void Restart(); void Restart();
void TruncatedFinal(byte *hash, size_t size); void TruncatedFinal(byte *hash, size_t size);
//unsigned int BlockSize() const { return r(); } // that's the idea behind it
protected: protected:
inline unsigned int r() const {return 200 - 2 * m_digestSize;} inline unsigned int r() const {return BlockSize();}
FixedSizeSecBlock<word64, 25> m_state; FixedSizeSecBlock<word64, 25> m_state;
unsigned int m_digestSize, m_counter; unsigned int m_digestSize, m_counter;
}; };
/// \brief Keccak message digest template /// \brief Keccak message digest template
@ -72,33 +72,48 @@ template<unsigned int T_DigestSize>
class Keccak_Final : public Keccak class Keccak_Final : public Keccak
{ {
public: public:
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize) CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * 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: private:
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math #if !defined(__BORLANDC__)
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC // 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 /// \brief Keccak-224 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<28> Keccak_224; DOCUMENTED_TYPEDEF(Keccak_Final<28>, Keccak_224);
/// \brief Keccak-256 message digest /// \brief Keccak-256 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<32> Keccak_256; DOCUMENTED_TYPEDEF(Keccak_Final<32>, Keccak_256);
/// \brief Keccak-384 message digest /// \brief Keccak-384 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<48> Keccak_384; DOCUMENTED_TYPEDEF(Keccak_Final<48>, Keccak_384);
/// \brief Keccak-512 message digest /// \brief Keccak-512 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<64> Keccak_512; DOCUMENTED_TYPEDEF(Keccak_Final<64>, Keccak_512);
NAMESPACE_END 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" #include "algparam.h"
#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8) #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 #endif
// Yet another SunStudio/SunCC workaround. Failed self tests // Yet another SunStudio/SunCC workaround. Failed self tests

View File

@ -10,7 +10,6 @@
#include "lea.h" #include "lea.h"
#include "misc.h" #include "misc.h"
#include "adv_simd.h"
// Uncomment for benchmarking C++ against SSE or NEON. // Uncomment for benchmarking C++ against SSE or NEON.
// Do so in both simon.cpp and simon-simd.cpp. // Do so in both simon.cpp and simon-simd.cpp.
@ -18,6 +17,7 @@
// #undef CRYPTOPP_ARM_NEON_AVAILABLE // #undef CRYPTOPP_ARM_NEON_AVAILABLE
#if (CRYPTOPP_SSSE3_AVAILABLE) #if (CRYPTOPP_SSSE3_AVAILABLE)
# include "adv_simd.h"
# include <pmmintrin.h> # include <pmmintrin.h>
# include <tmmintrin.h> # include <tmmintrin.h>
#endif #endif
@ -26,38 +26,41 @@
# include <ammintrin.h> # include <ammintrin.h>
#endif #endif
#if defined(__AVX512F__) && defined(__AVX512VL__) #if defined(__AVX512F__)
# define CRYPTOPP_AVX512_ROTATE 1 # define CRYPTOPP_AVX512_ROTATE 1
# include <immintrin.h> # include <immintrin.h>
#endif #endif
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) #if (CRYPTOPP_ARM_NEON_AVAILABLE)
# include <arm_neon.h> # include "adv_simd.h"
# ifndef _M_ARM64
# include <arm_neon.h>
# endif
#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) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h> # include <stdint.h>
# include <arm_acle.h> # include <arm_acle.h>
#endif #endif
// Do not port this to POWER architecture. Naively we hoped // Do not port this to POWER architecture. Naively we hoped
// for a 2x to 3x speedup. The result was a 5x slow down // for a 2x to 3x speedup. The result was a 5x slow down.
// because of the rotates and scattered loads. // The table below shows MiB/s and cpb.
// //
// C++: // C++:
// <TD>LEA-128(128)/CTR (128-bit key)<TD>C++<TD>207<TD>15.64<TD>0.593<TD>2015 // <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>0.699<TD>2378 // <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<TD>0.842<TD>2861 // <TD>LEA-128(256)/CTR (256-bit key)<TD>C++<TD>124<TD>26.2
// //
// Power8: // Power8:
// <TD>LEA-128(128)/CTR (128-bit key)<TD>Power8<TD>37<TD>88.7<TD>0.595<TD>2023 // <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>0.699<TD>2375 // <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<TD>1.006<TD>3419 // <TD>LEA-128(256)/CTR (256-bit key)<TD>Power8<TD>28<TD>116.0
#undef CRYPTOPP_POWER8_AVAILABLE #undef CRYPTOPP_POWER8_AVAILABLE
#if defined(CRYPTOPP_POWER8_AVAILABLE) #if defined(CRYPTOPP_POWER8_AVAILABLE)
# include "adv_simd.h"
# include "ppc_simd.h" # include "ppc_simd.h"
#endif #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, 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) 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, 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, 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) 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, 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 #endif // CRYPTOPP_ARM_NEON_AVAILABLE

View File

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

View File

@ -18,11 +18,12 @@
# endif # endif
#endif #endif
// Issue 340 // Issue 340 and Issue 793
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wconversion"
# pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wsign-conversion"
# pragma GCC diagnostic ignored "-Wunused-function"
#endif #endif
#include "cryptlib.h" #include "cryptlib.h"
@ -101,35 +102,6 @@
#endif // CRYPTOPP_DOXYGEN_PROCESSING #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) NAMESPACE_BEGIN(CryptoPP)
// Forward declaration for IntToString specialization // 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> template <class T1, class T2>
inline bool SafeConvert(T1 from, T2 &to) inline bool SafeConvert(T1 from, T2 &to)
{ {
to = (T2)from; to = static_cast<T2>(from);
if (from != to || (from > 0) != (to > 0)) if (from != to || (from > 0) != (to > 0))
return false; return false;
return true; return true;
@ -632,7 +604,7 @@ template <class T>
std::string IntToString(T value, unsigned int base = 10) std::string IntToString(T value, unsigned int base = 10)
{ {
// Hack... set the high bit for uppercase. // 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'; const char CH = !!(base & HIGH_BIT) ? 'A' : 'a';
base &= ~HIGH_BIT; 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 buf1 the first buffer
/// \param buf2 the second buffer /// \param buf2 the second buffer
/// \param count the size of the buffers, in bytes /// \param count the size of the buffers, in bytes
/// \details The function effectively performs an XOR of the elements in two equally sized buffers /// \details The function effectively performs an XOR of the elements in two equally sized
/// and retruns a result based on the XOR operation. The function is near constant-time because /// buffers and retruns a result based on the XOR operation. The function is near
/// CPU micro-code timings could affect the "constant-ness". Calling code is responsible for /// constant-time because CPU micro-code timings could affect the "constant-ness".
/// mitigating timing attacks if the buffers are not equally sized. /// Calling code is responsible for mitigating timing attacks if the buffers are not
/// equally sized.
/// \sa ModPowerOf2 /// \sa ModPowerOf2
CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count); 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 /// \brief Tests whether a value is a power of 2
/// \param value the value to test /// \param value the value to test
/// \returns true if value is a power of 2, false otherwise /// \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 /// \details The function creates a mask of <tt>value - 1</tt> and returns the result
/// an AND operation compared to 0. If value is 0 or less than 0, then the function returns false. /// of an AND operation compared to 0. If value is 0 or less than 0, then the function
/// returns false.
template <class T> template <class T>
inline bool IsPowerOf2(const T &value) inline bool IsPowerOf2(const T &value)
{ {
@ -933,13 +907,65 @@ inline bool IsPowerOf2<word64>(const word64 &value)
# endif // __x86_64__ # endif // __x86_64__
#endif // __BMI__ #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 /// \brief Performs a saturating subtract clamped at 0
/// \tparam T1 class or type /// \tparam T1 class or type
/// \tparam T2 class or type /// \tparam T2 class or type
/// \param a the minuend /// \param a the minuend
/// \param b the subtrahend /// \param b the subtrahend
/// \returns the difference produced by the saturating subtract /// \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 /// \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>). /// avoid a branch by using an instruction like a conditional move (<tt>CMOVE</tt>).
template <class T1, class T2> template <class T1, class T2>
@ -955,8 +981,8 @@ inline T1 SaturatingSubtract(const T1 &a, const T2 &b)
/// \param a the minuend /// \param a the minuend
/// \param b the subtrahend /// \param b the subtrahend
/// \returns the difference produced by the saturating subtract /// \returns the difference produced by the saturating subtract
/// \details Saturating arithmetic restricts results to a fixed range. Results that are less than /// \details Saturating arithmetic restricts results to a fixed range. Results that are
/// 1 are clamped at 1. /// less than 1 are clamped at 1.
/// \details Use of saturating arithmetic in places can be advantageous because it can /// \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>). /// avoid a branch by using an instruction like a conditional move (<tt>CMOVE</tt>).
template <class T1, class T2> 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 /// 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 /// an allocation succeeds. If the call to set_new_handler fails, then CallNewHandler throws
/// a bad_alloc exception. /// a bad_alloc exception.
/// \sa AlignedAllocate, AlignedDeallocate, UnalignedAllocate, UnalignedDeallocate
CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler(); CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
/// \brief Performs an addition with carry on a block of bytes /// \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. /// then a 0x21 error is returned on Windows which eventually results in an InvalidArgument() exception.
std::wstring StringWiden(const char *str, bool throwOnError = true); std::wstring StringWiden(const char *str, bool throwOnError = true);
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
/// \brief Allocates a buffer on 16-byte boundary /// \brief Allocates a buffer on 16-byte boundary
/// \param size the size of the buffer /// \param size the size of the buffer
/// \details AlignedAllocate is primarily used when the data will be proccessed by MMX, SSE2 and NEON /// \details AlignedAllocate is primarily used when the data will be
/// instructions. The assembly language routines rely on the alignment. If the alignment is not /// 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 /// respected, then a SIGBUS could be generated on Unix and Linux, and an
/// EXCEPTION_DATATYPE_MISALIGNMENT could be generated on Windows. /// EXCEPTION_DATATYPE_MISALIGNMENT could be generated on Windows.
/// \note AlignedAllocate and AlignedDeallocate are available when CRYPTOPP_BOOL_ALIGN16 is /// \details Formerly, AlignedAllocate and AlignedDeallocate were only
/// defined. CRYPTOPP_BOOL_ALIGN16 is defined in config.h /// 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); CRYPTOPP_DLL void* CRYPTOPP_API AlignedAllocate(size_t size);
/// \brief Frees a buffer allocated with AlignedAllocate /// \brief Frees a buffer allocated with AlignedAllocate
/// \param ptr the buffer to free /// \param ptr the buffer to free
/// \note AlignedAllocate and AlignedDeallocate are available when CRYPTOPP_BOOL_ALIGN16 is /// \since AlignedDeallocate for SIMD since Crypto++ 1.0, AlignedAllocate
/// defined. CRYPTOPP_BOOL_ALIGN16 is defined in config.h /// 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); 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 /// \brief Allocates a buffer
/// \param size the size of the 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); CRYPTOPP_DLL void * CRYPTOPP_API UnalignedAllocate(size_t size);
/// \brief Frees a buffer allocated with UnalignedAllocate /// \brief Frees a buffer allocated with UnalignedAllocate
/// \param ptr the buffer to free /// \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); CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *ptr);
// ************** rotate functions *************** // ************** 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://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884 // http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226 // and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(R < THIS_SIZE); CRYPTOPP_ASSERT(R < THIS_SIZE);
return T((x<<R)|(x>>(-R&MASK))); 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://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884 // http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226 // and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(R < THIS_SIZE); CRYPTOPP_ASSERT(R < THIS_SIZE);
return T((x >> R)|(x<<(-R&MASK))); 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://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884 // http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226 // and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE); CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x<<y)|(x>>(-y&MASK))); 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://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// http://software.intel.com/en-us/forums/topic/580884 // http://software.intel.com/en-us/forums/topic/580884
// and http://llvm.org/bugs/show_bug.cgi?id=24226 // and http://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE); CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x >> y)|(x<<(-y&MASK))); 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 /// \since Crypto++ 3.0
template <class T> inline T rotlVariable(T x, unsigned int y) template <class T> inline T rotlVariable(T x, unsigned int y)
{ {
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE); CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x<<y)|(x>>(-y&MASK))); 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 /// \since Crypto++ 3.0
template <class T> inline T rotrVariable(T x, unsigned int y) template <class T> inline T rotrVariable(T x, unsigned int y)
{ {
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
CRYPTOPP_ASSERT(y < THIS_SIZE); CRYPTOPP_ASSERT(y < THIS_SIZE);
return T((x>>y)|(x<<(-y&MASK))); 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 /// \since Crypto++ 3.0
template <class T> inline T rotlMod(T x, unsigned int y) template <class T> inline T rotlMod(T x, unsigned int y)
{ {
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
return T((x<<(y&MASK))|(x>>(-y&MASK))); 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 /// \since Crypto++ 3.0
template <class T> inline T rotrMod(T x, unsigned int y) template <class T> inline T rotrMod(T x, unsigned int y)
{ {
static const unsigned int THIS_SIZE = sizeof(T)*8; CRYPTOPP_CONSTANT(THIS_SIZE = sizeof(T)*8)
static const unsigned int MASK = THIS_SIZE-1; CRYPTOPP_CONSTANT(MASK = THIS_SIZE-1)
return T((x>>(y&MASK))|(x<<(-y&MASK))); return T((x>>(y&MASK))|(x<<(-y&MASK)));
} }

View File

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

View File

@ -11,12 +11,11 @@
#include "config.h" #include "config.h"
#include "stdcpp.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> # 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) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
# include <stdint.h> # include <stdint.h>
# include <arm_acle.h> # include <arm_acle.h>

View File

@ -8,8 +8,10 @@
#ifndef CRYPTOPP_IMPORTS #ifndef CRYPTOPP_IMPORTS
// Win32 has CryptoAPI and <wincrypt.h>. Windows 10 and Windows Store 10 have CNG and <bcrypt.h>. // 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. // There's a hole for Windows Phone 8 and Windows Store 8. There is no userland RNG available.
// Also see http://stackoverflow.com/questions/36974545/random-numbers-for-windows-phone-8-and-windows-store-8 // 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) #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.") # 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 #endif

View File

@ -50,6 +50,7 @@ public:
unsigned int DigestSize() const {return DIGESTSIZE;} unsigned int DigestSize() const {return DIGESTSIZE;}
void TruncatedFinal(byte *hash, size_t size); void TruncatedFinal(byte *hash, size_t size);
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return B::ToEnum() == BIG_ENDIAN_ORDER ? "Panama-BE" : "Panama-LE";} 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: protected:
void Init() {Panama<B>::Reset();} 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 // 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 "pch.h"
#include "cryptlib.h" #include "cryptlib.h"
#include "poly1305.h"
#include "aes.h" #include "aes.h"
#include "cpu.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> using namespace CryptoPP;
std::string Poly1305_Base<T>::AlgorithmProvider() const
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_HashBlocks(word32 h[5], word32 r[4], const byte *input, size_t length, word32 padbit)
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)
{ {
word32 r0, r1, r2, r3; word32 r0, r1, r2, r3;
word32 s1, s2, s3; word32 s1, s2, s3;
word32 h0, h1, h2, h3, h4, c; word32 h0, h1, h2, h3, h4, c;
word64 d0, d1, d2, d3; word64 d0, d1, d2, d3;
r0 = m_r[0]; r1 = m_r[1]; r0 = r[0]; r1 = r[1];
r2 = m_r[2]; r3 = m_r[3]; r2 = r[2]; r3 = r[3];
s1 = r1 + (r1 >> 2); s1 = r1 + (r1 >> 2);
s2 = r2 + (r2 >> 2); s2 = r2 + (r2 >> 2);
s3 = r3 + (r3 >> 2); s3 = r3 + (r3 >> 2);
h0 = m_h[0]; h1 = m_h[1]; h2 = m_h[2]; h0 = h[0]; h1 = h[1]; h2 = h[2];
h3 = m_h[3]; h4 = m_h[4]; h3 = h[3]; h4 = h[4];
while (length >= BLOCKSIZE) while (length >= 16)
{ {
// h += m[i] // h += m[i]
h0 = (word32)(d0 = (word64)h0 + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 0)); 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)); h3 += (c = CONSTANT_TIME_CARRY(h2,c));
h4 += CONSTANT_TIME_CARRY(h3,c); h4 += CONSTANT_TIME_CARRY(h3,c);
input += BLOCKSIZE; input += 16;
length -= BLOCKSIZE; length -= 16;
} }
m_h[0] = h0; m_h[1] = h1; m_h[2] = h2; h[0] = h0; h[1] = h1; h[2] = h2;
m_h[3] = h3; m_h[4] = h4; h[3] = h3; h[4] = h4;
} }
template <class T> void Poly1305_HashFinal(word32 h[5], word32 n[4], byte *mac, size_t size)
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)
{ {
word32 h0, h1, h2, h3, h4; word32 h0, h1, h2, h3, h4;
word32 g0, g1, g2, g3, g4; word32 g0, g1, g2, g3, g4;
word32 mask; word32 mask;
word64 t; word64 t;
h0 = m_h[0]; h0 = h[0];
h1 = m_h[1]; h1 = h[1];
h2 = m_h[2]; h2 = h[2];
h3 = m_h[3]; h3 = h[3];
h4 = m_h[4]; h4 = h[4];
// compare to modulus by computing h + -p // compare to modulus by computing h + -p
g0 = (word32)(t = (word64)h0 + 5); 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; h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3;
// mac = (h + nonce) % (2^128) // mac = (h + nonce) % (2^128)
h0 = (word32)(t = (word64)h0 + m_n[0]); h0 = (word32)(t = (word64)h0 + n[0]);
h1 = (word32)(t = (word64)h1 + (t >> 32) + m_n[1]); h1 = (word32)(t = (word64)h1 + (t >> 32) + n[1]);
h2 = (word32)(t = (word64)h2 + (t >> 32) + m_n[2]); h2 = (word32)(t = (word64)h2 + (t >> 32) + n[2]);
h3 = (word32)(t = (word64)h3 + (t >> 32) + m_n[3]); 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 + 0, h0);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 4, h1); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 4, h1);
@ -237,21 +151,150 @@ void Poly1305_Base<T>::HashFinal(byte *mac, size_t size)
} }
else 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 + 0, h0);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, m + 4, h1); 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 + 8, h2);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, m + 12, h3); 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> template <class T>
void Poly1305_Base<T>::Resynchronize(const byte *nonce, int nonceLength) void Poly1305_Base<T>::Resynchronize(const byte *nonce, int nonceLength)
{ {
CRYPTOPP_ASSERT(nonceLength == -1 || nonceLength == (int)BLOCKSIZE); CRYPTOPP_ASSERT(nonceLength == -1 || nonceLength == (int)BLOCKSIZE);
nonceLength == -1 ? nonceLength = BLOCKSIZE : nonceLength; 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> template <class T>
@ -264,7 +307,93 @@ template <class T>
void Poly1305_Base<T>::Restart() void Poly1305_Base<T>::Restart()
{ {
m_h[0] = m_h[1] = m_h[2] = m_h[3] = m_h[4] = 0; 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; 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 // 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 /// \file poly1305.h
/// \brief Classes for Poly1305 message authentication code /// \brief Classes for Poly1305 message authentication code
/// \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide /// \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 /// 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. /// 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 Crypto++ also supplies the IETF's version of Poly1305. It is a slightly different
/// must be changed after each message. It can be accomplished in one of two ways. First, you /// algorithm than Bernstein's version.
/// 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>
/// \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES /// \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> /// 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 #ifndef CRYPTOPP_POLY1305_H
#define CRYPTOPP_POLY1305_H #define CRYPTOPP_POLY1305_H
@ -52,8 +33,11 @@
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
////////////////////////////// Bernstein Poly1305 //////////////////////////////
/// \brief Poly1305 message authentication code base class /// \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 /// \since Crypto++ 6.0
template <class T> template <class T>
class CRYPTOPP_NO_VTABLE Poly1305_Base : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 16>, public MessageAuthenticationCode 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(DIGESTSIZE=T::BLOCKSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE) CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
virtual ~Poly1305_Base() {}
Poly1305_Base() : m_idx(0), m_used(true) {} Poly1305_Base() : m_idx(0), m_used(true) {}
void Resynchronize (const byte *iv, int ivLength=-1); void Resynchronize (const byte *iv, int ivLength=-1);
@ -83,6 +68,7 @@ public:
std::string AlgorithmProvider() const; std::string AlgorithmProvider() const;
protected: protected:
// TODO: No longer needed. Remove at next major version bump
void HashBlocks(const byte *input, size_t length, word32 padbit); void HashBlocks(const byte *input, size_t length, word32 padbit);
void HashFinal(byte *mac, size_t length); 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 /// \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 /// 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. /// 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 /// 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); /// <pre> SecByteBlock key(32), nonce(16);
/// prng.GenerateBlock(key, key.size()); /// prng.GenerateBlock(key, key.size());
/// prng.GenerateBlock(nonce, nonce.size()); /// prng.GenerateBlock(nonce, nonce.size());
@ -118,8 +108,7 @@ protected:
/// poly1305.Final(...);</pre> /// poly1305.Final(...);</pre>
/// ///
/// \details Second, you can create a Poly1305 object, reuse the key, and set a fresh nonce /// \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 /// for each message. The second and subsequent nonces can be generated using GetNextIV().
/// RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
/// <pre> SecByteBlock key(32), nonce(16); /// <pre> SecByteBlock key(32), nonce(16);
/// prng.GenerateBlock(key, key.size()); /// prng.GenerateBlock(key, key.size());
/// prng.GenerateBlock(nonce, nonce.size()); /// prng.GenerateBlock(nonce, nonce.size());
@ -136,8 +125,9 @@ protected:
/// poly1305.Update(...); /// poly1305.Update(...);
/// poly1305.Final(...); /// poly1305.Final(...);
/// ...</pre> /// ...</pre>
/// \warning The Poly1305 class does not enforce a fresh nonce for each message. The source code /// \warning Each message must have a unique security context. The Poly1305 class does not
/// will assert in debug builds to alert of nonce reuse. No action is taken in release builds. /// 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 /// \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> and Andy Polyakov <A
/// HREF="http://www.openssl.org/blog/blog/2016/02/15/poly1305-revised/">Poly1305 Revised</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 keyLength the size of the byte array, in bytes
/// \param nonce a byte array used to key the cipher /// \param nonce a byte array used to key the cipher
/// \param nonceLength the size of the byte array, in bytes /// \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 /// \details The key is 32 bytes and a concatenation <tt>key = {k,s}</tt>, where
/// bytes used for <tt>r</tt>. /// <tt>k</tt> is the AES key and <tt>r</tt> is additional key that gets clamped.
/// \details Each message requires a unique security context. You can use GetNextIV() and /// The key is clamped internally so there is no need to perform the operation
/// Resynchronize() to set a new nonce under a key for a message. /// 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) 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)));} {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 NAMESPACE_END
#endif // CRYPTOPP_POLY1305_H #endif // CRYPTOPP_POLY1305_H

View File

@ -39,9 +39,10 @@
/// builtins. When using XLC with -qxlcompatmacros the compiler pretends to /// 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 /// be GCC, Clang and XLC all at once but it can only consume it's variety
/// of builtins. /// of builtins.
/// \details At Crypto++ 8.0 the various VectorFunc{Name} were renamed to /// \details At Crypto++ 8.0 the various <tt>Vector{FuncName}</tt> were
/// VecFunc{Name}. For example, VectorAnd was changed to VecAnd. The name /// renamed to <tt>Vec{FuncName}</tt>. For example, <tt>VectorAnd</tt> was
/// change helped consolidate two slightly different implementations. /// 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 /// \since Crypto++ 6.0, LLVM Clang compiler support since Crypto++ 8.0
// Use __ALTIVEC__, _ARCH_PWR7 and _ARCH_PWR8 when detecting actual // Use __ALTIVEC__, _ARCH_PWR7 and _ARCH_PWR8 when detecting actual
@ -175,7 +176,8 @@ inline T VecReverse(const T data)
#endif #endif
} }
//////////////////////// Loads //////////////////////// /// \name LOAD OPERATIONS
//@{
/// \brief Loads a vector from a byte array /// \brief Loads a vector from a byte array
/// \param src the byte array /// \param src the byte array
@ -503,7 +505,10 @@ inline uint32x4_p VecLoadBE(int off, const byte src[16])
#endif // _ARCH_PWR7 #endif // _ARCH_PWR7
} }
//////////////////////// Stores //////////////////////// //@}
/// \name STORE OPERATIONS
//@{
/// \brief Stores a vector to a byte array /// \brief Stores a vector to a byte array
/// \tparam T vector type /// \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); return VecStoreBE((uint8x16_p)data, off, (byte*)dest);
} }
//////////////////////// Miscellaneous //////////////////////// //@}
/// \brief Permutes a vector /// \name LOGICAL OPERATIONS
/// \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 AND two vectors /// \brief AND two vectors
/// \tparam T1 vector type /// \tparam T1 vector type
@ -947,6 +918,11 @@ inline T1 VecXor(const T1 vec1, const T2 vec2)
return (T1)vec_xor(vec1, (T1)vec2); return (T1)vec_xor(vec1, (T1)vec2);
} }
//@}
/// \name ARITHMETIC OPERATIONS
//@{
/// \brief Add two vectors /// \brief Add two vectors
/// \tparam T1 vector type /// \tparam T1 vector type
/// \tparam T2 vector type /// \tparam T2 vector type
@ -1013,6 +989,48 @@ inline uint32x4_p VecAdd64(const uint32x4_p& vec1, const uint32x4_p& vec2)
#endif #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 /// \brief Shift a vector left
/// \tparam C shift byte count /// \tparam C shift byte count
/// \tparam T vector type /// \tparam T vector type
@ -1172,6 +1190,49 @@ inline uint32x4_p VecRotateLeft(const uint32x4_p vec)
return vec_rl(vec, m); 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) #if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief Rotate a packed vector left /// \brief Rotate a packed vector left
@ -1190,6 +1251,22 @@ inline uint64x2_p VecRotateLeft(const uint64x2_p vec)
return vec_rl(vec, m); 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 #endif
/// \brief Rotate a packed vector right /// \brief Rotate a packed vector right
@ -1207,6 +1284,21 @@ inline uint32x4_p VecRotateRight(const uint32x4_p vec)
return vec_rl(vec, m); 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) #if defined(_ARCH_PWR8) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
/// \brief Rotate a packed vector right /// \brief Rotate a packed vector right
@ -1225,6 +1317,22 @@ inline uint64x2_p VecRotateRight(const uint64x2_p vec)
return vec_rl(vec, m); 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 #endif
/// \brief Exchange high and low double words /// \brief Exchange high and low double words
@ -1254,10 +1362,12 @@ inline T VecSwapWords(const T vec)
template <class T> template <class T>
inline T VecGetLow(const T val) inline T VecGetLow(const T val)
{ {
//const T zero = {0}; #if (CRYPTOPP_BIG_ENDIAN) && (_ARCH_PWR8)
//const uint8x16_p mask = {16,16,16,16, 16,16,16,16, 8,9,10,11, 12,13,14,15 }; const T zero = {0};
//return (T)vec_perm(zero, val, mask); return (T)VecMergeLow((uint64x2_p)zero, (uint64x2_p)val);
#else
return VecShiftRightOctet<8>(VecShiftLeftOctet<8>(val)); return VecShiftRightOctet<8>(VecShiftLeftOctet<8>(val));
#endif
} }
/// \brief Extract a dword from a vector /// \brief Extract a dword from a vector
@ -1274,10 +1384,12 @@ inline T VecGetLow(const T val)
template <class T> template <class T>
inline T VecGetHigh(const T val) inline T VecGetHigh(const T val)
{ {
//const T zero = {0}; #if (CRYPTOPP_BIG_ENDIAN) && (_ARCH_PWR8)
//const uint8x16_p mask = {16,16,16,16, 16,16,16,16, 0,1,2,3, 4,5,6,7 }; const T zero = {0};
//return (T)vec_perm(zero, val, mask); return (T)VecMergeHigh((uint64x2_p)zero, (uint64x2_p)val);
#else
return VecShiftRightOctet<8>(val); return VecShiftRightOctet<8>(val);
#endif
} }
/// \brief Compare two vectors /// \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); return 0 == vec_all_eq((uint32x4_p)vec1, (uint32x4_p)vec2);
} }
//@}
//////////////////////// Power8 Crypto //////////////////////// //////////////////////// Power8 Crypto ////////////////////////
#if defined(__CRYPTO__) || defined(CRYPTOPP_DOXYGEN_PROCESSING) #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 /// \brief One round of AES encryption
/// \tparam T1 vector type /// \tparam T1 vector type
/// \tparam T2 vector type /// \tparam T2 vector type
@ -1418,6 +1678,11 @@ inline T1 VecDecryptLast(const T1 state, const T2 key)
#endif #endif
} }
//@}
/// \name SHA DIGESTS
//@{
/// \brief SHA256 Sigma functions /// \brief SHA256 Sigma functions
/// \tparam func function /// \tparam func function
/// \tparam fmask function mask /// \tparam fmask function mask
@ -1468,6 +1733,8 @@ inline T VecSHA512(const T vec)
#endif #endif
} }
//@}
#endif // __CRYPTO__ #endif // __CRYPTO__
#endif // _ALTIVEC_ #endif // _ALTIVEC_

View File

@ -379,7 +379,7 @@ public:
{ {
static HashIdentifier CRYPTOPP_API Lookup() 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) # if defined(CRYPTOPP_MSC_VERSION)
# define MASM_RDRAND_ASM_AVAILABLE 1 # define MASM_RDRAND_ASM_AVAILABLE 1
@ -54,7 +54,7 @@ extern "C" void CRYPTOPP_FASTCALL MASM_RDSEED_GenerateBlock(byte*, size_t);
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
#if defined(CRYPTOPP_CPUID_AVAILABLE) #if defined(CRYPTOPP_CPUID_AVAILABLE) && !defined(CRYPTOPP_DISABLE_ASM)
// Fills 4 bytes // Fills 4 bytes
inline void RDRAND32(void* output) inline void RDRAND32(void* output)

View File

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

View File

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

View File

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

View File

@ -23,15 +23,20 @@
#include "pch.h" #include "pch.h"
#include "config.h" #include "config.h"
#include "misc.h" #include "misc.h"
#include "adv_simd.h"
#if (CRYPTOPP_AESNI_AVAILABLE) #if (CRYPTOPP_AESNI_AVAILABLE)
# include "adv_simd.h"
# include <emmintrin.h>
# include <smmintrin.h> # include <smmintrin.h>
# include <wmmintrin.h> # include <wmmintrin.h>
#endif #endif
// C1189: error: This header is specific to ARM targets
#if (CRYPTOPP_ARM_NEON_AVAILABLE) #if (CRYPTOPP_ARM_NEON_AVAILABLE)
# include <arm_neon.h> # include "adv_simd.h"
# ifndef _M_ARM64
# include <arm_neon.h>
# endif
#endif #endif
#if (CRYPTOPP_ARM_ACLE_AVAILABLE) #if (CRYPTOPP_ARM_ACLE_AVAILABLE)
@ -40,6 +45,7 @@
#endif #endif
#if defined(CRYPTOPP_POWER8_AES_AVAILABLE) #if defined(CRYPTOPP_POWER8_AES_AVAILABLE)
# include "adv_simd.h"
# include "ppc_simd.h" # include "ppc_simd.h"
#endif #endif
@ -191,7 +197,7 @@ static inline void ARMV8_Enc_6_Blocks(uint64x2_t &data0, uint64x2_t &data1,
uint8x16_t key; uint8x16_t key;
for (unsigned int i=0; i<rounds-1; ++i) 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 // AES single round encryption
block0 = vaeseq_u8(block0, key); block0 = vaeseq_u8(block0, key);
// AES mix columns // 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]); 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) for (size_t i = 0; i < 16; ++i)
data[i] += x[i]; data[i] += x[i];
#else #else
#pragma omp simd
for (size_t i = 0; i < 16; ++i) for (size_t i = 0; i < 16; ++i)
data[i] += x[i]; data[i] += x[i];
#endif #endif
@ -111,10 +112,13 @@ std::string Salsa20_Policy::AlgorithmProvider() const
void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) 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)) // Latch a good value
throw InvalidRounds(Salsa20::StaticAlgorithmName(), m_rounds); m_rounds = rounds;
// m_state is reordered for SSE2 // m_state is reordered for SSE2
GetBlock<word32, LittleEndian> get1(key); 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) 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)) if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds); 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> class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{ {
protected: protected:
Salsa20_Policy() : m_rounds(ROUNDS) {}
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length); void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
@ -49,6 +50,7 @@ protected:
std::string AlgorithmProvider() const; std::string AlgorithmProvider() const;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
FixedSizeAlignedSecBlock<word32, 16> m_state; FixedSizeAlignedSecBlock<word32, 16> m_state;
int m_rounds; int m_rounds;
}; };

View File

@ -20,6 +20,15 @@
# include <omp.h> # include <omp.h>
#endif #endif
// https://github.com/weidai11/cryptopp/issues/777
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
# if defined(__clang__)
# pragma GCC diagnostic ignored "-Wtautological-compare"
# elif defined(__GNUC__)
# pragma GCC diagnostic ignored "-Wtype-limits"
# endif
#endif
ANONYMOUS_NAMESPACE_BEGIN ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::byte; using CryptoPP::byte;
@ -32,40 +41,48 @@ using CryptoPP::rotlConstant;
using CryptoPP::LITTLE_ENDIAN_ORDER; using CryptoPP::LITTLE_ENDIAN_ORDER;
using CryptoPP::AlignedSecByteBlock; using CryptoPP::AlignedSecByteBlock;
static inline void LE32ENC(byte* out, word32 in) inline void LE32ENC(byte* out, word32 in)
{ {
PutWord(false, LITTLE_ENDIAN_ORDER, out, in); PutWord(false, LITTLE_ENDIAN_ORDER, out, in);
} }
static inline word32 LE32DEC(const byte* in) inline word32 LE32DEC(const byte* in)
{ {
return GetWord<word32>(false, LITTLE_ENDIAN_ORDER, in); return GetWord<word32>(false, LITTLE_ENDIAN_ORDER, in);
} }
static inline word64 LE64DEC(const byte* in) inline word64 LE64DEC(const byte* in)
{ {
return GetWord<word64>(false, LITTLE_ENDIAN_ORDER, in); return GetWord<word64>(false, LITTLE_ENDIAN_ORDER, in);
} }
static inline void BlockCopy(byte* dest, byte* src, size_t len) inline void BlockCopy(byte* dest, byte* src, size_t len)
{ {
// OpenMP 4.0 released July 2013.
#if _OPENMP >= 201307
#pragma omp simd
for (size_t i = 0; i < len; ++i) for (size_t i = 0; i < len; ++i)
dest[i] = src[i]; dest[i] = src[i];
#else
for (size_t i = 0; i < len; ++i)
dest[i] = src[i];
#endif
} }
static inline void BlockXOR(byte* dest, byte* src, size_t len) inline void BlockXOR(byte* dest, byte* src, size_t len)
{ {
#ifdef _MSC_VER // OpenMP 4.0 released July 2013.
#if _OPENMP >= 201307
#pragma omp simd
for (size_t i = 0; i < len; ++i) for (size_t i = 0; i < len; ++i)
dest[i] ^= src[i]; dest[i] ^= src[i];
#else #else
#pragma omp simd
for (size_t i = 0; i < len; ++i) for (size_t i = 0; i < len; ++i)
dest[i] ^= src[i]; dest[i] ^= src[i];
#endif #endif
} }
static inline void PBKDF2_SHA256(byte* buf, size_t dkLen, inline void PBKDF2_SHA256(byte* buf, size_t dkLen,
const byte* passwd, size_t passwdlen, const byte* passwd, size_t passwdlen,
const byte* salt, size_t saltlen, byte count) const byte* salt, size_t saltlen, byte count)
{ {
@ -76,7 +93,7 @@ static inline void PBKDF2_SHA256(byte* buf, size_t dkLen,
pbkdf.DeriveKey(buf, dkLen, 0, passwd, passwdlen, salt, saltlen, count, 0.0f); pbkdf.DeriveKey(buf, dkLen, 0, passwd, passwdlen, salt, saltlen, count, 0.0f);
} }
static inline void Salsa20_8(byte B[64]) inline void Salsa20_8(byte B[64])
{ {
word32 B32[16]; word32 B32[16];
@ -89,7 +106,7 @@ static inline void Salsa20_8(byte B[64])
LE32ENC(&B[4 * i], B32[i]); LE32ENC(&B[4 * i], B32[i]);
} }
static inline void BlockMix(byte* B, byte* Y, size_t r) inline void BlockMix(byte* B, byte* Y, size_t r)
{ {
byte X[64]; byte X[64];
@ -115,13 +132,13 @@ static inline void BlockMix(byte* B, byte* Y, size_t r)
BlockCopy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64); BlockCopy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);
} }
static inline word64 Integerify(byte* B, size_t r) inline word64 Integerify(byte* B, size_t r)
{ {
byte* X = &B[(2 * r - 1) * 64]; byte* X = &B[(2 * r - 1) * 64];
return LE64DEC(X); return LE64DEC(X);
} }
static inline void Smix(byte* B, size_t r, word64 N, byte* V, byte* XY) inline void Smix(byte* B, size_t r, word64 N, byte* V, byte* XY)
{ {
byte* X = XY; byte* X = XY;
byte* Y = XY+128*r; byte* Y = XY+128*r;

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