commit
437a9c8d1f
|
@ -7,3 +7,6 @@
|
||||||
[submodule "MCServer/Plugins/TransAPI"]
|
[submodule "MCServer/Plugins/TransAPI"]
|
||||||
path = MCServer/Plugins/TransAPI
|
path = MCServer/Plugins/TransAPI
|
||||||
url = https://github.com/bearbin/transapi.git
|
url = https://github.com/bearbin/transapi.git
|
||||||
|
[submodule "lib/polarssl"]
|
||||||
|
path = lib/polarssl
|
||||||
|
url = https://github.com/polarssl/polarssl
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
cmake_minimum_required (VERSION 2.6)
|
cmake_minimum_required (VERSION 2.6)
|
||||||
|
|
||||||
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
||||||
|
@ -92,12 +91,6 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Under clang, we need to disable ASM support in CryptoPP:
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
add_definitions(-DCRYPTOPP_DISABLE_ASM)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
# Under Windows, we need Lua as DLL; on *nix we need it linked statically:
|
# Under Windows, we need Lua as DLL; on *nix we need it linked statically:
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_definitions(-DLUA_BUILD_AS_DLL)
|
add_definitions(-DLUA_BUILD_AS_DLL)
|
||||||
|
@ -183,7 +176,6 @@ project (MCServer)
|
||||||
# Include all the libraries:
|
# Include all the libraries:
|
||||||
add_subdirectory(lib/inifile/)
|
add_subdirectory(lib/inifile/)
|
||||||
add_subdirectory(lib/jsoncpp/)
|
add_subdirectory(lib/jsoncpp/)
|
||||||
add_subdirectory(lib/cryptopp/)
|
|
||||||
add_subdirectory(lib/zlib/)
|
add_subdirectory(lib/zlib/)
|
||||||
add_subdirectory(lib/lua/)
|
add_subdirectory(lib/lua/)
|
||||||
add_subdirectory(lib/tolua++/)
|
add_subdirectory(lib/tolua++/)
|
||||||
|
@ -192,6 +184,12 @@ add_subdirectory(lib/expat/)
|
||||||
add_subdirectory(lib/luaexpat/)
|
add_subdirectory(lib/luaexpat/)
|
||||||
add_subdirectory(lib/md5/)
|
add_subdirectory(lib/md5/)
|
||||||
|
|
||||||
|
|
||||||
|
# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
|
||||||
|
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
|
||||||
|
add_subdirectory(lib/polarssl/ EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
|
||||||
# Remove disabling the maximum warning level:
|
# Remove disabling the maximum warning level:
|
||||||
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
|
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
|
||||||
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
|
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
|
||||||
|
|
|
@ -63,9 +63,11 @@ endif()
|
||||||
|
|
||||||
# Set include paths to the used libraries:
|
# Set include paths to the used libraries:
|
||||||
include_directories("../../lib")
|
include_directories("../../lib")
|
||||||
|
include_directories("../../lib/polarssl/include")
|
||||||
include_directories("../../src")
|
include_directories("../../src")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function(flatten_files arg1)
|
function(flatten_files arg1)
|
||||||
set(res "")
|
set(res "")
|
||||||
foreach(f ${${arg1}})
|
foreach(f ${${arg1}})
|
||||||
|
@ -77,11 +79,11 @@ endfunction()
|
||||||
|
|
||||||
|
|
||||||
# Include the libraries:
|
# Include the libraries:
|
||||||
file(GLOB CRYPTOPP_SRC "../../lib/cryptopp/*.cpp")
|
file(GLOB POLARSSL_SRC "../../lib/polarssl/library/*.c")
|
||||||
file(GLOB CRYPTOPP_HDR "../../lib/cryptopp/*.h")
|
file(GLOB POLARSSL_HDR "../../lib/polarssl/include/polarssl/*.h")
|
||||||
flatten_files(CRYPTOPP_SRC)
|
flatten_files(POLARSSL_SRC)
|
||||||
flatten_files(CRYPTOPP_HDR)
|
flatten_files(POLARSSL_HDR)
|
||||||
source_group("CryptoPP" FILES ${CRYPTOPP_SRC} ${CRYPTOPP_HDR})
|
source_group("PolarSSL" FILES ${POLARSSL_SRC} ${POLARSSL_HDR})
|
||||||
|
|
||||||
file(GLOB ZLIB_SRC "../../lib/zlib/*.c")
|
file(GLOB ZLIB_SRC "../../lib/zlib/*.c")
|
||||||
file(GLOB ZLIB_HDR "../../lib/zlib/*.h")
|
file(GLOB ZLIB_HDR "../../lib/zlib/*.h")
|
||||||
|
@ -96,12 +98,14 @@ set(SHARED_SRC
|
||||||
../../src/StringUtils.cpp
|
../../src/StringUtils.cpp
|
||||||
../../src/Log.cpp
|
../../src/Log.cpp
|
||||||
../../src/MCLogger.cpp
|
../../src/MCLogger.cpp
|
||||||
|
../../src/Crypto.cpp
|
||||||
)
|
)
|
||||||
set(SHARED_HDR
|
set(SHARED_HDR
|
||||||
../../src/ByteBuffer.h
|
../../src/ByteBuffer.h
|
||||||
../../src/StringUtils.h
|
../../src/StringUtils.h
|
||||||
../../src/Log.h
|
../../src/Log.h
|
||||||
../../src/MCLogger.h
|
../../src/MCLogger.h
|
||||||
|
../../src/Crypto.h
|
||||||
)
|
)
|
||||||
set(SHARED_OSS_SRC
|
set(SHARED_OSS_SRC
|
||||||
../../src/OSSupport/CriticalSection.cpp
|
../../src/OSSupport/CriticalSection.cpp
|
||||||
|
@ -145,8 +149,8 @@ add_executable(ProtoProxy
|
||||||
${SHARED_HDR}
|
${SHARED_HDR}
|
||||||
${SHARED_OSS_SRC}
|
${SHARED_OSS_SRC}
|
||||||
${SHARED_OSS_HDR}
|
${SHARED_OSS_HDR}
|
||||||
${CRYPTOPP_SRC}
|
${POLARSSL_SRC}
|
||||||
${CRYPTOPP_HDR}
|
${POLARSSL_HDR}
|
||||||
${ZLIB_SRC}
|
${ZLIB_SRC}
|
||||||
${ZLIB_HDR}
|
${ZLIB_HDR}
|
||||||
)
|
)
|
||||||
|
|
|
@ -378,13 +378,13 @@ bool cConnection::RelayFromServer(void)
|
||||||
}
|
}
|
||||||
case csEncryptedUnderstood:
|
case csEncryptedUnderstood:
|
||||||
{
|
{
|
||||||
m_ServerDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
m_ServerDecryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
||||||
return DecodeServersPackets(Buffer, res);
|
return DecodeServersPackets(Buffer, res);
|
||||||
}
|
}
|
||||||
case csEncryptedUnknown:
|
case csEncryptedUnknown:
|
||||||
{
|
{
|
||||||
m_ServerDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
m_ServerDecryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
||||||
return CLIENTSEND(Buffer, res);
|
return CLIENTSEND(Buffer, res);
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ bool cConnection::RelayFromClient(void)
|
||||||
case csEncryptedUnknown:
|
case csEncryptedUnknown:
|
||||||
{
|
{
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
|
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
|
||||||
m_ServerEncryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
m_ServerEncryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
|
||||||
return SERVERSEND(Buffer, res);
|
return SERVERSEND(Buffer, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,13 +473,13 @@ bool cConnection::SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, const char * a_Data, int a_Size, const char * a_Peer)
|
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, int a_Size, const char * a_Peer)
|
||||||
{
|
{
|
||||||
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
|
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
|
||||||
const byte * Data = (const byte *)a_Data;
|
const Byte * Data = (const Byte *)a_Data;
|
||||||
while (a_Size > 0)
|
while (a_Size > 0)
|
||||||
{
|
{
|
||||||
byte Buffer[64 KiB];
|
Byte Buffer[64 KiB];
|
||||||
int NumBytes = (a_Size > sizeof(Buffer)) ? sizeof(Buffer) : a_Size;
|
int NumBytes = (a_Size > sizeof(Buffer)) ? sizeof(Buffer) : a_Size;
|
||||||
a_Encryptor.ProcessData(Buffer, Data, NumBytes);
|
a_Encryptor.ProcessData(Buffer, Data, NumBytes);
|
||||||
bool res = SendData(a_Socket, (const char *)Buffer, NumBytes, a_Peer);
|
bool res = SendData(a_Socket, (const char *)Buffer, NumBytes, a_Peer);
|
||||||
|
@ -497,7 +497,7 @@ bool cConnection::SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, co
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
|
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
|
||||||
{
|
{
|
||||||
AString All;
|
AString All;
|
||||||
a_Data.ReadAll(All);
|
a_Data.ReadAll(All);
|
||||||
|
@ -2701,7 +2701,7 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
||||||
int Length = 0;
|
int Length = 0;
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case 0: Length = 1; break; // byte
|
case 0: Length = 1; break; // Byte
|
||||||
case 1: Length = 2; break; // short
|
case 1: Length = 2; break; // short
|
||||||
case 2: Length = 4; break; // int
|
case 2: Length = 4; break; // int
|
||||||
case 3: Length = 4; break; // float
|
case 3: Length = 4; break; // float
|
||||||
|
@ -2860,37 +2860,26 @@ void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
|
||||||
void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, const AString & a_Nonce)
|
void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, const AString & a_Nonce)
|
||||||
{
|
{
|
||||||
// Generate the shared secret and encrypt using the server's public key
|
// Generate the shared secret and encrypt using the server's public key
|
||||||
byte SharedSecret[16];
|
Byte SharedSecret[16];
|
||||||
byte EncryptedSecret[128];
|
Byte EncryptedSecret[128];
|
||||||
memset(SharedSecret, 0, sizeof(SharedSecret)); // Use all zeroes for the initial secret
|
memset(SharedSecret, 0, sizeof(SharedSecret)); // Use all zeroes for the initial secret
|
||||||
RSA::PublicKey pk;
|
m_Server.GetPrivateKey().Encrypt(SharedSecret, sizeof(SharedSecret), EncryptedSecret, sizeof(EncryptedSecret));
|
||||||
CryptoPP::StringSource src(a_ServerPublicKey, true);
|
|
||||||
ByteQueue bq;
|
m_ServerEncryptor.Init(SharedSecret, SharedSecret);
|
||||||
src.TransferTo(bq);
|
m_ServerDecryptor.Init(SharedSecret, SharedSecret);
|
||||||
bq.MessageEnd();
|
|
||||||
pk.Load(bq);
|
|
||||||
RSAES<PKCS1v15>::Encryptor rsaEncryptor(pk);
|
|
||||||
RandomPool rng;
|
|
||||||
time_t CurTime = time(NULL);
|
|
||||||
rng.Put((const byte *)&CurTime, sizeof(CurTime));
|
|
||||||
int EncryptedLength = rsaEncryptor.FixedCiphertextLength();
|
|
||||||
ASSERT(EncryptedLength <= sizeof(EncryptedSecret));
|
|
||||||
rsaEncryptor.Encrypt(rng, SharedSecret, sizeof(SharedSecret), EncryptedSecret);
|
|
||||||
m_ServerEncryptor.SetKey(SharedSecret, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(SharedSecret, 16, true))(Name::FeedbackSize(), 1));
|
|
||||||
m_ServerDecryptor.SetKey(SharedSecret, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(SharedSecret, 16, true))(Name::FeedbackSize(), 1));
|
|
||||||
|
|
||||||
// Encrypt the nonce:
|
// Encrypt the nonce:
|
||||||
byte EncryptedNonce[128];
|
Byte EncryptedNonce[128];
|
||||||
rsaEncryptor.Encrypt(rng, (const byte *)(a_Nonce.data()), a_Nonce.size(), EncryptedNonce);
|
m_Server.GetPrivateKey().Encrypt((const Byte *)a_Nonce.data(), a_Nonce.size(), EncryptedNonce, sizeof(EncryptedNonce));
|
||||||
|
|
||||||
// Send the packet to the server:
|
// Send the packet to the server:
|
||||||
Log("Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER");
|
Log("Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER");
|
||||||
cByteBuffer ToServer(1024);
|
cByteBuffer ToServer(1024);
|
||||||
ToServer.WriteByte(0x01); // To server: Encryption key response
|
ToServer.WriteByte(0x01); // To server: Encryption key response
|
||||||
ToServer.WriteBEShort(EncryptedLength);
|
ToServer.WriteBEShort((short)sizeof(EncryptedSecret));
|
||||||
ToServer.WriteBuf(EncryptedSecret, EncryptedLength);
|
ToServer.WriteBuf(EncryptedSecret, sizeof(EncryptedSecret));
|
||||||
ToServer.WriteBEShort(EncryptedLength);
|
ToServer.WriteBEShort((short)sizeof(EncryptedNonce));
|
||||||
ToServer.WriteBuf(EncryptedNonce, EncryptedLength);
|
ToServer.WriteBuf(EncryptedNonce, sizeof(EncryptedNonce));
|
||||||
SERVERSEND(ToServer);
|
SERVERSEND(ToServer);
|
||||||
m_ServerState = csEncryptedUnderstood;
|
m_ServerState = csEncryptedUnderstood;
|
||||||
m_IsServerEncrypted = true;
|
m_IsServerEncrypted = true;
|
||||||
|
|
|
@ -62,14 +62,12 @@ public:
|
||||||
void LogFlush(void);
|
void LogFlush(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef CFB_Mode<AES>::Encryption Encryptor;
|
|
||||||
typedef CFB_Mode<AES>::Decryption Decryptor;
|
|
||||||
|
|
||||||
cByteBuffer m_ClientBuffer;
|
cByteBuffer m_ClientBuffer;
|
||||||
cByteBuffer m_ServerBuffer;
|
cByteBuffer m_ServerBuffer;
|
||||||
|
|
||||||
Decryptor m_ServerDecryptor;
|
cAESCFBDecryptor m_ServerDecryptor;
|
||||||
Encryptor m_ServerEncryptor;
|
cAESCFBEncryptor m_ServerEncryptor;
|
||||||
|
|
||||||
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
|
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
|
||||||
|
|
||||||
|
@ -111,10 +109,10 @@ protected:
|
||||||
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
|
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
|
||||||
|
|
||||||
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
||||||
bool SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, const char * a_Data, int a_Size, const char * a_Peer);
|
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, int a_Size, const char * a_Peer);
|
||||||
|
|
||||||
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
||||||
bool SendEncryptedData(SOCKET a_Socket, Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
||||||
|
|
||||||
/// Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped
|
/// Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped
|
||||||
bool DecodeClientsPackets(const char * a_Data, int a_Size);
|
bool DecodeClientsPackets(const char * a_Data, int a_Size);
|
||||||
|
|
|
@ -74,6 +74,8 @@ typedef unsigned long long UInt64;
|
||||||
typedef unsigned int UInt32;
|
typedef unsigned int UInt32;
|
||||||
typedef unsigned short UInt16;
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
|
typedef unsigned char Byte;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,12 +225,8 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "cryptopp/randpool.h"
|
#include "../../src/Crypto.h"
|
||||||
#include "cryptopp/aes.h"
|
|
||||||
#include "cryptopp/rsa.h"
|
|
||||||
#include "cryptopp/modes.h"
|
|
||||||
|
|
||||||
using namespace CryptoPP;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,8 @@ int cServer::Init(short a_ListenPort, short a_ConnectPort)
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
printf("Generating protocol encryption keypair...\n");
|
printf("Generating protocol encryption keypair...\n");
|
||||||
time_t CurTime = time(NULL);
|
m_PrivateKey.Generate();
|
||||||
RandomPool rng;
|
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
|
||||||
rng.Put((const byte *)&CurTime, sizeof(CurTime));
|
|
||||||
m_PrivateKey.GenerateRandomWithKeySize(rng, 1024);
|
|
||||||
RSA::PublicKey pk(m_PrivateKey);
|
|
||||||
m_PublicKey = pk;
|
|
||||||
|
|
||||||
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
sockaddr_in local;
|
sockaddr_in local;
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
class cServer
|
class cServer
|
||||||
{
|
{
|
||||||
SOCKET m_ListenSocket;
|
SOCKET m_ListenSocket;
|
||||||
RSA::PrivateKey m_PrivateKey;
|
cRSAPrivateKey m_PrivateKey;
|
||||||
RSA::PublicKey m_PublicKey;
|
AString m_PublicKeyDER;
|
||||||
short m_ConnectPort;
|
short m_ConnectPort;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -27,8 +27,8 @@ public:
|
||||||
int Init(short a_ListenPort, short a_ConnectPort);
|
int Init(short a_ListenPort, short a_ConnectPort);
|
||||||
void Run(void);
|
void Run(void);
|
||||||
|
|
||||||
RSA::PrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||||
RSA::PublicKey & GetPublicKey (void) { return m_PublicKey; }
|
const AString & GetPublicKeyDER (void) { return m_PublicKeyDER; }
|
||||||
|
|
||||||
short GetConnectPort(void) const { return m_ConnectPort; }
|
short GetConnectPort(void) const { return m_ConnectPort; }
|
||||||
} ;
|
} ;
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
cmake_minimum_required (VERSION 2.6)
|
|
||||||
project (cryptopp)
|
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCRYPTOPP_DISABLE_ASM")
|
|
||||||
endif()
|
|
||||||
include_directories ("${PROJECT_SOURCE_DIR}/../../src/")
|
|
||||||
|
|
||||||
file(GLOB cryptopp_SRC
|
|
||||||
"*.cpp"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(cryptopp ${cryptopp_SRC})
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,51 +0,0 @@
|
||||||
Compilation Copyright (c) 1995-2013 by Wei Dai. All rights reserved.
|
|
||||||
This copyright applies only to this software distribution package
|
|
||||||
as a compilation, and does not imply a copyright on any particular
|
|
||||||
file in the package.
|
|
||||||
|
|
||||||
All individual files in this compilation are placed in the public domain by
|
|
||||||
Wei Dai and other contributors.
|
|
||||||
|
|
||||||
I would like to thank the following authors for placing their works into
|
|
||||||
the public domain:
|
|
||||||
|
|
||||||
Joan Daemen - 3way.cpp
|
|
||||||
Leonard Janke - cast.cpp, seal.cpp
|
|
||||||
Steve Reid - cast.cpp
|
|
||||||
Phil Karn - des.cpp
|
|
||||||
Andrew M. Kuchling - md2.cpp, md4.cpp
|
|
||||||
Colin Plumb - md5.cpp
|
|
||||||
Seal Woods - rc6.cpp
|
|
||||||
Chris Morgan - rijndael.cpp
|
|
||||||
Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp
|
|
||||||
Richard De Moliner - safer.cpp
|
|
||||||
Matthew Skala - twofish.cpp
|
|
||||||
Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp
|
|
||||||
Ronny Van Keer - sha3.cpp
|
|
||||||
|
|
||||||
The Crypto++ Library (as a compilation) is currently licensed under the Boost
|
|
||||||
Software License 1.0 (http://www.boost.org/users/license.html).
|
|
||||||
|
|
||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
|
||||||
obtaining a copy of the software and accompanying documentation covered by
|
|
||||||
this license (the "Software") to use, reproduce, display, distribute,
|
|
||||||
execute, and transmit the Software, and to prepare derivative works of the
|
|
||||||
Software, and to permit third-parties to whom the Software is furnished to
|
|
||||||
do so, all subject to the following:
|
|
||||||
|
|
||||||
The copyright notices in the Software and this entire statement, including
|
|
||||||
the above license grant, this restriction and the following disclaimer,
|
|
||||||
must be included in all copies of the Software, in whole or in part, and
|
|
||||||
all derivative works of the Software, unless such copies or derivative
|
|
||||||
works are solely in the form of machine-executable object code generated by
|
|
||||||
a source language processor.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,452 +0,0 @@
|
||||||
Crypto++: a C++ Class Library of Cryptographic Schemes
|
|
||||||
Version 5.6.2 - 2/20/2013
|
|
||||||
|
|
||||||
Crypto++ Library is a free C++ class library of cryptographic schemes.
|
|
||||||
Currently the library contains the following algorithms:
|
|
||||||
|
|
||||||
algorithm type name
|
|
||||||
|
|
||||||
authenticated encryption schemes GCM, CCM, EAX
|
|
||||||
|
|
||||||
high speed stream ciphers Panama, Sosemanuk, Salsa20, XSalsa20
|
|
||||||
|
|
||||||
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
|
|
||||||
CAST-256
|
|
||||||
|
|
||||||
IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
|
|
||||||
other block ciphers Camellia, SEED, RC5, Blowfish, TEA, XTEA,
|
|
||||||
Skipjack, SHACAL-2
|
|
||||||
|
|
||||||
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
|
|
||||||
CFB, OFB, counter mode (CTR)
|
|
||||||
|
|
||||||
message authentication codes VMAC, HMAC, GMAC, CMAC, CBC-MAC, DMAC,
|
|
||||||
Two-Track-MAC
|
|
||||||
|
|
||||||
SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and
|
|
||||||
hash functions SHA-512), SHA-3, Tiger, WHIRLPOOL, RIPEMD-128,
|
|
||||||
RIPEMD-256, RIPEMD-160, RIPEMD-320
|
|
||||||
|
|
||||||
RSA, DSA, ElGamal, Nyberg-Rueppel (NR),
|
|
||||||
public-key cryptography Rabin-Williams (RW), LUC, LUCELG,
|
|
||||||
DLIES (variants of DHAES), ESIGN
|
|
||||||
|
|
||||||
padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363
|
|
||||||
systems EMSA2 and EMSA5
|
|
||||||
|
|
||||||
Diffie-Hellman (DH), Unified Diffie-Hellman
|
|
||||||
key agreement schemes (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF,
|
|
||||||
XTR-DH
|
|
||||||
|
|
||||||
elliptic curve cryptography ECDSA, ECNR, ECIES, ECDH, ECMQV
|
|
||||||
|
|
||||||
insecure or obsolescent MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL
|
|
||||||
algorithms retained for backwards 3.0, WAKE-OFB, DESX (DES-XEX3), RC2,
|
|
||||||
compatibility and historical SAFER, 3-WAY, GOST, SHARK, CAST-128, Square
|
|
||||||
value
|
|
||||||
|
|
||||||
Other features include:
|
|
||||||
|
|
||||||
* pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool
|
|
||||||
* password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5,
|
|
||||||
PBKDF from PKCS #12 appendix B
|
|
||||||
* Shamir's secret sharing scheme and Rabin's information dispersal algorithm
|
|
||||||
(IDA)
|
|
||||||
* fast multi-precision integer (bignum) and polynomial operations
|
|
||||||
* finite field arithmetics, including GF(p) and GF(2^n)
|
|
||||||
* prime number generation and verification
|
|
||||||
* useful non-cryptographic algorithms
|
|
||||||
+ DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and
|
|
||||||
zlib (RFC 1950) format support
|
|
||||||
+ hex, base-32, and base-64 coding/decoding
|
|
||||||
+ 32-bit CRC and Adler32 checksum
|
|
||||||
* class wrappers for these operating system features (optional):
|
|
||||||
+ high resolution timers on Windows, Unix, and Mac OS
|
|
||||||
+ Berkeley and Windows style sockets
|
|
||||||
+ Windows named pipes
|
|
||||||
+ /dev/random, /dev/urandom, /dev/srandom
|
|
||||||
+ Microsoft's CryptGenRandom on Windows
|
|
||||||
* A high level interface for most of the above, using a filter/pipeline
|
|
||||||
metaphor
|
|
||||||
* benchmarks and validation testing
|
|
||||||
* x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used
|
|
||||||
algorithms, with run-time CPU feature detection and code selection
|
|
||||||
* some versions are available in FIPS 140-2 validated form
|
|
||||||
|
|
||||||
You are welcome to use it for any purpose without paying me, but see
|
|
||||||
License.txt for the fine print.
|
|
||||||
|
|
||||||
The following compilers are supported for this release. Please visit
|
|
||||||
http://www.cryptopp.com the most up to date build instructions and porting notes.
|
|
||||||
|
|
||||||
* MSVC 6.0 - 2010
|
|
||||||
* GCC 3.3 - 4.5
|
|
||||||
* C++Builder 2010
|
|
||||||
* Intel C++ Compiler 9 - 11.1
|
|
||||||
* Sun Studio 12u1, Express 11/08, Express 06/10
|
|
||||||
|
|
||||||
*** Important Usage Notes ***
|
|
||||||
|
|
||||||
1. If a constructor for A takes a pointer to an object B (except primitive
|
|
||||||
types such as int and char), then A owns B and will delete B at A's
|
|
||||||
destruction. If a constructor for A takes a reference to an object B,
|
|
||||||
then the caller retains ownership of B and should not destroy it until
|
|
||||||
A no longer needs it.
|
|
||||||
|
|
||||||
2. Crypto++ is thread safe at the class level. This means you can use
|
|
||||||
Crypto++ safely in a multithreaded application, but you must provide
|
|
||||||
synchronization when multiple threads access a common Crypto++ object.
|
|
||||||
|
|
||||||
*** MSVC-Specific Information ***
|
|
||||||
|
|
||||||
On Windows, Crypto++ can be compiled into 3 forms: a static library
|
|
||||||
including all algorithms, a DLL with only FIPS Approved algorithms, and
|
|
||||||
a static library with only algorithms not in the DLL.
|
|
||||||
(FIPS Approved means Approved according to the FIPS 140-2 standard.)
|
|
||||||
The DLL may be used by itself, or it may be used together with the second
|
|
||||||
form of the static library. MSVC project files are included to build
|
|
||||||
all three forms, and sample applications using each of the three forms
|
|
||||||
are also included.
|
|
||||||
|
|
||||||
To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET
|
|
||||||
2003) or "cryptest.sln" (for MSVC 2005 - 2010) workspace file and build one or
|
|
||||||
more of the following projects:
|
|
||||||
|
|
||||||
cryptopp - This builds the DLL. Please note that if you wish to use Crypto++
|
|
||||||
as a FIPS validated module, you must use a pre-built DLL that has undergone
|
|
||||||
the FIPS validation process instead of building your own.
|
|
||||||
dlltest - This builds a sample application that only uses the DLL.
|
|
||||||
cryptest Non-DLL-Import Configuration - This builds the full static library
|
|
||||||
along with a full test driver.
|
|
||||||
cryptest DLL-Import Configuration - This builds a static library containing
|
|
||||||
only algorithms not in the DLL, along with a full test driver that uses
|
|
||||||
both the DLL and the static library.
|
|
||||||
|
|
||||||
To use the Crypto++ DLL in your application, #include "dll.h" before including
|
|
||||||
any other Crypto++ header files, and place the DLL in the same directory as
|
|
||||||
your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp")
|
|
||||||
so you don't have to explicitly list the import library in your project
|
|
||||||
settings. To use a static library form of Crypto++, make the "cryptlib"
|
|
||||||
project a dependency of your application project, or specify it as
|
|
||||||
an additional library to link with in your project settings.
|
|
||||||
In either case you should check the compiler options to
|
|
||||||
make sure that the library and your application are using the same C++
|
|
||||||
run-time libraries and calling conventions.
|
|
||||||
|
|
||||||
*** DLL Memory Management ***
|
|
||||||
|
|
||||||
Because it's possible for the Crypto++ DLL to delete objects allocated
|
|
||||||
by the calling application, they must use the same C++ memory heap. Three
|
|
||||||
methods are provided to achieve this.
|
|
||||||
1. The calling application can tell Crypto++ what heap to use. This method
|
|
||||||
is required when the calling application uses a non-standard heap.
|
|
||||||
2. Crypto++ can tell the calling application what heap to use. This method
|
|
||||||
is required when the calling application uses a statically linked C++ Run
|
|
||||||
Time Library. (Method 1 does not work in this case because the Crypto++ DLL
|
|
||||||
is initialized before the calling application's heap is initialized.)
|
|
||||||
3. Crypto++ can automatically use the heap provided by the calling application's
|
|
||||||
dynamically linked C++ Run Time Library. The calling application must
|
|
||||||
make sure that the dynamically linked C++ Run Time Library is initialized
|
|
||||||
before Crypto++ is loaded. (At this time it is not clear if it is possible
|
|
||||||
to control the order in which DLLs are initialized on Windows 9x machines,
|
|
||||||
so it might be best to avoid using this method.)
|
|
||||||
|
|
||||||
When Crypto++ attaches to a new process, it searches all modules loaded
|
|
||||||
into the process space for exported functions "GetNewAndDeleteForCryptoPP"
|
|
||||||
and "SetNewAndDeleteFromCryptoPP". If one of these functions is found,
|
|
||||||
Crypto++ uses methods 1 or 2, respectively, by calling the function.
|
|
||||||
Otherwise, method 3 is used.
|
|
||||||
|
|
||||||
*** GCC-Specific Information ***
|
|
||||||
|
|
||||||
A makefile is included for you to compile Crypto++ with GCC. Make sure
|
|
||||||
you are using GNU Make and GNU ld. The make process will produce two files,
|
|
||||||
libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation
|
|
||||||
suite.
|
|
||||||
|
|
||||||
*** Documentation and Support ***
|
|
||||||
|
|
||||||
Crypto++ is documented through inline comments in header files, which are
|
|
||||||
processed through Doxygen to produce an HTML reference manual. You can find
|
|
||||||
a link to the manual from http://www.cryptopp.com. Also at that site is
|
|
||||||
the Crypto++ FAQ, which you should browse through before attempting to
|
|
||||||
use this library, because it will likely answer many of questions that
|
|
||||||
may come up.
|
|
||||||
|
|
||||||
If you run into any problems, please try the Crypto++ mailing list.
|
|
||||||
The subscription information and the list archive are available on
|
|
||||||
http://www.cryptopp.com. You can also email me directly by visiting
|
|
||||||
http://www.weidai.com, but you will probably get a faster response through
|
|
||||||
the mailing list.
|
|
||||||
|
|
||||||
*** History ***
|
|
||||||
|
|
||||||
1.0 - First public release. Withdrawn at the request of RSA DSI.
|
|
||||||
- included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA,
|
|
||||||
MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression
|
|
||||||
- had a serious bug in the RSA key generation code.
|
|
||||||
|
|
||||||
1.1 - Removed RSA, RC4, RC5
|
|
||||||
- Disabled calls to RSAREF's non-public functions
|
|
||||||
- Minor bugs fixed
|
|
||||||
|
|
||||||
2.0 - a completely new, faster multiprecision integer class
|
|
||||||
- added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser,
|
|
||||||
elliptic curve algorithms
|
|
||||||
- added the Lucas strong probable primality test
|
|
||||||
- ElGamal encryption and signature schemes modified to avoid weaknesses
|
|
||||||
- Diamond changed to Diamond2 because of key schedule weakness
|
|
||||||
- fixed bug in WAKE key setup
|
|
||||||
- SHS class renamed to SHA
|
|
||||||
- lots of miscellaneous optimizations
|
|
||||||
|
|
||||||
2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC,
|
|
||||||
OAEP, PSSR, SHARK
|
|
||||||
- added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms
|
|
||||||
- added back RC5 and a new RSA
|
|
||||||
- optimizations in elliptic curves over GF(p)
|
|
||||||
- changed Rabin to use OAEP and PSSR
|
|
||||||
- changed many classes to allow copy constructors to work correctly
|
|
||||||
- improved exception generation and handling
|
|
||||||
|
|
||||||
2.2 - added SEAL, CAST-128, Square
|
|
||||||
- fixed bug in HAVAL (padding problem)
|
|
||||||
- fixed bug in triple-DES (decryption order was reversed)
|
|
||||||
- fixed bug in RC5 (couldn't handle key length not a multiple of 4)
|
|
||||||
- changed HMAC to conform to RFC-2104 (which is not compatible
|
|
||||||
with the original HMAC)
|
|
||||||
- changed secret sharing and information dispersal to use GF(2^32)
|
|
||||||
instead of GF(65521)
|
|
||||||
- removed zero knowledge prover/verifier for graph isomorphism
|
|
||||||
- removed several utility classes in favor of the C++ standard library
|
|
||||||
|
|
||||||
2.3 - ported to EGCS
|
|
||||||
- fixed incomplete workaround of min/max conflict in MSVC
|
|
||||||
|
|
||||||
3.0 - placed all names into the "CryptoPP" namespace
|
|
||||||
- added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS
|
|
||||||
- added abstract base classes PK_SimpleKeyAgreementDomain and
|
|
||||||
PK_AuthenticatedKeyAgreementDomain
|
|
||||||
- changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain
|
|
||||||
interface and to perform domain parameter and key validation
|
|
||||||
- changed interfaces of PK_Signer and PK_Verifier to sign and verify
|
|
||||||
messages instead of message digests
|
|
||||||
- changed OAEP to conform to PKCS#1 v2.0
|
|
||||||
- changed benchmark code to produce HTML tables as output
|
|
||||||
- changed PSSR to track IEEE P1363a
|
|
||||||
- renamed ElGamalSignature to NR and changed it to track IEEE P1363
|
|
||||||
- renamed ECKEP to ECMQVC and changed it to track IEEE P1363
|
|
||||||
- renamed several other classes for clarity
|
|
||||||
- removed support for calling RSAREF
|
|
||||||
- removed option to compile old SHA (SHA-0)
|
|
||||||
- removed option not to throw exceptions
|
|
||||||
|
|
||||||
3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC
|
|
||||||
- added interface for querying supported key lengths of symmetric ciphers
|
|
||||||
and MACs
|
|
||||||
- added sample code for RSA signature and verification
|
|
||||||
- changed CBC-CTS to be compatible with RFC 2040
|
|
||||||
- updated SEAL to version 3.0 of the cipher specification
|
|
||||||
- optimized multiprecision squaring and elliptic curves over GF(p)
|
|
||||||
- fixed bug in MARS key setup
|
|
||||||
- fixed bug with attaching objects to Deflator
|
|
||||||
|
|
||||||
3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC
|
|
||||||
- renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3
|
|
||||||
- optimized ARC4
|
|
||||||
- generalized DSA to allow keys longer than 1024 bits
|
|
||||||
- fixed bugs in GF2N and ModularArithmetic that can cause calculation errors
|
|
||||||
- fixed crashing bug in Inflator when given invalid inputs
|
|
||||||
- fixed endian bug in Serpent
|
|
||||||
- fixed padding bug in Tiger
|
|
||||||
|
|
||||||
4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512),
|
|
||||||
and XTR-DH
|
|
||||||
- added a faster variant of Rabin's Information Dispersal Algorithm (IDA)
|
|
||||||
- added class wrappers for these operating system features:
|
|
||||||
- high resolution timers on Windows, Unix, and MacOS
|
|
||||||
- Berkeley and Windows style sockets
|
|
||||||
- Windows named pipes
|
|
||||||
- /dev/random and /dev/urandom on Linux and FreeBSD
|
|
||||||
- Microsoft's CryptGenRandom on Windows
|
|
||||||
- added support for SEC 1 elliptic curve key format and compressed points
|
|
||||||
- added support for X.509 public key format (subjectPublicKeyInfo) for
|
|
||||||
RSA, DSA, and elliptic curve schemes
|
|
||||||
- added support for DER and OpenPGP signature format for DSA
|
|
||||||
- added support for ZLIB compressed data format (RFC 1950)
|
|
||||||
- changed elliptic curve encryption to use ECIES (as defined in SEC 1)
|
|
||||||
- changed MARS key schedule to reflect the latest specification
|
|
||||||
- changed BufferedTransformation interface to support multiple channels
|
|
||||||
and messages
|
|
||||||
- changed CAST and SHA-1 implementations to use public domain source code
|
|
||||||
- fixed bug in StringSource
|
|
||||||
- optmized multi-precision integer code for better performance
|
|
||||||
|
|
||||||
4.1 - added more support for the recommended elliptic curve parameters in SEC 2
|
|
||||||
- added Panama MAC, MARC4
|
|
||||||
- added IV stealing feature to CTS mode
|
|
||||||
- added support for PKCS #8 private key format for RSA, DSA, and elliptic
|
|
||||||
curve schemes
|
|
||||||
- changed Deflate, MD5, Rijndael, and Twofish to use public domain code
|
|
||||||
- fixed a bug with flushing compressed streams
|
|
||||||
- fixed a bug with decompressing stored blocks
|
|
||||||
- fixed a bug with EC point decompression using non-trinomial basis
|
|
||||||
- fixed a bug in NetworkSource::GeneralPump()
|
|
||||||
- fixed a performance issue with EC over GF(p) decryption
|
|
||||||
- fixed syntax to allow GCC to compile without -fpermissive
|
|
||||||
- relaxed some restrictions in the license
|
|
||||||
|
|
||||||
4.2 - added support for longer HMAC keys
|
|
||||||
- added MD4 (which is not secure so use for compatibility purposes only)
|
|
||||||
- added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2,
|
|
||||||
and MSVC 7.0
|
|
||||||
- changed MD2 to use public domain code
|
|
||||||
- fixed a bug with decompressing multiple messages with the same object
|
|
||||||
- fixed a bug in CBC-MAC with MACing multiple messages with the same object
|
|
||||||
- fixed a bug in RC5 and RC6 with zero-length keys
|
|
||||||
- fixed a bug in Adler32 where incorrect checksum may be generated
|
|
||||||
|
|
||||||
5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5
|
|
||||||
- added key validation for encryption and signature public/private keys
|
|
||||||
- renamed StreamCipher interface to SymmetricCipher, which is now implemented
|
|
||||||
by both stream ciphers and block cipher modes including ECB and CBC
|
|
||||||
- added keying interfaces to support resetting of keys and IVs without
|
|
||||||
having to destroy and recreate objects
|
|
||||||
- changed filter interface to support non-blocking input/output
|
|
||||||
- changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows
|
|
||||||
- grouped related classes inside structs to help templates, for example
|
|
||||||
AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption
|
|
||||||
- where possible, typedefs have been added to improve backwards
|
|
||||||
compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined
|
|
||||||
- changed Serpent, HAVAL and IDEA to use public domain code
|
|
||||||
- implemented SSE2 optimizations for Integer operations
|
|
||||||
- fixed a bug in HMAC::TruncatedFinal()
|
|
||||||
- fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02
|
|
||||||
|
|
||||||
5.01 - added known answer test for X9.17 RNG in FIPS 140 power-up self test
|
|
||||||
- submitted to NIST/CSE, but not publicly released
|
|
||||||
|
|
||||||
5.02 - changed EDC test to MAC integrity check using HMAC/SHA1
|
|
||||||
- improved performance of integrity check
|
|
||||||
- added blinding to defend against RSA timing attack
|
|
||||||
|
|
||||||
5.03 - created DLL version of Crypto++ for FIPS 140-2 validation
|
|
||||||
- fixed vulnerabilities in GetNextIV for CTR and OFB modes
|
|
||||||
|
|
||||||
5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL
|
|
||||||
|
|
||||||
5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard
|
|
||||||
- added blinding for RSA and Rabin to defend against timing attacks
|
|
||||||
on decryption operations
|
|
||||||
- changed signing and decryption APIs to support the above
|
|
||||||
- changed WaitObjectContainer to allow waiting for more than 64
|
|
||||||
objects at a time on Win32 platforms
|
|
||||||
- fixed a bug in CBC and ECB modes with processing non-aligned data
|
|
||||||
- fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2
|
|
||||||
signature scheme (these fixes are not backwards compatible)
|
|
||||||
- fixed a number of compiler warnings, minor bugs, and portability problems
|
|
||||||
- removed Sapphire
|
|
||||||
|
|
||||||
5.2 - merged in changes for 5.01 - 5.0.4
|
|
||||||
- added support for using encoding parameters and key derivation parameters
|
|
||||||
with public key encryption (implemented by OAEP and DL/ECIES)
|
|
||||||
- added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320,
|
|
||||||
RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode
|
|
||||||
- added ThreadUserTimer for timing thread CPU usage
|
|
||||||
- added option for password-based key derivation functions
|
|
||||||
to iterate until a mimimum elapsed thread CPU time is reached
|
|
||||||
- added option (on by default) for DEFLATE compression to detect
|
|
||||||
uncompressible files and process them more quickly
|
|
||||||
- improved compatibility and performance on 64-bit platforms,
|
|
||||||
including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64
|
|
||||||
- fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding.
|
|
||||||
- fixed encoding/decoding of PKCS #8 privateKeyInfo to properly
|
|
||||||
handle optional attributes
|
|
||||||
|
|
||||||
5.2.1 - fixed bug in the "dlltest" DLL testing program
|
|
||||||
- fixed compiling with STLport using VC .NET
|
|
||||||
- fixed compiling with -fPIC using GCC
|
|
||||||
- fixed compiling with -msse2 on systems without memalign()
|
|
||||||
- fixed inability to instantiate PanamaMAC
|
|
||||||
- fixed problems with inline documentation
|
|
||||||
|
|
||||||
5.2.2 - added SHA-224
|
|
||||||
- put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL
|
|
||||||
|
|
||||||
5.2.3 - fixed issues with FIPS algorithm test vectors
|
|
||||||
- put RSASSA-ISO into DLL
|
|
||||||
|
|
||||||
5.3 - ported to MSVC 2005 with support for x86-64
|
|
||||||
- added defense against AES timing attacks, and more AES test vectors
|
|
||||||
- changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR"
|
|
||||||
|
|
||||||
5.4 - added Salsa20
|
|
||||||
- updated Whirlpool to version 3.0
|
|
||||||
- ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006
|
|
||||||
|
|
||||||
5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly)
|
|
||||||
- improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20,
|
|
||||||
Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2)
|
|
||||||
- optimized Camellia and added defense against timing attacks
|
|
||||||
- updated benchmarks code to show cycles per byte and to time key/IV setup
|
|
||||||
- started using OpenMP for increased multi-core speed
|
|
||||||
- enabled GCC optimization flags by default in GNUmakefile
|
|
||||||
- added blinding and computational error checking for RW signing
|
|
||||||
- changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce
|
|
||||||
the risk of reusing random numbers and IVs after virtual machine state
|
|
||||||
rollback
|
|
||||||
- changed default FIPS mode RNG from AutoSeededX917RNG<DES_EDE3> to
|
|
||||||
AutoSeededX917RNG<AES>
|
|
||||||
- fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV
|
|
||||||
- moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak"
|
|
||||||
- removed HAVAL, MD5-MAC, XMAC
|
|
||||||
|
|
||||||
5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines
|
|
||||||
|
|
||||||
5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama
|
|
||||||
to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64)
|
|
||||||
- fixed Salsa20 initialization crash on non-SSE2 machines
|
|
||||||
- fixed Whirlpool crash on Pentium 2 machines
|
|
||||||
- fixed possible branch prediction analysis (BPA) vulnerability in
|
|
||||||
MontgomeryReduce(), which may affect security of RSA, RW, LUC
|
|
||||||
- fixed link error with MSVC 2003 when using "debug DLL" form of runtime library
|
|
||||||
- fixed crash in SSE2_Add on P4 machines when compiled with
|
|
||||||
MSVC 6.0 SP5 with Processor Pack
|
|
||||||
- ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0,
|
|
||||||
and Borland C++Builder 2007
|
|
||||||
|
|
||||||
5.6.0 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
|
|
||||||
- added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED
|
|
||||||
- added support for variable length IVs
|
|
||||||
- added OIDs for Brainpool elliptic curve parameters
|
|
||||||
- improved AES and SHA-256 speed on x86 and x64
|
|
||||||
- changed BlockTransformation interface to no longer assume data alignment
|
|
||||||
- fixed incorrect VMAC computation on message lengths
|
|
||||||
that are >64 mod 128 (x86 assembly version is not affected)
|
|
||||||
- fixed compiler error in vmac.cpp on x86 with GCC -fPIC
|
|
||||||
- fixed run-time validation error on x86-64 with GCC 4.3.2 -O2
|
|
||||||
- fixed HashFilter bug when putMessage=true
|
|
||||||
- fixed AES-CTR data alignment bug that causes incorrect encryption on ARM
|
|
||||||
- removed WORD64_AVAILABLE; compiler support for 64-bit int is now required
|
|
||||||
- ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11
|
|
||||||
|
|
||||||
5.6.1 - added support for AES-NI and CLMUL instruction sets in AES and GMAC/GCM
|
|
||||||
- removed WAKE-CFB
|
|
||||||
- fixed several bugs in the SHA-256 x86/x64 assembly code:
|
|
||||||
* incorrect hash on non-SSE2 x86 machines on non-aligned input
|
|
||||||
* incorrect hash on x86 machines when input crosses 0x80000000
|
|
||||||
* incorrect hash on x64 when compiled with GCC with optimizations enabled
|
|
||||||
- fixed bugs in AES x86 and x64 assembly causing crashes in some MSVC build configurations
|
|
||||||
- switched to a public domain implementation of MARS
|
|
||||||
- ported to MSVC 2010, GCC 4.5.1, Sun Studio 12u1, C++Builder 2010, Intel C++ Compiler 11.1
|
|
||||||
- renamed the MSVC DLL project to "cryptopp" for compatibility with MSVC 2010
|
|
||||||
|
|
||||||
5.6.2 - changed license to Boost Software License 1.0
|
|
||||||
- added SHA-3 (Keccak)
|
|
||||||
- updated DSA to FIPS 186-3 (see DSA2 class)
|
|
||||||
- fixed Blowfish minimum keylength to be 4 bytes (32 bits)
|
|
||||||
- fixed Salsa validation failure when compiling with GCC 4.6
|
|
||||||
- fixed infinite recursion when on x64, assembly disabled, and no AESNI
|
|
||||||
- ported to MSVC 2012, GCC 4.7, Clang 3.2, Solaris Studio 12.3, Intel C++ Compiler 13.0
|
|
||||||
|
|
||||||
Written by Wei Dai
|
|
|
@ -1,77 +0,0 @@
|
||||||
// adler32.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "adler32.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void Adler32::Update(const byte *input, size_t length)
|
|
||||||
{
|
|
||||||
const unsigned long BASE = 65521;
|
|
||||||
|
|
||||||
unsigned long s1 = m_s1;
|
|
||||||
unsigned long s2 = m_s2;
|
|
||||||
|
|
||||||
if (length % 8 != 0)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
s1 += *input++;
|
|
||||||
s2 += s1;
|
|
||||||
length--;
|
|
||||||
} while (length % 8 != 0);
|
|
||||||
|
|
||||||
if (s1 >= BASE)
|
|
||||||
s1 -= BASE;
|
|
||||||
s2 %= BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (length > 0)
|
|
||||||
{
|
|
||||||
s1 += input[0]; s2 += s1;
|
|
||||||
s1 += input[1]; s2 += s1;
|
|
||||||
s1 += input[2]; s2 += s1;
|
|
||||||
s1 += input[3]; s2 += s1;
|
|
||||||
s1 += input[4]; s2 += s1;
|
|
||||||
s1 += input[5]; s2 += s1;
|
|
||||||
s1 += input[6]; s2 += s1;
|
|
||||||
s1 += input[7]; s2 += s1;
|
|
||||||
|
|
||||||
length -= 8;
|
|
||||||
input += 8;
|
|
||||||
|
|
||||||
if (s1 >= BASE)
|
|
||||||
s1 -= BASE;
|
|
||||||
if (length % 0x8000 == 0)
|
|
||||||
s2 %= BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(s1 < BASE);
|
|
||||||
assert(s2 < BASE);
|
|
||||||
|
|
||||||
m_s1 = (word16)s1;
|
|
||||||
m_s2 = (word16)s2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Adler32::TruncatedFinal(byte *hash, size_t size)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(size);
|
|
||||||
|
|
||||||
switch (size)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
hash[3] = byte(m_s1);
|
|
||||||
case 3:
|
|
||||||
hash[2] = byte(m_s1 >> 8);
|
|
||||||
case 2:
|
|
||||||
hash[1] = byte(m_s2);
|
|
||||||
case 1:
|
|
||||||
hash[0] = byte(m_s2 >> 8);
|
|
||||||
case 0:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ADLER32_H
|
|
||||||
#define CRYPTOPP_ADLER32_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! ADLER-32 checksum calculations
|
|
||||||
class Adler32 : public HashTransformation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
|
|
||||||
Adler32() {Reset();}
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void TruncatedFinal(byte *hash, size_t size);
|
|
||||||
unsigned int DigestSize() const {return DIGESTSIZE;}
|
|
||||||
static const char * StaticAlgorithmName() {return "Adler32";}
|
|
||||||
std::string AlgorithmName() const {return StaticAlgorithmName();}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Reset() {m_s1 = 1; m_s2 = 0;}
|
|
||||||
|
|
||||||
word16 m_s1, m_s2;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef CRYPTOPP_AES_H
|
|
||||||
#define CRYPTOPP_AES_H
|
|
||||||
|
|
||||||
#include "rijndael.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
|
|
||||||
DOCUMENTED_TYPEDEF(Rijndael, AES);
|
|
||||||
|
|
||||||
typedef RijndaelEncryption AESEncryption;
|
|
||||||
typedef RijndaelDecryption AESDecryption;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,340 +0,0 @@
|
||||||
// algebra.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice
|
|
||||||
#define CRYPTOPP_ALGEBRA_CPP
|
|
||||||
|
|
||||||
#include "algebra.h"
|
|
||||||
#include "integer.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
|
|
||||||
{
|
|
||||||
return this->Add(a, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
// make copy of a in case Inverse() overwrites it
|
|
||||||
Element a1(a);
|
|
||||||
return this->Add(a1, Inverse(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
return a = this->Add(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
return a = this->Subtract(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const T& AbstractRing<T>::Square(const Element &a) const
|
|
||||||
{
|
|
||||||
return this->Multiply(a, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const T& AbstractRing<T>::Divide(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
// make copy of a in case MultiplicativeInverse() overwrites it
|
|
||||||
Element a1(a);
|
|
||||||
return this->Multiply(a1, this->MultiplicativeInverse(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
Element q;
|
|
||||||
this->DivisionAlgorithm(result, q, a, b);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
Element g[3]={b, a};
|
|
||||||
unsigned int i0=0, i1=1, i2=2;
|
|
||||||
|
|
||||||
while (!this->Equal(g[i1], this->Identity()))
|
|
||||||
{
|
|
||||||
g[i2] = this->Mod(g[i0], g[i1]);
|
|
||||||
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result = g[i0];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> const typename QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(const Element &a) const
|
|
||||||
{
|
|
||||||
Element g[3]={m_modulus, a};
|
|
||||||
Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
|
|
||||||
Element y;
|
|
||||||
unsigned int i0=0, i1=1, i2=2;
|
|
||||||
|
|
||||||
while (!this->Equal(g[i1], this->Identity()))
|
|
||||||
{
|
|
||||||
// y = g[i0] / g[i1];
|
|
||||||
// g[i2] = g[i0] % g[i1];
|
|
||||||
m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
|
|
||||||
// v[i2] = v[i0] - (v[i1] * y);
|
|
||||||
v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
|
|
||||||
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base, const Integer &exponent) const
|
|
||||||
{
|
|
||||||
Element result;
|
|
||||||
this->SimultaneousMultiply(&result, base, &exponent, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
|
||||||
{
|
|
||||||
const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount());
|
|
||||||
if (expLen==0)
|
|
||||||
return this->Identity();
|
|
||||||
|
|
||||||
const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
|
|
||||||
const unsigned tableSize = 1<<w;
|
|
||||||
std::vector<Element> powerTable(tableSize << w);
|
|
||||||
|
|
||||||
powerTable[1] = x;
|
|
||||||
powerTable[tableSize] = y;
|
|
||||||
if (w==1)
|
|
||||||
powerTable[3] = this->Add(x,y);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
powerTable[2] = this->Double(x);
|
|
||||||
powerTable[2*tableSize] = this->Double(y);
|
|
||||||
|
|
||||||
unsigned i, j;
|
|
||||||
|
|
||||||
for (i=3; i<tableSize; i+=2)
|
|
||||||
powerTable[i] = Add(powerTable[i-2], powerTable[2]);
|
|
||||||
for (i=1; i<tableSize; i+=2)
|
|
||||||
for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
|
|
||||||
powerTable[j] = Add(powerTable[j-tableSize], y);
|
|
||||||
|
|
||||||
for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
|
|
||||||
powerTable[i] = Add(powerTable[i-2*tableSize], powerTable[2*tableSize]);
|
|
||||||
for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
|
|
||||||
for (j=i+2; j<i+tableSize; j+=2)
|
|
||||||
powerTable[j] = Add(powerTable[j-1], x);
|
|
||||||
}
|
|
||||||
|
|
||||||
Element result;
|
|
||||||
unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
|
|
||||||
bool firstTime = true;
|
|
||||||
|
|
||||||
for (int i = expLen-1; i>=0; i--)
|
|
||||||
{
|
|
||||||
power1 = 2*power1 + e1.GetBit(i);
|
|
||||||
power2 = 2*power2 + e2.GetBit(i);
|
|
||||||
|
|
||||||
if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
|
|
||||||
{
|
|
||||||
unsigned squaresBefore = prevPosition-i;
|
|
||||||
unsigned squaresAfter = 0;
|
|
||||||
prevPosition = i;
|
|
||||||
while ((power1 || power2) && power1%2 == 0 && power2%2==0)
|
|
||||||
{
|
|
||||||
power1 /= 2;
|
|
||||||
power2 /= 2;
|
|
||||||
squaresBefore--;
|
|
||||||
squaresAfter++;
|
|
||||||
}
|
|
||||||
if (firstTime)
|
|
||||||
{
|
|
||||||
result = powerTable[(power2<<w) + power1];
|
|
||||||
firstTime = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (squaresBefore--)
|
|
||||||
result = this->Double(result);
|
|
||||||
if (power1 || power2)
|
|
||||||
Accumulate(result, powerTable[(power2<<w) + power1]);
|
|
||||||
}
|
|
||||||
while (squaresAfter--)
|
|
||||||
result = this->Double(result);
|
|
||||||
power1 = power2 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end)
|
|
||||||
{
|
|
||||||
if (end-begin == 1)
|
|
||||||
return group.ScalarMultiply(begin->base, begin->exponent);
|
|
||||||
else if (end-begin == 2)
|
|
||||||
return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Integer q, t;
|
|
||||||
Iterator last = end;
|
|
||||||
--last;
|
|
||||||
|
|
||||||
std::make_heap(begin, end);
|
|
||||||
std::pop_heap(begin, end);
|
|
||||||
|
|
||||||
while (!!begin->exponent)
|
|
||||||
{
|
|
||||||
// last->exponent is largest exponent, begin->exponent is next largest
|
|
||||||
t = last->exponent;
|
|
||||||
Integer::Divide(last->exponent, q, t, begin->exponent);
|
|
||||||
|
|
||||||
if (q == Integer::One())
|
|
||||||
group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply()
|
|
||||||
else
|
|
||||||
group.Accumulate(begin->base, group.ScalarMultiply(last->base, q));
|
|
||||||
|
|
||||||
std::push_heap(begin, end);
|
|
||||||
std::pop_heap(begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return group.ScalarMultiply(last->base, last->exponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WindowSlider
|
|
||||||
{
|
|
||||||
WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
|
|
||||||
: exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false)
|
|
||||||
{
|
|
||||||
if (windowSize == 0)
|
|
||||||
{
|
|
||||||
unsigned int expLen = exp.BitCount();
|
|
||||||
windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7)))));
|
|
||||||
}
|
|
||||||
windowModulus <<= windowSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FindNextWindow()
|
|
||||||
{
|
|
||||||
unsigned int expLen = exp.WordCount() * WORD_BITS;
|
|
||||||
unsigned int skipCount = firstTime ? 0 : windowSize;
|
|
||||||
firstTime = false;
|
|
||||||
while (!exp.GetBit(skipCount))
|
|
||||||
{
|
|
||||||
if (skipCount >= expLen)
|
|
||||||
{
|
|
||||||
finished = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
skipCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
exp >>= skipCount;
|
|
||||||
windowBegin += skipCount;
|
|
||||||
expWindow = word32(exp % (word(1) << windowSize));
|
|
||||||
|
|
||||||
if (fastNegate && exp.GetBit(windowSize))
|
|
||||||
{
|
|
||||||
negateNext = true;
|
|
||||||
expWindow = (word32(1) << windowSize) - expWindow;
|
|
||||||
exp += windowModulus;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
negateNext = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer exp, windowModulus;
|
|
||||||
unsigned int windowSize, windowBegin;
|
|
||||||
word32 expWindow;
|
|
||||||
bool fastNegate, negateNext, firstTime, finished;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const
|
|
||||||
{
|
|
||||||
std::vector<std::vector<Element> > buckets(expCount);
|
|
||||||
std::vector<WindowSlider> exponents;
|
|
||||||
exponents.reserve(expCount);
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i=0; i<expCount; i++)
|
|
||||||
{
|
|
||||||
assert(expBegin->NotNegative());
|
|
||||||
exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
|
|
||||||
exponents[i].FindNextWindow();
|
|
||||||
buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int expBitPosition = 0;
|
|
||||||
Element g = base;
|
|
||||||
bool notDone = true;
|
|
||||||
|
|
||||||
while (notDone)
|
|
||||||
{
|
|
||||||
notDone = false;
|
|
||||||
for (i=0; i<expCount; i++)
|
|
||||||
{
|
|
||||||
if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
|
|
||||||
{
|
|
||||||
Element &bucket = buckets[i][exponents[i].expWindow/2];
|
|
||||||
if (exponents[i].negateNext)
|
|
||||||
Accumulate(bucket, Inverse(g));
|
|
||||||
else
|
|
||||||
Accumulate(bucket, g);
|
|
||||||
exponents[i].FindNextWindow();
|
|
||||||
}
|
|
||||||
notDone = notDone || !exponents[i].finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notDone)
|
|
||||||
{
|
|
||||||
g = Double(g);
|
|
||||||
expBitPosition++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<expCount; i++)
|
|
||||||
{
|
|
||||||
Element &r = *results++;
|
|
||||||
r = buckets[i][buckets[i].size()-1];
|
|
||||||
if (buckets[i].size() > 1)
|
|
||||||
{
|
|
||||||
for (int j = (int)buckets[i].size()-2; j >= 1; j--)
|
|
||||||
{
|
|
||||||
Accumulate(buckets[i][j], buckets[i][j+1]);
|
|
||||||
Accumulate(r, buckets[i][j]);
|
|
||||||
}
|
|
||||||
Accumulate(buckets[i][0], buckets[i][1]);
|
|
||||||
r = Add(Double(r), buckets[i][0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T AbstractRing<T>::Exponentiate(const Element &base, const Integer &exponent) const
|
|
||||||
{
|
|
||||||
Element result;
|
|
||||||
SimultaneousExponentiate(&result, base, &exponent, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
|
||||||
{
|
|
||||||
return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(x, e1, y, e2);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Element, class Iterator> Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end)
|
|
||||||
{
|
|
||||||
return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(), begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const
|
|
||||||
{
|
|
||||||
MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base, exponents, expCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,285 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ALGEBRA_H
|
|
||||||
#define CRYPTOPP_ALGEBRA_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
class Integer;
|
|
||||||
|
|
||||||
// "const Element&" returned by member functions are references
|
|
||||||
// to internal data members. Since each object may have only
|
|
||||||
// one such data member for holding results, the following code
|
|
||||||
// will produce incorrect results:
|
|
||||||
// abcd = group.Add(group.Add(a,b), group.Add(c,d));
|
|
||||||
// But this should be fine:
|
|
||||||
// abcd = group.Add(a, group.Add(b, group.Add(c,d));
|
|
||||||
|
|
||||||
//! Abstract Group
|
|
||||||
template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
virtual ~AbstractGroup() {}
|
|
||||||
|
|
||||||
virtual bool Equal(const Element &a, const Element &b) const =0;
|
|
||||||
virtual const Element& Identity() const =0;
|
|
||||||
virtual const Element& Add(const Element &a, const Element &b) const =0;
|
|
||||||
virtual const Element& Inverse(const Element &a) const =0;
|
|
||||||
virtual bool InversionIsFast() const {return false;}
|
|
||||||
|
|
||||||
virtual const Element& Double(const Element &a) const;
|
|
||||||
virtual const Element& Subtract(const Element &a, const Element &b) const;
|
|
||||||
virtual Element& Accumulate(Element &a, const Element &b) const;
|
|
||||||
virtual Element& Reduce(Element &a, const Element &b) const;
|
|
||||||
|
|
||||||
virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
|
|
||||||
virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
|
|
||||||
|
|
||||||
virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Abstract Ring
|
|
||||||
template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
AbstractRing() {m_mg.m_pRing = this;}
|
|
||||||
AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
|
|
||||||
AbstractRing& operator=(const AbstractRing &source) {return *this;}
|
|
||||||
|
|
||||||
virtual bool IsUnit(const Element &a) const =0;
|
|
||||||
virtual const Element& MultiplicativeIdentity() const =0;
|
|
||||||
virtual const Element& Multiply(const Element &a, const Element &b) const =0;
|
|
||||||
virtual const Element& MultiplicativeInverse(const Element &a) const =0;
|
|
||||||
|
|
||||||
virtual const Element& Square(const Element &a) const;
|
|
||||||
virtual const Element& Divide(const Element &a, const Element &b) const;
|
|
||||||
|
|
||||||
virtual Element Exponentiate(const Element &a, const Integer &e) const;
|
|
||||||
virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
|
|
||||||
|
|
||||||
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
|
||||||
|
|
||||||
virtual const AbstractGroup<T>& MultiplicativeGroup() const
|
|
||||||
{return m_mg;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class MultiplicativeGroupT : public AbstractGroup<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const AbstractRing<T>& GetRing() const
|
|
||||||
{return *m_pRing;}
|
|
||||||
|
|
||||||
bool Equal(const Element &a, const Element &b) const
|
|
||||||
{return GetRing().Equal(a, b);}
|
|
||||||
|
|
||||||
const Element& Identity() const
|
|
||||||
{return GetRing().MultiplicativeIdentity();}
|
|
||||||
|
|
||||||
const Element& Add(const Element &a, const Element &b) const
|
|
||||||
{return GetRing().Multiply(a, b);}
|
|
||||||
|
|
||||||
Element& Accumulate(Element &a, const Element &b) const
|
|
||||||
{return a = GetRing().Multiply(a, b);}
|
|
||||||
|
|
||||||
const Element& Inverse(const Element &a) const
|
|
||||||
{return GetRing().MultiplicativeInverse(a);}
|
|
||||||
|
|
||||||
const Element& Subtract(const Element &a, const Element &b) const
|
|
||||||
{return GetRing().Divide(a, b);}
|
|
||||||
|
|
||||||
Element& Reduce(Element &a, const Element &b) const
|
|
||||||
{return a = GetRing().Divide(a, b);}
|
|
||||||
|
|
||||||
const Element& Double(const Element &a) const
|
|
||||||
{return GetRing().Square(a);}
|
|
||||||
|
|
||||||
Element ScalarMultiply(const Element &a, const Integer &e) const
|
|
||||||
{return GetRing().Exponentiate(a, e);}
|
|
||||||
|
|
||||||
Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
|
||||||
{return GetRing().CascadeExponentiate(x, e1, y, e2);}
|
|
||||||
|
|
||||||
void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
|
|
||||||
{GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
|
|
||||||
|
|
||||||
const AbstractRing<T> *m_pRing;
|
|
||||||
};
|
|
||||||
|
|
||||||
MultiplicativeGroupT m_mg;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
//! Base and Exponent
|
|
||||||
template <class T, class E = Integer>
|
|
||||||
struct BaseAndExponent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseAndExponent() {}
|
|
||||||
BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
|
|
||||||
bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
|
|
||||||
T base;
|
|
||||||
E exponent;
|
|
||||||
};
|
|
||||||
|
|
||||||
// VC60 workaround: incomplete member template support
|
|
||||||
template <class Element, class Iterator>
|
|
||||||
Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
|
|
||||||
template <class Element, class Iterator>
|
|
||||||
Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
//! Abstract Euclidean Domain
|
|
||||||
template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
|
|
||||||
|
|
||||||
virtual const Element& Mod(const Element &a, const Element &b) const =0;
|
|
||||||
virtual const Element& Gcd(const Element &a, const Element &b) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
mutable Element result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
//! EuclideanDomainOf
|
|
||||||
template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
EuclideanDomainOf() {}
|
|
||||||
|
|
||||||
bool Equal(const Element &a, const Element &b) const
|
|
||||||
{return a==b;}
|
|
||||||
|
|
||||||
const Element& Identity() const
|
|
||||||
{return Element::Zero();}
|
|
||||||
|
|
||||||
const Element& Add(const Element &a, const Element &b) const
|
|
||||||
{return result = a+b;}
|
|
||||||
|
|
||||||
Element& Accumulate(Element &a, const Element &b) const
|
|
||||||
{return a+=b;}
|
|
||||||
|
|
||||||
const Element& Inverse(const Element &a) const
|
|
||||||
{return result = -a;}
|
|
||||||
|
|
||||||
const Element& Subtract(const Element &a, const Element &b) const
|
|
||||||
{return result = a-b;}
|
|
||||||
|
|
||||||
Element& Reduce(Element &a, const Element &b) const
|
|
||||||
{return a-=b;}
|
|
||||||
|
|
||||||
const Element& Double(const Element &a) const
|
|
||||||
{return result = a.Doubled();}
|
|
||||||
|
|
||||||
const Element& MultiplicativeIdentity() const
|
|
||||||
{return Element::One();}
|
|
||||||
|
|
||||||
const Element& Multiply(const Element &a, const Element &b) const
|
|
||||||
{return result = a*b;}
|
|
||||||
|
|
||||||
const Element& Square(const Element &a) const
|
|
||||||
{return result = a.Squared();}
|
|
||||||
|
|
||||||
bool IsUnit(const Element &a) const
|
|
||||||
{return a.IsUnit();}
|
|
||||||
|
|
||||||
const Element& MultiplicativeInverse(const Element &a) const
|
|
||||||
{return result = a.MultiplicativeInverse();}
|
|
||||||
|
|
||||||
const Element& Divide(const Element &a, const Element &b) const
|
|
||||||
{return result = a/b;}
|
|
||||||
|
|
||||||
const Element& Mod(const Element &a, const Element &b) const
|
|
||||||
{return result = a%b;}
|
|
||||||
|
|
||||||
void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
|
|
||||||
{Element::Divide(r, q, a, d);}
|
|
||||||
|
|
||||||
bool operator==(const EuclideanDomainOf<T> &rhs) const
|
|
||||||
{return true;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable Element result;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Quotient Ring
|
|
||||||
template <class T> class QuotientRing : public AbstractRing<typename T::Element>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T EuclideanDomain;
|
|
||||||
typedef typename T::Element Element;
|
|
||||||
|
|
||||||
QuotientRing(const EuclideanDomain &domain, const Element &modulus)
|
|
||||||
: m_domain(domain), m_modulus(modulus) {}
|
|
||||||
|
|
||||||
const EuclideanDomain & GetDomain() const
|
|
||||||
{return m_domain;}
|
|
||||||
|
|
||||||
const Element& GetModulus() const
|
|
||||||
{return m_modulus;}
|
|
||||||
|
|
||||||
bool Equal(const Element &a, const Element &b) const
|
|
||||||
{return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
|
|
||||||
|
|
||||||
const Element& Identity() const
|
|
||||||
{return m_domain.Identity();}
|
|
||||||
|
|
||||||
const Element& Add(const Element &a, const Element &b) const
|
|
||||||
{return m_domain.Add(a, b);}
|
|
||||||
|
|
||||||
Element& Accumulate(Element &a, const Element &b) const
|
|
||||||
{return m_domain.Accumulate(a, b);}
|
|
||||||
|
|
||||||
const Element& Inverse(const Element &a) const
|
|
||||||
{return m_domain.Inverse(a);}
|
|
||||||
|
|
||||||
const Element& Subtract(const Element &a, const Element &b) const
|
|
||||||
{return m_domain.Subtract(a, b);}
|
|
||||||
|
|
||||||
Element& Reduce(Element &a, const Element &b) const
|
|
||||||
{return m_domain.Reduce(a, b);}
|
|
||||||
|
|
||||||
const Element& Double(const Element &a) const
|
|
||||||
{return m_domain.Double(a);}
|
|
||||||
|
|
||||||
bool IsUnit(const Element &a) const
|
|
||||||
{return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
|
|
||||||
|
|
||||||
const Element& MultiplicativeIdentity() const
|
|
||||||
{return m_domain.MultiplicativeIdentity();}
|
|
||||||
|
|
||||||
const Element& Multiply(const Element &a, const Element &b) const
|
|
||||||
{return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
|
|
||||||
|
|
||||||
const Element& Square(const Element &a) const
|
|
||||||
{return m_domain.Mod(m_domain.Square(a), m_modulus);}
|
|
||||||
|
|
||||||
const Element& MultiplicativeInverse(const Element &a) const;
|
|
||||||
|
|
||||||
bool operator==(const QuotientRing<T> &rhs) const
|
|
||||||
{return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
EuclideanDomain m_domain;
|
|
||||||
Element m_modulus;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
|
|
||||||
#include "algebra.cpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,75 +0,0 @@
|
||||||
// algparam.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "algparam.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
PAssignIntToInteger g_pAssignIntToInteger = NULL;
|
|
||||||
|
|
||||||
bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
if (strcmp(name, "ValueNames") == 0)
|
|
||||||
return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue);
|
|
||||||
else
|
|
||||||
return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlgorithmParametersBase::operator=(const AlgorithmParametersBase& rhs)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
if (strcmp(name, "ValueNames") == 0)
|
|
||||||
{
|
|
||||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType);
|
|
||||||
if (m_next.get())
|
|
||||||
m_next->GetVoidValue(name, valueType, pValue);
|
|
||||||
(*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (strcmp(name, m_name) == 0)
|
|
||||||
{
|
|
||||||
AssignValue(name, valueType, pValue);
|
|
||||||
m_used = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (m_next.get())
|
|
||||||
return m_next->GetVoidValue(name, valueType, pValue);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AlgorithmParameters::AlgorithmParameters()
|
|
||||||
: m_defaultThrowIfNotUsed(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x)
|
|
||||||
: m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed)
|
|
||||||
{
|
|
||||||
m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
|
|
||||||
}
|
|
||||||
|
|
||||||
AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x)
|
|
||||||
{
|
|
||||||
m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
if (m_next.get())
|
|
||||||
return m_next->GetVoidValue(name, valueType, pValue);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,398 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ALGPARAM_H
|
|
||||||
#define CRYPTOPP_ALGPARAM_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "smartptr.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! used to pass byte array input as part of a NameValuePairs object
|
|
||||||
/*! the deepCopy option is used when the NameValuePairs object can't
|
|
||||||
keep a copy of the data available */
|
|
||||||
class ConstByteArrayParameter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
|
|
||||||
{
|
|
||||||
Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
|
|
||||||
}
|
|
||||||
ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
|
|
||||||
{
|
|
||||||
Assign(data, size, deepCopy);
|
|
||||||
}
|
|
||||||
template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
|
|
||||||
{
|
|
||||||
CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
|
|
||||||
Assign((const byte *)string.data(), string.size(), deepCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Assign(const byte *data, size_t size, bool deepCopy)
|
|
||||||
{
|
|
||||||
if (deepCopy)
|
|
||||||
m_block.Assign(data, size);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_data = data;
|
|
||||||
m_size = size;
|
|
||||||
}
|
|
||||||
m_deepCopy = deepCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
|
|
||||||
const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
|
|
||||||
size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_deepCopy;
|
|
||||||
const byte *m_data;
|
|
||||||
size_t m_size;
|
|
||||||
SecByteBlock m_block;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ByteArrayParameter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
|
|
||||||
: m_data(data), m_size(size) {}
|
|
||||||
ByteArrayParameter(SecByteBlock &block)
|
|
||||||
: m_data(block.begin()), m_size(block.size()) {}
|
|
||||||
|
|
||||||
byte *begin() const {return m_data;}
|
|
||||||
byte *end() const {return m_data + m_size;}
|
|
||||||
size_t size() const {return m_size;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
byte *m_data;
|
|
||||||
size_t m_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
|
|
||||||
: m_pairs1(pairs1), m_pairs2(pairs2) {}
|
|
||||||
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const NameValuePairs &m_pairs1, &m_pairs2;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class BASE>
|
|
||||||
class GetValueHelperClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
|
|
||||||
: m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
|
|
||||||
{
|
|
||||||
if (strcmp(m_name, "ValueNames") == 0)
|
|
||||||
{
|
|
||||||
m_found = m_getValueNames = true;
|
|
||||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
|
|
||||||
if (searchFirst)
|
|
||||||
searchFirst->GetVoidValue(m_name, valueType, pValue);
|
|
||||||
if (typeid(T) != typeid(BASE))
|
|
||||||
pObject->BASE::GetVoidValue(m_name, valueType, pValue);
|
|
||||||
((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
|
|
||||||
{
|
|
||||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
|
|
||||||
*reinterpret_cast<const T **>(pValue) = pObject;
|
|
||||||
m_found = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_found && searchFirst)
|
|
||||||
m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
|
|
||||||
|
|
||||||
if (!m_found && typeid(T) != typeid(BASE))
|
|
||||||
m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const {return m_found;}
|
|
||||||
|
|
||||||
template <class R>
|
|
||||||
GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
|
|
||||||
{
|
|
||||||
if (m_getValueNames)
|
|
||||||
(*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
|
|
||||||
if (!m_found && strcmp(name, m_name) == 0)
|
|
||||||
{
|
|
||||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
|
|
||||||
*reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
|
|
||||||
m_found = true;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetValueHelperClass<T,BASE> &Assignable()
|
|
||||||
{
|
|
||||||
#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
|
|
||||||
if (m_getValueNames)
|
|
||||||
((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
|
|
||||||
if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
|
|
||||||
{
|
|
||||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
|
|
||||||
*reinterpret_cast<T *>(m_pValue) = *m_pObject;
|
|
||||||
m_found = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const T *m_pObject;
|
|
||||||
const char *m_name;
|
|
||||||
const std::type_info *m_valueType;
|
|
||||||
void *m_pValue;
|
|
||||||
bool m_found, m_getValueNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class BASE, class T>
|
|
||||||
GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
|
|
||||||
{
|
|
||||||
return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
|
|
||||||
{
|
|
||||||
return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
template <class R>
|
|
||||||
R Hack_DefaultValueFromConstReferenceType(const R &)
|
|
||||||
{
|
|
||||||
return R();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class R>
|
|
||||||
bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
|
|
||||||
{
|
|
||||||
return source.GetValue(name, const_cast<R &>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, class BASE>
|
|
||||||
class AssignFromHelperClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AssignFromHelperClass(T *pObject, const NameValuePairs &source)
|
|
||||||
: m_pObject(pObject), m_source(source), m_done(false)
|
|
||||||
{
|
|
||||||
if (source.GetThisObject(*pObject))
|
|
||||||
m_done = true;
|
|
||||||
else if (typeid(BASE) != typeid(T))
|
|
||||||
pObject->BASE::AssignFrom(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class R>
|
|
||||||
AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
|
|
||||||
{
|
|
||||||
if (!m_done)
|
|
||||||
{
|
|
||||||
R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
|
|
||||||
if (!Hack_GetValueIntoConstReference(m_source, name, value))
|
|
||||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
|
|
||||||
(m_pObject->*pm)(value);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class R, class S>
|
|
||||||
AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
|
|
||||||
{
|
|
||||||
if (!m_done)
|
|
||||||
{
|
|
||||||
R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
|
|
||||||
if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
|
|
||||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
|
|
||||||
S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
|
|
||||||
if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
|
|
||||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
|
|
||||||
(m_pObject->*pm)(value1, value2);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T *m_pObject;
|
|
||||||
const NameValuePairs &m_source;
|
|
||||||
bool m_done;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class BASE, class T>
|
|
||||||
AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
|
|
||||||
{
|
|
||||||
return AssignFromHelperClass<T, BASE>(pObject, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
|
|
||||||
{
|
|
||||||
return AssignFromHelperClass<T, T>(pObject, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
// to allow the linker to discard Integer code if not needed.
|
|
||||||
typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
|
|
||||||
CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
|
|
||||||
|
|
||||||
CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
|
|
||||||
|
|
||||||
class CRYPTOPP_DLL AlgorithmParametersBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class ParameterNotUsed : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// this is actually a move, not a copy
|
|
||||||
AlgorithmParametersBase(const AlgorithmParametersBase &x)
|
|
||||||
: m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
|
|
||||||
{
|
|
||||||
m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
|
|
||||||
x.m_used = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
|
|
||||||
: m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
|
|
||||||
|
|
||||||
virtual ~AlgorithmParametersBase()
|
|
||||||
{
|
|
||||||
#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
|
|
||||||
if (!std::uncaught_exception())
|
|
||||||
#else
|
|
||||||
try
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (m_throwIfNotUsed && !m_used)
|
|
||||||
throw ParameterNotUsed(m_name);
|
|
||||||
}
|
|
||||||
#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class AlgorithmParameters;
|
|
||||||
void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
|
|
||||||
|
|
||||||
virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
|
|
||||||
virtual void MoveInto(void *p) const =0; // not really const
|
|
||||||
|
|
||||||
const char *m_name;
|
|
||||||
bool m_throwIfNotUsed;
|
|
||||||
mutable bool m_used;
|
|
||||||
member_ptr<AlgorithmParametersBase> m_next;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class AlgorithmParametersTemplate : public AlgorithmParametersBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
|
|
||||||
: AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
// special case for retrieving an Integer parameter when an int was passed in
|
|
||||||
if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
|
|
||||||
{
|
|
||||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
|
|
||||||
*reinterpret_cast<T *>(pValue) = m_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInto(void *buffer) const
|
|
||||||
{
|
|
||||||
AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
|
|
||||||
|
|
||||||
class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AlgorithmParameters();
|
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
|
||||||
template <class T>
|
|
||||||
AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
|
|
||||||
: m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
|
|
||||||
, m_defaultThrowIfNotUsed(throwIfNotUsed)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AlgorithmParameters(const AlgorithmParameters &x);
|
|
||||||
|
|
||||||
AlgorithmParameters & operator=(const AlgorithmParameters &x);
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
|
|
||||||
{
|
|
||||||
member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
|
|
||||||
p->m_next.reset(m_next.release());
|
|
||||||
m_next.reset(p.release());
|
|
||||||
m_defaultThrowIfNotUsed = throwIfNotUsed;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
AlgorithmParameters & operator()(const char *name, const T &value)
|
|
||||||
{
|
|
||||||
return operator()(name, value, m_defaultThrowIfNotUsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
member_ptr<AlgorithmParametersBase> m_next;
|
|
||||||
bool m_defaultThrowIfNotUsed;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Create an object that implements NameValuePairs for passing parameters
|
|
||||||
/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
|
|
||||||
\note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
|
|
||||||
such as MSVC 7.0 and earlier.
|
|
||||||
\note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
|
|
||||||
repeatedly using operator() on the object returned by MakeParameters, for example:
|
|
||||||
AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
|
|
||||||
*/
|
|
||||||
#ifdef __BORLANDC__
|
|
||||||
typedef AlgorithmParameters MakeParameters;
|
|
||||||
#else
|
|
||||||
template <class T>
|
|
||||||
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
|
|
||||||
{
|
|
||||||
return AlgorithmParameters()(name, value, throwIfNotUsed);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
|
|
||||||
#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
|
|
||||||
#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,81 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ARGNAMES_H
|
|
||||||
#define CRYPTOPP_ARGNAMES_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
DOCUMENTED_NAMESPACE_BEGIN(Name)
|
|
||||||
|
|
||||||
#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;}
|
|
||||||
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(InputFileNameWide) //!< const wchar_t *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(OutputFileNameWide) //!< const wchar_t *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte *
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes
|
|
||||||
CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes
|
|
||||||
|
|
||||||
DOCUMENTED_NAMESPACE_END
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,597 +0,0 @@
|
||||||
// asn.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "asn.h"
|
|
||||||
|
|
||||||
#include <iomanip>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
USING_NAMESPACE(std)
|
|
||||||
|
|
||||||
/// DER Length
|
|
||||||
size_t DERLengthEncode(BufferedTransformation &bt, lword length)
|
|
||||||
{
|
|
||||||
size_t i=0;
|
|
||||||
if (length <= 0x7f)
|
|
||||||
{
|
|
||||||
bt.Put(byte(length));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bt.Put(byte(BytePrecision(length) | 0x80));
|
|
||||||
i++;
|
|
||||||
for (int j=BytePrecision(length); j; --j)
|
|
||||||
{
|
|
||||||
bt.Put(byte(length >> (j-1)*8));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
|
|
||||||
if (!bt.Get(b))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!(b & 0x80))
|
|
||||||
{
|
|
||||||
definiteLength = true;
|
|
||||||
length = b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int lengthBytes = b & 0x7f;
|
|
||||||
|
|
||||||
if (lengthBytes == 0)
|
|
||||||
{
|
|
||||||
definiteLength = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
definiteLength = true;
|
|
||||||
length = 0;
|
|
||||||
while (lengthBytes--)
|
|
||||||
{
|
|
||||||
if (length >> (8*(sizeof(length)-1)))
|
|
||||||
BERDecodeError(); // length about to overflow
|
|
||||||
|
|
||||||
if (!bt.Get(b))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
length = (length << 8) | b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
|
|
||||||
{
|
|
||||||
lword lw;
|
|
||||||
bool definiteLength;
|
|
||||||
if (!BERLengthDecode(bt, lw, definiteLength))
|
|
||||||
BERDecodeError();
|
|
||||||
if (!SafeConvert(lw, length))
|
|
||||||
BERDecodeError();
|
|
||||||
return definiteLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DEREncodeNull(BufferedTransformation &out)
|
|
||||||
{
|
|
||||||
out.Put(TAG_NULL);
|
|
||||||
out.Put(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BERDecodeNull(BufferedTransformation &in)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!in.Get(b) || b != TAG_NULL)
|
|
||||||
BERDecodeError();
|
|
||||||
size_t length;
|
|
||||||
if (!BERLengthDecode(in, length) || length != 0)
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ASN Strings
|
|
||||||
size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
|
|
||||||
{
|
|
||||||
bt.Put(OCTET_STRING);
|
|
||||||
size_t lengthBytes = DERLengthEncode(bt, strLen);
|
|
||||||
bt.Put(str, strLen);
|
|
||||||
return 1+lengthBytes+strLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
|
|
||||||
{
|
|
||||||
return DEREncodeOctetString(bt, str.begin(), str.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!bt.Get(b) || b != OCTET_STRING)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
size_t bc;
|
|
||||||
if (!BERLengthDecode(bt, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
str.resize(bc);
|
|
||||||
if (bc != bt.Get(str, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
return bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!bt.Get(b) || b != OCTET_STRING)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
size_t bc;
|
|
||||||
if (!BERLengthDecode(bt, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
bt.TransferTo(str, bc);
|
|
||||||
return bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
|
|
||||||
{
|
|
||||||
bt.Put(asnTag);
|
|
||||||
size_t lengthBytes = DERLengthEncode(bt, str.size());
|
|
||||||
bt.Put((const byte *)str.data(), str.size());
|
|
||||||
return 1+lengthBytes+str.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!bt.Get(b) || b != asnTag)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
size_t bc;
|
|
||||||
if (!BERLengthDecode(bt, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
SecByteBlock temp(bc);
|
|
||||||
if (bc != bt.Get(temp, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
str.assign((char *)temp.begin(), bc);
|
|
||||||
return bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ASN BitString
|
|
||||||
size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
|
|
||||||
{
|
|
||||||
bt.Put(BIT_STRING);
|
|
||||||
size_t lengthBytes = DERLengthEncode(bt, strLen+1);
|
|
||||||
bt.Put((byte)unusedBits);
|
|
||||||
bt.Put(str, strLen);
|
|
||||||
return 2+lengthBytes+strLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!bt.Get(b) || b != BIT_STRING)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
size_t bc;
|
|
||||||
if (!BERLengthDecode(bt, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
byte unused;
|
|
||||||
if (!bt.Get(unused))
|
|
||||||
BERDecodeError();
|
|
||||||
unusedBits = unused;
|
|
||||||
str.resize(bc-1);
|
|
||||||
if ((bc-1) != bt.Get(str, bc-1))
|
|
||||||
BERDecodeError();
|
|
||||||
return bc-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
|
|
||||||
{
|
|
||||||
byte tag;
|
|
||||||
source.Peek(tag);
|
|
||||||
BERGeneralDecoder decoder(source, tag);
|
|
||||||
DERGeneralEncoder encoder(dest, tag);
|
|
||||||
if (decoder.IsDefiniteLength())
|
|
||||||
decoder.TransferTo(encoder, decoder.RemainingLength());
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (!decoder.EndReached())
|
|
||||||
DERReencode(decoder, encoder);
|
|
||||||
}
|
|
||||||
decoder.MessageEnd();
|
|
||||||
encoder.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OID::EncodeValue(BufferedTransformation &bt, word32 v)
|
|
||||||
{
|
|
||||||
for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
|
|
||||||
bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
|
|
||||||
bt.Put((byte)(v & 0x7f));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
size_t i=0;
|
|
||||||
v = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (!bt.Get(b))
|
|
||||||
BERDecodeError();
|
|
||||||
i++;
|
|
||||||
if (v >> (8*sizeof(v)-7)) // v about to overflow
|
|
||||||
BERDecodeError();
|
|
||||||
v <<= 7;
|
|
||||||
v += b & 0x7f;
|
|
||||||
if (!(b & 0x80))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OID::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
assert(m_values.size() >= 2);
|
|
||||||
ByteQueue temp;
|
|
||||||
temp.Put(byte(m_values[0] * 40 + m_values[1]));
|
|
||||||
for (size_t i=2; i<m_values.size(); i++)
|
|
||||||
EncodeValue(temp, m_values[i]);
|
|
||||||
bt.Put(OBJECT_IDENTIFIER);
|
|
||||||
DERLengthEncode(bt, temp.CurrentSize());
|
|
||||||
temp.TransferTo(bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OID::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
size_t length;
|
|
||||||
if (!BERLengthDecode(bt, length) || length < 1)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
if (!bt.Get(b))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
length--;
|
|
||||||
m_values.resize(2);
|
|
||||||
m_values[0] = b / 40;
|
|
||||||
m_values[1] = b % 40;
|
|
||||||
|
|
||||||
while (length > 0)
|
|
||||||
{
|
|
||||||
word32 v;
|
|
||||||
size_t valueLen = DecodeValue(bt, v);
|
|
||||||
if (valueLen > length)
|
|
||||||
BERDecodeError();
|
|
||||||
m_values.push_back(v);
|
|
||||||
length -= valueLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
OID oid(bt);
|
|
||||||
if (*this != oid)
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
|
|
||||||
{
|
|
||||||
if (m_flags & PUT_OBJECTS)
|
|
||||||
return *AttachedTransformation();
|
|
||||||
else
|
|
||||||
return TheBitBucket();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncodedObjectFilter::Put(const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
if (m_nCurrentObject == m_nObjects)
|
|
||||||
{
|
|
||||||
AttachedTransformation()->Put(inString, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyPutter lazyPutter(m_queue, inString, length);
|
|
||||||
|
|
||||||
while (m_queue.AnyRetrievable())
|
|
||||||
{
|
|
||||||
switch (m_state)
|
|
||||||
{
|
|
||||||
case IDENTIFIER:
|
|
||||||
if (!m_queue.Get(m_id))
|
|
||||||
return;
|
|
||||||
m_queue.TransferTo(CurrentTarget(), 1);
|
|
||||||
m_state = LENGTH; // fall through
|
|
||||||
case LENGTH:
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
|
|
||||||
{
|
|
||||||
m_queue.TransferTo(CurrentTarget(), 1);
|
|
||||||
m_level--;
|
|
||||||
m_state = IDENTIFIER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ByteQueue::Walker walker(m_queue);
|
|
||||||
bool definiteLength;
|
|
||||||
if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
|
|
||||||
return;
|
|
||||||
m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
|
|
||||||
if (!((m_id & CONSTRUCTED) || definiteLength))
|
|
||||||
BERDecodeError();
|
|
||||||
if (!definiteLength)
|
|
||||||
{
|
|
||||||
if (!(m_id & CONSTRUCTED))
|
|
||||||
BERDecodeError();
|
|
||||||
m_level++;
|
|
||||||
m_state = IDENTIFIER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_state = BODY; // fall through
|
|
||||||
}
|
|
||||||
case BODY:
|
|
||||||
m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
|
|
||||||
|
|
||||||
if (m_lengthRemaining == 0)
|
|
||||||
m_state = IDENTIFIER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_state == IDENTIFIER && m_level == 0)
|
|
||||||
{
|
|
||||||
// just finished processing a level 0 object
|
|
||||||
++m_nCurrentObject;
|
|
||||||
|
|
||||||
if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
|
|
||||||
AttachedTransformation()->MessageEnd();
|
|
||||||
|
|
||||||
if (m_nCurrentObject == m_nObjects)
|
|
||||||
{
|
|
||||||
if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
|
|
||||||
AttachedTransformation()->MessageEnd();
|
|
||||||
|
|
||||||
if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
|
|
||||||
AttachedTransformation()->MessageSeriesEnd();
|
|
||||||
|
|
||||||
m_queue.TransferAllTo(*AttachedTransformation());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
|
|
||||||
: m_inQueue(inQueue), m_finished(false)
|
|
||||||
{
|
|
||||||
Init(asnTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
|
|
||||||
: m_inQueue(inQueue), m_finished(false)
|
|
||||||
{
|
|
||||||
Init(asnTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BERGeneralDecoder::Init(byte asnTag)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!m_inQueue.Get(b) || b != asnTag)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
if (!m_definiteLength && !(asnTag & CONSTRUCTED))
|
|
||||||
BERDecodeError(); // cannot be primitive and have indefinite length
|
|
||||||
}
|
|
||||||
|
|
||||||
BERGeneralDecoder::~BERGeneralDecoder()
|
|
||||||
{
|
|
||||||
try // avoid throwing in constructor
|
|
||||||
{
|
|
||||||
if (!m_finished)
|
|
||||||
MessageEnd();
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BERGeneralDecoder::EndReached() const
|
|
||||||
{
|
|
||||||
if (m_definiteLength)
|
|
||||||
return m_length == 0;
|
|
||||||
else
|
|
||||||
{ // check end-of-content octets
|
|
||||||
word16 i;
|
|
||||||
return (m_inQueue.PeekWord16(i)==2 && i==0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte BERGeneralDecoder::PeekByte() const
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!Peek(b))
|
|
||||||
BERDecodeError();
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BERGeneralDecoder::CheckByte(byte check)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!Get(b) || b != check)
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BERGeneralDecoder::MessageEnd()
|
|
||||||
{
|
|
||||||
m_finished = true;
|
|
||||||
if (m_definiteLength)
|
|
||||||
{
|
|
||||||
if (m_length != 0)
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // remove end-of-content octets
|
|
||||||
word16 i;
|
|
||||||
if (m_inQueue.GetWord16(i) != 2 || i != 0)
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
|
|
||||||
{
|
|
||||||
if (m_definiteLength && transferBytes > m_length)
|
|
||||||
transferBytes = m_length;
|
|
||||||
size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
|
|
||||||
ReduceLength(transferBytes);
|
|
||||||
return blockedBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
|
|
||||||
{
|
|
||||||
if (m_definiteLength)
|
|
||||||
end = STDMIN(m_length, end);
|
|
||||||
return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
lword BERGeneralDecoder::ReduceLength(lword delta)
|
|
||||||
{
|
|
||||||
if (m_definiteLength)
|
|
||||||
{
|
|
||||||
if (m_length < delta)
|
|
||||||
BERDecodeError();
|
|
||||||
m_length -= delta;
|
|
||||||
}
|
|
||||||
return delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
|
|
||||||
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
|
|
||||||
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DERGeneralEncoder::~DERGeneralEncoder()
|
|
||||||
{
|
|
||||||
try // avoid throwing in constructor
|
|
||||||
{
|
|
||||||
if (!m_finished)
|
|
||||||
MessageEnd();
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DERGeneralEncoder::MessageEnd()
|
|
||||||
{
|
|
||||||
m_finished = true;
|
|
||||||
lword length = CurrentSize();
|
|
||||||
m_outQueue.Put(m_asnTag);
|
|
||||||
DERLengthEncode(m_outQueue, length);
|
|
||||||
TransferTo(m_outQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *************************************************************
|
|
||||||
|
|
||||||
void X509PublicKey::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder subjectPublicKeyInfo(bt);
|
|
||||||
BERSequenceDecoder algorithm(subjectPublicKeyInfo);
|
|
||||||
GetAlgorithmID().BERDecodeAndCheck(algorithm);
|
|
||||||
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
|
|
||||||
algorithm.MessageEnd();
|
|
||||||
|
|
||||||
BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
|
|
||||||
subjectPublicKey.CheckByte(0); // unused bits
|
|
||||||
BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
|
|
||||||
subjectPublicKey.MessageEnd();
|
|
||||||
subjectPublicKeyInfo.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void X509PublicKey::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder subjectPublicKeyInfo(bt);
|
|
||||||
|
|
||||||
DERSequenceEncoder algorithm(subjectPublicKeyInfo);
|
|
||||||
GetAlgorithmID().DEREncode(algorithm);
|
|
||||||
DEREncodeAlgorithmParameters(algorithm);
|
|
||||||
algorithm.MessageEnd();
|
|
||||||
|
|
||||||
DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
|
|
||||||
subjectPublicKey.Put(0); // unused bits
|
|
||||||
DEREncodePublicKey(subjectPublicKey);
|
|
||||||
subjectPublicKey.MessageEnd();
|
|
||||||
|
|
||||||
subjectPublicKeyInfo.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder privateKeyInfo(bt);
|
|
||||||
word32 version;
|
|
||||||
BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
|
|
||||||
|
|
||||||
BERSequenceDecoder algorithm(privateKeyInfo);
|
|
||||||
GetAlgorithmID().BERDecodeAndCheck(algorithm);
|
|
||||||
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
|
|
||||||
algorithm.MessageEnd();
|
|
||||||
|
|
||||||
BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
|
|
||||||
BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
|
|
||||||
octetString.MessageEnd();
|
|
||||||
|
|
||||||
if (!privateKeyInfo.EndReached())
|
|
||||||
BERDecodeOptionalAttributes(privateKeyInfo);
|
|
||||||
privateKeyInfo.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder privateKeyInfo(bt);
|
|
||||||
DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
|
|
||||||
|
|
||||||
DERSequenceEncoder algorithm(privateKeyInfo);
|
|
||||||
GetAlgorithmID().DEREncode(algorithm);
|
|
||||||
DEREncodeAlgorithmParameters(algorithm);
|
|
||||||
algorithm.MessageEnd();
|
|
||||||
|
|
||||||
DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
|
|
||||||
DEREncodePrivateKey(octetString);
|
|
||||||
octetString.MessageEnd();
|
|
||||||
|
|
||||||
DEREncodeOptionalAttributes(privateKeyInfo);
|
|
||||||
privateKeyInfo.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
DERReencode(bt, m_optionalAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
m_optionalAttributes.CopyTo(bt);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,369 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ASN_H
|
|
||||||
#define CRYPTOPP_ASN_H
|
|
||||||
|
|
||||||
#include "filters.h"
|
|
||||||
#include "queue.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
// these tags and flags are not complete
|
|
||||||
enum ASNTag
|
|
||||||
{
|
|
||||||
BOOLEAN = 0x01,
|
|
||||||
INTEGER = 0x02,
|
|
||||||
BIT_STRING = 0x03,
|
|
||||||
OCTET_STRING = 0x04,
|
|
||||||
TAG_NULL = 0x05,
|
|
||||||
OBJECT_IDENTIFIER = 0x06,
|
|
||||||
OBJECT_DESCRIPTOR = 0x07,
|
|
||||||
EXTERNAL = 0x08,
|
|
||||||
REAL = 0x09,
|
|
||||||
ENUMERATED = 0x0a,
|
|
||||||
UTF8_STRING = 0x0c,
|
|
||||||
SEQUENCE = 0x10,
|
|
||||||
SET = 0x11,
|
|
||||||
NUMERIC_STRING = 0x12,
|
|
||||||
PRINTABLE_STRING = 0x13,
|
|
||||||
T61_STRING = 0x14,
|
|
||||||
VIDEOTEXT_STRING = 0x15,
|
|
||||||
IA5_STRING = 0x16,
|
|
||||||
UTC_TIME = 0x17,
|
|
||||||
GENERALIZED_TIME = 0x18,
|
|
||||||
GRAPHIC_STRING = 0x19,
|
|
||||||
VISIBLE_STRING = 0x1a,
|
|
||||||
GENERAL_STRING = 0x1b
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ASNIdFlag
|
|
||||||
{
|
|
||||||
UNIVERSAL = 0x00,
|
|
||||||
// DATA = 0x01,
|
|
||||||
// HEADER = 0x02,
|
|
||||||
CONSTRUCTED = 0x20,
|
|
||||||
APPLICATION = 0x40,
|
|
||||||
CONTEXT_SPECIFIC = 0x80,
|
|
||||||
PRIVATE = 0xc0
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void BERDecodeError() {throw BERDecodeErr();}
|
|
||||||
|
|
||||||
class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
|
|
||||||
UnknownOID(const char *err) : BERDecodeErr(err) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length);
|
|
||||||
// returns false if indefinite length
|
|
||||||
CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length);
|
|
||||||
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out);
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in);
|
|
||||||
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen);
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
|
|
||||||
|
|
||||||
// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
|
|
||||||
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0);
|
|
||||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
|
|
||||||
|
|
||||||
// BER decode from source and DER reencode into dest
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest);
|
|
||||||
|
|
||||||
//! Object Identifier
|
|
||||||
class CRYPTOPP_DLL OID
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
OID() {}
|
|
||||||
OID(word32 v) : m_values(1, v) {}
|
|
||||||
OID(BufferedTransformation &bt) {BERDecode(bt);}
|
|
||||||
|
|
||||||
inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
|
|
||||||
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
|
|
||||||
// throw BERDecodeErr() if decoded value doesn't equal this OID
|
|
||||||
void BERDecodeAndCheck(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
std::vector<word32> m_values;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void EncodeValue(BufferedTransformation &bt, word32 v);
|
|
||||||
static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
|
|
||||||
};
|
|
||||||
|
|
||||||
class EncodedObjectFilter : public Filter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
|
|
||||||
EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
|
|
||||||
|
|
||||||
void Put(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
|
|
||||||
unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BufferedTransformation & CurrentTarget();
|
|
||||||
|
|
||||||
word32 m_flags;
|
|
||||||
unsigned int m_nObjects, m_nCurrentObject, m_level;
|
|
||||||
std::vector<unsigned int> m_positions;
|
|
||||||
ByteQueue m_queue;
|
|
||||||
enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
|
|
||||||
byte m_id;
|
|
||||||
lword m_lengthRemaining;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! BER General Decoder
|
|
||||||
class CRYPTOPP_DLL BERGeneralDecoder : public Store
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
|
|
||||||
explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
|
|
||||||
~BERGeneralDecoder();
|
|
||||||
|
|
||||||
bool IsDefiniteLength() const {return m_definiteLength;}
|
|
||||||
lword RemainingLength() const {assert(m_definiteLength); return m_length;}
|
|
||||||
bool EndReached() const;
|
|
||||||
byte PeekByte() const;
|
|
||||||
void CheckByte(byte b);
|
|
||||||
|
|
||||||
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
|
||||||
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
|
|
||||||
|
|
||||||
// call this to denote end of sequence
|
|
||||||
void MessageEnd();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
BufferedTransformation &m_inQueue;
|
|
||||||
bool m_finished, m_definiteLength;
|
|
||||||
lword m_length;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Init(byte asnTag);
|
|
||||||
void StoreInitialize(const NameValuePairs ¶meters) {assert(false);}
|
|
||||||
lword ReduceLength(lword delta);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DER General Encoder
|
|
||||||
class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
|
||||||
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
|
||||||
~DERGeneralEncoder();
|
|
||||||
|
|
||||||
// call this to denote end of sequence
|
|
||||||
void MessageEnd();
|
|
||||||
|
|
||||||
private:
|
|
||||||
BufferedTransformation &m_outQueue;
|
|
||||||
bool m_finished;
|
|
||||||
|
|
||||||
byte m_asnTag;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! BER Sequence Decoder
|
|
||||||
class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
|
||||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
|
||||||
explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
|
||||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DER Sequence Encoder
|
|
||||||
class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
|
||||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
|
||||||
explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
|
||||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! BER Set Decoder
|
|
||||||
class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
|
|
||||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
|
||||||
explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
|
|
||||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DER Set Encoder
|
|
||||||
class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
|
|
||||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
|
||||||
explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
|
|
||||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class ASNOptional : public member_ptr<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (seqDecoder.Peek(b) && (b & mask) == tag)
|
|
||||||
reset(new T(seqDecoder));
|
|
||||||
}
|
|
||||||
void DEREncode(BufferedTransformation &out)
|
|
||||||
{
|
|
||||||
if (this->get() != NULL)
|
|
||||||
this->get()->DEREncode(out);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class BASE>
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Save(BufferedTransformation &bt) const
|
|
||||||
{BEREncode(bt);}
|
|
||||||
void Load(BufferedTransformation &bt)
|
|
||||||
{BERDecode(bt);}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! encodes/decodes subjectPublicKeyInfo
|
|
||||||
class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
virtual OID GetAlgorithmID() const =0;
|
|
||||||
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
|
|
||||||
{BERDecodeNull(bt); return false;}
|
|
||||||
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
|
|
||||||
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
|
|
||||||
|
|
||||||
//! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
|
|
||||||
virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
|
|
||||||
//! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
|
|
||||||
virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! encodes/decodes privateKeyInfo
|
|
||||||
class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
virtual OID GetAlgorithmID() const =0;
|
|
||||||
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
|
|
||||||
{BERDecodeNull(bt); return false;}
|
|
||||||
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
|
|
||||||
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
|
|
||||||
|
|
||||||
//! decode privateKey part of privateKeyInfo, without the OCTET STRING header
|
|
||||||
virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
|
|
||||||
//! encode privateKey part of privateKeyInfo, without the OCTET STRING header
|
|
||||||
virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
|
|
||||||
|
|
||||||
//! decode optional attributes including context-specific tag
|
|
||||||
/*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
|
|
||||||
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
|
|
||||||
//! encode optional attributes including context-specific tag
|
|
||||||
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ByteQueue m_optionalAttributes;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
//! DER Encode Unsigned
|
|
||||||
/*! for INTEGER, BOOLEAN, and ENUM */
|
|
||||||
template <class T>
|
|
||||||
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
|
|
||||||
{
|
|
||||||
byte buf[sizeof(w)+1];
|
|
||||||
unsigned int bc;
|
|
||||||
if (asnTag == BOOLEAN)
|
|
||||||
{
|
|
||||||
buf[sizeof(w)] = w ? 0xff : 0;
|
|
||||||
bc = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf[0] = 0;
|
|
||||||
for (unsigned int i=0; i<sizeof(w); i++)
|
|
||||||
buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
|
|
||||||
bc = sizeof(w);
|
|
||||||
while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
|
|
||||||
--bc;
|
|
||||||
if (buf[sizeof(w)+1-bc] & 0x80)
|
|
||||||
++bc;
|
|
||||||
}
|
|
||||||
out.Put(asnTag);
|
|
||||||
size_t lengthBytes = DERLengthEncode(out, bc);
|
|
||||||
out.Put(buf+sizeof(w)+1-bc, bc);
|
|
||||||
return 1+lengthBytes+bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! BER Decode Unsigned
|
|
||||||
// VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro
|
|
||||||
// CW41 workaround: std::numeric_limits<T>::max causes a template error
|
|
||||||
template <class T>
|
|
||||||
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
|
|
||||||
T minValue = 0, T maxValue = 0xffffffff)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!in.Get(b) || b != asnTag)
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
size_t bc;
|
|
||||||
BERLengthDecode(in, bc);
|
|
||||||
|
|
||||||
SecByteBlock buf(bc);
|
|
||||||
|
|
||||||
if (bc != in.Get(buf, bc))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
const byte *ptr = buf;
|
|
||||||
while (bc > sizeof(w) && *ptr == 0)
|
|
||||||
{
|
|
||||||
bc--;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
if (bc > sizeof(w))
|
|
||||||
BERDecodeError();
|
|
||||||
|
|
||||||
w = 0;
|
|
||||||
for (unsigned int i=0; i<bc; i++)
|
|
||||||
w = (w << 8) | ptr[i];
|
|
||||||
|
|
||||||
if (w < minValue || w > maxValue)
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
|
||||||
{return lhs.m_values == rhs.m_values;}
|
|
||||||
inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
|
||||||
{return lhs.m_values != rhs.m_values;}
|
|
||||||
inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
|
||||||
{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
|
|
||||||
inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
|
|
||||||
{return ::CryptoPP::OID(lhs)+=rhs;}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,180 +0,0 @@
|
||||||
// authenc.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "authenc.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
|
|
||||||
{
|
|
||||||
unsigned int blockSize = AuthenticationBlockSize();
|
|
||||||
unsigned int &num = m_bufferedDataLength;
|
|
||||||
byte* data = m_buffer.begin();
|
|
||||||
|
|
||||||
if (num != 0) // process left over data
|
|
||||||
{
|
|
||||||
if (num+len >= blockSize)
|
|
||||||
{
|
|
||||||
memcpy(data+num, input, blockSize-num);
|
|
||||||
AuthenticateBlocks(data, blockSize);
|
|
||||||
input += (blockSize-num);
|
|
||||||
len -= (blockSize-num);
|
|
||||||
num = 0;
|
|
||||||
// drop through and do the rest
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(data+num, input, len);
|
|
||||||
num += (unsigned int)len;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now process the input data in blocks of blockSize bytes and save the leftovers to m_data
|
|
||||||
if (len >= blockSize)
|
|
||||||
{
|
|
||||||
size_t leftOver = AuthenticateBlocks(input, len);
|
|
||||||
input += (len - leftOver);
|
|
||||||
len = leftOver;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data, input, len);
|
|
||||||
num = (unsigned int)len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
m_state = State_Start;
|
|
||||||
|
|
||||||
SetKeyWithoutResync(userKey, keylength, params);
|
|
||||||
m_state = State_KeySet;
|
|
||||||
|
|
||||||
size_t length;
|
|
||||||
const byte *iv = GetIVAndThrowIfInvalid(params, length);
|
|
||||||
if (iv)
|
|
||||||
Resynchronize(iv, (int)length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
|
|
||||||
{
|
|
||||||
if (m_state < State_KeySet)
|
|
||||||
throw BadState(AlgorithmName(), "Resynchronize", "key is set");
|
|
||||||
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
|
|
||||||
m_state = State_KeySet;
|
|
||||||
|
|
||||||
Resync(iv, this->ThrowIfInvalidIVLength(length));
|
|
||||||
m_state = State_IVSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
|
|
||||||
{
|
|
||||||
if (length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (m_state)
|
|
||||||
{
|
|
||||||
case State_Start:
|
|
||||||
case State_KeySet:
|
|
||||||
throw BadState(AlgorithmName(), "Update", "setting key and IV");
|
|
||||||
case State_IVSet:
|
|
||||||
AuthenticateData(input, length);
|
|
||||||
m_totalHeaderLength += length;
|
|
||||||
break;
|
|
||||||
case State_AuthUntransformed:
|
|
||||||
case State_AuthTransformed:
|
|
||||||
AuthenticateLastConfidentialBlock();
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
m_state = State_AuthFooter;
|
|
||||||
// fall through
|
|
||||||
case State_AuthFooter:
|
|
||||||
AuthenticateData(input, length);
|
|
||||||
m_totalFooterLength += length;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
m_totalMessageLength += length;
|
|
||||||
if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
|
|
||||||
|
|
||||||
reswitch:
|
|
||||||
switch (m_state)
|
|
||||||
{
|
|
||||||
case State_Start:
|
|
||||||
case State_KeySet:
|
|
||||||
throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
|
|
||||||
case State_AuthFooter:
|
|
||||||
throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
|
|
||||||
case State_IVSet:
|
|
||||||
AuthenticateLastHeaderBlock();
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
|
|
||||||
goto reswitch;
|
|
||||||
case State_AuthUntransformed:
|
|
||||||
AuthenticateData(inString, length);
|
|
||||||
AccessSymmetricCipher().ProcessData(outString, inString, length);
|
|
||||||
break;
|
|
||||||
case State_AuthTransformed:
|
|
||||||
AccessSymmetricCipher().ProcessData(outString, inString, length);
|
|
||||||
AuthenticateData(outString, length);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
|
|
||||||
{
|
|
||||||
if (m_totalHeaderLength > MaxHeaderLength())
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
|
|
||||||
|
|
||||||
if (m_totalFooterLength > MaxFooterLength())
|
|
||||||
{
|
|
||||||
if (MaxFooterLength() == 0)
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
|
|
||||||
else
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_state)
|
|
||||||
{
|
|
||||||
case State_Start:
|
|
||||||
case State_KeySet:
|
|
||||||
throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
|
|
||||||
|
|
||||||
case State_IVSet:
|
|
||||||
AuthenticateLastHeaderBlock();
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
case State_AuthUntransformed:
|
|
||||||
case State_AuthTransformed:
|
|
||||||
AuthenticateLastConfidentialBlock();
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
case State_AuthFooter:
|
|
||||||
AuthenticateLastFooterBlock(mac, macSize);
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_state = State_KeySet;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,49 +0,0 @@
|
||||||
#ifndef CRYPTOPP_AUTHENC_H
|
|
||||||
#define CRYPTOPP_AUTHENC_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! .
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AuthenticatedSymmetricCipherBase() : m_state(State_Start) {}
|
|
||||||
|
|
||||||
bool IsRandomAccess() const {return false;}
|
|
||||||
bool IsSelfInverting() const {return true;}
|
|
||||||
void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);}
|
|
||||||
|
|
||||||
void SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms);
|
|
||||||
void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;}
|
|
||||||
void Resynchronize(const byte *iv, int length=-1);
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
|
||||||
void TruncatedFinal(byte *mac, size_t macSize);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void AuthenticateData(const byte *data, size_t len);
|
|
||||||
const SymmetricCipher & GetSymmetricCipher() const {return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
|
|
||||||
|
|
||||||
virtual SymmetricCipher & AccessSymmetricCipher() =0;
|
|
||||||
virtual bool AuthenticationIsOnPlaintext() const =0;
|
|
||||||
virtual unsigned int AuthenticationBlockSize() const =0;
|
|
||||||
virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) =0;
|
|
||||||
virtual void Resync(const byte *iv, size_t len) =0;
|
|
||||||
virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0;
|
|
||||||
virtual void AuthenticateLastHeaderBlock() =0;
|
|
||||||
virtual void AuthenticateLastConfidentialBlock() {}
|
|
||||||
virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0;
|
|
||||||
|
|
||||||
enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter};
|
|
||||||
State m_state;
|
|
||||||
unsigned int m_bufferedDataLength;
|
|
||||||
lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength;
|
|
||||||
AlignedSecByteBlock m_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,39 +0,0 @@
|
||||||
// base32.cpp - written and placed in the public domain by Frank Palazzolo, based on hex.cpp by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "base32.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
static const byte s_vecUpper[] = "ABCDEFGHIJKMNPQRSTUVWXYZ23456789";
|
|
||||||
static const byte s_vecLower[] = "abcdefghijkmnpqrstuvwxyz23456789";
|
|
||||||
|
|
||||||
void Base32Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true);
|
|
||||||
m_filter->Initialize(CombinedNameValuePairs(
|
|
||||||
parameters,
|
|
||||||
MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 5, true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Base32Decoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
BaseN_Decoder::Initialize(CombinedNameValuePairs(
|
|
||||||
parameters,
|
|
||||||
MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 5, true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const int *Base32Decoder::GetDefaultDecodingLookupArray()
|
|
||||||
{
|
|
||||||
static volatile bool s_initialized = false;
|
|
||||||
static int s_array[256];
|
|
||||||
|
|
||||||
if (!s_initialized)
|
|
||||||
{
|
|
||||||
InitializeDecodingLookupArray(s_array, s_vecUpper, 32, true);
|
|
||||||
s_initialized = true;
|
|
||||||
}
|
|
||||||
return s_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,38 +0,0 @@
|
||||||
#ifndef CRYPTOPP_BASE32_H
|
|
||||||
#define CRYPTOPP_BASE32_H
|
|
||||||
|
|
||||||
#include "basecode.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Converts given data to base 32, the default code is based on draft-ietf-idn-dude-02.txt
|
|
||||||
/*! To specify alternative code, call Initialize() with EncodingLookupArray parameter. */
|
|
||||||
class Base32Encoder : public SimpleProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Base32Encoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
|
|
||||||
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
|
|
||||||
{
|
|
||||||
IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Decode base 32 data back to bytes, the default code is based on draft-ietf-idn-dude-02.txt
|
|
||||||
/*! To specify alternative code, call Initialize() with DecodingLookupArray parameter. */
|
|
||||||
class Base32Decoder : public BaseN_Decoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Base32Decoder(BufferedTransformation *attachment = NULL)
|
|
||||||
: BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,42 +0,0 @@
|
||||||
// base64.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
static const byte s_vec[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
||||||
static const byte s_padding = '=';
|
|
||||||
|
|
||||||
void Base64Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
bool insertLineBreaks = parameters.GetValueWithDefault(Name::InsertLineBreaks(), true);
|
|
||||||
int maxLineLength = parameters.GetIntValueWithDefault(Name::MaxLineLength(), 72);
|
|
||||||
|
|
||||||
const char *lineBreak = insertLineBreaks ? "\n" : "";
|
|
||||||
|
|
||||||
m_filter->Initialize(CombinedNameValuePairs(
|
|
||||||
parameters,
|
|
||||||
MakeParameters(Name::EncodingLookupArray(), &s_vec[0], false)
|
|
||||||
(Name::PaddingByte(), s_padding)
|
|
||||||
(Name::GroupSize(), insertLineBreaks ? maxLineLength : 0)
|
|
||||||
(Name::Separator(), ConstByteArrayParameter(lineBreak))
|
|
||||||
(Name::Terminator(), ConstByteArrayParameter(lineBreak))
|
|
||||||
(Name::Log2Base(), 6, true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const int *Base64Decoder::GetDecodingLookupArray()
|
|
||||||
{
|
|
||||||
static volatile bool s_initialized = false;
|
|
||||||
static int s_array[256];
|
|
||||||
|
|
||||||
if (!s_initialized)
|
|
||||||
{
|
|
||||||
InitializeDecodingLookupArray(s_array, s_vec, 64, false);
|
|
||||||
s_initialized = true;
|
|
||||||
}
|
|
||||||
return s_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef CRYPTOPP_BASE64_H
|
|
||||||
#define CRYPTOPP_BASE64_H
|
|
||||||
|
|
||||||
#include "basecode.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Base64 Encoder Class
|
|
||||||
class Base64Encoder : public SimpleProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Base64Encoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = true, int maxLineLength = 72)
|
|
||||||
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
|
|
||||||
{
|
|
||||||
IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Base64 Decoder Class
|
|
||||||
class Base64Decoder : public BaseN_Decoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Base64Decoder(BufferedTransformation *attachment = NULL)
|
|
||||||
: BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int * CRYPTOPP_API GetDecodingLookupArray();
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,238 +0,0 @@
|
||||||
// basecode.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "basecode.h"
|
|
||||||
#include "fltrimpl.h"
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet);
|
|
||||||
|
|
||||||
parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar);
|
|
||||||
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
|
|
||||||
throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive");
|
|
||||||
|
|
||||||
byte padding;
|
|
||||||
bool pad;
|
|
||||||
if (parameters.GetValue(Name::PaddingByte(), padding))
|
|
||||||
pad = parameters.GetValueWithDefault(Name::Pad(), true);
|
|
||||||
else
|
|
||||||
pad = false;
|
|
||||||
m_padding = pad ? padding : -1;
|
|
||||||
|
|
||||||
m_bytePos = m_bitPos = 0;
|
|
||||||
|
|
||||||
int i = 8;
|
|
||||||
while (i%m_bitsPerChar != 0)
|
|
||||||
i += 8;
|
|
||||||
m_outputBlockSize = i/m_bitsPerChar;
|
|
||||||
|
|
||||||
m_outBuf.New(m_outputBlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
FILTER_BEGIN;
|
|
||||||
while (m_inputPosition < length)
|
|
||||||
{
|
|
||||||
if (m_bytePos == 0)
|
|
||||||
memset(m_outBuf, 0, m_outputBlockSize);
|
|
||||||
|
|
||||||
{
|
|
||||||
unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
assert(m_bitPos < m_bitsPerChar);
|
|
||||||
unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos;
|
|
||||||
m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget);
|
|
||||||
if (bitsLeftInSource >= bitsLeftInTarget)
|
|
||||||
{
|
|
||||||
m_bitPos = 0;
|
|
||||||
++m_bytePos;
|
|
||||||
bitsLeftInSource -= bitsLeftInTarget;
|
|
||||||
if (bitsLeftInSource == 0)
|
|
||||||
break;
|
|
||||||
b <<= bitsLeftInTarget;
|
|
||||||
b &= 0xff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_bitPos += bitsLeftInSource;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(m_bytePos <= m_outputBlockSize);
|
|
||||||
if (m_bytePos == m_outputBlockSize)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0; i<m_bytePos; i++)
|
|
||||||
{
|
|
||||||
assert(m_outBuf[i] < (1 << m_bitsPerChar));
|
|
||||||
m_outBuf[i] = m_alphabet[m_outBuf[i]];
|
|
||||||
}
|
|
||||||
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
|
|
||||||
|
|
||||||
m_bytePos = m_bitPos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (messageEnd)
|
|
||||||
{
|
|
||||||
if (m_bitPos > 0)
|
|
||||||
++m_bytePos;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i=0; i<m_bytePos; i++)
|
|
||||||
m_outBuf[i] = m_alphabet[m_outBuf[i]];
|
|
||||||
|
|
||||||
if (m_padding != -1 && m_bytePos > 0)
|
|
||||||
{
|
|
||||||
memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos);
|
|
||||||
m_bytePos = m_outputBlockSize;
|
|
||||||
}
|
|
||||||
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
|
|
||||||
m_bytePos = m_bitPos = 0;
|
|
||||||
}
|
|
||||||
FILTER_END_NO_MESSAGE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup);
|
|
||||||
|
|
||||||
parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar);
|
|
||||||
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
|
|
||||||
throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive");
|
|
||||||
|
|
||||||
m_bytePos = m_bitPos = 0;
|
|
||||||
|
|
||||||
int i = m_bitsPerChar;
|
|
||||||
while (i%8 != 0)
|
|
||||||
i += m_bitsPerChar;
|
|
||||||
m_outputBlockSize = i/8;
|
|
||||||
|
|
||||||
m_outBuf.New(m_outputBlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
FILTER_BEGIN;
|
|
||||||
while (m_inputPosition < length)
|
|
||||||
{
|
|
||||||
unsigned int value;
|
|
||||||
value = m_lookup[begin[m_inputPosition++]];
|
|
||||||
if (value >= 256)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_bytePos == 0 && m_bitPos == 0)
|
|
||||||
memset(m_outBuf, 0, m_outputBlockSize);
|
|
||||||
|
|
||||||
{
|
|
||||||
int newBitPos = m_bitPos + m_bitsPerChar;
|
|
||||||
if (newBitPos <= 8)
|
|
||||||
m_outBuf[m_bytePos] |= value << (8-newBitPos);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_outBuf[m_bytePos] |= value >> (newBitPos-8);
|
|
||||||
m_outBuf[m_bytePos+1] |= value << (16-newBitPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bitPos = newBitPos;
|
|
||||||
while (m_bitPos >= 8)
|
|
||||||
{
|
|
||||||
m_bitPos -= 8;
|
|
||||||
++m_bytePos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_bytePos == m_outputBlockSize)
|
|
||||||
{
|
|
||||||
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
|
|
||||||
m_bytePos = m_bitPos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (messageEnd)
|
|
||||||
{
|
|
||||||
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
|
|
||||||
m_bytePos = m_bitPos = 0;
|
|
||||||
}
|
|
||||||
FILTER_END_NO_MESSAGE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive)
|
|
||||||
{
|
|
||||||
std::fill(lookup, lookup+256, -1);
|
|
||||||
|
|
||||||
for (unsigned int i=0; i<base; i++)
|
|
||||||
{
|
|
||||||
if (caseInsensitive && isalpha(alphabet[i]))
|
|
||||||
{
|
|
||||||
assert(lookup[toupper(alphabet[i])] == -1);
|
|
||||||
lookup[toupper(alphabet[i])] = i;
|
|
||||||
assert(lookup[tolower(alphabet[i])] == -1);
|
|
||||||
lookup[tolower(alphabet[i])] = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(lookup[alphabet[i]] == -1);
|
|
||||||
lookup[alphabet[i]] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grouper::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
m_groupSize = parameters.GetIntValueWithDefault(Name::GroupSize(), 0);
|
|
||||||
ConstByteArrayParameter separator, terminator;
|
|
||||||
if (m_groupSize)
|
|
||||||
parameters.GetRequiredParameter("Grouper", Name::Separator(), separator);
|
|
||||||
else
|
|
||||||
parameters.GetValue(Name::Separator(), separator);
|
|
||||||
parameters.GetValue(Name::Terminator(), terminator);
|
|
||||||
|
|
||||||
m_separator.Assign(separator.begin(), separator.size());
|
|
||||||
m_terminator.Assign(terminator.begin(), terminator.size());
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Grouper::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
FILTER_BEGIN;
|
|
||||||
if (m_groupSize)
|
|
||||||
{
|
|
||||||
while (m_inputPosition < length)
|
|
||||||
{
|
|
||||||
if (m_counter == m_groupSize)
|
|
||||||
{
|
|
||||||
FILTER_OUTPUT(1, m_separator, m_separator.size(), 0);
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len;
|
|
||||||
FILTER_OUTPUT2(2, len = STDMIN(length-m_inputPosition, m_groupSize-m_counter),
|
|
||||||
begin+m_inputPosition, len, 0);
|
|
||||||
m_inputPosition += len;
|
|
||||||
m_counter += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
FILTER_OUTPUT(3, begin, length, 0);
|
|
||||||
|
|
||||||
if (messageEnd)
|
|
||||||
{
|
|
||||||
FILTER_OUTPUT(4, m_terminator, m_terminator.size(), messageEnd);
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
|
||||||
FILTER_END_NO_MESSAGE_END
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,86 +0,0 @@
|
||||||
#ifndef CRYPTOPP_BASECODE_H
|
|
||||||
#define CRYPTOPP_BASECODE_H
|
|
||||||
|
|
||||||
#include "filters.h"
|
|
||||||
#include "algparam.h"
|
|
||||||
#include "argnames.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! base n encoder, where n is a power of 2
|
|
||||||
class CRYPTOPP_DLL BaseN_Encoder : public Unflushable<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseN_Encoder(BufferedTransformation *attachment=NULL)
|
|
||||||
{Detach(attachment);}
|
|
||||||
|
|
||||||
BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1)
|
|
||||||
{
|
|
||||||
Detach(attachment);
|
|
||||||
IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet)
|
|
||||||
(Name::Log2Base(), log2base)
|
|
||||||
(Name::Pad(), padding != -1)
|
|
||||||
(Name::PaddingByte(), byte(padding)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const byte *m_alphabet;
|
|
||||||
int m_padding, m_bitsPerChar, m_outputBlockSize;
|
|
||||||
int m_bytePos, m_bitPos;
|
|
||||||
SecByteBlock m_outBuf;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! base n decoder, where n is a power of 2
|
|
||||||
class CRYPTOPP_DLL BaseN_Decoder : public Unflushable<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BaseN_Decoder(BufferedTransformation *attachment=NULL)
|
|
||||||
{Detach(attachment);}
|
|
||||||
|
|
||||||
BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL)
|
|
||||||
{
|
|
||||||
Detach(attachment);
|
|
||||||
IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const int *m_lookup;
|
|
||||||
int m_padding, m_bitsPerChar, m_outputBlockSize;
|
|
||||||
int m_bytePos, m_bitPos;
|
|
||||||
SecByteBlock m_outBuf;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! filter that breaks input stream into groups of fixed size
|
|
||||||
class CRYPTOPP_DLL Grouper : public Bufferless<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Grouper(BufferedTransformation *attachment=NULL)
|
|
||||||
{Detach(attachment);}
|
|
||||||
|
|
||||||
Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL)
|
|
||||||
{
|
|
||||||
Detach(attachment);
|
|
||||||
IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize)
|
|
||||||
(Name::Separator(), ConstByteArrayParameter(separator))
|
|
||||||
(Name::Terminator(), ConstByteArrayParameter(terminator)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SecByteBlock m_separator, m_terminator;
|
|
||||||
size_t m_groupSize, m_counter;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,62 +0,0 @@
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "cbcmac.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void CBC_MAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
AccessCipher().SetKey(key, length, params);
|
|
||||||
m_reg.CleanNew(AccessCipher().BlockSize());
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBC_MAC_Base::Update(const byte *input, size_t length)
|
|
||||||
{
|
|
||||||
unsigned int blockSize = AccessCipher().BlockSize();
|
|
||||||
|
|
||||||
while (m_counter && length)
|
|
||||||
{
|
|
||||||
m_reg[m_counter++] ^= *input++;
|
|
||||||
if (m_counter == blockSize)
|
|
||||||
ProcessBuf();
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length >= blockSize)
|
|
||||||
{
|
|
||||||
size_t leftOver = AccessCipher().AdvancedProcessBlocks(m_reg, input, m_reg, length, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
|
||||||
input += (length - leftOver);
|
|
||||||
length = leftOver;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (length--)
|
|
||||||
{
|
|
||||||
m_reg[m_counter++] ^= *input++;
|
|
||||||
if (m_counter == blockSize)
|
|
||||||
ProcessBuf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBC_MAC_Base::TruncatedFinal(byte *mac, size_t size)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(size);
|
|
||||||
|
|
||||||
if (m_counter)
|
|
||||||
ProcessBuf();
|
|
||||||
|
|
||||||
memcpy(mac, m_reg, size);
|
|
||||||
memset(m_reg, 0, AccessCipher().BlockSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBC_MAC_Base::ProcessBuf()
|
|
||||||
{
|
|
||||||
AccessCipher().ProcessBlock(m_reg);
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,50 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CBCMAC_H
|
|
||||||
#define CRYPTOPP_CBCMAC_H
|
|
||||||
|
|
||||||
#include "seckey.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CBC_MAC_Base() {}
|
|
||||||
|
|
||||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void TruncatedFinal(byte *mac, size_t size);
|
|
||||||
unsigned int DigestSize() const {return const_cast<CBC_MAC_Base*>(this)->AccessCipher().BlockSize();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BlockCipher & AccessCipher() =0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ProcessBuf();
|
|
||||||
SecByteBlock m_reg;
|
|
||||||
unsigned int m_counter;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://www.weidai.com/scan-mirror/mac.html#CBC-MAC">CBC-MAC</a>
|
|
||||||
/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation.
|
|
||||||
Secure only for fixed length messages. For variable length messages use CMAC or DMAC.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CBC_MAC() {}
|
|
||||||
CBC_MAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
|
|
||||||
{this->SetKey(key, length);}
|
|
||||||
|
|
||||||
static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BlockCipher & AccessCipher() {return m_cipher;}
|
|
||||||
typename T::Encryption m_cipher;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,140 +0,0 @@
|
||||||
// ccm.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "ccm.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
BlockCipher &blockCipher = AccessBlockCipher();
|
|
||||||
|
|
||||||
blockCipher.SetKey(userKey, keylength, params);
|
|
||||||
|
|
||||||
if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
|
|
||||||
|
|
||||||
m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
|
|
||||||
if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
|
|
||||||
|
|
||||||
m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
|
|
||||||
m_L = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCM_Base::Resync(const byte *iv, size_t len)
|
|
||||||
{
|
|
||||||
BlockCipher &cipher = AccessBlockCipher();
|
|
||||||
|
|
||||||
m_L = REQUIRED_BLOCKSIZE-1-(int)len;
|
|
||||||
assert(m_L >= 2);
|
|
||||||
if (m_L > 8)
|
|
||||||
m_L = 8;
|
|
||||||
|
|
||||||
m_buffer[0] = byte(m_L-1); // flag
|
|
||||||
memcpy(m_buffer+1, iv, len);
|
|
||||||
memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
|
|
||||||
|
|
||||||
if (m_state >= State_IVSet)
|
|
||||||
m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
|
|
||||||
else
|
|
||||||
m_ctr.SetCipherWithIV(cipher, m_buffer);
|
|
||||||
|
|
||||||
m_ctr.Seek(REQUIRED_BLOCKSIZE);
|
|
||||||
m_aadLength = 0;
|
|
||||||
m_messageLength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
|
|
||||||
{
|
|
||||||
if (m_state != State_IVSet)
|
|
||||||
throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
|
|
||||||
|
|
||||||
m_aadLength = headerLength;
|
|
||||||
m_messageLength = messageLength;
|
|
||||||
|
|
||||||
byte *cbcBuffer = CBC_Buffer();
|
|
||||||
const BlockCipher &cipher = GetBlockCipher();
|
|
||||||
|
|
||||||
cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
|
|
||||||
PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
|
|
||||||
memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
|
|
||||||
cipher.ProcessBlock(cbcBuffer);
|
|
||||||
|
|
||||||
if (headerLength>0)
|
|
||||||
{
|
|
||||||
assert(m_bufferedDataLength == 0);
|
|
||||||
|
|
||||||
if (headerLength < ((1<<16) - (1<<8)))
|
|
||||||
{
|
|
||||||
PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
|
|
||||||
m_bufferedDataLength = 2;
|
|
||||||
}
|
|
||||||
else if (headerLength < (W64LIT(1)<<32))
|
|
||||||
{
|
|
||||||
m_buffer[0] = 0xff;
|
|
||||||
m_buffer[1] = 0xfe;
|
|
||||||
PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
|
|
||||||
m_bufferedDataLength = 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_buffer[0] = 0xff;
|
|
||||||
m_buffer[1] = 0xff;
|
|
||||||
PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
|
|
||||||
m_bufferedDataLength = 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
|
|
||||||
{
|
|
||||||
byte *cbcBuffer = CBC_Buffer();
|
|
||||||
const BlockCipher &cipher = GetBlockCipher();
|
|
||||||
return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCM_Base::AuthenticateLastHeaderBlock()
|
|
||||||
{
|
|
||||||
byte *cbcBuffer = CBC_Buffer();
|
|
||||||
const BlockCipher &cipher = GetBlockCipher();
|
|
||||||
|
|
||||||
if (m_aadLength != m_totalHeaderLength)
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
|
|
||||||
|
|
||||||
if (m_bufferedDataLength > 0)
|
|
||||||
{
|
|
||||||
xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
|
|
||||||
cipher.ProcessBlock(cbcBuffer);
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCM_Base::AuthenticateLastConfidentialBlock()
|
|
||||||
{
|
|
||||||
byte *cbcBuffer = CBC_Buffer();
|
|
||||||
const BlockCipher &cipher = GetBlockCipher();
|
|
||||||
|
|
||||||
if (m_messageLength != m_totalMessageLength)
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
|
|
||||||
|
|
||||||
if (m_bufferedDataLength > 0)
|
|
||||||
{
|
|
||||||
xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
|
|
||||||
cipher.ProcessBlock(cbcBuffer);
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
|
|
||||||
{
|
|
||||||
m_ctr.Seek(0);
|
|
||||||
m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,101 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CCM_H
|
|
||||||
#define CRYPTOPP_CCM_H
|
|
||||||
|
|
||||||
#include "authenc.h"
|
|
||||||
#include "modes.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! .
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCM_Base()
|
|
||||||
: m_digestSize(0), m_L(0) {}
|
|
||||||
|
|
||||||
// AuthenticatedSymmetricCipher
|
|
||||||
std::string AlgorithmName() const
|
|
||||||
{return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
|
|
||||||
size_t MinKeyLength() const
|
|
||||||
{return GetBlockCipher().MinKeyLength();}
|
|
||||||
size_t MaxKeyLength() const
|
|
||||||
{return GetBlockCipher().MaxKeyLength();}
|
|
||||||
size_t DefaultKeyLength() const
|
|
||||||
{return GetBlockCipher().DefaultKeyLength();}
|
|
||||||
size_t GetValidKeyLength(size_t n) const
|
|
||||||
{return GetBlockCipher().GetValidKeyLength(n);}
|
|
||||||
bool IsValidKeyLength(size_t n) const
|
|
||||||
{return GetBlockCipher().IsValidKeyLength(n);}
|
|
||||||
unsigned int OptimalDataAlignment() const
|
|
||||||
{return GetBlockCipher().OptimalDataAlignment();}
|
|
||||||
IV_Requirement IVRequirement() const
|
|
||||||
{return UNIQUE_IV;}
|
|
||||||
unsigned int IVSize() const
|
|
||||||
{return 8;}
|
|
||||||
unsigned int MinIVLength() const
|
|
||||||
{return 7;}
|
|
||||||
unsigned int MaxIVLength() const
|
|
||||||
{return 13;}
|
|
||||||
unsigned int DigestSize() const
|
|
||||||
{return m_digestSize;}
|
|
||||||
lword MaxHeaderLength() const
|
|
||||||
{return W64LIT(0)-1;}
|
|
||||||
lword MaxMessageLength() const
|
|
||||||
{return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}
|
|
||||||
bool NeedsPrespecifiedDataLengths() const
|
|
||||||
{return true;}
|
|
||||||
void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// AuthenticatedSymmetricCipherBase
|
|
||||||
bool AuthenticationIsOnPlaintext() const
|
|
||||||
{return true;}
|
|
||||||
unsigned int AuthenticationBlockSize() const
|
|
||||||
{return GetBlockCipher().BlockSize();}
|
|
||||||
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms);
|
|
||||||
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);
|
|
||||||
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
|
|
||||||
|
|
||||||
virtual BlockCipher & AccessBlockCipher() =0;
|
|
||||||
virtual int DefaultDigestSize() const =0;
|
|
||||||
|
|
||||||
const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
|
|
||||||
byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
|
|
||||||
|
|
||||||
enum {REQUIRED_BLOCKSIZE = 16};
|
|
||||||
int m_digestSize, m_L;
|
|
||||||
word64 m_messageLength, m_aadLength;
|
|
||||||
CTR_Mode_ExternalCipher::Encryption m_ctr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! .
|
|
||||||
template <class T_BlockCipher, int T_DefaultDigestSize, bool T_IsEncryption>
|
|
||||||
class CCM_Final : public CCM_Base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static std::string StaticAlgorithmName()
|
|
||||||
{return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");}
|
|
||||||
bool IsForwardTransformation() const
|
|
||||||
{return T_IsEncryption;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BlockCipher & AccessBlockCipher() {return m_cipher;}
|
|
||||||
int DefaultDigestSize() const {return T_DefaultDigestSize;}
|
|
||||||
typename T_BlockCipher::Encryption m_cipher;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <a href="http://www.cryptolounge.org/wiki/CCM">CCM</a>
|
|
||||||
template <class T_BlockCipher, int T_DefaultDigestSize = 16>
|
|
||||||
struct CCM : public AuthenticatedSymmetricCipherDocumentation
|
|
||||||
{
|
|
||||||
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, true> Encryption;
|
|
||||||
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, false> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,309 +0,0 @@
|
||||||
// channels.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "channels.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
USING_NAMESPACE(std)
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel)
|
|
||||||
{
|
|
||||||
m_defaultRoutes.push_back(Route(&destination, channel));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel)
|
|
||||||
{
|
|
||||||
RangeRoute route(begin, end, Route(&destination, channel));
|
|
||||||
RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route);
|
|
||||||
m_routes.insert(it, route);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
class MessageRouteIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef MessageSwitch::RouteList::const_iterator RouteIterator;
|
|
||||||
typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator;
|
|
||||||
|
|
||||||
bool m_useDefault;
|
|
||||||
RouteIterator m_itRouteCurrent, m_itRouteEnd;
|
|
||||||
DefaultIterator m_itDefaultCurrent, m_itDefaultEnd;
|
|
||||||
|
|
||||||
MessageRouteIterator(MessageSwitch &ms, const std::string &channel)
|
|
||||||
: m_channel(channel)
|
|
||||||
{
|
|
||||||
pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
|
|
||||||
if (range.first == range.second)
|
|
||||||
{
|
|
||||||
m_useDefault = true;
|
|
||||||
m_itListCurrent = cs.m_defaultRoutes.begin();
|
|
||||||
m_itListEnd = cs.m_defaultRoutes.end();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_useDefault = false;
|
|
||||||
m_itMapCurrent = range.first;
|
|
||||||
m_itMapEnd = range.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool End() const
|
|
||||||
{
|
|
||||||
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Next()
|
|
||||||
{
|
|
||||||
if (m_useDefault)
|
|
||||||
++m_itListCurrent;
|
|
||||||
else
|
|
||||||
++m_itMapCurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedTransformation & Destination()
|
|
||||||
{
|
|
||||||
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string & Message()
|
|
||||||
{
|
|
||||||
if (m_useDefault)
|
|
||||||
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
|
|
||||||
else
|
|
||||||
return m_itMapCurrent->second.second;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void MessageSwitch::Put(byte inByte);
|
|
||||||
void MessageSwitch::Put(const byte *inString, unsigned int length);
|
|
||||||
|
|
||||||
void MessageSwitch::Flush(bool completeFlush, int propagation=-1);
|
|
||||||
void MessageSwitch::MessageEnd(int propagation=-1);
|
|
||||||
void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
|
||||||
void MessageSwitch::MessageSeriesEnd(int propagation=-1);
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// ChannelRouteIterator
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
void ChannelRouteIterator::Reset(const std::string &channel)
|
|
||||||
{
|
|
||||||
m_channel = channel;
|
|
||||||
pair<MapIterator, MapIterator> range = m_cs.m_routeMap.equal_range(channel);
|
|
||||||
if (range.first == range.second)
|
|
||||||
{
|
|
||||||
m_useDefault = true;
|
|
||||||
m_itListCurrent = m_cs.m_defaultRoutes.begin();
|
|
||||||
m_itListEnd = m_cs.m_defaultRoutes.end();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_useDefault = false;
|
|
||||||
m_itMapCurrent = range.first;
|
|
||||||
m_itMapEnd = range.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelRouteIterator::End() const
|
|
||||||
{
|
|
||||||
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelRouteIterator::Next()
|
|
||||||
{
|
|
||||||
if (m_useDefault)
|
|
||||||
++m_itListCurrent;
|
|
||||||
else
|
|
||||||
++m_itMapCurrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedTransformation & ChannelRouteIterator::Destination()
|
|
||||||
{
|
|
||||||
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string & ChannelRouteIterator::Channel()
|
|
||||||
{
|
|
||||||
if (m_useDefault)
|
|
||||||
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
|
|
||||||
else
|
|
||||||
return m_itMapCurrent->second.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// ChannelSwitch
|
|
||||||
///////////////////
|
|
||||||
|
|
||||||
size_t ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
if (m_blocked)
|
|
||||||
{
|
|
||||||
m_blocked = false;
|
|
||||||
goto WasBlocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_it.Reset(channel);
|
|
||||||
|
|
||||||
while (!m_it.End())
|
|
||||||
{
|
|
||||||
WasBlocked:
|
|
||||||
if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking))
|
|
||||||
{
|
|
||||||
m_blocked = true;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_it.Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::IsolatedInitialize(const NameValuePairs ¶meters/* =g_nullNameValuePairs */)
|
|
||||||
{
|
|
||||||
m_routeMap.clear();
|
|
||||||
m_defaultRoutes.clear();
|
|
||||||
m_blocked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
|
||||||
{
|
|
||||||
if (m_blocked)
|
|
||||||
{
|
|
||||||
m_blocked = false;
|
|
||||||
goto WasBlocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_it.Reset(channel);
|
|
||||||
|
|
||||||
while (!m_it.End())
|
|
||||||
{
|
|
||||||
WasBlocked:
|
|
||||||
if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking))
|
|
||||||
{
|
|
||||||
m_blocked = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_it.Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
|
||||||
{
|
|
||||||
if (m_blocked)
|
|
||||||
{
|
|
||||||
m_blocked = false;
|
|
||||||
goto WasBlocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_it.Reset(channel);
|
|
||||||
|
|
||||||
while (!m_it.End())
|
|
||||||
{
|
|
||||||
WasBlocked:
|
|
||||||
if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation))
|
|
||||||
{
|
|
||||||
m_blocked = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_it.Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, size_t &size)
|
|
||||||
{
|
|
||||||
m_it.Reset(channel);
|
|
||||||
if (!m_it.End())
|
|
||||||
{
|
|
||||||
BufferedTransformation &target = m_it.Destination();
|
|
||||||
const std::string &channel = m_it.Channel();
|
|
||||||
m_it.Next();
|
|
||||||
if (m_it.End()) // there is only one target channel
|
|
||||||
return target.ChannelCreatePutSpace(channel, size);
|
|
||||||
}
|
|
||||||
size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
ChannelRouteIterator it(*this);
|
|
||||||
it.Reset(channel);
|
|
||||||
|
|
||||||
if (!it.End())
|
|
||||||
{
|
|
||||||
BufferedTransformation &target = it.Destination();
|
|
||||||
const std::string &targetChannel = it.Channel();
|
|
||||||
it.Next();
|
|
||||||
if (it.End()) // there is only one target channel
|
|
||||||
return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChannelPut2(channel, inString, length, messageEnd, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination)
|
|
||||||
{
|
|
||||||
m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr<std::string>(NULL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination)
|
|
||||||
{
|
|
||||||
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
|
|
||||||
if (it->first == &destination && !it->second.get())
|
|
||||||
{
|
|
||||||
m_defaultRoutes.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
|
|
||||||
{
|
|
||||||
m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
|
|
||||||
{
|
|
||||||
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
|
|
||||||
if (it->first == &destination && (it->second.get() && *it->second == outChannel))
|
|
||||||
{
|
|
||||||
m_defaultRoutes.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
|
|
||||||
{
|
|
||||||
m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
|
|
||||||
{
|
|
||||||
typedef ChannelSwitch::RouteMap::iterator MapIterator;
|
|
||||||
pair<MapIterator, MapIterator> range = m_routeMap.equal_range(inChannel);
|
|
||||||
|
|
||||||
for (MapIterator it = range.first; it != range.second; ++it)
|
|
||||||
if (it->second.first == &destination && it->second.second == outChannel)
|
|
||||||
{
|
|
||||||
m_routeMap.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,123 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CHANNELS_H
|
|
||||||
#define CRYPTOPP_CHANNELS_H
|
|
||||||
|
|
||||||
#include "simple.h"
|
|
||||||
#include "smartptr.h"
|
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
//! Route input on default channel to different and/or multiple channels based on message sequence number
|
|
||||||
class MessageSwitch : public Sink
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel);
|
|
||||||
void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel);
|
|
||||||
|
|
||||||
void Put(byte inByte);
|
|
||||||
void Put(const byte *inString, unsigned int length);
|
|
||||||
|
|
||||||
void Flush(bool completeFlush, int propagation=-1);
|
|
||||||
void MessageEnd(int propagation=-1);
|
|
||||||
void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
|
||||||
void MessageSeriesEnd(int propagation=-1);
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::pair<BufferedTransformation *, std::string> Route;
|
|
||||||
struct RangeRoute
|
|
||||||
{
|
|
||||||
RangeRoute(unsigned int begin, unsigned int end, const Route &route)
|
|
||||||
: begin(begin), end(end), route(route) {}
|
|
||||||
bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;}
|
|
||||||
unsigned int begin, end;
|
|
||||||
Route route;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::list<RangeRoute> RouteList;
|
|
||||||
typedef std::list<Route> DefaultRouteList;
|
|
||||||
|
|
||||||
RouteList m_routes;
|
|
||||||
DefaultRouteList m_defaultRoutes;
|
|
||||||
unsigned int m_nCurrentMessage;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class ChannelSwitchTypedefs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::pair<BufferedTransformation *, std::string> Route;
|
|
||||||
typedef std::multimap<std::string, Route> RouteMap;
|
|
||||||
|
|
||||||
typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute;
|
|
||||||
typedef std::list<DefaultRoute> DefaultRouteList;
|
|
||||||
|
|
||||||
// SunCC workaround: can't use const_iterator here
|
|
||||||
typedef RouteMap::iterator MapIterator;
|
|
||||||
typedef DefaultRouteList::iterator ListIterator;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChannelSwitch;
|
|
||||||
|
|
||||||
class ChannelRouteIterator : public ChannelSwitchTypedefs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ChannelSwitch& m_cs;
|
|
||||||
std::string m_channel;
|
|
||||||
bool m_useDefault;
|
|
||||||
MapIterator m_itMapCurrent, m_itMapEnd;
|
|
||||||
ListIterator m_itListCurrent, m_itListEnd;
|
|
||||||
|
|
||||||
ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {}
|
|
||||||
void Reset(const std::string &channel);
|
|
||||||
bool End() const;
|
|
||||||
void Next();
|
|
||||||
BufferedTransformation & Destination();
|
|
||||||
const std::string & Channel();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Route input to different and/or multiple channels based on channel ID
|
|
||||||
class CRYPTOPP_DLL ChannelSwitch : public Multichannel<Sink>, public ChannelSwitchTypedefs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ChannelSwitch() : m_it(*this), m_blocked(false) {}
|
|
||||||
ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false)
|
|
||||||
{
|
|
||||||
AddDefaultRoute(destination);
|
|
||||||
}
|
|
||||||
ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false)
|
|
||||||
{
|
|
||||||
AddDefaultRoute(destination, outChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs);
|
|
||||||
|
|
||||||
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true);
|
|
||||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
|
|
||||||
|
|
||||||
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
|
|
||||||
|
|
||||||
void AddDefaultRoute(BufferedTransformation &destination);
|
|
||||||
void RemoveDefaultRoute(BufferedTransformation &destination);
|
|
||||||
void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
|
|
||||||
void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
|
|
||||||
void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
|
|
||||||
void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
|
|
||||||
|
|
||||||
private:
|
|
||||||
RouteMap m_routeMap;
|
|
||||||
DefaultRouteList m_defaultRoutes;
|
|
||||||
|
|
||||||
ChannelRouteIterator m_it;
|
|
||||||
bool m_blocked;
|
|
||||||
|
|
||||||
friend class ChannelRouteIterator;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,122 +0,0 @@
|
||||||
// cmac.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "cmac.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
static void MulU(byte *k, unsigned int length)
|
|
||||||
{
|
|
||||||
byte carry = 0;
|
|
||||||
|
|
||||||
for (int i=length-1; i>=1; i-=2)
|
|
||||||
{
|
|
||||||
byte carry2 = k[i] >> 7;
|
|
||||||
k[i] += k[i] + carry;
|
|
||||||
carry = k[i-1] >> 7;
|
|
||||||
k[i-1] += k[i-1] + carry2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (carry)
|
|
||||||
{
|
|
||||||
switch (length)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
k[7] ^= 0x1b;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
k[15] ^= 0x87;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
k[30] ^= 4;
|
|
||||||
k[31] ^= 0x23;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
BlockCipher &cipher = AccessCipher();
|
|
||||||
unsigned int blockSize = cipher.BlockSize();
|
|
||||||
|
|
||||||
cipher.SetKey(key, length, params);
|
|
||||||
m_reg.CleanNew(3*blockSize);
|
|
||||||
m_counter = 0;
|
|
||||||
|
|
||||||
cipher.ProcessBlock(m_reg, m_reg+blockSize);
|
|
||||||
MulU(m_reg+blockSize, blockSize);
|
|
||||||
memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
|
|
||||||
MulU(m_reg+2*blockSize, blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMAC_Base::Update(const byte *input, size_t length)
|
|
||||||
{
|
|
||||||
if (!length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BlockCipher &cipher = AccessCipher();
|
|
||||||
unsigned int blockSize = cipher.BlockSize();
|
|
||||||
|
|
||||||
if (m_counter > 0)
|
|
||||||
{
|
|
||||||
unsigned int len = UnsignedMin(blockSize - m_counter, length);
|
|
||||||
xorbuf(m_reg+m_counter, input, len);
|
|
||||||
length -= len;
|
|
||||||
input += len;
|
|
||||||
m_counter += len;
|
|
||||||
|
|
||||||
if (m_counter == blockSize && length > 0)
|
|
||||||
{
|
|
||||||
cipher.ProcessBlock(m_reg);
|
|
||||||
m_counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length > blockSize)
|
|
||||||
{
|
|
||||||
assert(m_counter == 0);
|
|
||||||
size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
|
||||||
input += (length - leftOver);
|
|
||||||
length = leftOver;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length > 0)
|
|
||||||
{
|
|
||||||
assert(m_counter + length <= blockSize);
|
|
||||||
xorbuf(m_reg+m_counter, input, length);
|
|
||||||
m_counter += (unsigned int)length;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(m_counter > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(size);
|
|
||||||
|
|
||||||
BlockCipher &cipher = AccessCipher();
|
|
||||||
unsigned int blockSize = cipher.BlockSize();
|
|
||||||
|
|
||||||
if (m_counter < blockSize)
|
|
||||||
{
|
|
||||||
m_reg[m_counter] ^= 0x80;
|
|
||||||
cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
|
||||||
|
|
||||||
memcpy(mac, m_reg, size);
|
|
||||||
|
|
||||||
m_counter = 0;
|
|
||||||
memset(m_reg, 0, blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,52 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CMAC_H
|
|
||||||
#define CRYPTOPP_CMAC_H
|
|
||||||
|
|
||||||
#include "seckey.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CMAC_Base() {}
|
|
||||||
|
|
||||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void TruncatedFinal(byte *mac, size_t size);
|
|
||||||
unsigned int DigestSize() const {return GetCipher().BlockSize();}
|
|
||||||
unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();}
|
|
||||||
unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class EAX_Base;
|
|
||||||
|
|
||||||
const BlockCipher & GetCipher() const {return const_cast<CMAC_Base*>(this)->AccessCipher();}
|
|
||||||
virtual BlockCipher & AccessCipher() =0;
|
|
||||||
|
|
||||||
void ProcessBuf();
|
|
||||||
SecByteBlock m_reg;
|
|
||||||
unsigned int m_counter;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <a href="http://www.cryptolounge.org/wiki/CMAC">CMAC</a>
|
|
||||||
/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */
|
|
||||||
template <class T>
|
|
||||||
class CMAC : public MessageAuthenticationCodeImpl<CMAC_Base, CMAC<T> >, public SameKeyLengthAs<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CMAC() {}
|
|
||||||
CMAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
|
|
||||||
{this->SetKey(key, length);}
|
|
||||||
|
|
||||||
static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BlockCipher & AccessCipher() {return m_cipher;}
|
|
||||||
typename T::Encryption m_cipher;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,462 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CONFIG_H
|
|
||||||
#define CRYPTOPP_CONFIG_H
|
|
||||||
|
|
||||||
// ***************** Important Settings ********************
|
|
||||||
|
|
||||||
// define this if running on a big-endian CPU
|
|
||||||
#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
|
|
||||||
# define IS_BIG_ENDIAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// define this if running on a little-endian CPU
|
|
||||||
// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
|
|
||||||
#ifndef IS_BIG_ENDIAN
|
|
||||||
# define IS_LITTLE_ENDIAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// define this if you want to disable all OS-dependent features,
|
|
||||||
// such as sockets and OS-provided random number generators
|
|
||||||
#define NO_OS_DEPENDENCE
|
|
||||||
|
|
||||||
// Define this to use features provided by Microsoft's CryptoAPI.
|
|
||||||
// Currently the only feature used is random number generation.
|
|
||||||
// This macro will be ignored if NO_OS_DEPENDENCE is defined.
|
|
||||||
// #define USE_MS_CRYPTOAPI
|
|
||||||
|
|
||||||
// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
|
|
||||||
#ifndef DSA_1024_BIT_MODULUS_ONLY
|
|
||||||
# define DSA_1024_BIT_MODULUS_ONLY 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ***************** Less Important Settings ***************
|
|
||||||
|
|
||||||
// define this to retain (as much as possible) old deprecated function and class names
|
|
||||||
// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
|
||||||
|
|
||||||
#define GZIP_OS_CODE 0
|
|
||||||
|
|
||||||
// Try this if your CPU has 256K internal cache or a slow multiply instruction
|
|
||||||
// and you want a (possibly) faster IDEA implementation using log tables
|
|
||||||
// #define IDEA_LARGECACHE
|
|
||||||
|
|
||||||
// Define this if, for the linear congruential RNG, you want to use
|
|
||||||
// the original constants as specified in S.K. Park and K.W. Miller's
|
|
||||||
// CACM paper.
|
|
||||||
// #define LCRNG_ORIGINAL_NUMBERS
|
|
||||||
|
|
||||||
// choose which style of sockets to wrap (mostly useful for cygwin which has both)
|
|
||||||
#define PREFER_BERKELEY_STYLE_SOCKETS
|
|
||||||
// #define PREFER_WINDOWS_STYLE_SOCKETS
|
|
||||||
|
|
||||||
// set the name of Rijndael cipher, was "Rijndael" before version 5.3
|
|
||||||
#define CRYPTOPP_RIJNDAEL_NAME "AES"
|
|
||||||
|
|
||||||
// ***************** Important Settings Again ********************
|
|
||||||
// But the defaults should be ok.
|
|
||||||
|
|
||||||
// namespace support is now required
|
|
||||||
#ifdef NO_NAMESPACE
|
|
||||||
# error namespace support is now required
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Define this to workaround a Microsoft CryptoAPI bug where
|
|
||||||
// each call to CryptAcquireContext causes a 100 KB memory leak.
|
|
||||||
// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
|
|
||||||
#define WORKAROUND_MS_BUG_Q258000
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
|
|
||||||
// Avoid putting "CryptoPP::" in front of everything in Doxygen output
|
|
||||||
# define CryptoPP
|
|
||||||
# define NAMESPACE_BEGIN(x)
|
|
||||||
# define NAMESPACE_END
|
|
||||||
// Get Doxygen to generate better documentation for these typedefs
|
|
||||||
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
|
|
||||||
#else
|
|
||||||
# define NAMESPACE_BEGIN(x) namespace x {
|
|
||||||
# define NAMESPACE_END }
|
|
||||||
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
|
|
||||||
#endif
|
|
||||||
#define ANONYMOUS_NAMESPACE_BEGIN namespace {
|
|
||||||
#define USING_NAMESPACE(x) using namespace x;
|
|
||||||
#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
|
|
||||||
#define DOCUMENTED_NAMESPACE_END }
|
|
||||||
|
|
||||||
// What is the type of the third parameter to bind?
|
|
||||||
// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
|
|
||||||
// Unfortunately there is no way to tell whether or not socklen_t is defined.
|
|
||||||
// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
|
|
||||||
#ifndef TYPE_OF_SOCKLEN_T
|
|
||||||
# if defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
# define TYPE_OF_SOCKLEN_T int
|
|
||||||
# else
|
|
||||||
# define TYPE_OF_SOCKLEN_T ::socklen_t
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
|
|
||||||
# define __USE_W32_SOCKETS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
typedef unsigned short word16;
|
|
||||||
typedef unsigned int word32;
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
|
||||||
typedef unsigned __int64 word64;
|
|
||||||
#define W64LIT(x) x##ui64
|
|
||||||
#else
|
|
||||||
typedef unsigned long long word64;
|
|
||||||
#define W64LIT(x) x##ULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// define large word type, used for file offsets and such
|
|
||||||
typedef word64 lword;
|
|
||||||
const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// define hword, word, and dword. these are used for multiprecision integer arithmetic
|
|
||||||
// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
|
|
||||||
#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
|
|
||||||
typedef word32 hword;
|
|
||||||
typedef word64 word;
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_NATIVE_DWORD_AVAILABLE
|
|
||||||
#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
|
|
||||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
|
|
||||||
// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
|
|
||||||
// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
|
|
||||||
typedef word32 hword;
|
|
||||||
typedef word64 word;
|
|
||||||
typedef __uint128_t dword;
|
|
||||||
typedef __uint128_t word128;
|
|
||||||
#define CRYPTOPP_WORD128_AVAILABLE
|
|
||||||
#else
|
|
||||||
// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
|
|
||||||
typedef word16 hword;
|
|
||||||
typedef word32 word;
|
|
||||||
typedef word64 dword;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// being here means the native register size is probably 32 bits or less
|
|
||||||
#define CRYPTOPP_BOOL_SLOW_WORD64 1
|
|
||||||
typedef word16 hword;
|
|
||||||
typedef word32 word;
|
|
||||||
typedef word64 dword;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef CRYPTOPP_BOOL_SLOW_WORD64
|
|
||||||
#define CRYPTOPP_BOOL_SLOW_WORD64 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const unsigned int WORD_SIZE = sizeof(word);
|
|
||||||
const unsigned int WORD_BITS = WORD_SIZE * 8;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
|
|
||||||
// This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
|
|
||||||
#if defined(_M_X64) || defined(__x86_64__)
|
|
||||||
#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
|
|
||||||
#else
|
|
||||||
// L1 cache line size is 32 on Pentium III and earlier
|
|
||||||
#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#if _MSC_VER == 1200
|
|
||||||
#include <malloc.h>
|
|
||||||
#endif
|
|
||||||
#if _MSC_VER > 1200 || defined(_mm_free)
|
|
||||||
#define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_ALIGN_DATA
|
|
||||||
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
|
|
||||||
#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_ALIGN_DATA(x)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_SECTION_ALIGN16
|
|
||||||
#if defined(__GNUC__) && !defined(__APPLE__)
|
|
||||||
// the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
|
|
||||||
#define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_SECTION_ALIGN16
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__fastcall)
|
|
||||||
#define CRYPTOPP_FASTCALL __fastcall
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_FASTCALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// VC60 workaround: it doesn't allow typename in some places
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
|
||||||
#define CPP_TYPENAME
|
|
||||||
#else
|
|
||||||
#define CPP_TYPENAME typename
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// VC60 workaround: can't cast unsigned __int64 to float or double
|
|
||||||
#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
|
|
||||||
#define CRYPTOPP_VC6_INT64 (__int64)
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_VC6_INT64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define CRYPTOPP_NO_VTABLE __declspec(novtable)
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_NO_VTABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
// 4231: nonstandard extension used : 'extern' before template explicit instantiation
|
|
||||||
// 4250: dominance
|
|
||||||
// 4251: member needs to have dll-interface
|
|
||||||
// 4275: base needs to have dll-interface
|
|
||||||
// 4660: explicitly instantiating a class that's already implicitly instantiated
|
|
||||||
// 4661: no suitable definition provided for explicit template instantiation request
|
|
||||||
// 4786: identifer was truncated in debug information
|
|
||||||
// 4355: 'this' : used in base member initializer list
|
|
||||||
// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
|
|
||||||
# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
|
||||||
// 8037: non-const function called for const object. needed to work around BCB2006 bug
|
|
||||||
# pragma warn -8037
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) || defined(ANDROID_NDK)
|
|
||||||
#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
|
|
||||||
#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings
|
|
||||||
#define CRYPTOPP_DISABLE_ASM
|
|
||||||
#define CRYPTOPP_DISABLE_SSE2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
|
|
||||||
// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
|
|
||||||
#define CRYPTOPP_X86_ASM_AVAILABLE
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300)
|
|
||||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed.
|
|
||||||
// GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version.
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102)
|
|
||||||
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
|
|
||||||
#define CRYPTOPP_X64_MASM_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
|
|
||||||
#define CRYPTOPP_X64_ASM_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__))
|
|
||||||
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_DISABLE_SSSE3) && !defined(CRYPTOPP_DISABLE_AESNI) && CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE && (CRYPTOPP_GCC_VERSION >= 40400 || _MSC_FULL_VER >= 150030729 || __INTEL_COMPILER >= 1110)
|
|
||||||
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
|
|
||||||
#define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// how to allocate 16-byte aligned memory (for SSE2)
|
|
||||||
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
|
|
||||||
#define CRYPTOPP_MM_MALLOC_AVAILABLE
|
|
||||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
|
||||||
#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
|
|
||||||
#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
|
|
||||||
#define CRYPTOPP_MEMALIGN_AVAILABLE
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_NO_ALIGNED_ALLOC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// how to disable inlining
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
|
||||||
# define CRYPTOPP_NOINLINE_DOTDOTDOT
|
|
||||||
# define CRYPTOPP_NOINLINE __declspec(noinline)
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
# define CRYPTOPP_NOINLINE_DOTDOTDOT
|
|
||||||
# define CRYPTOPP_NOINLINE __attribute__((noinline))
|
|
||||||
#else
|
|
||||||
# define CRYPTOPP_NOINLINE_DOTDOTDOT ...
|
|
||||||
# define CRYPTOPP_NOINLINE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// how to declare class constants
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER)
|
|
||||||
# define CRYPTOPP_CONSTANT(x) enum {x};
|
|
||||||
#else
|
|
||||||
# define CRYPTOPP_CONSTANT(x) static const int x;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_M_X64) || defined(__x86_64__)
|
|
||||||
#define CRYPTOPP_BOOL_X64 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_X64 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// see http://predef.sourceforge.net/prearch.html
|
|
||||||
#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)
|
|
||||||
#define CRYPTOPP_BOOL_X86 1
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_BOOL_X86 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
|
|
||||||
#define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRYPTOPP_VERSION 562
|
|
||||||
|
|
||||||
// ***************** determine availability of OS features ********************
|
|
||||||
|
|
||||||
#ifndef NO_OS_DEPENDENCE
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
#define CRYPTOPP_WIN32_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
|
|
||||||
#define CRYPTOPP_UNIX_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
# define HIGHRES_TIMER_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
|
||||||
# define HAS_BERKELEY_STYLE_SOCKETS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
|
||||||
# define HAS_WINDOWS_STYLE_SOCKETS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS))
|
|
||||||
# define SOCKETS_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
|
|
||||||
# define USE_WINDOWS_STYLE_SOCKETS
|
|
||||||
#else
|
|
||||||
# define USE_BERKELEY_STYLE_SOCKETS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
|
|
||||||
# define WINDOWS_PIPES_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI)
|
|
||||||
# define NONBLOCKING_RNG_AVAILABLE
|
|
||||||
# define OS_RNG_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
|
|
||||||
# define NONBLOCKING_RNG_AVAILABLE
|
|
||||||
# define BLOCKING_RNG_AVAILABLE
|
|
||||||
# define OS_RNG_AVAILABLE
|
|
||||||
# define HAS_PTHREADS
|
|
||||||
# define THREADS_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
|
||||||
# define HAS_WINTHREADS
|
|
||||||
# define THREADS_AVAILABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // NO_OS_DEPENDENCE
|
|
||||||
|
|
||||||
// ***************** DLL related ********************
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_EXPORTS
|
|
||||||
#define CRYPTOPP_IS_DLL
|
|
||||||
#define CRYPTOPP_DLL __declspec(dllexport)
|
|
||||||
#elif defined(CRYPTOPP_IMPORTS)
|
|
||||||
#define CRYPTOPP_IS_DLL
|
|
||||||
#define CRYPTOPP_DLL __declspec(dllimport)
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_DLL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRYPTOPP_API __cdecl
|
|
||||||
|
|
||||||
#else // CRYPTOPP_WIN32_AVAILABLE
|
|
||||||
|
|
||||||
#define CRYPTOPP_DLL
|
|
||||||
#define CRYPTOPP_API
|
|
||||||
|
|
||||||
#endif // CRYPTOPP_WIN32_AVAILABLE
|
|
||||||
|
|
||||||
#if defined(__MWERKS__)
|
|
||||||
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
|
|
||||||
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
|
|
||||||
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
|
|
||||||
#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__MWERKS__)
|
|
||||||
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
|
|
||||||
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
|
|
||||||
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
|
|
||||||
#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,199 +0,0 @@
|
||||||
// cpu.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
|
||||||
#include <signal.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
|
||||||
#include <emmintrin.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_CPUID_AVAILABLE
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
|
|
||||||
|
|
||||||
bool CpuId(word32 input, word32 *output)
|
|
||||||
{
|
|
||||||
__cpuid((int *)output, input);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
|
||||||
extern "C" {
|
|
||||||
typedef void (*SigHandler)(int);
|
|
||||||
|
|
||||||
static jmp_buf s_jmpNoCPUID;
|
|
||||||
static void SigIllHandlerCPUID(int)
|
|
||||||
{
|
|
||||||
longjmp(s_jmpNoCPUID, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jmp_buf s_jmpNoSSE2;
|
|
||||||
static void SigIllHandlerSSE2(int)
|
|
||||||
{
|
|
||||||
longjmp(s_jmpNoSSE2, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool CpuId(word32 input, word32 *output)
|
|
||||||
{
|
|
||||||
#ifdef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, input
|
|
||||||
cpuid
|
|
||||||
mov edi, output
|
|
||||||
mov [edi], eax
|
|
||||||
mov [edi+4], ebx
|
|
||||||
mov [edi+8], ecx
|
|
||||||
mov [edi+12], edx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__except (1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
|
|
||||||
if (oldHandler == SIG_ERR)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool result = true;
|
|
||||||
if (setjmp(s_jmpNoCPUID))
|
|
||||||
result = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
asm
|
|
||||||
(
|
|
||||||
// save ebx in case -fPIC is being used
|
|
||||||
#if CRYPTOPP_BOOL_X86
|
|
||||||
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
|
|
||||||
#else
|
|
||||||
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
|
|
||||||
#endif
|
|
||||||
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
|
|
||||||
: "a" (input)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
signal(SIGILL, oldHandler);
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool TrySSE2()
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_BOOL_X64
|
|
||||||
return true;
|
|
||||||
#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
|
||||||
AS2(por xmm0, xmm0) // executing SSE2 instruction
|
|
||||||
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
|
||||||
__m128i x = _mm_setzero_si128();
|
|
||||||
return _mm_cvtsi128_si32(x) == 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
__except (1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
|
|
||||||
if (oldHandler == SIG_ERR)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool result = true;
|
|
||||||
if (setjmp(s_jmpNoSSE2))
|
|
||||||
result = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
|
||||||
__asm __volatile ("por %xmm0, %xmm0");
|
|
||||||
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
|
||||||
__m128i x = _mm_setzero_si128();
|
|
||||||
result = _mm_cvtsi128_si32(x) == 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
signal(SIGILL, oldHandler);
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool g_x86DetectionDone = false;
|
|
||||||
bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_hasAESNI = false, g_hasCLMUL = false, g_isP4 = false;
|
|
||||||
word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
||||||
|
|
||||||
void DetectX86Features()
|
|
||||||
{
|
|
||||||
word32 cpuid[4], cpuid1[4];
|
|
||||||
if (!CpuId(0, cpuid))
|
|
||||||
return;
|
|
||||||
if (!CpuId(1, cpuid1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
|
|
||||||
if ((cpuid1[3] & (1 << 26)) != 0)
|
|
||||||
g_hasSSE2 = TrySSE2();
|
|
||||||
g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
|
|
||||||
g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
|
|
||||||
g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
|
|
||||||
|
|
||||||
if ((cpuid1[3] & (1 << 25)) != 0)
|
|
||||||
g_hasISSE = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
word32 cpuid2[4];
|
|
||||||
CpuId(0x080000000, cpuid2);
|
|
||||||
if (cpuid2[0] >= 0x080000001)
|
|
||||||
{
|
|
||||||
CpuId(0x080000001, cpuid2);
|
|
||||||
g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::swap(cpuid[2], cpuid[3]);
|
|
||||||
if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
|
|
||||||
{
|
|
||||||
g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
|
|
||||||
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
|
|
||||||
}
|
|
||||||
else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
|
|
||||||
{
|
|
||||||
CpuId(0x80000005, cpuid);
|
|
||||||
g_cacheLineSize = GETBYTE(cpuid[2], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_cacheLineSize)
|
|
||||||
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
||||||
|
|
||||||
g_x86DetectionDone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,345 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CPU_H
|
|
||||||
#define CRYPTOPP_CPU_H
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
|
|
||||||
#define CRYPTOPP_X86_ASM_AVAILABLE
|
|
||||||
#define CRYPTOPP_BOOL_X64 1
|
|
||||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
|
|
||||||
#define NAMESPACE_END
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
|
||||||
#include <emmintrin.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
|
||||||
#if !defined(__GNUC__) || defined(__SSSE3__) || defined(__INTEL_COMPILER)
|
|
||||||
#include <tmmintrin.h>
|
|
||||||
#else
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_shuffle_epi8 (__m128i a, __m128i b)
|
|
||||||
{
|
|
||||||
asm ("pshufb %1, %0" : "+x"(a) : "xm"(b));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if !defined(__GNUC__) || defined(__SSE4_1__) || defined(__INTEL_COMPILER)
|
|
||||||
#include <smmintrin.h>
|
|
||||||
#else
|
|
||||||
__inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_extract_epi32 (__m128i a, const int i)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
asm ("pextrd %2, %1, %0" : "=rm"(r) : "x"(a), "i"(i));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_insert_epi32 (__m128i a, int b, const int i)
|
|
||||||
{
|
|
||||||
asm ("pinsrd %2, %1, %0" : "+x"(a) : "rm"(b), "i"(i));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if !defined(__GNUC__) || (defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER)
|
|
||||||
#include <wmmintrin.h>
|
|
||||||
#else
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_clmulepi64_si128 (__m128i a, __m128i b, const int i)
|
|
||||||
{
|
|
||||||
asm ("pclmulqdq %2, %1, %0" : "+x"(a) : "xm"(b), "i"(i));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_aeskeygenassist_si128 (__m128i a, const int i)
|
|
||||||
{
|
|
||||||
__m128i r;
|
|
||||||
asm ("aeskeygenassist %2, %1, %0" : "=x"(r) : "xm"(a), "i"(i));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_aesimc_si128 (__m128i a)
|
|
||||||
{
|
|
||||||
__m128i r;
|
|
||||||
asm ("aesimc %1, %0" : "=x"(r) : "xm"(a));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_aesenc_si128 (__m128i a, __m128i b)
|
|
||||||
{
|
|
||||||
asm ("aesenc %1, %0" : "+x"(a) : "xm"(b));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_aesenclast_si128 (__m128i a, __m128i b)
|
|
||||||
{
|
|
||||||
asm ("aesenclast %1, %0" : "+x"(a) : "xm"(b));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_aesdec_si128 (__m128i a, __m128i b)
|
|
||||||
{
|
|
||||||
asm ("aesdec %1, %0" : "+x"(a) : "xm"(b));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
|
||||||
_mm_aesdeclast_si128 (__m128i a, __m128i b)
|
|
||||||
{
|
|
||||||
asm ("aesdeclast %1, %0" : "+x"(a) : "xm"(b));
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
|
|
||||||
|
|
||||||
#define CRYPTOPP_CPUID_AVAILABLE
|
|
||||||
|
|
||||||
// these should not be used directly
|
|
||||||
extern CRYPTOPP_DLL bool g_x86DetectionDone;
|
|
||||||
extern CRYPTOPP_DLL bool g_hasSSSE3;
|
|
||||||
extern CRYPTOPP_DLL bool g_hasAESNI;
|
|
||||||
extern CRYPTOPP_DLL bool g_hasCLMUL;
|
|
||||||
extern CRYPTOPP_DLL bool g_isP4;
|
|
||||||
extern CRYPTOPP_DLL word32 g_cacheLineSize;
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
|
|
||||||
CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output);
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_X64
|
|
||||||
inline bool HasSSE2() {return true;}
|
|
||||||
inline bool HasISSE() {return true;}
|
|
||||||
inline bool HasMMX() {return true;}
|
|
||||||
#else
|
|
||||||
|
|
||||||
extern CRYPTOPP_DLL bool g_hasSSE2;
|
|
||||||
extern CRYPTOPP_DLL bool g_hasISSE;
|
|
||||||
extern CRYPTOPP_DLL bool g_hasMMX;
|
|
||||||
|
|
||||||
inline bool HasSSE2()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_hasSSE2;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool HasISSE()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_hasISSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool HasMMX()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_hasMMX;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline bool HasSSSE3()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_hasSSSE3;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool HasAESNI()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_hasAESNI;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool HasCLMUL()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_hasCLMUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsP4()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_isP4;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int GetCacheLineSize()
|
|
||||||
{
|
|
||||||
if (!g_x86DetectionDone)
|
|
||||||
DetectX86Features();
|
|
||||||
return g_cacheLineSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
inline int GetCacheLineSize()
|
|
||||||
{
|
|
||||||
return CRYPTOPP_L1_CACHE_LINE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
#define AS1(x) x*newline*
|
|
||||||
#define AS2(x, y) x, y*newline*
|
|
||||||
#define AS3(x, y, z) x, y, z*newline*
|
|
||||||
#define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
|
|
||||||
#define ASL(x) label##x:*newline*
|
|
||||||
#define ASJ(x, y, z) x label##y*newline*
|
|
||||||
#define ASC(x, y) x label##y*newline*
|
|
||||||
#define AS_HEX(y) 0##y##h
|
|
||||||
#elif defined(_MSC_VER) || defined(__BORLANDC__)
|
|
||||||
#define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
|
||||||
#define AS1(x) __asm {x}
|
|
||||||
#define AS2(x, y) __asm {x, y}
|
|
||||||
#define AS3(x, y, z) __asm {x, y, z}
|
|
||||||
#define ASS(x, y, a, b, c, d) __asm {x, y, (a)*64+(b)*16+(c)*4+(d)}
|
|
||||||
#define ASL(x) __asm {label##x:}
|
|
||||||
#define ASJ(x, y, z) __asm {x label##y}
|
|
||||||
#define ASC(x, y) __asm {x label##y}
|
|
||||||
#define CRYPTOPP_NAKED __declspec(naked)
|
|
||||||
#define AS_HEX(y) 0x##y
|
|
||||||
#else
|
|
||||||
#define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
|
|
||||||
// define these in two steps to allow arguments to be expanded
|
|
||||||
#define GNU_AS1(x) #x ";"
|
|
||||||
#define GNU_AS2(x, y) #x ", " #y ";"
|
|
||||||
#define GNU_AS3(x, y, z) #x ", " #y ", " #z ";"
|
|
||||||
#define GNU_ASL(x) "\n" #x ":"
|
|
||||||
#define GNU_ASJ(x, y, z) #x " " #y #z ";"
|
|
||||||
#define AS1(x) GNU_AS1(x)
|
|
||||||
#define AS2(x, y) GNU_AS2(x, y)
|
|
||||||
#define AS3(x, y, z) GNU_AS3(x, y, z)
|
|
||||||
#define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
|
|
||||||
#define ASL(x) GNU_ASL(x)
|
|
||||||
#define ASJ(x, y, z) GNU_ASJ(x, y, z)
|
|
||||||
#define ASC(x, y) #x " " #y ";"
|
|
||||||
#define CRYPTOPP_NAKED
|
|
||||||
#define AS_HEX(y) 0x##y
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IF0(y)
|
|
||||||
#define IF1(y) y
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
#define ASM_MOD(x, y) ((x) MOD (y))
|
|
||||||
#define XMMWORD_PTR XMMWORD PTR
|
|
||||||
#else
|
|
||||||
// GNU assembler doesn't seem to have mod operator
|
|
||||||
#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
|
|
||||||
// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
|
|
||||||
#define XMMWORD_PTR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_X86
|
|
||||||
#define AS_REG_1 ecx
|
|
||||||
#define AS_REG_2 edx
|
|
||||||
#define AS_REG_3 esi
|
|
||||||
#define AS_REG_4 edi
|
|
||||||
#define AS_REG_5 eax
|
|
||||||
#define AS_REG_6 ebx
|
|
||||||
#define AS_REG_7 ebp
|
|
||||||
#define AS_REG_1d ecx
|
|
||||||
#define AS_REG_2d edx
|
|
||||||
#define AS_REG_3d esi
|
|
||||||
#define AS_REG_4d edi
|
|
||||||
#define AS_REG_5d eax
|
|
||||||
#define AS_REG_6d ebx
|
|
||||||
#define AS_REG_7d ebp
|
|
||||||
#define WORD_SZ 4
|
|
||||||
#define WORD_REG(x) e##x
|
|
||||||
#define WORD_PTR DWORD PTR
|
|
||||||
#define AS_PUSH_IF86(x) AS1(push e##x)
|
|
||||||
#define AS_POP_IF86(x) AS1(pop e##x)
|
|
||||||
#define AS_JCXZ jecxz
|
|
||||||
#elif CRYPTOPP_BOOL_X64
|
|
||||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
#define AS_REG_1 rcx
|
|
||||||
#define AS_REG_2 rdx
|
|
||||||
#define AS_REG_3 r8
|
|
||||||
#define AS_REG_4 r9
|
|
||||||
#define AS_REG_5 rax
|
|
||||||
#define AS_REG_6 r10
|
|
||||||
#define AS_REG_7 r11
|
|
||||||
#define AS_REG_1d ecx
|
|
||||||
#define AS_REG_2d edx
|
|
||||||
#define AS_REG_3d r8d
|
|
||||||
#define AS_REG_4d r9d
|
|
||||||
#define AS_REG_5d eax
|
|
||||||
#define AS_REG_6d r10d
|
|
||||||
#define AS_REG_7d r11d
|
|
||||||
#else
|
|
||||||
#define AS_REG_1 rdi
|
|
||||||
#define AS_REG_2 rsi
|
|
||||||
#define AS_REG_3 rdx
|
|
||||||
#define AS_REG_4 rcx
|
|
||||||
#define AS_REG_5 r8
|
|
||||||
#define AS_REG_6 r9
|
|
||||||
#define AS_REG_7 r10
|
|
||||||
#define AS_REG_1d edi
|
|
||||||
#define AS_REG_2d esi
|
|
||||||
#define AS_REG_3d edx
|
|
||||||
#define AS_REG_4d ecx
|
|
||||||
#define AS_REG_5d r8d
|
|
||||||
#define AS_REG_6d r9d
|
|
||||||
#define AS_REG_7d r10d
|
|
||||||
#endif
|
|
||||||
#define WORD_SZ 8
|
|
||||||
#define WORD_REG(x) r##x
|
|
||||||
#define WORD_PTR QWORD PTR
|
|
||||||
#define AS_PUSH_IF86(x)
|
|
||||||
#define AS_POP_IF86(x)
|
|
||||||
#define AS_JCXZ jrcxz
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// helper macro for stream cipher output
|
|
||||||
#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
|
|
||||||
AS2( test inputPtr, inputPtr)\
|
|
||||||
ASC( jz, labelPrefix##3)\
|
|
||||||
AS2( test inputPtr, 15)\
|
|
||||||
ASC( jnz, labelPrefix##7)\
|
|
||||||
AS2( pxor xmm##x0, [inputPtr+p0*16])\
|
|
||||||
AS2( pxor xmm##x1, [inputPtr+p1*16])\
|
|
||||||
AS2( pxor xmm##x2, [inputPtr+p2*16])\
|
|
||||||
AS2( pxor xmm##x3, [inputPtr+p3*16])\
|
|
||||||
AS2( add inputPtr, increment*16)\
|
|
||||||
ASC( jmp, labelPrefix##3)\
|
|
||||||
ASL(labelPrefix##7)\
|
|
||||||
AS2( movdqu xmm##t, [inputPtr+p0*16])\
|
|
||||||
AS2( pxor xmm##x0, xmm##t)\
|
|
||||||
AS2( movdqu xmm##t, [inputPtr+p1*16])\
|
|
||||||
AS2( pxor xmm##x1, xmm##t)\
|
|
||||||
AS2( movdqu xmm##t, [inputPtr+p2*16])\
|
|
||||||
AS2( pxor xmm##x2, xmm##t)\
|
|
||||||
AS2( movdqu xmm##t, [inputPtr+p3*16])\
|
|
||||||
AS2( pxor xmm##x3, xmm##t)\
|
|
||||||
AS2( add inputPtr, increment*16)\
|
|
||||||
ASL(labelPrefix##3)\
|
|
||||||
AS2( test outputPtr, 15)\
|
|
||||||
ASC( jnz, labelPrefix##8)\
|
|
||||||
AS2( movdqa [outputPtr+p0*16], xmm##x0)\
|
|
||||||
AS2( movdqa [outputPtr+p1*16], xmm##x1)\
|
|
||||||
AS2( movdqa [outputPtr+p2*16], xmm##x2)\
|
|
||||||
AS2( movdqa [outputPtr+p3*16], xmm##x3)\
|
|
||||||
ASC( jmp, labelPrefix##9)\
|
|
||||||
ASL(labelPrefix##8)\
|
|
||||||
AS2( movdqu [outputPtr+p0*16], xmm##x0)\
|
|
||||||
AS2( movdqu [outputPtr+p1*16], xmm##x1)\
|
|
||||||
AS2( movdqu [outputPtr+p2*16], xmm##x2)\
|
|
||||||
AS2( movdqu [outputPtr+p3*16], xmm##x3)\
|
|
||||||
ASL(labelPrefix##9)\
|
|
||||||
AS2( add outputPtr, increment*16)
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,160 +0,0 @@
|
||||||
// crc.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "crc.h"
|
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
/* Table of CRC-32's of all single byte values (made by makecrc.c) */
|
|
||||||
const word32 CRC32::m_tab[] = {
|
|
||||||
#ifdef IS_LITTLE_ENDIAN
|
|
||||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
|
||||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
|
||||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
|
||||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
|
||||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
|
||||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
|
||||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
|
||||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
|
||||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
|
||||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
|
||||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
|
||||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
|
||||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
|
||||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
|
||||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
|
||||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
|
||||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
|
||||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
|
||||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
|
||||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
|
||||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
|
||||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
|
||||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
|
||||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
|
||||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
|
||||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
|
||||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
|
||||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
|
||||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
|
||||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
|
||||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
|
||||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
|
||||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
|
||||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
|
||||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
|
||||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
|
||||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
|
||||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
|
||||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
|
||||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
|
||||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
|
||||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
|
||||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
|
||||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
|
||||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
|
||||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
|
||||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
|
||||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
|
||||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
|
||||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
|
||||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
|
||||||
0x2d02ef8dL
|
|
||||||
#else
|
|
||||||
0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
|
|
||||||
0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
|
|
||||||
0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
|
|
||||||
0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
|
|
||||||
0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
|
|
||||||
0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
|
|
||||||
0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
|
|
||||||
0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
|
|
||||||
0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
|
|
||||||
0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
|
|
||||||
0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
|
|
||||||
0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
|
|
||||||
0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
|
|
||||||
0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
|
|
||||||
0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
|
|
||||||
0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
|
|
||||||
0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
|
|
||||||
0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
|
|
||||||
0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
|
|
||||||
0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
|
|
||||||
0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
|
|
||||||
0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
|
|
||||||
0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
|
|
||||||
0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
|
|
||||||
0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
|
|
||||||
0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
|
|
||||||
0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
|
|
||||||
0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
|
|
||||||
0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
|
|
||||||
0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
|
|
||||||
0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
|
|
||||||
0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
|
|
||||||
0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
|
|
||||||
0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
|
|
||||||
0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
|
|
||||||
0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
|
|
||||||
0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
|
|
||||||
0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
|
|
||||||
0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
|
|
||||||
0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
|
|
||||||
0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
|
|
||||||
0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
|
|
||||||
0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
|
|
||||||
0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
|
|
||||||
0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
|
|
||||||
0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
|
|
||||||
0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
|
|
||||||
0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
|
|
||||||
0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
|
|
||||||
0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
|
|
||||||
0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
|
|
||||||
0x8def022dL
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
CRC32::CRC32()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRC32::Update(const byte *s, size_t n)
|
|
||||||
{
|
|
||||||
word32 crc = m_crc;
|
|
||||||
|
|
||||||
for(; !IsAligned<word32>(s) && n > 0; n--)
|
|
||||||
crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
|
|
||||||
|
|
||||||
while (n >= 4)
|
|
||||||
{
|
|
||||||
crc ^= *(const word32 *)s;
|
|
||||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
|
||||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
|
||||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
|
||||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
|
||||||
n -= 4;
|
|
||||||
s += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (n--)
|
|
||||||
crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
|
|
||||||
|
|
||||||
m_crc = crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRC32::TruncatedFinal(byte *hash, size_t size)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(size);
|
|
||||||
|
|
||||||
m_crc ^= CRC32_NEGL;
|
|
||||||
for (size_t i=0; i<size; i++)
|
|
||||||
hash[i] = GetCrcByte(i);
|
|
||||||
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef CRYPTOPP_CRC32_H
|
|
||||||
#define CRYPTOPP_CRC32_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
const word32 CRC32_NEGL = 0xffffffffL;
|
|
||||||
|
|
||||||
#ifdef IS_LITTLE_ENDIAN
|
|
||||||
#define CRC32_INDEX(c) (c & 0xff)
|
|
||||||
#define CRC32_SHIFTED(c) (c >> 8)
|
|
||||||
#else
|
|
||||||
#define CRC32_INDEX(c) (c >> 24)
|
|
||||||
#define CRC32_SHIFTED(c) (c << 8)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! CRC Checksum Calculation
|
|
||||||
class CRC32 : public HashTransformation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
|
|
||||||
CRC32();
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void TruncatedFinal(byte *hash, size_t size);
|
|
||||||
unsigned int DigestSize() const {return DIGESTSIZE;}
|
|
||||||
static const char * StaticAlgorithmName() {return "CRC32";}
|
|
||||||
std::string AlgorithmName() const {return StaticAlgorithmName();}
|
|
||||||
|
|
||||||
void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
|
|
||||||
byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Reset() {m_crc = CRC32_NEGL;}
|
|
||||||
|
|
||||||
static const word32 m_tab[256];
|
|
||||||
word32 m_crc;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,828 +0,0 @@
|
||||||
// cryptlib.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "filters.h"
|
|
||||||
#include "algparam.h"
|
|
||||||
#include "fips140.h"
|
|
||||||
#include "argnames.h"
|
|
||||||
#include "fltrimpl.h"
|
|
||||||
#include "trdlocal.h"
|
|
||||||
#include "osrng.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
|
|
||||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
|
|
||||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
|
|
||||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
|
|
||||||
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
|
|
||||||
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const std::string DEFAULT_CHANNEL;
|
|
||||||
const std::string AAD_CHANNEL = "AAD";
|
|
||||||
const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL;
|
|
||||||
|
|
||||||
class NullNameValuePairs : public NameValuePairs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;}
|
|
||||||
};
|
|
||||||
|
|
||||||
simple_ptr<NullNameValuePairs> s_pNullNameValuePairs(new NullNameValuePairs);
|
|
||||||
const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
|
|
||||||
|
|
||||||
BufferedTransformation & TheBitBucket()
|
|
||||||
{
|
|
||||||
static BitBucket bitBucket;
|
|
||||||
return bitBucket;
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm::Algorithm(bool checkSelfTestStatus)
|
|
||||||
{
|
|
||||||
if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled())
|
|
||||||
{
|
|
||||||
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread())
|
|
||||||
throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed.");
|
|
||||||
|
|
||||||
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED)
|
|
||||||
throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
this->ThrowIfInvalidKeyLength(length);
|
|
||||||
this->UncheckedSetKey(key, (unsigned int)length, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds)
|
|
||||||
{
|
|
||||||
SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
|
|
||||||
{
|
|
||||||
SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length)
|
|
||||||
{
|
|
||||||
if (!IsValidKeyLength(length))
|
|
||||||
throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::ThrowIfResynchronizable()
|
|
||||||
{
|
|
||||||
if (IsResynchronizable())
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv)
|
|
||||||
{
|
|
||||||
if (!iv && IVRequirement() == UNPREDICTABLE_RANDOM_IV)
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size)
|
|
||||||
{
|
|
||||||
if (size < 0)
|
|
||||||
return IVSize();
|
|
||||||
else if ((size_t)size < MinIVLength())
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength()));
|
|
||||||
else if ((size_t)size > MaxIVLength())
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength()));
|
|
||||||
else
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size)
|
|
||||||
{
|
|
||||||
ConstByteArrayParameter ivWithLength;
|
|
||||||
const byte *iv;
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
try {found = params.GetValue(Name::IV(), ivWithLength);}
|
|
||||||
catch (const NameValuePairs::ValueTypeMismatch &) {}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
iv = ivWithLength.begin();
|
|
||||||
ThrowIfInvalidIV(iv);
|
|
||||||
size = ThrowIfInvalidIVLength((int)ivWithLength.size());
|
|
||||||
return iv;
|
|
||||||
}
|
|
||||||
else if (params.GetValue(Name::IV(), iv))
|
|
||||||
{
|
|
||||||
ThrowIfInvalidIV(iv);
|
|
||||||
size = IVSize();
|
|
||||||
return iv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ThrowIfResynchronizable();
|
|
||||||
size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV)
|
|
||||||
{
|
|
||||||
rng.GenerateBlock(IV, IVSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
|
|
||||||
{
|
|
||||||
size_t blockSize = BlockSize();
|
|
||||||
size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize;
|
|
||||||
size_t xorIncrement = xorBlocks ? blockSize : 0;
|
|
||||||
size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize;
|
|
||||||
|
|
||||||
if (flags & BT_ReverseDirection)
|
|
||||||
{
|
|
||||||
assert(length % blockSize == 0);
|
|
||||||
inBlocks += length - blockSize;
|
|
||||||
xorBlocks += length - blockSize;
|
|
||||||
outBlocks += length - blockSize;
|
|
||||||
inIncrement = 0-inIncrement;
|
|
||||||
xorIncrement = 0-xorIncrement;
|
|
||||||
outIncrement = 0-outIncrement;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (length >= blockSize)
|
|
||||||
{
|
|
||||||
if (flags & BT_XorInput)
|
|
||||||
{
|
|
||||||
xorbuf(outBlocks, xorBlocks, inBlocks, blockSize);
|
|
||||||
ProcessBlock(outBlocks);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
|
|
||||||
if (flags & BT_InBlockIsCounter)
|
|
||||||
const_cast<byte *>(inBlocks)[blockSize-1]++;
|
|
||||||
inBlocks += inIncrement;
|
|
||||||
outBlocks += outIncrement;
|
|
||||||
xorBlocks += xorIncrement;
|
|
||||||
length -= blockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int BlockTransformation::OptimalDataAlignment() const
|
|
||||||
{
|
|
||||||
return GetAlignmentOf<word32>();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int StreamTransformation::OptimalDataAlignment() const
|
|
||||||
{
|
|
||||||
return GetAlignmentOf<word32>();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int HashTransformation::OptimalDataAlignment() const
|
|
||||||
{
|
|
||||||
return GetAlignmentOf<word32>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
assert(MinLastBlockSize() == 0); // this function should be overriden otherwise
|
|
||||||
|
|
||||||
if (length == MandatoryBlockSize())
|
|
||||||
ProcessData(outString, inString, length);
|
|
||||||
else if (length != 0)
|
|
||||||
throw NotImplemented(AlgorithmName() + ": this object does't support a special last block");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
|
|
||||||
{
|
|
||||||
if (headerLength > MaxHeaderLength())
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
|
|
||||||
|
|
||||||
if (messageLength > MaxMessageLength())
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength()));
|
|
||||||
|
|
||||||
if (footerLength > MaxFooterLength())
|
|
||||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
|
|
||||||
|
|
||||||
UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedSymmetricCipher::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)
|
|
||||||
{
|
|
||||||
Resynchronize(iv, ivLength);
|
|
||||||
SpecifyDataLengths(headerLength, messageLength);
|
|
||||||
Update(header, headerLength);
|
|
||||||
ProcessString(ciphertext, message, messageLength);
|
|
||||||
TruncatedFinal(mac, macSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AuthenticatedSymmetricCipher::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)
|
|
||||||
{
|
|
||||||
Resynchronize(iv, ivLength);
|
|
||||||
SpecifyDataLengths(headerLength, ciphertextLength);
|
|
||||||
Update(header, headerLength);
|
|
||||||
ProcessString(message, ciphertext, ciphertextLength);
|
|
||||||
return TruncatedVerify(mac, macLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int RandomNumberGenerator::GenerateBit()
|
|
||||||
{
|
|
||||||
return GenerateByte() & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte RandomNumberGenerator::GenerateByte()
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
GenerateBlock(&b, 1);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
|
|
||||||
{
|
|
||||||
word32 range = max-min;
|
|
||||||
const int maxBits = BitPrecision(range);
|
|
||||||
|
|
||||||
word32 value;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
GenerateBlock((byte *)&value, sizeof(value));
|
|
||||||
value = Crop(value, maxBits);
|
|
||||||
} while (value > range);
|
|
||||||
|
|
||||||
return value+min;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RandomNumberGenerator::GenerateBlock(byte *output, size_t size)
|
|
||||||
{
|
|
||||||
ArraySink s(output, size);
|
|
||||||
GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RandomNumberGenerator::DiscardBytes(size_t n)
|
|
||||||
{
|
|
||||||
GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
|
|
||||||
{
|
|
||||||
FixedSizeSecBlock<byte, 256> buffer;
|
|
||||||
while (length)
|
|
||||||
{
|
|
||||||
size_t len = UnsignedMin(buffer.size(), length);
|
|
||||||
GenerateBlock(buffer, len);
|
|
||||||
target.ChannelPut(channel, buffer, len);
|
|
||||||
length -= len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! see NullRNG()
|
|
||||||
class ClassNullRNG : public RandomNumberGenerator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::string AlgorithmName() const {return "NullRNG";}
|
|
||||||
void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");}
|
|
||||||
};
|
|
||||||
|
|
||||||
RandomNumberGenerator & NullRNG()
|
|
||||||
{
|
|
||||||
static ClassNullRNG s_nullRNG;
|
|
||||||
return s_nullRNG;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLength)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(digestLength);
|
|
||||||
SecByteBlock digest(digestLength);
|
|
||||||
TruncatedFinal(digest, digestLength);
|
|
||||||
return VerifyBufsEqual(digest, digestIn, digestLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const
|
|
||||||
{
|
|
||||||
if (size > DigestSize())
|
|
||||||
throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
|
|
||||||
{
|
|
||||||
const BufferedTransformation *t = AttachedTransformation();
|
|
||||||
return t ? t->GetMaxWaitObjectCount() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
|
||||||
{
|
|
||||||
BufferedTransformation *t = AttachedTransformation();
|
|
||||||
if (t)
|
|
||||||
t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation)
|
|
||||||
{
|
|
||||||
assert(!AttachedTransformation());
|
|
||||||
IsolatedInitialize(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
|
|
||||||
{
|
|
||||||
assert(!AttachedTransformation());
|
|
||||||
return IsolatedFlush(hardFlush, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
|
|
||||||
{
|
|
||||||
assert(!AttachedTransformation());
|
|
||||||
return IsolatedMessageSeriesEnd(blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size)
|
|
||||||
{
|
|
||||||
if (channel.empty())
|
|
||||||
return CreatePutSpace(size);
|
|
||||||
else
|
|
||||||
throw NoChannelSupport(AlgorithmName());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
if (channel.empty())
|
|
||||||
return Put2(begin, length, messageEnd, blocking);
|
|
||||||
else
|
|
||||||
throw NoChannelSupport(AlgorithmName());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
if (channel.empty())
|
|
||||||
return PutModifiable2(begin, length, messageEnd, blocking);
|
|
||||||
else
|
|
||||||
return ChannelPut2(channel, begin, length, messageEnd, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
|
||||||
{
|
|
||||||
if (channel.empty())
|
|
||||||
return Flush(completeFlush, propagation, blocking);
|
|
||||||
else
|
|
||||||
throw NoChannelSupport(AlgorithmName());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
|
||||||
{
|
|
||||||
if (channel.empty())
|
|
||||||
return MessageSeriesEnd(propagation, blocking);
|
|
||||||
else
|
|
||||||
throw NoChannelSupport(AlgorithmName());
|
|
||||||
}
|
|
||||||
|
|
||||||
lword BufferedTransformation::MaxRetrievable() const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->MaxRetrievable();
|
|
||||||
else
|
|
||||||
return CopyTo(TheBitBucket());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::AnyRetrievable() const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->AnyRetrievable();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
return Peek(b) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::Get(byte &outByte)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->Get(outByte);
|
|
||||||
else
|
|
||||||
return Get(&outByte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::Get(byte *outString, size_t getMax)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->Get(outString, getMax);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ArraySink arraySink(outString, getMax);
|
|
||||||
return (size_t)TransferTo(arraySink, getMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::Peek(byte &outByte) const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->Peek(outByte);
|
|
||||||
else
|
|
||||||
return Peek(&outByte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->Peek(outString, peekMax);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ArraySink arraySink(outString, peekMax);
|
|
||||||
return (size_t)CopyTo(arraySink, peekMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lword BufferedTransformation::Skip(lword skipMax)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->Skip(skipMax);
|
|
||||||
else
|
|
||||||
return TransferTo(TheBitBucket(), skipMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
lword BufferedTransformation::TotalBytesRetrievable() const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->TotalBytesRetrievable();
|
|
||||||
else
|
|
||||||
return MaxRetrievable();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int BufferedTransformation::NumberOfMessages() const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->NumberOfMessages();
|
|
||||||
else
|
|
||||||
return CopyMessagesTo(TheBitBucket());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::AnyMessages() const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->AnyMessages();
|
|
||||||
else
|
|
||||||
return NumberOfMessages() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferedTransformation::GetNextMessage()
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->GetNextMessage();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(!AnyMessages());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->SkipMessages(count);
|
|
||||||
else
|
|
||||||
return TransferMessagesTo(TheBitBucket(), count);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int maxMessages = messageCount;
|
|
||||||
for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
|
|
||||||
{
|
|
||||||
size_t blockedBytes;
|
|
||||||
lword transferredBytes;
|
|
||||||
|
|
||||||
while (AnyRetrievable())
|
|
||||||
{
|
|
||||||
transferredBytes = LWORD_MAX;
|
|
||||||
blockedBytes = TransferTo2(target, transferredBytes, channel, blocking);
|
|
||||||
if (blockedBytes > 0)
|
|
||||||
return blockedBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
bool result = GetNextMessage();
|
|
||||||
assert(result);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->CopyMessagesTo(target, count, channel);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferedTransformation::SkipAll()
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
AttachedTransformation()->SkipAll();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (SkipMessages()) {}
|
|
||||||
while (Skip()) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(!NumberOfMessageSeries());
|
|
||||||
|
|
||||||
unsigned int messageCount;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
messageCount = UINT_MAX;
|
|
||||||
size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
|
|
||||||
if (blockedBytes)
|
|
||||||
return blockedBytes;
|
|
||||||
}
|
|
||||||
while (messageCount != 0);
|
|
||||||
|
|
||||||
lword byteCount;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
byteCount = ULONG_MAX;
|
|
||||||
size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking);
|
|
||||||
if (blockedBytes)
|
|
||||||
return blockedBytes;
|
|
||||||
}
|
|
||||||
while (byteCount != 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
AttachedTransformation()->CopyAllTo(target, channel);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(!NumberOfMessageSeries());
|
|
||||||
while (CopyMessagesTo(target, UINT_MAX, channel)) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation())
|
|
||||||
AttachedTransformation()->SetRetrievalChannel(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
|
|
||||||
{
|
|
||||||
PutWord(false, order, m_buf, value);
|
|
||||||
return ChannelPut(channel, m_buf, 2, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
|
|
||||||
{
|
|
||||||
PutWord(false, order, m_buf, value);
|
|
||||||
return ChannelPut(channel, m_buf, 4, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
|
|
||||||
{
|
|
||||||
return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
|
|
||||||
{
|
|
||||||
return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const
|
|
||||||
{
|
|
||||||
byte buf[2] = {0, 0};
|
|
||||||
size_t len = Peek(buf, 2);
|
|
||||||
|
|
||||||
if (order)
|
|
||||||
value = (buf[0] << 8) | buf[1];
|
|
||||||
else
|
|
||||||
value = (buf[1] << 8) | buf[0];
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const
|
|
||||||
{
|
|
||||||
byte buf[4] = {0, 0, 0, 0};
|
|
||||||
size_t len = Peek(buf, 4);
|
|
||||||
|
|
||||||
if (order)
|
|
||||||
value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3];
|
|
||||||
else
|
|
||||||
value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0];
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order)
|
|
||||||
{
|
|
||||||
return (size_t)Skip(PeekWord16(value, order));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
|
|
||||||
{
|
|
||||||
return (size_t)Skip(PeekWord32(value, order));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferedTransformation::Attach(BufferedTransformation *newOut)
|
|
||||||
{
|
|
||||||
if (AttachedTransformation() && AttachedTransformation()->Attachable())
|
|
||||||
AttachedTransformation()->Attach(newOut);
|
|
||||||
else
|
|
||||||
Detach(newOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
|
|
||||||
{
|
|
||||||
GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
|
|
||||||
}
|
|
||||||
|
|
||||||
class PK_DefaultEncryptionFilter : public Unflushable<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters)
|
|
||||||
: m_rng(rng), m_encryptor(encryptor), m_parameters(parameters)
|
|
||||||
{
|
|
||||||
Detach(attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
FILTER_BEGIN;
|
|
||||||
m_plaintextQueue.Put(inString, length);
|
|
||||||
|
|
||||||
if (messageEnd)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
size_t plaintextLength;
|
|
||||||
if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength))
|
|
||||||
throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long");
|
|
||||||
size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
|
|
||||||
|
|
||||||
SecByteBlock plaintext(plaintextLength);
|
|
||||||
m_plaintextQueue.Get(plaintext, plaintextLength);
|
|
||||||
m_ciphertext.resize(ciphertextLength);
|
|
||||||
m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd);
|
|
||||||
}
|
|
||||||
FILTER_END_NO_MESSAGE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomNumberGenerator &m_rng;
|
|
||||||
const PK_Encryptor &m_encryptor;
|
|
||||||
const NameValuePairs &m_parameters;
|
|
||||||
ByteQueue m_plaintextQueue;
|
|
||||||
SecByteBlock m_ciphertext;
|
|
||||||
};
|
|
||||||
|
|
||||||
BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
class PK_DefaultDecryptionFilter : public Unflushable<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters)
|
|
||||||
: m_rng(rng), m_decryptor(decryptor), m_parameters(parameters)
|
|
||||||
{
|
|
||||||
Detach(attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
FILTER_BEGIN;
|
|
||||||
m_ciphertextQueue.Put(inString, length);
|
|
||||||
|
|
||||||
if (messageEnd)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
size_t ciphertextLength;
|
|
||||||
if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength))
|
|
||||||
throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long");
|
|
||||||
size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
|
|
||||||
|
|
||||||
SecByteBlock ciphertext(ciphertextLength);
|
|
||||||
m_ciphertextQueue.Get(ciphertext, ciphertextLength);
|
|
||||||
m_plaintext.resize(maxPlaintextLength);
|
|
||||||
m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters);
|
|
||||||
if (!m_result.isValidCoding)
|
|
||||||
throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
|
|
||||||
}
|
|
||||||
|
|
||||||
FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd);
|
|
||||||
}
|
|
||||||
FILTER_END_NO_MESSAGE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomNumberGenerator &m_rng;
|
|
||||||
const PK_Decryptor &m_decryptor;
|
|
||||||
const NameValuePairs &m_parameters;
|
|
||||||
ByteQueue m_ciphertextQueue;
|
|
||||||
SecByteBlock m_plaintext;
|
|
||||||
DecodingResult m_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
|
||||||
return SignAndRestart(rng, *m, signature, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
|
|
||||||
m->Update(message, messageLen);
|
|
||||||
return SignAndRestart(rng, *m, signature, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength,
|
|
||||||
const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
|
|
||||||
InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength);
|
|
||||||
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
|
|
||||||
return SignAndRestart(rng, *m, signature, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
|
||||||
return VerifyAndRestart(*m);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLength) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
|
|
||||||
InputSignature(*m, signature, signatureLength);
|
|
||||||
m->Update(message, messageLen);
|
|
||||||
return VerifyAndRestart(*m);
|
|
||||||
}
|
|
||||||
|
|
||||||
DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
|
||||||
return RecoverAndRestart(recoveredMessage, *m);
|
|
||||||
}
|
|
||||||
|
|
||||||
DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage,
|
|
||||||
const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength,
|
|
||||||
const byte *signature, size_t signatureLength) const
|
|
||||||
{
|
|
||||||
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
|
|
||||||
InputSignature(*m, signature, signatureLength);
|
|
||||||
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
|
|
||||||
return RecoverAndRestart(recoveredMessage, *m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
|
||||||
{
|
|
||||||
GeneratePrivateKey(rng, privateKey);
|
|
||||||
GeneratePublicKey(rng, privateKey, publicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
|
||||||
{
|
|
||||||
GenerateStaticPrivateKey(rng, privateKey);
|
|
||||||
GenerateStaticPublicKey(rng, privateKey, publicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
|
||||||
{
|
|
||||||
GenerateEphemeralPrivateKey(rng, privateKey);
|
|
||||||
GenerateEphemeralPublicKey(rng, privateKey, publicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,258 +0,0 @@
|
||||||
// default.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "default.h"
|
|
||||||
#include "queue.h"
|
|
||||||
#include <time.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
static const unsigned int MASH_ITERATIONS = 200;
|
|
||||||
static const unsigned int SALTLENGTH = 8;
|
|
||||||
static const unsigned int BLOCKSIZE = Default_BlockCipher::Encryption::BLOCKSIZE;
|
|
||||||
static const unsigned int KEYLENGTH = Default_BlockCipher::Encryption::DEFAULT_KEYLENGTH;
|
|
||||||
|
|
||||||
// The purpose of this function Mash() is to take an arbitrary length input
|
|
||||||
// string and *deterministicly* produce an arbitrary length output string such
|
|
||||||
// that (1) it looks random, (2) no information about the input is
|
|
||||||
// deducible from it, and (3) it contains as much entropy as it can hold, or
|
|
||||||
// the amount of entropy in the input string, whichever is smaller.
|
|
||||||
|
|
||||||
static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
|
|
||||||
{
|
|
||||||
if (BytePrecision(outLen) > 2)
|
|
||||||
throw InvalidArgument("Mash: output legnth too large");
|
|
||||||
|
|
||||||
size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
|
|
||||||
byte b[2];
|
|
||||||
SecByteBlock buf(bufSize);
|
|
||||||
SecByteBlock outBuf(bufSize);
|
|
||||||
DefaultHashModule hash;
|
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
|
|
||||||
{
|
|
||||||
b[0] = (byte) (i >> 8);
|
|
||||||
b[1] = (byte) i;
|
|
||||||
hash.Update(b, 2);
|
|
||||||
hash.Update(in, inLen);
|
|
||||||
hash.Final(outBuf+i);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (iterations-- > 1)
|
|
||||||
{
|
|
||||||
memcpy(buf, outBuf, bufSize);
|
|
||||||
for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
|
|
||||||
{
|
|
||||||
b[0] = (byte) (i >> 8);
|
|
||||||
b[1] = (byte) i;
|
|
||||||
hash.Update(b, 2);
|
|
||||||
hash.Update(buf, bufSize);
|
|
||||||
hash.Final(outBuf+i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(out, outBuf, outLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, byte *key, byte *IV)
|
|
||||||
{
|
|
||||||
SecByteBlock temp(passphraseLength+saltLength);
|
|
||||||
memcpy(temp, passphrase, passphraseLength);
|
|
||||||
memcpy(temp+passphraseLength, salt, saltLength);
|
|
||||||
SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
|
|
||||||
Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
|
|
||||||
memcpy(key, keyIV, KEYLENGTH);
|
|
||||||
memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment)
|
|
||||||
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultEncryptor::DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
|
|
||||||
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DefaultEncryptor::FirstPut(const byte *)
|
|
||||||
{
|
|
||||||
// VC60 workaround: __LINE__ expansion bug
|
|
||||||
CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1);
|
|
||||||
CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2);
|
|
||||||
|
|
||||||
SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
|
|
||||||
DefaultHashModule hash;
|
|
||||||
|
|
||||||
// use hash(passphrase | time | clock) as salt
|
|
||||||
hash.Update(m_passphrase, m_passphrase.size());
|
|
||||||
time_t t=time(0);
|
|
||||||
hash.Update((byte *)&t, sizeof(t));
|
|
||||||
clock_t c=clock();
|
|
||||||
hash.Update((byte *)&c, sizeof(c));
|
|
||||||
hash.Final(salt);
|
|
||||||
|
|
||||||
// use hash(passphrase | salt) as key check
|
|
||||||
hash.Update(m_passphrase, m_passphrase.size());
|
|
||||||
hash.Update(salt, SALTLENGTH);
|
|
||||||
hash.Final(keyCheck);
|
|
||||||
|
|
||||||
AttachedTransformation()->Put(salt, SALTLENGTH);
|
|
||||||
|
|
||||||
// mash passphrase and salt together into key and IV
|
|
||||||
SecByteBlock key(KEYLENGTH);
|
|
||||||
SecByteBlock IV(BLOCKSIZE);
|
|
||||||
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
|
|
||||||
|
|
||||||
m_cipher.SetKeyWithIV(key, key.size(), IV);
|
|
||||||
SetFilter(new StreamTransformationFilter(m_cipher));
|
|
||||||
|
|
||||||
m_filter->Put(keyCheck, BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultEncryptor::LastPut(const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
m_filter->MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
|
|
||||||
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
|
|
||||||
, m_state(WAITING_FOR_KEYCHECK)
|
|
||||||
, m_passphrase((const byte *)p, strlen(p))
|
|
||||||
, m_throwException(throwException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
|
|
||||||
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
|
|
||||||
, m_state(WAITING_FOR_KEYCHECK)
|
|
||||||
, m_passphrase(passphrase, passphraseLength)
|
|
||||||
, m_throwException(throwException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultDecryptor::FirstPut(const byte *inString)
|
|
||||||
{
|
|
||||||
CheckKey(inString, inString+SALTLENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultDecryptor::LastPut(const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
if (m_filter.get() == NULL)
|
|
||||||
{
|
|
||||||
m_state = KEY_BAD;
|
|
||||||
if (m_throwException)
|
|
||||||
throw KeyBadErr();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_filter->MessageEnd();
|
|
||||||
m_state = WAITING_FOR_KEYCHECK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
|
|
||||||
{
|
|
||||||
SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
|
|
||||||
|
|
||||||
DefaultHashModule hash;
|
|
||||||
hash.Update(m_passphrase, m_passphrase.size());
|
|
||||||
hash.Update(salt, SALTLENGTH);
|
|
||||||
hash.Final(check);
|
|
||||||
|
|
||||||
SecByteBlock key(KEYLENGTH);
|
|
||||||
SecByteBlock IV(BLOCKSIZE);
|
|
||||||
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
|
|
||||||
|
|
||||||
m_cipher.SetKeyWithIV(key, key.size(), IV);
|
|
||||||
std::auto_ptr<StreamTransformationFilter> decryptor(new StreamTransformationFilter(m_cipher));
|
|
||||||
|
|
||||||
decryptor->Put(keyCheck, BLOCKSIZE);
|
|
||||||
decryptor->ForceNextPut();
|
|
||||||
decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
|
|
||||||
|
|
||||||
SetFilter(decryptor.release());
|
|
||||||
|
|
||||||
if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
|
|
||||||
{
|
|
||||||
m_state = KEY_BAD;
|
|
||||||
if (m_throwException)
|
|
||||||
throw KeyBadErr();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_state = KEY_GOOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
|
|
||||||
{
|
|
||||||
size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
|
|
||||||
SecByteBlock macKey(macKeyLength);
|
|
||||||
// since the MAC is encrypted there is no reason to mash the passphrase for many iterations
|
|
||||||
Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
|
|
||||||
return new DefaultMAC(macKey, macKeyLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment)
|
|
||||||
: ProxyFilter(NULL, 0, 0, attachment)
|
|
||||||
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
|
|
||||||
{
|
|
||||||
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
|
|
||||||
: ProxyFilter(NULL, 0, 0, attachment)
|
|
||||||
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
|
|
||||||
{
|
|
||||||
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
m_filter->MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
|
|
||||||
: ProxyFilter(NULL, 0, 0, attachment)
|
|
||||||
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
|
|
||||||
, m_throwException(throwException)
|
|
||||||
{
|
|
||||||
SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
|
|
||||||
: ProxyFilter(NULL, 0, 0, attachment)
|
|
||||||
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
|
|
||||||
, m_throwException(throwException)
|
|
||||||
{
|
|
||||||
SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
|
|
||||||
{
|
|
||||||
return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DefaultDecryptorWithMAC::CheckLastMAC() const
|
|
||||||
{
|
|
||||||
return m_hashVerifier->GetLastResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
|
|
||||||
{
|
|
||||||
m_filter->MessageEnd();
|
|
||||||
if (m_throwException && !CheckLastMAC())
|
|
||||||
throw MACBadErr();
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,104 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DEFAULT_H
|
|
||||||
#define CRYPTOPP_DEFAULT_H
|
|
||||||
|
|
||||||
#include "sha.h"
|
|
||||||
#include "hmac.h"
|
|
||||||
#include "des.h"
|
|
||||||
#include "filters.h"
|
|
||||||
#include "modes.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
typedef DES_EDE2 Default_BlockCipher;
|
|
||||||
typedef SHA DefaultHashModule;
|
|
||||||
typedef HMAC<DefaultHashModule> DefaultMAC;
|
|
||||||
|
|
||||||
//! Password-Based Encryptor using DES-EDE2
|
|
||||||
class DefaultEncryptor : public ProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment = NULL);
|
|
||||||
DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void FirstPut(const byte *);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SecByteBlock m_passphrase;
|
|
||||||
CBC_Mode<Default_BlockCipher>::Encryption m_cipher;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Password-Based Decryptor using DES-EDE2
|
|
||||||
class DefaultDecryptor : public ProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
|
|
||||||
DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
|
|
||||||
|
|
||||||
class Err : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Err(const std::string &s)
|
|
||||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, s) {}
|
|
||||||
};
|
|
||||||
class KeyBadErr : public Err {public: KeyBadErr() : Err("DefaultDecryptor: cannot decrypt message with this passphrase") {}};
|
|
||||||
|
|
||||||
enum State {WAITING_FOR_KEYCHECK, KEY_GOOD, KEY_BAD};
|
|
||||||
State CurrentState() const {return m_state;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void FirstPut(const byte *inString);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
State m_state;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CheckKey(const byte *salt, const byte *keyCheck);
|
|
||||||
|
|
||||||
SecByteBlock m_passphrase;
|
|
||||||
CBC_Mode<Default_BlockCipher>::Decryption m_cipher;
|
|
||||||
member_ptr<FilterWithBufferedInput> m_decryptor;
|
|
||||||
bool m_throwException;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Password-Based Encryptor using DES-EDE2 and HMAC/SHA-1
|
|
||||||
class DefaultEncryptorWithMAC : public ProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL);
|
|
||||||
DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void FirstPut(const byte *inString) {}
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
member_ptr<DefaultMAC> m_mac;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Password-Based Decryptor using DES-EDE2 and HMAC/SHA-1
|
|
||||||
class DefaultDecryptorWithMAC : public ProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class MACBadErr : public DefaultDecryptor::Err {public: MACBadErr() : DefaultDecryptor::Err("DefaultDecryptorWithMAC: MAC check failed") {}};
|
|
||||||
|
|
||||||
DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
|
|
||||||
DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
|
|
||||||
|
|
||||||
DefaultDecryptor::State CurrentState() const;
|
|
||||||
bool CheckLastMAC() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void FirstPut(const byte *inString) {}
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
member_ptr<DefaultMAC> m_mac;
|
|
||||||
HashVerifier *m_hashVerifier;
|
|
||||||
bool m_throwException;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,449 +0,0 @@
|
||||||
// des.cpp - modified by Wei Dai from Phil Karn's des.c
|
|
||||||
// The original code and all modifications are in the public domain.
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a major rewrite of my old public domain DES code written
|
|
||||||
* circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977
|
|
||||||
* public domain code. I pretty much kept my key scheduling code, but
|
|
||||||
* the actual encrypt/decrypt routines are taken from from Richard
|
|
||||||
* Outerbridge's DES code as printed in Schneier's "Applied Cryptography."
|
|
||||||
*
|
|
||||||
* This code is in the public domain. I would appreciate bug reports and
|
|
||||||
* enhancements.
|
|
||||||
*
|
|
||||||
* Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "des.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
|
||||||
|
|
||||||
// Richard Outerbridge's initial permutation algorithm
|
|
||||||
/*
|
|
||||||
inline void IPERM(word32 &left, word32 &right)
|
|
||||||
{
|
|
||||||
word32 work;
|
|
||||||
|
|
||||||
work = ((left >> 4) ^ right) & 0x0f0f0f0f;
|
|
||||||
right ^= work;
|
|
||||||
left ^= work << 4;
|
|
||||||
work = ((left >> 16) ^ right) & 0xffff;
|
|
||||||
right ^= work;
|
|
||||||
left ^= work << 16;
|
|
||||||
work = ((right >> 2) ^ left) & 0x33333333;
|
|
||||||
left ^= work;
|
|
||||||
right ^= (work << 2);
|
|
||||||
work = ((right >> 8) ^ left) & 0xff00ff;
|
|
||||||
left ^= work;
|
|
||||||
right ^= (work << 8);
|
|
||||||
right = rotl(right, 1);
|
|
||||||
work = (left ^ right) & 0xaaaaaaaa;
|
|
||||||
left ^= work;
|
|
||||||
right ^= work;
|
|
||||||
left = rotl(left, 1);
|
|
||||||
}
|
|
||||||
inline void FPERM(word32 &left, word32 &right)
|
|
||||||
{
|
|
||||||
word32 work;
|
|
||||||
|
|
||||||
right = rotr(right, 1);
|
|
||||||
work = (left ^ right) & 0xaaaaaaaa;
|
|
||||||
left ^= work;
|
|
||||||
right ^= work;
|
|
||||||
left = rotr(left, 1);
|
|
||||||
work = ((left >> 8) ^ right) & 0xff00ff;
|
|
||||||
right ^= work;
|
|
||||||
left ^= work << 8;
|
|
||||||
work = ((left >> 2) ^ right) & 0x33333333;
|
|
||||||
right ^= work;
|
|
||||||
left ^= work << 2;
|
|
||||||
work = ((right >> 16) ^ left) & 0xffff;
|
|
||||||
left ^= work;
|
|
||||||
right ^= work << 16;
|
|
||||||
work = ((right >> 4) ^ left) & 0x0f0f0f0f;
|
|
||||||
left ^= work;
|
|
||||||
right ^= work << 4;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Wei Dai's modification to Richard Outerbridge's initial permutation
|
|
||||||
// algorithm, this one is faster if you have access to rotate instructions
|
|
||||||
// (like in MSVC)
|
|
||||||
static inline void IPERM(word32 &left, word32 &right)
|
|
||||||
{
|
|
||||||
word32 work;
|
|
||||||
|
|
||||||
right = rotlFixed(right, 4U);
|
|
||||||
work = (left ^ right) & 0xf0f0f0f0;
|
|
||||||
left ^= work;
|
|
||||||
right = rotrFixed(right^work, 20U);
|
|
||||||
work = (left ^ right) & 0xffff0000;
|
|
||||||
left ^= work;
|
|
||||||
right = rotrFixed(right^work, 18U);
|
|
||||||
work = (left ^ right) & 0x33333333;
|
|
||||||
left ^= work;
|
|
||||||
right = rotrFixed(right^work, 6U);
|
|
||||||
work = (left ^ right) & 0x00ff00ff;
|
|
||||||
left ^= work;
|
|
||||||
right = rotlFixed(right^work, 9U);
|
|
||||||
work = (left ^ right) & 0xaaaaaaaa;
|
|
||||||
left = rotlFixed(left^work, 1U);
|
|
||||||
right ^= work;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void FPERM(word32 &left, word32 &right)
|
|
||||||
{
|
|
||||||
word32 work;
|
|
||||||
|
|
||||||
right = rotrFixed(right, 1U);
|
|
||||||
work = (left ^ right) & 0xaaaaaaaa;
|
|
||||||
right ^= work;
|
|
||||||
left = rotrFixed(left^work, 9U);
|
|
||||||
work = (left ^ right) & 0x00ff00ff;
|
|
||||||
right ^= work;
|
|
||||||
left = rotlFixed(left^work, 6U);
|
|
||||||
work = (left ^ right) & 0x33333333;
|
|
||||||
right ^= work;
|
|
||||||
left = rotlFixed(left^work, 18U);
|
|
||||||
work = (left ^ right) & 0xffff0000;
|
|
||||||
right ^= work;
|
|
||||||
left = rotlFixed(left^work, 20U);
|
|
||||||
work = (left ^ right) & 0xf0f0f0f0;
|
|
||||||
right ^= work;
|
|
||||||
left = rotrFixed(left^work, 4U);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
|
||||||
{
|
|
||||||
AssertValidKeyLength(length);
|
|
||||||
|
|
||||||
RawSetKey(GetCipherDirection(), userKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
/* Tables defined in the Data Encryption Standard documents
|
|
||||||
* Three of these tables, the initial permutation, the final
|
|
||||||
* permutation and the expansion operator, are regular enough that
|
|
||||||
* for speed, we hard-code them. They're here for reference only.
|
|
||||||
* Also, the S and P boxes are used by a separate program, gensp.c,
|
|
||||||
* to build the combined SP box, Spbox[]. They're also here just
|
|
||||||
* for reference.
|
|
||||||
*/
|
|
||||||
#ifdef notdef
|
|
||||||
/* initial permutation IP */
|
|
||||||
static byte ip[] = {
|
|
||||||
58, 50, 42, 34, 26, 18, 10, 2,
|
|
||||||
60, 52, 44, 36, 28, 20, 12, 4,
|
|
||||||
62, 54, 46, 38, 30, 22, 14, 6,
|
|
||||||
64, 56, 48, 40, 32, 24, 16, 8,
|
|
||||||
57, 49, 41, 33, 25, 17, 9, 1,
|
|
||||||
59, 51, 43, 35, 27, 19, 11, 3,
|
|
||||||
61, 53, 45, 37, 29, 21, 13, 5,
|
|
||||||
63, 55, 47, 39, 31, 23, 15, 7
|
|
||||||
};
|
|
||||||
|
|
||||||
/* final permutation IP^-1 */
|
|
||||||
static byte fp[] = {
|
|
||||||
40, 8, 48, 16, 56, 24, 64, 32,
|
|
||||||
39, 7, 47, 15, 55, 23, 63, 31,
|
|
||||||
38, 6, 46, 14, 54, 22, 62, 30,
|
|
||||||
37, 5, 45, 13, 53, 21, 61, 29,
|
|
||||||
36, 4, 44, 12, 52, 20, 60, 28,
|
|
||||||
35, 3, 43, 11, 51, 19, 59, 27,
|
|
||||||
34, 2, 42, 10, 50, 18, 58, 26,
|
|
||||||
33, 1, 41, 9, 49, 17, 57, 25
|
|
||||||
};
|
|
||||||
/* expansion operation matrix */
|
|
||||||
static byte ei[] = {
|
|
||||||
32, 1, 2, 3, 4, 5,
|
|
||||||
4, 5, 6, 7, 8, 9,
|
|
||||||
8, 9, 10, 11, 12, 13,
|
|
||||||
12, 13, 14, 15, 16, 17,
|
|
||||||
16, 17, 18, 19, 20, 21,
|
|
||||||
20, 21, 22, 23, 24, 25,
|
|
||||||
24, 25, 26, 27, 28, 29,
|
|
||||||
28, 29, 30, 31, 32, 1
|
|
||||||
};
|
|
||||||
/* The (in)famous S-boxes */
|
|
||||||
static byte sbox[8][64] = {
|
|
||||||
/* S1 */
|
|
||||||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
|
||||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
|
||||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
|
||||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
|
|
||||||
|
|
||||||
/* S2 */
|
|
||||||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
|
||||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
|
||||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
|
||||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
|
|
||||||
|
|
||||||
/* S3 */
|
|
||||||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
|
||||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
|
||||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
|
||||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
|
|
||||||
|
|
||||||
/* S4 */
|
|
||||||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
|
||||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
|
||||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
|
||||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
|
|
||||||
|
|
||||||
/* S5 */
|
|
||||||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
|
||||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
|
||||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
|
||||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
|
|
||||||
|
|
||||||
/* S6 */
|
|
||||||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
|
||||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
|
||||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
|
||||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
|
|
||||||
|
|
||||||
/* S7 */
|
|
||||||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
|
||||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
|
||||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
|
||||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
|
|
||||||
|
|
||||||
/* S8 */
|
|
||||||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
|
||||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
|
||||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
|
||||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 32-bit permutation function P used on the output of the S-boxes */
|
|
||||||
static byte p32i[] = {
|
|
||||||
16, 7, 20, 21,
|
|
||||||
29, 12, 28, 17,
|
|
||||||
1, 15, 23, 26,
|
|
||||||
5, 18, 31, 10,
|
|
||||||
2, 8, 24, 14,
|
|
||||||
32, 27, 3, 9,
|
|
||||||
19, 13, 30, 6,
|
|
||||||
22, 11, 4, 25
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* permuted choice table (key) */
|
|
||||||
static const byte pc1[] = {
|
|
||||||
57, 49, 41, 33, 25, 17, 9,
|
|
||||||
1, 58, 50, 42, 34, 26, 18,
|
|
||||||
10, 2, 59, 51, 43, 35, 27,
|
|
||||||
19, 11, 3, 60, 52, 44, 36,
|
|
||||||
|
|
||||||
63, 55, 47, 39, 31, 23, 15,
|
|
||||||
7, 62, 54, 46, 38, 30, 22,
|
|
||||||
14, 6, 61, 53, 45, 37, 29,
|
|
||||||
21, 13, 5, 28, 20, 12, 4
|
|
||||||
};
|
|
||||||
|
|
||||||
/* number left rotations of pc1 */
|
|
||||||
static const byte totrot[] = {
|
|
||||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
|
|
||||||
};
|
|
||||||
|
|
||||||
/* permuted choice key (table) */
|
|
||||||
static const byte pc2[] = {
|
|
||||||
14, 17, 11, 24, 1, 5,
|
|
||||||
3, 28, 15, 6, 21, 10,
|
|
||||||
23, 19, 12, 4, 26, 8,
|
|
||||||
16, 7, 27, 20, 13, 2,
|
|
||||||
41, 52, 31, 37, 47, 55,
|
|
||||||
30, 40, 51, 45, 33, 48,
|
|
||||||
44, 49, 39, 56, 34, 53,
|
|
||||||
46, 42, 50, 36, 29, 32
|
|
||||||
};
|
|
||||||
|
|
||||||
/* End of DES-defined tables */
|
|
||||||
|
|
||||||
/* bit 0 is left-most in byte */
|
|
||||||
static const int bytebit[] = {
|
|
||||||
0200,0100,040,020,010,04,02,01
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Set key (initialize key schedule array) */
|
|
||||||
void RawDES::RawSetKey(CipherDir dir, const byte *key)
|
|
||||||
{
|
|
||||||
SecByteBlock buffer(56+56+8);
|
|
||||||
byte *const pc1m=buffer; /* place to modify pc1 into */
|
|
||||||
byte *const pcr=pc1m+56; /* place to rotate pc1 into */
|
|
||||||
byte *const ks=pcr+56;
|
|
||||||
register int i,j,l;
|
|
||||||
int m;
|
|
||||||
|
|
||||||
for (j=0; j<56; j++) { /* convert pc1 to bits of key */
|
|
||||||
l=pc1[j]-1; /* integer bit location */
|
|
||||||
m = l & 07; /* find bit */
|
|
||||||
pc1m[j]=(key[l>>3] & /* find which key byte l is in */
|
|
||||||
bytebit[m]) /* and which bit of that byte */
|
|
||||||
? 1 : 0; /* and store 1-bit result */
|
|
||||||
}
|
|
||||||
for (i=0; i<16; i++) { /* key chunk for each iteration */
|
|
||||||
memset(ks,0,8); /* Clear key schedule */
|
|
||||||
for (j=0; j<56; j++) /* rotate pc1 the right amount */
|
|
||||||
pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
|
|
||||||
/* rotate left and right halves independently */
|
|
||||||
for (j=0; j<48; j++){ /* select bits individually */
|
|
||||||
/* check bit that goes to ks[j] */
|
|
||||||
if (pcr[pc2[j]-1]){
|
|
||||||
/* mask it in if it's there */
|
|
||||||
l= j % 6;
|
|
||||||
ks[j/6] |= bytebit[l] >> 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Now convert to odd/even interleaved form for use in F */
|
|
||||||
k[2*i] = ((word32)ks[0] << 24)
|
|
||||||
| ((word32)ks[2] << 16)
|
|
||||||
| ((word32)ks[4] << 8)
|
|
||||||
| ((word32)ks[6]);
|
|
||||||
k[2*i+1] = ((word32)ks[1] << 24)
|
|
||||||
| ((word32)ks[3] << 16)
|
|
||||||
| ((word32)ks[5] << 8)
|
|
||||||
| ((word32)ks[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir==DECRYPTION) // reverse key schedule order
|
|
||||||
for (i=0; i<16; i+=2)
|
|
||||||
{
|
|
||||||
std::swap(k[i], k[32-2-i]);
|
|
||||||
std::swap(k[i+1], k[32-1-i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const
|
|
||||||
{
|
|
||||||
word32 l = l_, r = r_;
|
|
||||||
const word32 *kptr=k;
|
|
||||||
|
|
||||||
for (unsigned i=0; i<8; i++)
|
|
||||||
{
|
|
||||||
word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
|
|
||||||
l ^= Spbox[6][(work) & 0x3f]
|
|
||||||
^ Spbox[4][(work >> 8) & 0x3f]
|
|
||||||
^ Spbox[2][(work >> 16) & 0x3f]
|
|
||||||
^ Spbox[0][(work >> 24) & 0x3f];
|
|
||||||
work = r ^ kptr[4*i+1];
|
|
||||||
l ^= Spbox[7][(work) & 0x3f]
|
|
||||||
^ Spbox[5][(work >> 8) & 0x3f]
|
|
||||||
^ Spbox[3][(work >> 16) & 0x3f]
|
|
||||||
^ Spbox[1][(work >> 24) & 0x3f];
|
|
||||||
|
|
||||||
work = rotrFixed(l, 4U) ^ kptr[4*i+2];
|
|
||||||
r ^= Spbox[6][(work) & 0x3f]
|
|
||||||
^ Spbox[4][(work >> 8) & 0x3f]
|
|
||||||
^ Spbox[2][(work >> 16) & 0x3f]
|
|
||||||
^ Spbox[0][(work >> 24) & 0x3f];
|
|
||||||
work = l ^ kptr[4*i+3];
|
|
||||||
r ^= Spbox[7][(work) & 0x3f]
|
|
||||||
^ Spbox[5][(work >> 8) & 0x3f]
|
|
||||||
^ Spbox[3][(work >> 16) & 0x3f]
|
|
||||||
^ Spbox[1][(work >> 24) & 0x3f];
|
|
||||||
}
|
|
||||||
|
|
||||||
l_ = l; r_ = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
|
||||||
{
|
|
||||||
AssertValidKeyLength(length);
|
|
||||||
|
|
||||||
m_des1.RawSetKey(GetCipherDirection(), userKey);
|
|
||||||
m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
|
||||||
{
|
|
||||||
word32 l,r;
|
|
||||||
Block::Get(inBlock)(l)(r);
|
|
||||||
IPERM(l,r);
|
|
||||||
m_des1.RawProcessBlock(l, r);
|
|
||||||
m_des2.RawProcessBlock(r, l);
|
|
||||||
m_des1.RawProcessBlock(l, r);
|
|
||||||
FPERM(l,r);
|
|
||||||
Block::Put(xorBlock, outBlock)(r)(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
|
||||||
{
|
|
||||||
AssertValidKeyLength(length);
|
|
||||||
|
|
||||||
m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16));
|
|
||||||
m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8);
|
|
||||||
m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
|
||||||
{
|
|
||||||
word32 l,r;
|
|
||||||
Block::Get(inBlock)(l)(r);
|
|
||||||
IPERM(l,r);
|
|
||||||
m_des1.RawProcessBlock(l, r);
|
|
||||||
m_des2.RawProcessBlock(r, l);
|
|
||||||
m_des3.RawProcessBlock(l, r);
|
|
||||||
FPERM(l,r);
|
|
||||||
Block::Put(xorBlock, outBlock)(r)(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
static inline bool CheckParity(byte b)
|
|
||||||
{
|
|
||||||
unsigned int a = b ^ (b >> 4);
|
|
||||||
return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DES::CheckKeyParityBits(const byte *key)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0; i<8; i++)
|
|
||||||
if (!CheckParity(key[i]))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES::CorrectKeyParityBits(byte *key)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0; i<8; i++)
|
|
||||||
if (!CheckParity(key[i]))
|
|
||||||
key[i] ^= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt or decrypt a block of data in ECB mode
|
|
||||||
void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
|
||||||
{
|
|
||||||
word32 l,r;
|
|
||||||
Block::Get(inBlock)(l)(r);
|
|
||||||
IPERM(l,r);
|
|
||||||
RawProcessBlock(l, r);
|
|
||||||
FPERM(l,r);
|
|
||||||
Block::Put(xorBlock, outBlock)(r)(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &)
|
|
||||||
{
|
|
||||||
AssertValidKeyLength(length);
|
|
||||||
|
|
||||||
if (!m_des.get())
|
|
||||||
m_des.reset(new DES::Encryption);
|
|
||||||
|
|
||||||
memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE);
|
|
||||||
m_des->RawSetKey(GetCipherDirection(), key + 8);
|
|
||||||
memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
|
||||||
{
|
|
||||||
xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE);
|
|
||||||
m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock);
|
|
||||||
xorbuf(outBlock, m_x3, BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,144 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DES_H
|
|
||||||
#define CRYPTOPP_DES_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "seckey.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
class CRYPTOPP_DLL RawDES
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void RawSetKey(CipherDir direction, const byte *userKey);
|
|
||||||
void RawProcessBlock(word32 &l, word32 &r) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static const word32 Spbox[8][64];
|
|
||||||
|
|
||||||
FixedSizeSecBlock<word32, 32> k;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8>
|
|
||||||
{
|
|
||||||
// disable DES in DLL version by not exporting this function
|
|
||||||
static const char * StaticAlgorithmName() {return "DES";}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DES">DES</a>
|
|
||||||
/*! The DES implementation in Crypto++ ignores the parity bits
|
|
||||||
(the least significant bits of each byte) in the key. However
|
|
||||||
you can use CheckKeyParityBits() and CorrectKeyParityBits() to
|
|
||||||
check or correct the parity bits if you wish. */
|
|
||||||
class DES : public DES_Info, public BlockCipherDocumentation
|
|
||||||
{
|
|
||||||
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_Info>, public RawDES
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
//! check DES key parity bits
|
|
||||||
static bool CheckKeyParityBits(const byte *key);
|
|
||||||
//! correct DES key parity bits
|
|
||||||
static void CorrectKeyParityBits(byte *key);
|
|
||||||
|
|
||||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
|
||||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
|
|
||||||
{
|
|
||||||
CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE2</a>
|
|
||||||
class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation
|
|
||||||
{
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE2_Info>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
RawDES m_des1, m_des2;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
|
||||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
|
|
||||||
{
|
|
||||||
CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE3</a>
|
|
||||||
class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation
|
|
||||||
{
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE3_Info>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
RawDES m_des1, m_des2, m_des3;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
|
||||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
|
|
||||||
{
|
|
||||||
static const char *StaticAlgorithmName() {return "DES-XEX3";}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESX">DES-XEX3</a>, AKA DESX
|
|
||||||
class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation
|
|
||||||
{
|
|
||||||
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_XEX3_Info>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
FixedSizeSecBlock<byte, BLOCKSIZE> m_x1, m_x3;
|
|
||||||
// VS2005 workaround: calling modules compiled with /clr gets unresolved external symbol DES::Base::ProcessAndXorBlock
|
|
||||||
// if we use DES::Encryption here directly without value_ptr.
|
|
||||||
value_ptr<DES::Encryption> m_des;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
|
||||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef DES::Encryption DESEncryption;
|
|
||||||
typedef DES::Decryption DESDecryption;
|
|
||||||
|
|
||||||
typedef DES_EDE2::Encryption DES_EDE2_Encryption;
|
|
||||||
typedef DES_EDE2::Decryption DES_EDE2_Decryption;
|
|
||||||
|
|
||||||
typedef DES_EDE3::Encryption DES_EDE3_Encryption;
|
|
||||||
typedef DES_EDE3::Decryption DES_EDE3_Decryption;
|
|
||||||
|
|
||||||
typedef DES_XEX3::Encryption DES_XEX3_Encryption;
|
|
||||||
typedef DES_XEX3::Decryption DES_XEX3_Decryption;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,95 +0,0 @@
|
||||||
// This file is mostly generated by Phil Karn's gensp.c
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "des.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
// VC60 workaround: gives a C4786 warning without this function
|
|
||||||
// when runtime lib is set to multithread debug DLL
|
|
||||||
// even though warning 4786 is disabled!
|
|
||||||
void DES_VC60Workaround()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const word32 RawDES::Spbox[8][64] = {
|
|
||||||
{
|
|
||||||
0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000,
|
|
||||||
0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004,
|
|
||||||
0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404,
|
|
||||||
0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000,
|
|
||||||
0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400,
|
|
||||||
0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404,
|
|
||||||
0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400,
|
|
||||||
0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004},
|
|
||||||
{
|
|
||||||
0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020,
|
|
||||||
0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020,
|
|
||||||
0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000,
|
|
||||||
0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020,
|
|
||||||
0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000,
|
|
||||||
0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000,
|
|
||||||
0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020,
|
|
||||||
0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000},
|
|
||||||
{
|
|
||||||
0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200,
|
|
||||||
0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208,
|
|
||||||
0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208,
|
|
||||||
0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000,
|
|
||||||
0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000,
|
|
||||||
0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008,
|
|
||||||
0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008,
|
|
||||||
0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200},
|
|
||||||
{
|
|
||||||
0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001,
|
|
||||||
0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001,
|
|
||||||
0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080,
|
|
||||||
0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081,
|
|
||||||
0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000,
|
|
||||||
0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080,
|
|
||||||
0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081,
|
|
||||||
0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080},
|
|
||||||
{
|
|
||||||
0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000,
|
|
||||||
0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000,
|
|
||||||
0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100,
|
|
||||||
0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100,
|
|
||||||
0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100,
|
|
||||||
0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000,
|
|
||||||
0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000,
|
|
||||||
0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100},
|
|
||||||
{
|
|
||||||
0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000,
|
|
||||||
0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010,
|
|
||||||
0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010,
|
|
||||||
0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000,
|
|
||||||
0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010,
|
|
||||||
0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000,
|
|
||||||
0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010,
|
|
||||||
0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010},
|
|
||||||
{
|
|
||||||
0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800,
|
|
||||||
0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802,
|
|
||||||
0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002,
|
|
||||||
0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800,
|
|
||||||
0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002,
|
|
||||||
0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800,
|
|
||||||
0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802,
|
|
||||||
0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002},
|
|
||||||
{
|
|
||||||
0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000,
|
|
||||||
0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040,
|
|
||||||
0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000,
|
|
||||||
0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000,
|
|
||||||
0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040,
|
|
||||||
0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040,
|
|
||||||
0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000,
|
|
||||||
0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000}
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,19 +0,0 @@
|
||||||
// dh.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "dh.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void DH_TestInstantiations()
|
|
||||||
{
|
|
||||||
DH dh1;
|
|
||||||
DH dh2(NullRNG(), 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,99 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DH_H
|
|
||||||
#define CRYPTOPP_DH_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gfpcrypt.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! ,
|
|
||||||
template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
|
|
||||||
class DH_Domain : public DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element>
|
|
||||||
{
|
|
||||||
typedef DL_SimpleKeyAgreementDomainBase<typename GROUP_PARAMETERS::Element> Base;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef GROUP_PARAMETERS GroupParameters;
|
|
||||||
typedef typename GroupParameters::Element Element;
|
|
||||||
typedef DL_KeyAgreementAlgorithm_DH<Element, COFACTOR_OPTION> DH_Algorithm;
|
|
||||||
typedef DH_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
|
|
||||||
|
|
||||||
DH_Domain() {}
|
|
||||||
|
|
||||||
DH_Domain(const GroupParameters ¶ms)
|
|
||||||
: m_groupParameters(params) {}
|
|
||||||
|
|
||||||
DH_Domain(BufferedTransformation &bt)
|
|
||||||
{m_groupParameters.BERDecode(bt);}
|
|
||||||
|
|
||||||
template <class T2>
|
|
||||||
DH_Domain(RandomNumberGenerator &v1, const T2 &v2)
|
|
||||||
{m_groupParameters.Initialize(v1, v2);}
|
|
||||||
|
|
||||||
template <class T2, class T3>
|
|
||||||
DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3)
|
|
||||||
{m_groupParameters.Initialize(v1, v2, v3);}
|
|
||||||
|
|
||||||
template <class T2, class T3, class T4>
|
|
||||||
DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4)
|
|
||||||
{m_groupParameters.Initialize(v1, v2, v3, v4);}
|
|
||||||
|
|
||||||
template <class T1, class T2>
|
|
||||||
DH_Domain(const T1 &v1, const T2 &v2)
|
|
||||||
{m_groupParameters.Initialize(v1, v2);}
|
|
||||||
|
|
||||||
template <class T1, class T2, class T3>
|
|
||||||
DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3)
|
|
||||||
{m_groupParameters.Initialize(v1, v2, v3);}
|
|
||||||
|
|
||||||
template <class T1, class T2, class T3, class T4>
|
|
||||||
DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
|
|
||||||
{m_groupParameters.Initialize(v1, v2, v3, v4);}
|
|
||||||
|
|
||||||
const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
|
|
||||||
GroupParameters & AccessGroupParameters() {return m_groupParameters;}
|
|
||||||
|
|
||||||
void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
|
||||||
{
|
|
||||||
Base::GeneratePublicKey(rng, privateKey, publicKey);
|
|
||||||
|
|
||||||
if (FIPS_140_2_ComplianceEnabled())
|
|
||||||
{
|
|
||||||
SecByteBlock privateKey2(this->PrivateKeyLength());
|
|
||||||
this->GeneratePrivateKey(rng, privateKey2);
|
|
||||||
|
|
||||||
SecByteBlock publicKey2(this->PublicKeyLength());
|
|
||||||
Base::GeneratePublicKey(rng, privateKey2, publicKey2);
|
|
||||||
|
|
||||||
SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength());
|
|
||||||
bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2);
|
|
||||||
bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey);
|
|
||||||
|
|
||||||
if (!agreed1 || !agreed2 || agreedValue != agreedValue2)
|
|
||||||
throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string CRYPTOPP_API StaticAlgorithmName()
|
|
||||||
{return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();}
|
|
||||||
std::string AlgorithmName() const {return StaticAlgorithmName();}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
|
|
||||||
{return Singleton<DH_Algorithm>().Ref();}
|
|
||||||
DL_GroupParameters<Element> & AccessAbstractGroupParameters()
|
|
||||||
{return m_groupParameters;}
|
|
||||||
|
|
||||||
GroupParameters m_groupParameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime>;
|
|
||||||
|
|
||||||
//! <a href="http://www.weidai.com/scan-mirror/ka.html#DH">Diffie-Hellman</a> in GF(p) with key validation
|
|
||||||
typedef DH_Domain<DL_GroupParameters_GFP_DefaultSafePrime> DH;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,22 +0,0 @@
|
||||||
// dh2.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "dh2.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void DH2_TestInstantiations()
|
|
||||||
{
|
|
||||||
DH2 dh(*(SimpleKeyAgreementDomain*)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DH2::Agree(byte *agreedValue,
|
|
||||||
const byte *staticSecretKey, const byte *ephemeralSecretKey,
|
|
||||||
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
|
|
||||||
bool validateStaticOtherPublicKey) const
|
|
||||||
{
|
|
||||||
return d1.Agree(agreedValue, staticSecretKey, staticOtherPublicKey, validateStaticOtherPublicKey)
|
|
||||||
&& d2.Agree(agreedValue+d1.AgreedValueLength(), ephemeralSecretKey, ephemeralOtherPublicKey, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,58 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DH2_H
|
|
||||||
#define CRYPTOPP_DH2_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
/// <a href="http://www.weidai.com/scan-mirror/ka.html#DH2">Unified Diffie-Hellman</a>
|
|
||||||
class DH2 : public AuthenticatedKeyAgreementDomain
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DH2(SimpleKeyAgreementDomain &domain)
|
|
||||||
: d1(domain), d2(domain) {}
|
|
||||||
DH2(SimpleKeyAgreementDomain &staticDomain, SimpleKeyAgreementDomain &ephemeralDomain)
|
|
||||||
: d1(staticDomain), d2(ephemeralDomain) {}
|
|
||||||
|
|
||||||
CryptoParameters & AccessCryptoParameters() {return d1.AccessCryptoParameters();}
|
|
||||||
|
|
||||||
unsigned int AgreedValueLength() const
|
|
||||||
{return d1.AgreedValueLength() + d2.AgreedValueLength();}
|
|
||||||
|
|
||||||
unsigned int StaticPrivateKeyLength() const
|
|
||||||
{return d1.PrivateKeyLength();}
|
|
||||||
unsigned int StaticPublicKeyLength() const
|
|
||||||
{return d1.PublicKeyLength();}
|
|
||||||
void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
|
|
||||||
{d1.GeneratePrivateKey(rng, privateKey);}
|
|
||||||
void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
|
||||||
{d1.GeneratePublicKey(rng, privateKey, publicKey);}
|
|
||||||
void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
|
||||||
{d1.GenerateKeyPair(rng, privateKey, publicKey);}
|
|
||||||
|
|
||||||
unsigned int EphemeralPrivateKeyLength() const
|
|
||||||
{return d2.PrivateKeyLength();}
|
|
||||||
unsigned int EphemeralPublicKeyLength() const
|
|
||||||
{return d2.PublicKeyLength();}
|
|
||||||
void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
|
|
||||||
{d2.GeneratePrivateKey(rng, privateKey);}
|
|
||||||
void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
|
|
||||||
{d2.GeneratePublicKey(rng, privateKey, publicKey);}
|
|
||||||
void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
|
||||||
{d2.GenerateKeyPair(rng, privateKey, publicKey);}
|
|
||||||
|
|
||||||
bool Agree(byte *agreedValue,
|
|
||||||
const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
|
|
||||||
const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
|
|
||||||
bool validateStaticOtherPublicKey=true) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SimpleKeyAgreementDomain &d1, &d2;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,146 +0,0 @@
|
||||||
// dll.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
|
|
||||||
#define CRYPTOPP_DEFAULT_NO_DLL
|
|
||||||
|
|
||||||
#include "dll.h"
|
|
||||||
#pragma warning(default: 4660)
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_EXPORTS) && defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
template<> const byte PKCS_DigestDecoration<SHA1>::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
|
|
||||||
template<> const unsigned int PKCS_DigestDecoration<SHA1>::length = sizeof(PKCS_DigestDecoration<SHA1>::decoration);
|
|
||||||
|
|
||||||
template<> const byte PKCS_DigestDecoration<SHA224>::decoration[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c};
|
|
||||||
template<> const unsigned int PKCS_DigestDecoration<SHA224>::length = sizeof(PKCS_DigestDecoration<SHA224>::decoration);
|
|
||||||
|
|
||||||
template<> const byte PKCS_DigestDecoration<SHA256>::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
|
|
||||||
template<> const unsigned int PKCS_DigestDecoration<SHA256>::length = sizeof(PKCS_DigestDecoration<SHA256>::decoration);
|
|
||||||
|
|
||||||
template<> const byte PKCS_DigestDecoration<SHA384>::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
|
|
||||||
template<> const unsigned int PKCS_DigestDecoration<SHA384>::length = sizeof(PKCS_DigestDecoration<SHA384>::decoration);
|
|
||||||
|
|
||||||
template<> const byte PKCS_DigestDecoration<SHA512>::decoration[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
|
|
||||||
template<> const unsigned int PKCS_DigestDecoration<SHA512>::length = sizeof(PKCS_DigestDecoration<SHA512>::decoration);
|
|
||||||
|
|
||||||
template<> const byte EMSA2HashId<SHA>::id = 0x33;
|
|
||||||
template<> const byte EMSA2HashId<SHA224>::id = 0x38;
|
|
||||||
template<> const byte EMSA2HashId<SHA256>::id = 0x34;
|
|
||||||
template<> const byte EMSA2HashId<SHA384>::id = 0x36;
|
|
||||||
template<> const byte EMSA2HashId<SHA512>::id = 0x35;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_EXPORTS
|
|
||||||
|
|
||||||
USING_NAMESPACE(CryptoPP)
|
|
||||||
|
|
||||||
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
|
|
||||||
using std::set_new_handler;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static PNew s_pNew = NULL;
|
|
||||||
static PDelete s_pDelete = NULL;
|
|
||||||
|
|
||||||
static void * New (size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
while (!(p = malloc(size)))
|
|
||||||
CallNewHandler();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetNewAndDeleteFunctionPointers()
|
|
||||||
{
|
|
||||||
void *p = NULL;
|
|
||||||
HMODULE hModule = NULL;
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
VirtualQuery(p, &mbi, sizeof(mbi));
|
|
||||||
|
|
||||||
if (p >= (char *)mbi.BaseAddress + mbi.RegionSize)
|
|
||||||
break;
|
|
||||||
|
|
||||||
p = (char *)mbi.BaseAddress + mbi.RegionSize;
|
|
||||||
|
|
||||||
if (!mbi.AllocationBase || mbi.AllocationBase == hModule)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
hModule = HMODULE(mbi.AllocationBase);
|
|
||||||
|
|
||||||
PGetNewAndDelete pGetNewAndDelete = (PGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteForCryptoPP");
|
|
||||||
if (pGetNewAndDelete)
|
|
||||||
{
|
|
||||||
pGetNewAndDelete(s_pNew, s_pDelete);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSetNewAndDelete pSetNewAndDelete = (PSetNewAndDelete)GetProcAddress(hModule, "SetNewAndDeleteFromCryptoPP");
|
|
||||||
if (pSetNewAndDelete)
|
|
||||||
{
|
|
||||||
s_pNew = &New;
|
|
||||||
s_pDelete = &free;
|
|
||||||
pSetNewAndDelete(s_pNew, s_pDelete, &set_new_handler);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try getting these directly using mangled names of new and delete operators
|
|
||||||
|
|
||||||
hModule = GetModuleHandle("msvcrtd");
|
|
||||||
if (!hModule)
|
|
||||||
hModule = GetModuleHandle("msvcrt");
|
|
||||||
if (hModule)
|
|
||||||
{
|
|
||||||
// 32-bit versions
|
|
||||||
s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPAXI@Z");
|
|
||||||
s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPAX@Z");
|
|
||||||
if (s_pNew && s_pDelete)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 64-bit versions
|
|
||||||
s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPEAX_K@Z");
|
|
||||||
s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPEAX@Z");
|
|
||||||
if (s_pNew && s_pDelete)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputDebugString("Crypto++ was not able to obtain new and delete function pointers.\n");
|
|
||||||
throw 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * operator new (size_t size)
|
|
||||||
{
|
|
||||||
if (!s_pNew)
|
|
||||||
SetNewAndDeleteFunctionPointers();
|
|
||||||
|
|
||||||
return s_pNew(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete (void * p)
|
|
||||||
{
|
|
||||||
s_pDelete(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void * operator new [] (size_t size)
|
|
||||||
{
|
|
||||||
return operator new (size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete [] (void * p)
|
|
||||||
{
|
|
||||||
operator delete (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #ifdef CRYPTOPP_EXPORTS
|
|
|
@ -1,70 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DLL_H
|
|
||||||
#define CRYPTOPP_DLL_H
|
|
||||||
|
|
||||||
#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL)
|
|
||||||
#ifdef CRYPTOPP_CONFIG_H
|
|
||||||
#error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files.
|
|
||||||
#endif
|
|
||||||
#define CRYPTOPP_IMPORTS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "aes.h"
|
|
||||||
#include "cbcmac.h"
|
|
||||||
#include "ccm.h"
|
|
||||||
#include "cmac.h"
|
|
||||||
#include "channels.h"
|
|
||||||
#include "des.h"
|
|
||||||
#include "dh.h"
|
|
||||||
#include "dsa.h"
|
|
||||||
#include "ec2n.h"
|
|
||||||
#include "eccrypto.h"
|
|
||||||
#include "ecp.h"
|
|
||||||
#include "files.h"
|
|
||||||
#include "fips140.h"
|
|
||||||
#include "gcm.h"
|
|
||||||
#include "hex.h"
|
|
||||||
#include "hmac.h"
|
|
||||||
#include "modes.h"
|
|
||||||
#include "mqueue.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
#include "osrng.h"
|
|
||||||
#include "pkcspad.h"
|
|
||||||
#include "pssr.h"
|
|
||||||
#include "randpool.h"
|
|
||||||
#include "rsa.h"
|
|
||||||
#include "rw.h"
|
|
||||||
#include "sha.h"
|
|
||||||
#include "trdlocal.h"
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#ifdef _DLL
|
|
||||||
// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain()
|
|
||||||
#ifdef NDEBUG
|
|
||||||
#pragma comment(lib, "msvcrt")
|
|
||||||
#else
|
|
||||||
#pragma comment(lib, "msvcrtd")
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma comment(lib, "cryptopp")
|
|
||||||
|
|
||||||
#endif // #ifdef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include <new> // for new_handler
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
|
|
||||||
using std::new_handler;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void * (CRYPTOPP_API * PNew)(size_t);
|
|
||||||
typedef void (CRYPTOPP_API * PDelete)(void *);
|
|
||||||
typedef void (CRYPTOPP_API * PGetNewAndDelete)(PNew &, PDelete &);
|
|
||||||
typedef new_handler (CRYPTOPP_API * PSetNewHandler)(new_handler);
|
|
||||||
typedef void (CRYPTOPP_API * PSetNewAndDelete)(PNew, PDelete, PSetNewHandler);
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,93 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DMAC_H
|
|
||||||
#define CRYPTOPP_DMAC_H
|
|
||||||
|
|
||||||
#include "cbcmac.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class T>
|
|
||||||
class CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs<T>, public MessageAuthenticationCode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static std::string StaticAlgorithmName() {return std::string("DMAC(") + T::StaticAlgorithmName() + ")";}
|
|
||||||
|
|
||||||
CRYPTOPP_CONSTANT(DIGESTSIZE=T::BLOCKSIZE)
|
|
||||||
|
|
||||||
DMAC_Base() {}
|
|
||||||
|
|
||||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void TruncatedFinal(byte *mac, size_t size);
|
|
||||||
unsigned int DigestSize() const {return DIGESTSIZE;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
byte *GenerateSubKeys(const byte *key, size_t keylength);
|
|
||||||
|
|
||||||
size_t m_subkeylength;
|
|
||||||
SecByteBlock m_subkeys;
|
|
||||||
CBC_MAC<T> m_mac1;
|
|
||||||
typename T::Encryption m_f2;
|
|
||||||
unsigned int m_counter;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DMAC
|
|
||||||
/*! Based on "CBC MAC for Real-Time Data Sources" by Erez Petrank
|
|
||||||
and Charles Rackoff. T should be a class derived from BlockCipherDocumentation.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
class DMAC : public MessageAuthenticationCodeFinal<DMAC_Base<T> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DMAC() {}
|
|
||||||
DMAC(const byte *key, size_t length=DMAC_Base<T>::DEFAULT_KEYLENGTH)
|
|
||||||
{this->SetKey(key, length);}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void DMAC_Base<T>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
m_subkeylength = T::StaticGetValidKeyLength(T::BLOCKSIZE);
|
|
||||||
m_subkeys.resize(2*UnsignedMin((unsigned int)T::BLOCKSIZE, m_subkeylength));
|
|
||||||
m_mac1.SetKey(GenerateSubKeys(key, length), m_subkeylength, params);
|
|
||||||
m_f2.SetKey(m_subkeys+m_subkeys.size()/2, m_subkeylength, params);
|
|
||||||
m_counter = 0;
|
|
||||||
m_subkeys.resize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void DMAC_Base<T>::Update(const byte *input, size_t length)
|
|
||||||
{
|
|
||||||
m_mac1.Update(input, length);
|
|
||||||
m_counter = (unsigned int)((m_counter + length) % T::BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void DMAC_Base<T>::TruncatedFinal(byte *mac, size_t size)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(size);
|
|
||||||
|
|
||||||
byte pad[T::BLOCKSIZE];
|
|
||||||
byte padByte = byte(T::BLOCKSIZE-m_counter);
|
|
||||||
memset(pad, padByte, padByte);
|
|
||||||
m_mac1.Update(pad, padByte);
|
|
||||||
m_mac1.TruncatedFinal(mac, size);
|
|
||||||
m_f2.ProcessBlock(mac);
|
|
||||||
|
|
||||||
m_counter = 0; // reset for next message
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
byte *DMAC_Base<T>::GenerateSubKeys(const byte *key, size_t keylength)
|
|
||||||
{
|
|
||||||
typename T::Encryption cipher(key, keylength);
|
|
||||||
memset(m_subkeys, 0, m_subkeys.size());
|
|
||||||
cipher.ProcessBlock(m_subkeys);
|
|
||||||
m_subkeys[m_subkeys.size()/2 + T::BLOCKSIZE - 1] = 1;
|
|
||||||
cipher.ProcessBlock(m_subkeys+m_subkeys.size()/2);
|
|
||||||
return m_subkeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,63 +0,0 @@
|
||||||
// dsa.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "dsa.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat)
|
|
||||||
{
|
|
||||||
Integer r, s;
|
|
||||||
StringStore store(signature, signatureLen);
|
|
||||||
ArraySink sink(buffer, bufferSize);
|
|
||||||
|
|
||||||
switch (fromFormat)
|
|
||||||
{
|
|
||||||
case DSA_P1363:
|
|
||||||
r.Decode(store, signatureLen/2);
|
|
||||||
s.Decode(store, signatureLen/2);
|
|
||||||
break;
|
|
||||||
case DSA_DER:
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(store);
|
|
||||||
r.BERDecode(seq);
|
|
||||||
s.BERDecode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DSA_OPENPGP:
|
|
||||||
r.OpenPGPDecode(store);
|
|
||||||
s.OpenPGPDecode(store);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (toFormat)
|
|
||||||
{
|
|
||||||
case DSA_P1363:
|
|
||||||
r.Encode(sink, bufferSize/2);
|
|
||||||
s.Encode(sink, bufferSize/2);
|
|
||||||
break;
|
|
||||||
case DSA_DER:
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(sink);
|
|
||||||
r.DEREncode(seq);
|
|
||||||
s.DEREncode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DSA_OPENPGP:
|
|
||||||
r.OpenPGPEncode(sink);
|
|
||||||
s.OpenPGPEncode(sink);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (size_t)sink.TotalPutLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef CRYPTOPP_DSA_H
|
|
||||||
#define CRYPTOPP_DSA_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "gfpcrypt.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
/*! The DSA signature format used by Crypto++ is as defined by IEEE P1363.
|
|
||||||
Java uses the DER format, and OpenPGP uses the OpenPGP format. */
|
|
||||||
enum DSASignatureFormat {DSA_P1363, DSA_DER, DSA_OPENPGP};
|
|
||||||
/** This function converts between these formats, and returns length of signature in the target format.
|
|
||||||
If toFormat == DSA_P1363, bufferSize must equal publicKey.SignatureLength() */
|
|
||||||
size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat,
|
|
||||||
const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat);
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
|
||||||
|
|
||||||
typedef DSA::Signer DSAPrivateKey;
|
|
||||||
typedef DSA::Verifier DSAPublicKey;
|
|
||||||
|
|
||||||
const int MIN_DSA_PRIME_LENGTH = DSA::MIN_PRIME_LENGTH;
|
|
||||||
const int MAX_DSA_PRIME_LENGTH = DSA::MAX_PRIME_LENGTH;
|
|
||||||
const int DSA_PRIME_LENGTH_MULTIPLE = DSA::PRIME_LENGTH_MULTIPLE;
|
|
||||||
|
|
||||||
inline bool GenerateDSAPrimes(const byte *seed, size_t seedLength, int &counter, Integer &p, unsigned int primeLength, Integer &q)
|
|
||||||
{return DSA::GeneratePrimes(seed, seedLength, counter, p, primeLength, q);}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,59 +0,0 @@
|
||||||
// eax.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "eax.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void EAX_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
AccessMAC().SetKey(userKey, keylength, params);
|
|
||||||
m_buffer.New(2*AccessMAC().TagSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EAX_Base::Resync(const byte *iv, size_t len)
|
|
||||||
{
|
|
||||||
MessageAuthenticationCode &mac = AccessMAC();
|
|
||||||
unsigned int blockSize = mac.TagSize();
|
|
||||||
|
|
||||||
memset(m_buffer, 0, blockSize);
|
|
||||||
mac.Update(m_buffer, blockSize);
|
|
||||||
mac.CalculateDigest(m_buffer+blockSize, iv, len);
|
|
||||||
|
|
||||||
m_buffer[blockSize-1] = 1;
|
|
||||||
mac.Update(m_buffer, blockSize);
|
|
||||||
|
|
||||||
m_ctr.SetCipherWithIV(AccessMAC().AccessCipher(), m_buffer+blockSize, blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t EAX_Base::AuthenticateBlocks(const byte *data, size_t len)
|
|
||||||
{
|
|
||||||
AccessMAC().Update(data, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EAX_Base::AuthenticateLastHeaderBlock()
|
|
||||||
{
|
|
||||||
assert(m_bufferedDataLength == 0);
|
|
||||||
MessageAuthenticationCode &mac = AccessMAC();
|
|
||||||
unsigned int blockSize = mac.TagSize();
|
|
||||||
|
|
||||||
mac.Final(m_buffer);
|
|
||||||
xorbuf(m_buffer+blockSize, m_buffer, blockSize);
|
|
||||||
|
|
||||||
memset(m_buffer, 0, blockSize);
|
|
||||||
m_buffer[blockSize-1] = 2;
|
|
||||||
mac.Update(m_buffer, blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EAX_Base::AuthenticateLastFooterBlock(byte *tag, size_t macSize)
|
|
||||||
{
|
|
||||||
assert(m_bufferedDataLength == 0);
|
|
||||||
MessageAuthenticationCode &mac = AccessMAC();
|
|
||||||
unsigned int blockSize = mac.TagSize();
|
|
||||||
|
|
||||||
mac.TruncatedFinal(m_buffer, macSize);
|
|
||||||
xorbuf(tag, m_buffer, m_buffer+blockSize, macSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,91 +0,0 @@
|
||||||
#ifndef CRYPTOPP_EAX_H
|
|
||||||
#define CRYPTOPP_EAX_H
|
|
||||||
|
|
||||||
#include "authenc.h"
|
|
||||||
#include "modes.h"
|
|
||||||
#include "cmac.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! .
|
|
||||||
class CRYPTOPP_NO_VTABLE EAX_Base : public AuthenticatedSymmetricCipherBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// AuthenticatedSymmetricCipher
|
|
||||||
std::string AlgorithmName() const
|
|
||||||
{return GetMAC().GetCipher().AlgorithmName() + std::string("/EAX");}
|
|
||||||
size_t MinKeyLength() const
|
|
||||||
{return GetMAC().MinKeyLength();}
|
|
||||||
size_t MaxKeyLength() const
|
|
||||||
{return GetMAC().MaxKeyLength();}
|
|
||||||
size_t DefaultKeyLength() const
|
|
||||||
{return GetMAC().DefaultKeyLength();}
|
|
||||||
size_t GetValidKeyLength(size_t n) const
|
|
||||||
{return GetMAC().GetValidKeyLength(n);}
|
|
||||||
bool IsValidKeyLength(size_t n) const
|
|
||||||
{return GetMAC().IsValidKeyLength(n);}
|
|
||||||
unsigned int OptimalDataAlignment() const
|
|
||||||
{return GetMAC().OptimalDataAlignment();}
|
|
||||||
IV_Requirement IVRequirement() const
|
|
||||||
{return UNIQUE_IV;}
|
|
||||||
unsigned int IVSize() const
|
|
||||||
{return GetMAC().TagSize();}
|
|
||||||
unsigned int MinIVLength() const
|
|
||||||
{return 0;}
|
|
||||||
unsigned int MaxIVLength() const
|
|
||||||
{return UINT_MAX;}
|
|
||||||
unsigned int DigestSize() const
|
|
||||||
{return GetMAC().TagSize();}
|
|
||||||
lword MaxHeaderLength() const
|
|
||||||
{return LWORD_MAX;}
|
|
||||||
lword MaxMessageLength() const
|
|
||||||
{return LWORD_MAX;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// AuthenticatedSymmetricCipherBase
|
|
||||||
bool AuthenticationIsOnPlaintext() const
|
|
||||||
{return false;}
|
|
||||||
unsigned int AuthenticationBlockSize() const
|
|
||||||
{return 1;}
|
|
||||||
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms);
|
|
||||||
void Resync(const byte *iv, size_t len);
|
|
||||||
size_t AuthenticateBlocks(const byte *data, size_t len);
|
|
||||||
void AuthenticateLastHeaderBlock();
|
|
||||||
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
|
|
||||||
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
|
|
||||||
const CMAC_Base & GetMAC() const {return const_cast<EAX_Base *>(this)->AccessMAC();}
|
|
||||||
virtual CMAC_Base & AccessMAC() =0;
|
|
||||||
|
|
||||||
CTR_Mode_ExternalCipher::Encryption m_ctr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! .
|
|
||||||
template <class T_BlockCipher, bool T_IsEncryption>
|
|
||||||
class EAX_Final : public EAX_Base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static std::string StaticAlgorithmName()
|
|
||||||
{return T_BlockCipher::StaticAlgorithmName() + std::string("/EAX");}
|
|
||||||
bool IsForwardTransformation() const
|
|
||||||
{return T_IsEncryption;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CMAC_Base & AccessMAC() {return m_cmac;}
|
|
||||||
CMAC<T_BlockCipher> m_cmac;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef EAX // EAX is defined to 11 on GCC 3.4.3, OpenSolaris 8.11
|
|
||||||
#undef EAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <a href="http://www.cryptolounge.org/wiki/EAX">EAX</a>
|
|
||||||
template <class T_BlockCipher>
|
|
||||||
struct EAX : public AuthenticatedSymmetricCipherDocumentation
|
|
||||||
{
|
|
||||||
typedef EAX_Final<T_BlockCipher, true> Encryption;
|
|
||||||
typedef EAX_Final<T_BlockCipher, false> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,292 +0,0 @@
|
||||||
// ec2n.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "ec2n.h"
|
|
||||||
#include "asn.h"
|
|
||||||
|
|
||||||
#include "algebra.cpp"
|
|
||||||
#include "eprecomp.cpp"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
EC2N::EC2N(BufferedTransformation &bt)
|
|
||||||
: m_field(BERDecodeGF2NP(bt))
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
m_field->BERDecodeElement(seq, m_a);
|
|
||||||
m_field->BERDecodeElement(seq, m_b);
|
|
||||||
// skip optional seed
|
|
||||||
if (!seq.EndReached())
|
|
||||||
{
|
|
||||||
SecByteBlock seed;
|
|
||||||
unsigned int unused;
|
|
||||||
BERDecodeBitString(seq, seed, unused);
|
|
||||||
}
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EC2N::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
m_field->DEREncode(bt);
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
m_field->DEREncodeElement(seq, m_a);
|
|
||||||
m_field->DEREncodeElement(seq, m_b);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, size_t encodedPointLen) const
|
|
||||||
{
|
|
||||||
StringStore store(encodedPoint, encodedPointLen);
|
|
||||||
return DecodePoint(P, store, encodedPointLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const
|
|
||||||
{
|
|
||||||
byte type;
|
|
||||||
if (encodedPointLen < 1 || !bt.Get(type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
P.identity = true;
|
|
||||||
return true;
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if (encodedPointLen != EncodedPointSize(true))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
P.identity = false;
|
|
||||||
P.x.Decode(bt, m_field->MaxElementByteLength());
|
|
||||||
|
|
||||||
if (P.x.IsZero())
|
|
||||||
{
|
|
||||||
P.y = m_field->SquareRoot(m_b);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldElement z = m_field->Square(P.x);
|
|
||||||
assert(P.x == m_field->SquareRoot(z));
|
|
||||||
P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z);
|
|
||||||
assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a));
|
|
||||||
z = m_field->SolveQuadraticEquation(P.y);
|
|
||||||
assert(m_field->Add(m_field->Square(z), z) == P.y);
|
|
||||||
z.SetCoefficient(0, type & 1);
|
|
||||||
|
|
||||||
P.y = m_field->Multiply(z, P.x);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
if (encodedPointLen != EncodedPointSize(false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned int len = m_field->MaxElementByteLength();
|
|
||||||
P.identity = false;
|
|
||||||
P.x.Decode(bt, len);
|
|
||||||
P.y.Decode(bt, len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EC2N::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
|
|
||||||
{
|
|
||||||
if (P.identity)
|
|
||||||
NullStore().TransferTo(bt, EncodedPointSize(compressed));
|
|
||||||
else if (compressed)
|
|
||||||
{
|
|
||||||
bt.Put(2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0)));
|
|
||||||
P.x.Encode(bt, m_field->MaxElementByteLength());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int len = m_field->MaxElementByteLength();
|
|
||||||
bt.Put(4); // uncompressed
|
|
||||||
P.x.Encode(bt, len);
|
|
||||||
P.y.Encode(bt, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
|
|
||||||
{
|
|
||||||
ArraySink sink(encodedPoint, EncodedPointSize(compressed));
|
|
||||||
EncodePoint(sink, P, compressed);
|
|
||||||
assert(sink.TotalPutLength() == EncodedPointSize(compressed));
|
|
||||||
}
|
|
||||||
|
|
||||||
EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
SecByteBlock str;
|
|
||||||
BERDecodeOctetString(bt, str);
|
|
||||||
Point P;
|
|
||||||
if (!DecodePoint(P, str, str.size()))
|
|
||||||
BERDecodeError();
|
|
||||||
return P;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
|
|
||||||
{
|
|
||||||
SecByteBlock str(EncodedPointSize(compressed));
|
|
||||||
EncodePoint(str, P, compressed);
|
|
||||||
DEREncodeOctetString(bt, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EC2N::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
bool pass = !!m_b;
|
|
||||||
pass = pass && m_a.CoefficientCount() <= m_field->MaxElementBitLength();
|
|
||||||
pass = pass && m_b.CoefficientCount() <= m_field->MaxElementBitLength();
|
|
||||||
|
|
||||||
if (level >= 1)
|
|
||||||
pass = pass && m_field->GetModulus().IsIrreducible();
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EC2N::VerifyPoint(const Point &P) const
|
|
||||||
{
|
|
||||||
const FieldElement &x = P.x, &y = P.y;
|
|
||||||
return P.identity ||
|
|
||||||
(x.CoefficientCount() <= m_field->MaxElementBitLength()
|
|
||||||
&& y.CoefficientCount() <= m_field->MaxElementBitLength()
|
|
||||||
&& !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EC2N::Equal(const Point &P, const Point &Q) const
|
|
||||||
{
|
|
||||||
if (P.identity && Q.identity)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (P.identity && !Q.identity)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!P.identity && Q.identity)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
const EC2N::Point& EC2N::Identity() const
|
|
||||||
{
|
|
||||||
return Singleton<Point>().Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
const EC2N::Point& EC2N::Inverse(const Point &P) const
|
|
||||||
{
|
|
||||||
if (P.identity)
|
|
||||||
return P;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_R.identity = false;
|
|
||||||
m_R.y = m_field->Add(P.x, P.y);
|
|
||||||
m_R.x = P.x;
|
|
||||||
return m_R;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const
|
|
||||||
{
|
|
||||||
if (P.identity) return Q;
|
|
||||||
if (Q.identity) return P;
|
|
||||||
if (Equal(P, Q)) return Double(P);
|
|
||||||
if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Identity();
|
|
||||||
|
|
||||||
FieldElement t = m_field->Add(P.y, Q.y);
|
|
||||||
t = m_field->Divide(t, m_field->Add(P.x, Q.x));
|
|
||||||
FieldElement x = m_field->Square(t);
|
|
||||||
m_field->Accumulate(x, t);
|
|
||||||
m_field->Accumulate(x, Q.x);
|
|
||||||
m_field->Accumulate(x, m_a);
|
|
||||||
m_R.y = m_field->Add(P.y, m_field->Multiply(t, x));
|
|
||||||
m_field->Accumulate(x, P.x);
|
|
||||||
m_field->Accumulate(m_R.y, x);
|
|
||||||
|
|
||||||
m_R.x.swap(x);
|
|
||||||
m_R.identity = false;
|
|
||||||
return m_R;
|
|
||||||
}
|
|
||||||
|
|
||||||
const EC2N::Point& EC2N::Double(const Point &P) const
|
|
||||||
{
|
|
||||||
if (P.identity) return P;
|
|
||||||
if (!m_field->IsUnit(P.x)) return Identity();
|
|
||||||
|
|
||||||
FieldElement t = m_field->Divide(P.y, P.x);
|
|
||||||
m_field->Accumulate(t, P.x);
|
|
||||||
m_R.y = m_field->Square(P.x);
|
|
||||||
m_R.x = m_field->Square(t);
|
|
||||||
m_field->Accumulate(m_R.x, t);
|
|
||||||
m_field->Accumulate(m_R.x, m_a);
|
|
||||||
m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x));
|
|
||||||
m_field->Accumulate(m_R.y, m_R.x);
|
|
||||||
|
|
||||||
m_R.identity = false;
|
|
||||||
return m_R;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
/*
|
|
||||||
EcPrecomputation<EC2N>& EcPrecomputation<EC2N>::operator=(const EcPrecomputation<EC2N> &rhs)
|
|
||||||
{
|
|
||||||
m_ec = rhs.m_ec;
|
|
||||||
m_ep = rhs.m_ep;
|
|
||||||
m_ep.m_group = m_ec.get();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EcPrecomputation<EC2N>::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base)
|
|
||||||
{
|
|
||||||
m_ec.reset(new EC2N(ec));
|
|
||||||
m_ep.SetGroupAndBase(*m_ec, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EcPrecomputation<EC2N>::Precompute(unsigned int maxExpBits, unsigned int storage)
|
|
||||||
{
|
|
||||||
m_ep.Precompute(maxExpBits, storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EcPrecomputation<EC2N>::Load(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
word32 version;
|
|
||||||
BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
|
|
||||||
m_ep.m_exponentBase.BERDecode(seq);
|
|
||||||
m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1;
|
|
||||||
m_ep.m_bases.clear();
|
|
||||||
while (!seq.EndReached())
|
|
||||||
m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq));
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EcPrecomputation<EC2N>::Save(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
DEREncodeUnsigned<word32>(seq, 1); // version
|
|
||||||
m_ep.m_exponentBase.DEREncode(seq);
|
|
||||||
for (unsigned i=0; i<m_ep.m_bases.size(); i++)
|
|
||||||
m_ec->DEREncodePoint(seq, m_ep.m_bases[i]);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
EC2N::Point EcPrecomputation<EC2N>::Exponentiate(const Integer &exponent) const
|
|
||||||
{
|
|
||||||
return m_ep.Exponentiate(exponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
EC2N::Point EcPrecomputation<EC2N>::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const
|
|
||||||
{
|
|
||||||
return m_ep.CascadeExponentiate(exponent, static_cast<const EcPrecomputation<EC2N> &>(pc2).m_ep, exponent2);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,113 +0,0 @@
|
||||||
#ifndef CRYPTOPP_EC2N_H
|
|
||||||
#define CRYPTOPP_EC2N_H
|
|
||||||
|
|
||||||
#include "gf2n.h"
|
|
||||||
#include "eprecomp.h"
|
|
||||||
#include "smartptr.h"
|
|
||||||
#include "pubkey.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Elliptic Curve Point
|
|
||||||
struct CRYPTOPP_DLL EC2NPoint
|
|
||||||
{
|
|
||||||
EC2NPoint() : identity(true) {}
|
|
||||||
EC2NPoint(const PolynomialMod2 &x, const PolynomialMod2 &y)
|
|
||||||
: identity(false), x(x), y(y) {}
|
|
||||||
|
|
||||||
bool operator==(const EC2NPoint &t) const
|
|
||||||
{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
|
|
||||||
bool operator< (const EC2NPoint &t) const
|
|
||||||
{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
|
|
||||||
|
|
||||||
bool identity;
|
|
||||||
PolynomialMod2 x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<EC2NPoint>;
|
|
||||||
|
|
||||||
//! Elliptic Curve over GF(2^n)
|
|
||||||
class CRYPTOPP_DLL EC2N : public AbstractGroup<EC2NPoint>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef GF2NP Field;
|
|
||||||
typedef Field::Element FieldElement;
|
|
||||||
typedef EC2NPoint Point;
|
|
||||||
|
|
||||||
EC2N() {}
|
|
||||||
EC2N(const Field &field, const Field::Element &a, const Field::Element &b)
|
|
||||||
: m_field(field), m_a(a), m_b(b) {}
|
|
||||||
// construct from BER encoded parameters
|
|
||||||
// this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
|
|
||||||
EC2N(BufferedTransformation &bt);
|
|
||||||
|
|
||||||
// encode the fields fieldID and curve of the sequence ECParameters
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
bool Equal(const Point &P, const Point &Q) const;
|
|
||||||
const Point& Identity() const;
|
|
||||||
const Point& Inverse(const Point &P) const;
|
|
||||||
bool InversionIsFast() const {return true;}
|
|
||||||
const Point& Add(const Point &P, const Point &Q) const;
|
|
||||||
const Point& Double(const Point &P) const;
|
|
||||||
|
|
||||||
Point Multiply(const Integer &k, const Point &P) const
|
|
||||||
{return ScalarMultiply(P, k);}
|
|
||||||
Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
|
|
||||||
{return CascadeScalarMultiply(P, k1, Q, k2);}
|
|
||||||
|
|
||||||
bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
|
|
||||||
bool VerifyPoint(const Point &P) const;
|
|
||||||
|
|
||||||
unsigned int EncodedPointSize(bool compressed = false) const
|
|
||||||
{return 1 + (compressed?1:2)*m_field->MaxElementByteLength();}
|
|
||||||
// returns false if point is compressed and not valid (doesn't check if uncompressed)
|
|
||||||
bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
|
|
||||||
bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
|
|
||||||
void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
|
|
||||||
void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
|
|
||||||
|
|
||||||
Point BERDecodePoint(BufferedTransformation &bt) const;
|
|
||||||
void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
|
|
||||||
|
|
||||||
Integer FieldSize() const {return Integer::Power2(m_field->MaxElementBitLength());}
|
|
||||||
const Field & GetField() const {return *m_field;}
|
|
||||||
const FieldElement & GetA() const {return m_a;}
|
|
||||||
const FieldElement & GetB() const {return m_b;}
|
|
||||||
|
|
||||||
bool operator==(const EC2N &rhs) const
|
|
||||||
{return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
clonable_ptr<Field> m_field;
|
|
||||||
FieldElement m_a, m_b;
|
|
||||||
mutable Point m_R;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<EC2N::Point>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<EC2N::Point>;
|
|
||||||
|
|
||||||
template <class T> class EcPrecomputation;
|
|
||||||
|
|
||||||
//! EC2N precomputation
|
|
||||||
template<> class EcPrecomputation<EC2N> : public DL_GroupPrecomputation<EC2N::Point>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef EC2N EllipticCurve;
|
|
||||||
|
|
||||||
// DL_GroupPrecomputation
|
|
||||||
const AbstractGroup<Element> & GetGroup() const {return m_ec;}
|
|
||||||
Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec.BERDecodePoint(bt);}
|
|
||||||
void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec.DEREncodePoint(bt, v, false);}
|
|
||||||
|
|
||||||
// non-inherited
|
|
||||||
void SetCurve(const EC2N &ec) {m_ec = ec;}
|
|
||||||
const EC2N & GetCurve() const {return m_ec;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
EC2N m_ec;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,694 +0,0 @@
|
||||||
// eccrypto.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "eccrypto.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
#include "oids.h"
|
|
||||||
#include "hex.h"
|
|
||||||
#include "argnames.h"
|
|
||||||
#include "ec2n.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void ECDSA_TestInstantiations()
|
|
||||||
{
|
|
||||||
ECDSA<EC2N>::Signer t1;
|
|
||||||
ECDSA<EC2N>::Verifier t2(t1);
|
|
||||||
ECNR<ECP>::Signer t3;
|
|
||||||
ECNR<ECP>::Verifier t4(t3);
|
|
||||||
ECIES<ECP>::Encryptor t5;
|
|
||||||
ECIES<EC2N>::Decryptor t6;
|
|
||||||
ECDH<ECP>::Domain t7;
|
|
||||||
ECMQV<ECP>::Domain t8;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// VC60 workaround: complains when these functions are put into an anonymous namespace
|
|
||||||
static Integer ConvertToInteger(const PolynomialMod2 &x)
|
|
||||||
{
|
|
||||||
unsigned int l = x.ByteCount();
|
|
||||||
SecByteBlock temp(l);
|
|
||||||
x.Encode(temp, l);
|
|
||||||
return Integer(temp, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Integer ConvertToInteger(const Integer &x)
|
|
||||||
{
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CheckMOVCondition(const Integer &q, const Integer &r)
|
|
||||||
{
|
|
||||||
// see "Updated standards for validating elliptic curves", http://eprint.iacr.org/2007/343
|
|
||||||
Integer t = 1;
|
|
||||||
unsigned int n = q.IsEven() ? 1 : q.BitCount(), m = r.BitCount();
|
|
||||||
|
|
||||||
for (unsigned int i=n; DiscreteLogWorkFactor(i)<m/2; i+=n)
|
|
||||||
{
|
|
||||||
if (q.IsEven())
|
|
||||||
t = (t+t)%r;
|
|
||||||
else
|
|
||||||
t = (t*q)%r;
|
|
||||||
if (t == 1)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
|
|
||||||
template <class T> struct EcRecommendedParameters;
|
|
||||||
|
|
||||||
template<> struct EcRecommendedParameters<EC2N>
|
|
||||||
{
|
|
||||||
EcRecommendedParameters(const OID &oid, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h)
|
|
||||||
: oid(oid), t0(0), t1(0), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {}
|
|
||||||
EcRecommendedParameters(const OID &oid, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h)
|
|
||||||
: oid(oid), t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {}
|
|
||||||
EC2N *NewEC() const
|
|
||||||
{
|
|
||||||
StringSource ssA(a, true, new HexDecoder);
|
|
||||||
StringSource ssB(b, true, new HexDecoder);
|
|
||||||
if (t0 == 0)
|
|
||||||
return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
|
|
||||||
else
|
|
||||||
return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
|
|
||||||
};
|
|
||||||
|
|
||||||
OID oid;
|
|
||||||
unsigned int t0, t1, t2, t3, t4;
|
|
||||||
const char *a, *b, *g, *n;
|
|
||||||
unsigned int h;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct EcRecommendedParameters<ECP>
|
|
||||||
{
|
|
||||||
EcRecommendedParameters(const OID &oid, const char *p, const char *a, const char *b, const char *g, const char *n, unsigned int h)
|
|
||||||
: oid(oid), p(p), a(a), b(b), g(g), n(n), h(h) {}
|
|
||||||
ECP *NewEC() const
|
|
||||||
{
|
|
||||||
StringSource ssP(p, true, new HexDecoder);
|
|
||||||
StringSource ssA(a, true, new HexDecoder);
|
|
||||||
StringSource ssB(b, true, new HexDecoder);
|
|
||||||
return new ECP(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECP::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECP::FieldElement(ssB, (size_t)ssB.MaxRetrievable()));
|
|
||||||
};
|
|
||||||
|
|
||||||
OID oid;
|
|
||||||
const char *p;
|
|
||||||
const char *a, *b, *g, *n;
|
|
||||||
unsigned int h;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OIDLessThan
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator()(const EcRecommendedParameters<T>& a, const OID& b) {return a.oid < b;}
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator()(const OID& a, const EcRecommendedParameters<T>& b) {return a < b.oid;}
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator()(const EcRecommendedParameters<T>& a, const EcRecommendedParameters<T>& b) {return a.oid < b.oid;}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void GetRecommendedParameters(const EcRecommendedParameters<EC2N> *&begin, const EcRecommendedParameters<EC2N> *&end)
|
|
||||||
{
|
|
||||||
// this array must be sorted by OID
|
|
||||||
static const EcRecommendedParameters<EC2N> rec[] = {
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect163k1(),
|
|
||||||
163, 7, 6, 3, 0,
|
|
||||||
"000000000000000000000000000000000000000001",
|
|
||||||
"000000000000000000000000000000000000000001",
|
|
||||||
"0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9",
|
|
||||||
"04000000000000000000020108A2E0CC0D99F8A5EF",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect163r1(),
|
|
||||||
163, 7, 6, 3, 0,
|
|
||||||
"07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
|
|
||||||
"0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
|
|
||||||
"040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
|
|
||||||
"03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect239k1(),
|
|
||||||
239, 158, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
|
|
||||||
"2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect113r1(),
|
|
||||||
113, 9, 0,
|
|
||||||
"003088250CA6E7C7FE649CE85820F7",
|
|
||||||
"00E8BEE4D3E2260744188BE0E9C723",
|
|
||||||
"04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886",
|
|
||||||
"0100000000000000D9CCEC8A39E56F",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect113r2(),
|
|
||||||
113, 9, 0,
|
|
||||||
"00689918DBEC7E5A0DD6DFC0AA55C7",
|
|
||||||
"0095E9A9EC9B297BD4BF36E059184F",
|
|
||||||
"0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D",
|
|
||||||
"010000000000000108789B2496AF93",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect163r2(),
|
|
||||||
163, 7, 6, 3, 0,
|
|
||||||
"000000000000000000000000000000000000000001",
|
|
||||||
"020A601907B8C953CA1481EB10512F78744A3205FD",
|
|
||||||
"0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
|
|
||||||
"040000000000000000000292FE77E70C12A4234C33",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect283k1(),
|
|
||||||
283, 12, 7, 5, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
|
|
||||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect283r1(),
|
|
||||||
283, 12, 7, 5, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
|
|
||||||
"0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
|
|
||||||
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect131r1(),
|
|
||||||
131, 8, 3, 2, 0,
|
|
||||||
"07A11B09A76B562144418FF3FF8C2570B8",
|
|
||||||
"0217C05610884B63B9C6C7291678F9D341",
|
|
||||||
"040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150",
|
|
||||||
"0400000000000000023123953A9464B54D",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect131r2(),
|
|
||||||
131, 8, 3, 2, 0,
|
|
||||||
"03E5A88919D7CAFCBF415F07C2176573B2",
|
|
||||||
"04B8266A46C55657AC734CE38F018F2192",
|
|
||||||
"040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F",
|
|
||||||
"0400000000000000016954A233049BA98F",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect193r1(),
|
|
||||||
193, 15, 0,
|
|
||||||
"0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
|
|
||||||
"00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
|
|
||||||
"0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
|
|
||||||
"01000000000000000000000000C7F34A778F443ACC920EBA49",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect193r2(),
|
|
||||||
193, 15, 0,
|
|
||||||
"0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
|
|
||||||
"00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
|
|
||||||
"0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
|
|
||||||
"010000000000000000000000015AAB561B005413CCD4EE99D5",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect233k1(),
|
|
||||||
233, 74, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
|
|
||||||
"8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect233r1(),
|
|
||||||
233, 74, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
|
|
||||||
"0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
|
|
||||||
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect409k1(),
|
|
||||||
409, 87, 0,
|
|
||||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
|
|
||||||
"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect409r1(),
|
|
||||||
409, 87, 0,
|
|
||||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
|
|
||||||
"04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
|
|
||||||
"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
|
|
||||||
2),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect571k1(),
|
|
||||||
571, 10, 5, 2, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
|
|
||||||
"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<EC2N>(ASN1::sect571r1(),
|
|
||||||
571, 10, 5, 2, 0,
|
|
||||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
|
|
||||||
"040303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
|
|
||||||
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
|
|
||||||
2),
|
|
||||||
};
|
|
||||||
begin = rec;
|
|
||||||
end = rec + sizeof(rec)/sizeof(rec[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GetRecommendedParameters(const EcRecommendedParameters<ECP> *&begin, const EcRecommendedParameters<ECP> *&end)
|
|
||||||
{
|
|
||||||
// this array must be sorted by OID
|
|
||||||
static const EcRecommendedParameters<ECP> rec[] = {
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp192r1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
|
||||||
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
|
||||||
"04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp256r1(),
|
|
||||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
|
||||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
|
||||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
|
||||||
"046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
|
||||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP160r1(),
|
|
||||||
"E95E4A5F737059DC60DFC7AD95B3D8139515620F",
|
|
||||||
"340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
|
|
||||||
"1E589A8595423412134FAA2DBDEC95C8D8675E58",
|
|
||||||
"04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321",
|
|
||||||
"E95E4A5F737059DC60DF5991D45029409E60FC09",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP192r1(),
|
|
||||||
"C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
|
|
||||||
"6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
|
|
||||||
"469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
|
|
||||||
"04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
|
|
||||||
"C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP224r1(),
|
|
||||||
"D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
|
|
||||||
"68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
|
|
||||||
"2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
|
|
||||||
"040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
|
|
||||||
"D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP256r1(),
|
|
||||||
"A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
|
|
||||||
"7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
|
|
||||||
"26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
|
|
||||||
"048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
|
|
||||||
"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP320r1(),
|
|
||||||
"D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
|
|
||||||
"3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
|
|
||||||
"520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
|
|
||||||
"0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
|
|
||||||
"D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP384r1(),
|
|
||||||
"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
|
|
||||||
"7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
|
|
||||||
"04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
|
|
||||||
"041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
|
|
||||||
"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::brainpoolP512r1(),
|
|
||||||
"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
|
|
||||||
"7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
|
|
||||||
"3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
|
|
||||||
"0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
|
|
||||||
"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp112r1(),
|
|
||||||
"DB7C2ABF62E35E668076BEAD208B",
|
|
||||||
"DB7C2ABF62E35E668076BEAD2088",
|
|
||||||
"659EF8BA043916EEDE8911702B22",
|
|
||||||
"0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500",
|
|
||||||
"DB7C2ABF62E35E7628DFAC6561C5",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp112r2(),
|
|
||||||
"DB7C2ABF62E35E668076BEAD208B",
|
|
||||||
"6127C24C05F38A0AAAF65C0EF02C",
|
|
||||||
"51DEF1815DB5ED74FCC34C85D709",
|
|
||||||
"044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97",
|
|
||||||
"36DF0AAFD8B8D7597CA10520D04B",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp160r1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
|
||||||
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
|
||||||
"044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32",
|
|
||||||
"0100000000000000000001F4C8F927AED3CA752257",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp160k1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
|
||||||
"0000000000000000000000000000000000000000",
|
|
||||||
"0000000000000000000000000000000000000007",
|
|
||||||
"043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE",
|
|
||||||
"0100000000000000000001B8FA16DFAB9ACA16B6B3",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp256k1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000007",
|
|
||||||
"0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp128r1(),
|
|
||||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
|
||||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
|
||||||
"E87579C11079F43DD824993C2CEE5ED3",
|
|
||||||
"04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83",
|
|
||||||
"FFFFFFFE0000000075A30D1B9038A115",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp128r2(),
|
|
||||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
|
||||||
"D6031998D1B3BBFEBF59CC9BBFF9AEE1",
|
|
||||||
"5EEEFCA380D02919DC2C6558BB6D8A5D",
|
|
||||||
"047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44",
|
|
||||||
"3FFFFFFF7FFFFFFFBE0024720613B5A3",
|
|
||||||
4),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp160r2(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
|
|
||||||
"B4E134D3FB59EB8BAB57274904664D5AF50388BA",
|
|
||||||
"0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
|
|
||||||
"0100000000000000000000351EE786A818F3A1A16B",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp192k1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
|
|
||||||
"000000000000000000000000000000000000000000000000",
|
|
||||||
"000000000000000000000000000000000000000000000003",
|
|
||||||
"04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp224k1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
|
|
||||||
"00000000000000000000000000000000000000000000000000000000",
|
|
||||||
"00000000000000000000000000000000000000000000000000000005",
|
|
||||||
"04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
|
|
||||||
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp224r1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
|
||||||
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
|
||||||
"04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp384r1(),
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
|
||||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
|
||||||
"04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
|
||||||
1),
|
|
||||||
EcRecommendedParameters<ECP>(ASN1::secp521r1(),
|
|
||||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
|
||||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
|
||||||
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
|
||||||
"0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
|
||||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
|
||||||
1),
|
|
||||||
};
|
|
||||||
begin = rec;
|
|
||||||
end = rec + sizeof(rec)/sizeof(rec[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC> OID DL_GroupParameters_EC<EC>::GetNextRecommendedParametersOID(const OID &oid)
|
|
||||||
{
|
|
||||||
const EcRecommendedParameters<EllipticCurve> *begin, *end;
|
|
||||||
GetRecommendedParameters(begin, end);
|
|
||||||
const EcRecommendedParameters<EllipticCurve> *it = std::upper_bound(begin, end, oid, OIDLessThan());
|
|
||||||
return (it == end ? OID() : it->oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC> void DL_GroupParameters_EC<EC>::Initialize(const OID &oid)
|
|
||||||
{
|
|
||||||
const EcRecommendedParameters<EllipticCurve> *begin, *end;
|
|
||||||
GetRecommendedParameters(begin, end);
|
|
||||||
const EcRecommendedParameters<EllipticCurve> *it = std::lower_bound(begin, end, oid, OIDLessThan());
|
|
||||||
if (it == end || it->oid != oid)
|
|
||||||
throw UnknownOID();
|
|
||||||
|
|
||||||
const EcRecommendedParameters<EllipticCurve> ¶m = *it;
|
|
||||||
m_oid = oid;
|
|
||||||
std::auto_ptr<EllipticCurve> ec(param.NewEC());
|
|
||||||
this->m_groupPrecomputation.SetCurve(*ec);
|
|
||||||
|
|
||||||
StringSource ssG(param.g, true, new HexDecoder);
|
|
||||||
Element G;
|
|
||||||
bool result = GetCurve().DecodePoint(G, ssG, (size_t)ssG.MaxRetrievable());
|
|
||||||
this->SetSubgroupGenerator(G);
|
|
||||||
assert(result);
|
|
||||||
|
|
||||||
StringSource ssN(param.n, true, new HexDecoder);
|
|
||||||
m_n.Decode(ssN, (size_t)ssN.MaxRetrievable());
|
|
||||||
m_k = param.h;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
bool DL_GroupParameters_EC<EC>::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
if (strcmp(name, Name::GroupOID()) == 0)
|
|
||||||
{
|
|
||||||
if (m_oid.m_values.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this->ThrowIfTypeMismatch(name, typeid(OID), valueType);
|
|
||||||
*reinterpret_cast<OID *>(pValue) = m_oid;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return GetValueHelper<DL_GroupParameters<Element> >(this, name, valueType, pValue).Assignable()
|
|
||||||
CRYPTOPP_GET_FUNCTION_ENTRY(Curve);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_GroupParameters_EC<EC>::AssignFrom(const NameValuePairs &source)
|
|
||||||
{
|
|
||||||
OID oid;
|
|
||||||
if (source.GetValue(Name::GroupOID(), oid))
|
|
||||||
Initialize(oid);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EllipticCurve ec;
|
|
||||||
Point G;
|
|
||||||
Integer n;
|
|
||||||
|
|
||||||
source.GetRequiredParameter("DL_GroupParameters_EC<EC>", Name::Curve(), ec);
|
|
||||||
source.GetRequiredParameter("DL_GroupParameters_EC<EC>", Name::SubgroupGenerator(), G);
|
|
||||||
source.GetRequiredParameter("DL_GroupParameters_EC<EC>", Name::SubgroupOrder(), n);
|
|
||||||
Integer k = source.GetValueWithDefault(Name::Cofactor(), Integer::Zero());
|
|
||||||
|
|
||||||
Initialize(ec, G, n, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_GroupParameters_EC<EC>::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AssignFrom(alg);
|
|
||||||
}
|
|
||||||
catch (InvalidArgument &)
|
|
||||||
{
|
|
||||||
throw NotImplemented("DL_GroupParameters_EC<EC>: curve generation is not implemented yet");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_GroupParameters_EC<EC>::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
if (!bt.Peek(b))
|
|
||||||
BERDecodeError();
|
|
||||||
if (b == OBJECT_IDENTIFIER)
|
|
||||||
Initialize(OID(bt));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
word32 version;
|
|
||||||
BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1); // check version
|
|
||||||
EllipticCurve ec(seq);
|
|
||||||
Point G = ec.BERDecodePoint(seq);
|
|
||||||
Integer n(seq);
|
|
||||||
Integer k;
|
|
||||||
bool cofactorPresent = !seq.EndReached();
|
|
||||||
if (cofactorPresent)
|
|
||||||
k.BERDecode(seq);
|
|
||||||
else
|
|
||||||
k = Integer::Zero();
|
|
||||||
seq.MessageEnd();
|
|
||||||
|
|
||||||
Initialize(ec, G, n, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_GroupParameters_EC<EC>::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
if (m_encodeAsOID && !m_oid.m_values.empty())
|
|
||||||
m_oid.DEREncode(bt);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
DEREncodeUnsigned<word32>(seq, 1); // version
|
|
||||||
GetCurve().DEREncode(seq);
|
|
||||||
GetCurve().DEREncodePoint(seq, this->GetSubgroupGenerator(), m_compress);
|
|
||||||
m_n.DEREncode(seq);
|
|
||||||
if (m_k.NotZero())
|
|
||||||
m_k.DEREncode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
Integer DL_GroupParameters_EC<EC>::GetCofactor() const
|
|
||||||
{
|
|
||||||
if (!m_k)
|
|
||||||
{
|
|
||||||
Integer q = GetCurve().FieldSize();
|
|
||||||
Integer qSqrt = q.SquareRoot();
|
|
||||||
m_k = (q+2*qSqrt+1)/m_n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_k;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
Integer DL_GroupParameters_EC<EC>::ConvertElementToInteger(const Element &element) const
|
|
||||||
{
|
|
||||||
return ConvertToInteger(element.x);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
bool DL_GroupParameters_EC<EC>::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
bool pass = GetCurve().ValidateParameters(rng, level);
|
|
||||||
|
|
||||||
Integer q = GetCurve().FieldSize();
|
|
||||||
pass = pass && m_n!=q;
|
|
||||||
|
|
||||||
if (level >= 2)
|
|
||||||
{
|
|
||||||
Integer qSqrt = q.SquareRoot();
|
|
||||||
pass = pass && m_n>4*qSqrt;
|
|
||||||
pass = pass && VerifyPrime(rng, m_n, level-2);
|
|
||||||
pass = pass && (m_k.IsZero() || m_k == (q+2*qSqrt+1)/m_n);
|
|
||||||
pass = pass && CheckMOVCondition(q, m_n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
bool DL_GroupParameters_EC<EC>::ValidateElement(unsigned int level, const Element &g, const DL_FixedBasePrecomputation<Element> *gpc) const
|
|
||||||
{
|
|
||||||
bool pass = !IsIdentity(g) && GetCurve().VerifyPoint(g);
|
|
||||||
if (level >= 1)
|
|
||||||
{
|
|
||||||
if (gpc)
|
|
||||||
pass = pass && gpc->Exponentiate(this->GetGroupPrecomputation(), Integer::One()) == g;
|
|
||||||
}
|
|
||||||
if (level >= 2 && pass)
|
|
||||||
{
|
|
||||||
const Integer &q = GetSubgroupOrder();
|
|
||||||
Element gq = gpc ? gpc->Exponentiate(this->GetGroupPrecomputation(), q) : this->ExponentiateElement(g, q);
|
|
||||||
pass = pass && IsIdentity(gq);
|
|
||||||
}
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_GroupParameters_EC<EC>::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
|
|
||||||
{
|
|
||||||
GetCurve().SimultaneousMultiply(results, base, exponents, exponentsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
CPP_TYPENAME DL_GroupParameters_EC<EC>::Element DL_GroupParameters_EC<EC>::MultiplyElements(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
return GetCurve().Add(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
CPP_TYPENAME DL_GroupParameters_EC<EC>::Element DL_GroupParameters_EC<EC>::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
|
|
||||||
{
|
|
||||||
return GetCurve().CascadeMultiply(exponent1, element1, exponent2, element2);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
OID DL_GroupParameters_EC<EC>::GetAlgorithmID() const
|
|
||||||
{
|
|
||||||
return ASN1::id_ecPublicKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_PublicKey_EC<EC>::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
|
|
||||||
{
|
|
||||||
typename EC::Point P;
|
|
||||||
if (!this->GetGroupParameters().GetCurve().DecodePoint(P, bt, size))
|
|
||||||
BERDecodeError();
|
|
||||||
this->SetPublicElement(P);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_PublicKey_EC<EC>::DEREncodePublicKey(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_PrivateKey_EC<EC>::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
word32 version;
|
|
||||||
BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1); // check version
|
|
||||||
|
|
||||||
BERGeneralDecoder dec(seq, OCTET_STRING);
|
|
||||||
if (!dec.IsDefiniteLength())
|
|
||||||
BERDecodeError();
|
|
||||||
Integer x;
|
|
||||||
x.Decode(dec, (size_t)dec.RemainingLength());
|
|
||||||
dec.MessageEnd();
|
|
||||||
if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0))
|
|
||||||
BERDecodeError();
|
|
||||||
if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0))
|
|
||||||
{
|
|
||||||
BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0);
|
|
||||||
this->AccessGroupParameters().BERDecode(parameters);
|
|
||||||
parameters.MessageEnd();
|
|
||||||
}
|
|
||||||
if (!seq.EndReached())
|
|
||||||
{
|
|
||||||
// skip over the public element
|
|
||||||
SecByteBlock subjectPublicKey;
|
|
||||||
unsigned int unusedBits;
|
|
||||||
BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1);
|
|
||||||
BERDecodeBitString(publicKey, subjectPublicKey, unusedBits);
|
|
||||||
publicKey.MessageEnd();
|
|
||||||
Element Q;
|
|
||||||
if (!(unusedBits == 0 && this->GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size())))
|
|
||||||
BERDecodeError();
|
|
||||||
}
|
|
||||||
seq.MessageEnd();
|
|
||||||
|
|
||||||
this->SetPrivateExponent(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class EC>
|
|
||||||
void DL_PrivateKey_EC<EC>::DEREncodePrivateKey(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder privateKey(bt);
|
|
||||||
DEREncodeUnsigned<word32>(privateKey, 1); // version
|
|
||||||
// SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve
|
|
||||||
// this will be changed to order of base point in a future version
|
|
||||||
this->GetPrivateExponent().DEREncodeAsOctetString(privateKey, this->GetGroupParameters().GetSubgroupOrder().ByteCount());
|
|
||||||
privateKey.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,280 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ECCRYPTO_H
|
|
||||||
#define CRYPTOPP_ECCRYPTO_H
|
|
||||||
|
|
||||||
/*! \file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pubkey.h"
|
|
||||||
#include "integer.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "hmac.h"
|
|
||||||
#include "sha.h"
|
|
||||||
#include "gfpcrypt.h"
|
|
||||||
#include "dh.h"
|
|
||||||
#include "mqv.h"
|
|
||||||
#include "ecp.h"
|
|
||||||
#include "ec2n.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Elliptic Curve Parameters
|
|
||||||
/*! This class corresponds to the ASN.1 sequence of the same name
|
|
||||||
in ANSI X9.62 (also SEC 1).
|
|
||||||
*/
|
|
||||||
template <class EC>
|
|
||||||
class DL_GroupParameters_EC : public DL_GroupParametersImpl<EcPrecomputation<EC> >
|
|
||||||
{
|
|
||||||
typedef DL_GroupParameters_EC<EC> ThisClass;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef EC EllipticCurve;
|
|
||||||
typedef typename EllipticCurve::Point Point;
|
|
||||||
typedef Point Element;
|
|
||||||
typedef IncompatibleCofactorMultiplication DefaultCofactorOption;
|
|
||||||
|
|
||||||
DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {}
|
|
||||||
DL_GroupParameters_EC(const OID &oid)
|
|
||||||
: m_compress(false), m_encodeAsOID(false) {Initialize(oid);}
|
|
||||||
DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
|
|
||||||
: m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);}
|
|
||||||
DL_GroupParameters_EC(BufferedTransformation &bt)
|
|
||||||
: m_compress(false), m_encodeAsOID(false) {BERDecode(bt);}
|
|
||||||
|
|
||||||
void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
|
|
||||||
{
|
|
||||||
this->m_groupPrecomputation.SetCurve(ec);
|
|
||||||
this->SetSubgroupGenerator(G);
|
|
||||||
m_n = n;
|
|
||||||
m_k = k;
|
|
||||||
}
|
|
||||||
void Initialize(const OID &oid);
|
|
||||||
|
|
||||||
// NameValuePairs
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
void AssignFrom(const NameValuePairs &source);
|
|
||||||
|
|
||||||
// GeneratibleCryptoMaterial interface
|
|
||||||
//! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values
|
|
||||||
/*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */
|
|
||||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
|
|
||||||
|
|
||||||
// DL_GroupParameters
|
|
||||||
const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
|
|
||||||
DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
|
|
||||||
const Integer & GetSubgroupOrder() const {return m_n;}
|
|
||||||
Integer GetCofactor() const;
|
|
||||||
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
|
|
||||||
bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const;
|
|
||||||
bool FastSubgroupCheckAvailable() const {return false;}
|
|
||||||
void EncodeElement(bool reversible, const Element &element, byte *encoded) const
|
|
||||||
{
|
|
||||||
if (reversible)
|
|
||||||
GetCurve().EncodePoint(encoded, element, m_compress);
|
|
||||||
else
|
|
||||||
element.x.Encode(encoded, GetEncodedElementSize(false));
|
|
||||||
}
|
|
||||||
unsigned int GetEncodedElementSize(bool reversible) const
|
|
||||||
{
|
|
||||||
if (reversible)
|
|
||||||
return GetCurve().EncodedPointSize(m_compress);
|
|
||||||
else
|
|
||||||
return GetCurve().GetField().MaxElementByteLength();
|
|
||||||
}
|
|
||||||
Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const
|
|
||||||
{
|
|
||||||
Point result;
|
|
||||||
if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true)))
|
|
||||||
throw DL_BadElement();
|
|
||||||
if (checkForGroupMembership && !ValidateElement(1, result, NULL))
|
|
||||||
throw DL_BadElement();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
Integer ConvertElementToInteger(const Element &element) const;
|
|
||||||
Integer GetMaxExponent() const {return GetSubgroupOrder()-1;}
|
|
||||||
bool IsIdentity(const Element &element) const {return element.identity;}
|
|
||||||
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
|
||||||
static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";}
|
|
||||||
|
|
||||||
// ASN1Key
|
|
||||||
OID GetAlgorithmID() const;
|
|
||||||
|
|
||||||
// used by MQV
|
|
||||||
Element MultiplyElements(const Element &a, const Element &b) const;
|
|
||||||
Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
|
|
||||||
|
|
||||||
// non-inherited
|
|
||||||
|
|
||||||
// enumerate OIDs for recommended parameters, use OID() to get first one
|
|
||||||
static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid);
|
|
||||||
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
void SetPointCompression(bool compress) {m_compress = compress;}
|
|
||||||
bool GetPointCompression() const {return m_compress;}
|
|
||||||
|
|
||||||
void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;}
|
|
||||||
bool GetEncodeAsOID() const {return m_encodeAsOID;}
|
|
||||||
|
|
||||||
const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();}
|
|
||||||
|
|
||||||
bool operator==(const ThisClass &rhs) const
|
|
||||||
{return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);}
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
|
||||||
const Point& GetBasePoint() const {return GetSubgroupGenerator();}
|
|
||||||
const Integer& GetBasePointOrder() const {return GetSubgroupOrder();}
|
|
||||||
void LoadRecommendedParameters(const OID &oid) {Initialize(oid);}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();}
|
|
||||||
unsigned int ExponentLength() const {return m_n.ByteCount();}
|
|
||||||
|
|
||||||
OID m_oid; // set if parameters loaded from a recommended curve
|
|
||||||
Integer m_n; // order of base point
|
|
||||||
bool m_compress, m_encodeAsOID;
|
|
||||||
mutable Integer m_k; // cofactor
|
|
||||||
};
|
|
||||||
|
|
||||||
//! EC public key
|
|
||||||
template <class EC>
|
|
||||||
class DL_PublicKey_EC : public DL_PublicKeyImpl<DL_GroupParameters_EC<EC> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename EC::Point Element;
|
|
||||||
|
|
||||||
void Initialize(const DL_GroupParameters_EC<EC> ¶ms, const Element &Q)
|
|
||||||
{this->AccessGroupParameters() = params; this->SetPublicElement(Q);}
|
|
||||||
void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q)
|
|
||||||
{this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);}
|
|
||||||
|
|
||||||
// X509PublicKey
|
|
||||||
void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
|
|
||||||
void DEREncodePublicKey(BufferedTransformation &bt) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! EC private key
|
|
||||||
template <class EC>
|
|
||||||
class DL_PrivateKey_EC : public DL_PrivateKeyImpl<DL_GroupParameters_EC<EC> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename EC::Point Element;
|
|
||||||
|
|
||||||
void Initialize(const DL_GroupParameters_EC<EC> ¶ms, const Integer &x)
|
|
||||||
{this->AccessGroupParameters() = params; this->SetPrivateExponent(x);}
|
|
||||||
void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x)
|
|
||||||
{this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);}
|
|
||||||
void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> ¶ms)
|
|
||||||
{this->GenerateRandom(rng, params);}
|
|
||||||
void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
|
|
||||||
{this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}
|
|
||||||
|
|
||||||
// PKCS8PrivateKey
|
|
||||||
void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
|
|
||||||
void DEREncodePrivateKey(BufferedTransformation &bt) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Elliptic Curve Diffie-Hellman, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECDH">ECDH</a>
|
|
||||||
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
|
|
||||||
struct ECDH
|
|
||||||
{
|
|
||||||
typedef DH_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Elliptic Curve Menezes-Qu-Vanstone, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECMQV">ECMQV</a>
|
|
||||||
template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
|
|
||||||
struct ECMQV
|
|
||||||
{
|
|
||||||
typedef MQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! EC keys
|
|
||||||
template <class EC>
|
|
||||||
struct DL_Keys_EC
|
|
||||||
{
|
|
||||||
typedef DL_PublicKey_EC<EC> PublicKey;
|
|
||||||
typedef DL_PrivateKey_EC<EC> PrivateKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class EC, class H>
|
|
||||||
struct ECDSA;
|
|
||||||
|
|
||||||
//! ECDSA keys
|
|
||||||
template <class EC>
|
|
||||||
struct DL_Keys_ECDSA
|
|
||||||
{
|
|
||||||
typedef DL_PublicKey_EC<EC> PublicKey;
|
|
||||||
typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC>, ECDSA<EC, SHA256> > PrivateKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! ECDSA algorithm
|
|
||||||
template <class EC>
|
|
||||||
class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA<typename EC::Point>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! ECNR algorithm
|
|
||||||
template <class EC>
|
|
||||||
class DL_Algorithm_ECNR : public DL_Algorithm_NR<typename EC::Point>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>
|
|
||||||
template <class EC, class H>
|
|
||||||
struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_SignatureMessageEncodingMethod_DSA, H>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
//! ECNR
|
|
||||||
template <class EC, class H = SHA>
|
|
||||||
struct ECNR : public DL_SS<DL_Keys_EC<EC>, DL_Algorithm_ECNR<EC>, DL_SignatureMessageEncodingMethod_NR, H>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Elliptic Curve Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">ECIES</a>
|
|
||||||
/*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2.
|
|
||||||
The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best
|
|
||||||
efficiency and security. */
|
|
||||||
template <class EC, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = false>
|
|
||||||
struct ECIES
|
|
||||||
: public DL_ES<
|
|
||||||
DL_Keys_EC<EC>,
|
|
||||||
DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>,
|
|
||||||
DL_KeyDerivationAlgorithm_P1363<typename EC::Point, DHAES_MODE, P1363_KDF2<SHA1> >,
|
|
||||||
DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
|
|
||||||
ECIES<EC> >
|
|
||||||
{
|
|
||||||
static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
|
|
||||||
#include "eccrypto.cpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<ECP>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<EC2N>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<ECP> >;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<EC2N> >;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<ECP>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<EC2N>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<ECP> >;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<EC2N> >;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<ECP>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<EC2N>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<ECP::Point>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<EC2N::Point>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<ECP>, ECDSA<ECP, SHA256> >;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC2N>, ECDSA<EC2N, SHA256> >;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,473 +0,0 @@
|
||||||
// ecp.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "ecp.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
|
|
||||||
#include "algebra.cpp"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
ANONYMOUS_NAMESPACE_BEGIN
|
|
||||||
static inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P)
|
|
||||||
{
|
|
||||||
return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P)
|
|
||||||
{
|
|
||||||
return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y));
|
|
||||||
}
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
ECP::ECP(const ECP &ecp, bool convertToMontgomeryRepresentation)
|
|
||||||
{
|
|
||||||
if (convertToMontgomeryRepresentation && !ecp.GetField().IsMontgomeryRepresentation())
|
|
||||||
{
|
|
||||||
m_fieldPtr.reset(new MontgomeryRepresentation(ecp.GetField().GetModulus()));
|
|
||||||
m_a = GetField().ConvertIn(ecp.m_a);
|
|
||||||
m_b = GetField().ConvertIn(ecp.m_b);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
operator=(ecp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ECP::ECP(BufferedTransformation &bt)
|
|
||||||
: m_fieldPtr(new Field(bt))
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
GetField().BERDecodeElement(seq, m_a);
|
|
||||||
GetField().BERDecodeElement(seq, m_b);
|
|
||||||
// skip optional seed
|
|
||||||
if (!seq.EndReached())
|
|
||||||
{
|
|
||||||
SecByteBlock seed;
|
|
||||||
unsigned int unused;
|
|
||||||
BERDecodeBitString(seq, seed, unused);
|
|
||||||
}
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ECP::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
GetField().DEREncode(bt);
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
GetField().DEREncodeElement(seq, m_a);
|
|
||||||
GetField().DEREncodeElement(seq, m_b);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ECP::DecodePoint(ECP::Point &P, const byte *encodedPoint, size_t encodedPointLen) const
|
|
||||||
{
|
|
||||||
StringStore store(encodedPoint, encodedPointLen);
|
|
||||||
return DecodePoint(P, store, encodedPointLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const
|
|
||||||
{
|
|
||||||
byte type;
|
|
||||||
if (encodedPointLen < 1 || !bt.Get(type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
P.identity = true;
|
|
||||||
return true;
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if (encodedPointLen != EncodedPointSize(true))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Integer p = FieldSize();
|
|
||||||
|
|
||||||
P.identity = false;
|
|
||||||
P.x.Decode(bt, GetField().MaxElementByteLength());
|
|
||||||
P.y = ((P.x*P.x+m_a)*P.x+m_b) % p;
|
|
||||||
|
|
||||||
if (Jacobi(P.y, p) !=1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
P.y = ModularSquareRoot(P.y, p);
|
|
||||||
|
|
||||||
if ((type & 1) != P.y.GetBit(0))
|
|
||||||
P.y = p-P.y;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
if (encodedPointLen != EncodedPointSize(false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned int len = GetField().MaxElementByteLength();
|
|
||||||
P.identity = false;
|
|
||||||
P.x.Decode(bt, len);
|
|
||||||
P.y.Decode(bt, len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
|
|
||||||
{
|
|
||||||
if (P.identity)
|
|
||||||
NullStore().TransferTo(bt, EncodedPointSize(compressed));
|
|
||||||
else if (compressed)
|
|
||||||
{
|
|
||||||
bt.Put(2 + P.y.GetBit(0));
|
|
||||||
P.x.Encode(bt, GetField().MaxElementByteLength());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int len = GetField().MaxElementByteLength();
|
|
||||||
bt.Put(4); // uncompressed
|
|
||||||
P.x.Encode(bt, len);
|
|
||||||
P.y.Encode(bt, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ECP::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const
|
|
||||||
{
|
|
||||||
ArraySink sink(encodedPoint, EncodedPointSize(compressed));
|
|
||||||
EncodePoint(sink, P, compressed);
|
|
||||||
assert(sink.TotalPutLength() == EncodedPointSize(compressed));
|
|
||||||
}
|
|
||||||
|
|
||||||
ECP::Point ECP::BERDecodePoint(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
SecByteBlock str;
|
|
||||||
BERDecodeOctetString(bt, str);
|
|
||||||
Point P;
|
|
||||||
if (!DecodePoint(P, str, str.size()))
|
|
||||||
BERDecodeError();
|
|
||||||
return P;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ECP::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const
|
|
||||||
{
|
|
||||||
SecByteBlock str(EncodedPointSize(compressed));
|
|
||||||
EncodePoint(str, P, compressed);
|
|
||||||
DEREncodeOctetString(bt, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ECP::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
Integer p = FieldSize();
|
|
||||||
|
|
||||||
bool pass = p.IsOdd();
|
|
||||||
pass = pass && !m_a.IsNegative() && m_a<p && !m_b.IsNegative() && m_b<p;
|
|
||||||
|
|
||||||
if (level >= 1)
|
|
||||||
pass = pass && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive();
|
|
||||||
|
|
||||||
if (level >= 2)
|
|
||||||
pass = pass && VerifyPrime(rng, p);
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ECP::VerifyPoint(const Point &P) const
|
|
||||||
{
|
|
||||||
const FieldElement &x = P.x, &y = P.y;
|
|
||||||
Integer p = FieldSize();
|
|
||||||
return P.identity ||
|
|
||||||
(!x.IsNegative() && x<p && !y.IsNegative() && y<p
|
|
||||||
&& !(((x*x+m_a)*x+m_b-y*y)%p));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ECP::Equal(const Point &P, const Point &Q) const
|
|
||||||
{
|
|
||||||
if (P.identity && Q.identity)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (P.identity && !Q.identity)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!P.identity && Q.identity)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (GetField().Equal(P.x,Q.x) && GetField().Equal(P.y,Q.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
const ECP::Point& ECP::Identity() const
|
|
||||||
{
|
|
||||||
return Singleton<Point>().Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
const ECP::Point& ECP::Inverse(const Point &P) const
|
|
||||||
{
|
|
||||||
if (P.identity)
|
|
||||||
return P;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_R.identity = false;
|
|
||||||
m_R.x = P.x;
|
|
||||||
m_R.y = GetField().Inverse(P.y);
|
|
||||||
return m_R;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ECP::Point& ECP::Add(const Point &P, const Point &Q) const
|
|
||||||
{
|
|
||||||
if (P.identity) return Q;
|
|
||||||
if (Q.identity) return P;
|
|
||||||
if (GetField().Equal(P.x, Q.x))
|
|
||||||
return GetField().Equal(P.y, Q.y) ? Double(P) : Identity();
|
|
||||||
|
|
||||||
FieldElement t = GetField().Subtract(Q.y, P.y);
|
|
||||||
t = GetField().Divide(t, GetField().Subtract(Q.x, P.x));
|
|
||||||
FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), Q.x);
|
|
||||||
m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y);
|
|
||||||
|
|
||||||
m_R.x.swap(x);
|
|
||||||
m_R.identity = false;
|
|
||||||
return m_R;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ECP::Point& ECP::Double(const Point &P) const
|
|
||||||
{
|
|
||||||
if (P.identity || P.y==GetField().Identity()) return Identity();
|
|
||||||
|
|
||||||
FieldElement t = GetField().Square(P.x);
|
|
||||||
t = GetField().Add(GetField().Add(GetField().Double(t), t), m_a);
|
|
||||||
t = GetField().Divide(t, GetField().Double(P.y));
|
|
||||||
FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), P.x);
|
|
||||||
m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y);
|
|
||||||
|
|
||||||
m_R.x.swap(x);
|
|
||||||
m_R.identity = false;
|
|
||||||
return m_R;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, class Iterator> void ParallelInvert(const AbstractRing<T> &ring, Iterator begin, Iterator end)
|
|
||||||
{
|
|
||||||
size_t n = end-begin;
|
|
||||||
if (n == 1)
|
|
||||||
*begin = ring.MultiplicativeInverse(*begin);
|
|
||||||
else if (n > 1)
|
|
||||||
{
|
|
||||||
std::vector<T> vec((n+1)/2);
|
|
||||||
unsigned int i;
|
|
||||||
Iterator it;
|
|
||||||
|
|
||||||
for (i=0, it=begin; i<n/2; i++, it+=2)
|
|
||||||
vec[i] = ring.Multiply(*it, *(it+1));
|
|
||||||
if (n%2 == 1)
|
|
||||||
vec[n/2] = *it;
|
|
||||||
|
|
||||||
ParallelInvert(ring, vec.begin(), vec.end());
|
|
||||||
|
|
||||||
for (i=0, it=begin; i<n/2; i++, it+=2)
|
|
||||||
{
|
|
||||||
if (!vec[i])
|
|
||||||
{
|
|
||||||
*it = ring.MultiplicativeInverse(*it);
|
|
||||||
*(it+1) = ring.MultiplicativeInverse(*(it+1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::swap(*it, *(it+1));
|
|
||||||
*it = ring.Multiply(*it, vec[i]);
|
|
||||||
*(it+1) = ring.Multiply(*(it+1), vec[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (n%2 == 1)
|
|
||||||
*it = vec[n/2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ProjectivePoint
|
|
||||||
{
|
|
||||||
ProjectivePoint() {}
|
|
||||||
ProjectivePoint(const Integer &x, const Integer &y, const Integer &z)
|
|
||||||
: x(x), y(y), z(z) {}
|
|
||||||
|
|
||||||
Integer x,y,z;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProjectiveDoubling
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ProjectiveDoubling(const ModularArithmetic &mr, const Integer &m_a, const Integer &m_b, const ECPPoint &Q)
|
|
||||||
: mr(mr), firstDoubling(true), negated(false)
|
|
||||||
{
|
|
||||||
if (Q.identity)
|
|
||||||
{
|
|
||||||
sixteenY4 = P.x = P.y = mr.MultiplicativeIdentity();
|
|
||||||
aZ4 = P.z = mr.Identity();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
P.x = Q.x;
|
|
||||||
P.y = Q.y;
|
|
||||||
sixteenY4 = P.z = mr.MultiplicativeIdentity();
|
|
||||||
aZ4 = m_a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Double()
|
|
||||||
{
|
|
||||||
twoY = mr.Double(P.y);
|
|
||||||
P.z = mr.Multiply(P.z, twoY);
|
|
||||||
fourY2 = mr.Square(twoY);
|
|
||||||
S = mr.Multiply(fourY2, P.x);
|
|
||||||
aZ4 = mr.Multiply(aZ4, sixteenY4);
|
|
||||||
M = mr.Square(P.x);
|
|
||||||
M = mr.Add(mr.Add(mr.Double(M), M), aZ4);
|
|
||||||
P.x = mr.Square(M);
|
|
||||||
mr.Reduce(P.x, S);
|
|
||||||
mr.Reduce(P.x, S);
|
|
||||||
mr.Reduce(S, P.x);
|
|
||||||
P.y = mr.Multiply(M, S);
|
|
||||||
sixteenY4 = mr.Square(fourY2);
|
|
||||||
mr.Reduce(P.y, mr.Half(sixteenY4));
|
|
||||||
}
|
|
||||||
|
|
||||||
const ModularArithmetic &mr;
|
|
||||||
ProjectivePoint P;
|
|
||||||
bool firstDoubling, negated;
|
|
||||||
Integer sixteenY4, aZ4, twoY, fourY2, S, M;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ZIterator
|
|
||||||
{
|
|
||||||
ZIterator() {}
|
|
||||||
ZIterator(std::vector<ProjectivePoint>::iterator it) : it(it) {}
|
|
||||||
Integer& operator*() {return it->z;}
|
|
||||||
int operator-(ZIterator it2) {return int(it-it2.it);}
|
|
||||||
ZIterator operator+(int i) {return ZIterator(it+i);}
|
|
||||||
ZIterator& operator+=(int i) {it+=i; return *this;}
|
|
||||||
std::vector<ProjectivePoint>::iterator it;
|
|
||||||
};
|
|
||||||
|
|
||||||
ECP::Point ECP::ScalarMultiply(const Point &P, const Integer &k) const
|
|
||||||
{
|
|
||||||
Element result;
|
|
||||||
if (k.BitCount() <= 5)
|
|
||||||
AbstractGroup<ECPPoint>::SimultaneousMultiply(&result, P, &k, 1);
|
|
||||||
else
|
|
||||||
ECP::SimultaneousMultiply(&result, P, &k, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ECP::SimultaneousMultiply(ECP::Point *results, const ECP::Point &P, const Integer *expBegin, unsigned int expCount) const
|
|
||||||
{
|
|
||||||
if (!GetField().IsMontgomeryRepresentation())
|
|
||||||
{
|
|
||||||
ECP ecpmr(*this, true);
|
|
||||||
const ModularArithmetic &mr = ecpmr.GetField();
|
|
||||||
ecpmr.SimultaneousMultiply(results, ToMontgomery(mr, P), expBegin, expCount);
|
|
||||||
for (unsigned int i=0; i<expCount; i++)
|
|
||||||
results[i] = FromMontgomery(mr, results[i]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProjectiveDoubling rd(GetField(), m_a, m_b, P);
|
|
||||||
std::vector<ProjectivePoint> bases;
|
|
||||||
std::vector<WindowSlider> exponents;
|
|
||||||
exponents.reserve(expCount);
|
|
||||||
std::vector<std::vector<word32> > baseIndices(expCount);
|
|
||||||
std::vector<std::vector<bool> > negateBase(expCount);
|
|
||||||
std::vector<std::vector<word32> > exponentWindows(expCount);
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i=0; i<expCount; i++)
|
|
||||||
{
|
|
||||||
assert(expBegin->NotNegative());
|
|
||||||
exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 5));
|
|
||||||
exponents[i].FindNextWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int expBitPosition = 0;
|
|
||||||
bool notDone = true;
|
|
||||||
|
|
||||||
while (notDone)
|
|
||||||
{
|
|
||||||
notDone = false;
|
|
||||||
bool baseAdded = false;
|
|
||||||
for (i=0; i<expCount; i++)
|
|
||||||
{
|
|
||||||
if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
|
|
||||||
{
|
|
||||||
if (!baseAdded)
|
|
||||||
{
|
|
||||||
bases.push_back(rd.P);
|
|
||||||
baseAdded =true;
|
|
||||||
}
|
|
||||||
|
|
||||||
exponentWindows[i].push_back(exponents[i].expWindow);
|
|
||||||
baseIndices[i].push_back((word32)bases.size()-1);
|
|
||||||
negateBase[i].push_back(exponents[i].negateNext);
|
|
||||||
|
|
||||||
exponents[i].FindNextWindow();
|
|
||||||
}
|
|
||||||
notDone = notDone || !exponents[i].finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notDone)
|
|
||||||
{
|
|
||||||
rd.Double();
|
|
||||||
expBitPosition++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert from projective to affine coordinates
|
|
||||||
ParallelInvert(GetField(), ZIterator(bases.begin()), ZIterator(bases.end()));
|
|
||||||
for (i=0; i<bases.size(); i++)
|
|
||||||
{
|
|
||||||
if (bases[i].z.NotZero())
|
|
||||||
{
|
|
||||||
bases[i].y = GetField().Multiply(bases[i].y, bases[i].z);
|
|
||||||
bases[i].z = GetField().Square(bases[i].z);
|
|
||||||
bases[i].x = GetField().Multiply(bases[i].x, bases[i].z);
|
|
||||||
bases[i].y = GetField().Multiply(bases[i].y, bases[i].z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<BaseAndExponent<Point, Integer> > finalCascade;
|
|
||||||
for (i=0; i<expCount; i++)
|
|
||||||
{
|
|
||||||
finalCascade.resize(baseIndices[i].size());
|
|
||||||
for (unsigned int j=0; j<baseIndices[i].size(); j++)
|
|
||||||
{
|
|
||||||
ProjectivePoint &base = bases[baseIndices[i][j]];
|
|
||||||
if (base.z.IsZero())
|
|
||||||
finalCascade[j].base.identity = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
finalCascade[j].base.identity = false;
|
|
||||||
finalCascade[j].base.x = base.x;
|
|
||||||
if (negateBase[i][j])
|
|
||||||
finalCascade[j].base.y = GetField().Inverse(base.y);
|
|
||||||
else
|
|
||||||
finalCascade[j].base.y = base.y;
|
|
||||||
}
|
|
||||||
finalCascade[j].exponent = Integer(Integer::POSITIVE, 0, exponentWindows[i][j]);
|
|
||||||
}
|
|
||||||
results[i] = GeneralCascadeMultiplication(*this, finalCascade.begin(), finalCascade.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ECP::Point ECP::CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const
|
|
||||||
{
|
|
||||||
if (!GetField().IsMontgomeryRepresentation())
|
|
||||||
{
|
|
||||||
ECP ecpmr(*this, true);
|
|
||||||
const ModularArithmetic &mr = ecpmr.GetField();
|
|
||||||
return FromMontgomery(mr, ecpmr.CascadeScalarMultiply(ToMontgomery(mr, P), k1, ToMontgomery(mr, Q), k2));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return AbstractGroup<Point>::CascadeScalarMultiply(P, k1, Q, k2);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,126 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ECP_H
|
|
||||||
#define CRYPTOPP_ECP_H
|
|
||||||
|
|
||||||
#include "modarith.h"
|
|
||||||
#include "eprecomp.h"
|
|
||||||
#include "smartptr.h"
|
|
||||||
#include "pubkey.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Elliptical Curve Point
|
|
||||||
struct CRYPTOPP_DLL ECPPoint
|
|
||||||
{
|
|
||||||
ECPPoint() : identity(true) {}
|
|
||||||
ECPPoint(const Integer &x, const Integer &y)
|
|
||||||
: identity(false), x(x), y(y) {}
|
|
||||||
|
|
||||||
bool operator==(const ECPPoint &t) const
|
|
||||||
{return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);}
|
|
||||||
bool operator< (const ECPPoint &t) const
|
|
||||||
{return identity ? !t.identity : (!t.identity && (x<t.x || (x==t.x && y<t.y)));}
|
|
||||||
|
|
||||||
bool identity;
|
|
||||||
Integer x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<ECPPoint>;
|
|
||||||
|
|
||||||
//! Elliptic Curve over GF(p), where p is prime
|
|
||||||
class CRYPTOPP_DLL ECP : public AbstractGroup<ECPPoint>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef ModularArithmetic Field;
|
|
||||||
typedef Integer FieldElement;
|
|
||||||
typedef ECPPoint Point;
|
|
||||||
|
|
||||||
ECP() {}
|
|
||||||
ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false);
|
|
||||||
ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b)
|
|
||||||
: m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {}
|
|
||||||
// construct from BER encoded parameters
|
|
||||||
// this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters
|
|
||||||
ECP(BufferedTransformation &bt);
|
|
||||||
|
|
||||||
// encode the fields fieldID and curve of the sequence ECParameters
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
bool Equal(const Point &P, const Point &Q) const;
|
|
||||||
const Point& Identity() const;
|
|
||||||
const Point& Inverse(const Point &P) const;
|
|
||||||
bool InversionIsFast() const {return true;}
|
|
||||||
const Point& Add(const Point &P, const Point &Q) const;
|
|
||||||
const Point& Double(const Point &P) const;
|
|
||||||
Point ScalarMultiply(const Point &P, const Integer &k) const;
|
|
||||||
Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const;
|
|
||||||
void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const;
|
|
||||||
|
|
||||||
Point Multiply(const Integer &k, const Point &P) const
|
|
||||||
{return ScalarMultiply(P, k);}
|
|
||||||
Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const
|
|
||||||
{return CascadeScalarMultiply(P, k1, Q, k2);}
|
|
||||||
|
|
||||||
bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const;
|
|
||||||
bool VerifyPoint(const Point &P) const;
|
|
||||||
|
|
||||||
unsigned int EncodedPointSize(bool compressed = false) const
|
|
||||||
{return 1 + (compressed?1:2)*GetField().MaxElementByteLength();}
|
|
||||||
// returns false if point is compressed and not valid (doesn't check if uncompressed)
|
|
||||||
bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const;
|
|
||||||
bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const;
|
|
||||||
void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const;
|
|
||||||
void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
|
|
||||||
|
|
||||||
Point BERDecodePoint(BufferedTransformation &bt) const;
|
|
||||||
void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const;
|
|
||||||
|
|
||||||
Integer FieldSize() const {return GetField().GetModulus();}
|
|
||||||
const Field & GetField() const {return *m_fieldPtr;}
|
|
||||||
const FieldElement & GetA() const {return m_a;}
|
|
||||||
const FieldElement & GetB() const {return m_b;}
|
|
||||||
|
|
||||||
bool operator==(const ECP &rhs) const
|
|
||||||
{return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
clonable_ptr<Field> m_fieldPtr;
|
|
||||||
FieldElement m_a, m_b;
|
|
||||||
mutable Point m_R;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl<ECP::Point>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation<ECP::Point>;
|
|
||||||
|
|
||||||
template <class T> class EcPrecomputation;
|
|
||||||
|
|
||||||
//! ECP precomputation
|
|
||||||
template<> class EcPrecomputation<ECP> : public DL_GroupPrecomputation<ECP::Point>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef ECP EllipticCurve;
|
|
||||||
|
|
||||||
// DL_GroupPrecomputation
|
|
||||||
bool NeedConversions() const {return true;}
|
|
||||||
Element ConvertIn(const Element &P) const
|
|
||||||
{return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));};
|
|
||||||
Element ConvertOut(const Element &P) const
|
|
||||||
{return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));}
|
|
||||||
const AbstractGroup<Element> & GetGroup() const {return *m_ec;}
|
|
||||||
Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);}
|
|
||||||
void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);}
|
|
||||||
|
|
||||||
// non-inherited
|
|
||||||
void SetCurve(const ECP &ec)
|
|
||||||
{
|
|
||||||
m_ec.reset(new ECP(ec, true));
|
|
||||||
m_ecOriginal = ec;
|
|
||||||
}
|
|
||||||
const ECP & GetCurve() const {return *m_ecOriginal;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
value_ptr<ECP> m_ec, m_ecOriginal;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,17 +0,0 @@
|
||||||
// elgamal.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "elgamal.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void ElGamal_TestInstantiations()
|
|
||||||
{
|
|
||||||
ElGamalEncryptor test1(1, 1, 1);
|
|
||||||
ElGamalDecryptor test2(NullRNG(), 123);
|
|
||||||
ElGamalEncryptor test3(test2);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,121 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ELGAMAL_H
|
|
||||||
#define CRYPTOPP_ELGAMAL_H
|
|
||||||
|
|
||||||
#include "modexppc.h"
|
|
||||||
#include "dsa.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
class CRYPTOPP_NO_VTABLE ElGamalBase : public DL_KeyAgreementAlgorithm_DH<Integer, NoCofactorMultiplication>,
|
|
||||||
public DL_KeyDerivationAlgorithm<Integer>,
|
|
||||||
public DL_SymmetricEncryptionAlgorithm
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Derive(const DL_GroupParameters<Integer> &groupParams, byte *derivedKey, size_t derivedLength, const Integer &agreedElement, const Integer &ephemeralPublicKey, const NameValuePairs &derivationParams) const
|
|
||||||
{
|
|
||||||
agreedElement.Encode(derivedKey, derivedLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetSymmetricKeyLength(size_t plainTextLength) const
|
|
||||||
{
|
|
||||||
return GetGroupParameters().GetModulus().ByteCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetSymmetricCiphertextLength(size_t plainTextLength) const
|
|
||||||
{
|
|
||||||
unsigned int len = GetGroupParameters().GetModulus().ByteCount();
|
|
||||||
if (plainTextLength <= GetMaxSymmetricPlaintextLength(len))
|
|
||||||
return len;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetMaxSymmetricPlaintextLength(size_t cipherTextLength) const
|
|
||||||
{
|
|
||||||
unsigned int len = GetGroupParameters().GetModulus().ByteCount();
|
|
||||||
if (cipherTextLength == len)
|
|
||||||
return STDMIN(255U, len-3);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plainText, size_t plainTextLength, byte *cipherText, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
const Integer &p = GetGroupParameters().GetModulus();
|
|
||||||
unsigned int modulusLen = p.ByteCount();
|
|
||||||
|
|
||||||
SecByteBlock block(modulusLen-1);
|
|
||||||
rng.GenerateBlock(block, modulusLen-2-plainTextLength);
|
|
||||||
memcpy(block+modulusLen-2-plainTextLength, plainText, plainTextLength);
|
|
||||||
block[modulusLen-2] = (byte)plainTextLength;
|
|
||||||
|
|
||||||
a_times_b_mod_c(Integer(key, modulusLen), Integer(block, modulusLen-1), p).Encode(cipherText, modulusLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
DecodingResult SymmetricDecrypt(const byte *key, const byte *cipherText, size_t cipherTextLength, byte *plainText, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
const Integer &p = GetGroupParameters().GetModulus();
|
|
||||||
unsigned int modulusLen = p.ByteCount();
|
|
||||||
|
|
||||||
if (cipherTextLength != modulusLen)
|
|
||||||
return DecodingResult();
|
|
||||||
|
|
||||||
Integer m = a_times_b_mod_c(Integer(cipherText, modulusLen), Integer(key, modulusLen).InverseMod(p), p);
|
|
||||||
|
|
||||||
m.Encode(plainText, 1);
|
|
||||||
unsigned int plainTextLength = plainText[0];
|
|
||||||
if (plainTextLength > GetMaxSymmetricPlaintextLength(modulusLen))
|
|
||||||
return DecodingResult();
|
|
||||||
m >>= 8;
|
|
||||||
m.Encode(plainText, plainTextLength);
|
|
||||||
return DecodingResult(plainTextLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const DL_GroupParameters_GFP & GetGroupParameters() const =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class BASE, class SCHEME_OPTIONS, class KEY>
|
|
||||||
class ElGamalObjectImpl : public DL_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>, public ElGamalBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
size_t FixedMaxPlaintextLength() const {return this->MaxPlaintextLength(FixedCiphertextLength());}
|
|
||||||
size_t FixedCiphertextLength() const {return this->CiphertextLength(0);}
|
|
||||||
|
|
||||||
const DL_GroupParameters_GFP & GetGroupParameters() const {return this->GetKey().GetGroupParameters();}
|
|
||||||
|
|
||||||
DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const
|
|
||||||
{return Decrypt(rng, cipherText, FixedCiphertextLength(), plainText);}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const DL_KeyAgreementAlgorithm<Integer> & GetKeyAgreementAlgorithm() const {return *this;}
|
|
||||||
const DL_KeyDerivationAlgorithm<Integer> & GetKeyDerivationAlgorithm() const {return *this;}
|
|
||||||
const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ElGamalKeys
|
|
||||||
{
|
|
||||||
typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters;
|
|
||||||
typedef DL_PrivateKey_GFP_OldFormat<DL_CryptoKeys_GFP::PrivateKey> PrivateKey;
|
|
||||||
typedef DL_PublicKey_GFP_OldFormat<DL_CryptoKeys_GFP::PublicKey> PublicKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! ElGamal encryption scheme with non-standard padding
|
|
||||||
struct ElGamal
|
|
||||||
{
|
|
||||||
typedef DL_CryptoSchemeOptions<ElGamal, ElGamalKeys, int, int, int> SchemeOptions;
|
|
||||||
|
|
||||||
static const char * StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";}
|
|
||||||
|
|
||||||
typedef SchemeOptions::GroupParameters GroupParameters;
|
|
||||||
//! implements PK_Encryptor interface
|
|
||||||
typedef PK_FinalTemplate<ElGamalObjectImpl<DL_EncryptorBase<Integer>, SchemeOptions, SchemeOptions::PublicKey> > Encryptor;
|
|
||||||
//! implements PK_Decryptor interface
|
|
||||||
typedef PK_FinalTemplate<ElGamalObjectImpl<DL_DecryptorBase<Integer>, SchemeOptions, SchemeOptions::PrivateKey> > Decryptor;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef ElGamal::Encryptor ElGamalEncryptor;
|
|
||||||
typedef ElGamal::Decryptor ElGamalDecryptor;
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,34 +0,0 @@
|
||||||
// emsa2.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "emsa2.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void EMSA2Pad::ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
|
||||||
const byte *recoverableMessage, size_t recoverableMessageLength,
|
|
||||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
|
||||||
byte *representative, size_t representativeBitLength) const
|
|
||||||
{
|
|
||||||
assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
|
|
||||||
|
|
||||||
if (representativeBitLength % 8 != 7)
|
|
||||||
throw PK_SignatureScheme::InvalidKeyLength("EMSA2: EMSA2 requires a key length that is a multiple of 8");
|
|
||||||
|
|
||||||
size_t digestSize = hash.DigestSize();
|
|
||||||
size_t representativeByteLength = BitsToBytes(representativeBitLength);
|
|
||||||
|
|
||||||
representative[0] = messageEmpty ? 0x4b : 0x6b;
|
|
||||||
memset(representative+1, 0xbb, representativeByteLength-digestSize-4); // pad with 0xbb
|
|
||||||
byte *afterP2 = representative+representativeByteLength-digestSize-3;
|
|
||||||
afterP2[0] = 0xba;
|
|
||||||
hash.Final(afterP2+1);
|
|
||||||
representative[representativeByteLength-2] = *hashIdentifier.first;
|
|
||||||
representative[representativeByteLength-1] = 0xcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,86 +0,0 @@
|
||||||
#ifndef CRYPTOPP_EMSA2_H
|
|
||||||
#define CRYPTOPP_EMSA2_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
This file contains various padding schemes for public key algorithms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "pubkey.h"
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_IS_DLL
|
|
||||||
#include "sha.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
template <class H> class EMSA2HashId
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const byte id;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class BASE>
|
|
||||||
class EMSA2HashIdLookup : public BASE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct HashIdentifierLookup
|
|
||||||
{
|
|
||||||
template <class H> struct HashIdentifierLookup2
|
|
||||||
{
|
|
||||||
static HashIdentifier Lookup()
|
|
||||||
{
|
|
||||||
return HashIdentifier(&EMSA2HashId<H>::id, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// EMSA2HashId can be instantiated with the following classes.
|
|
||||||
class SHA1;
|
|
||||||
class RIPEMD160;
|
|
||||||
class RIPEMD128;
|
|
||||||
class SHA256;
|
|
||||||
class SHA384;
|
|
||||||
class SHA512;
|
|
||||||
class Whirlpool;
|
|
||||||
class SHA224;
|
|
||||||
// end of list
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_IS_DLL
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA1>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA224>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA256>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA384>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId<SHA512>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup<PK_DeterministicSignatureMessageEncodingMethod>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA2";}
|
|
||||||
|
|
||||||
size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
|
|
||||||
{return 8*digestLength + 31;}
|
|
||||||
|
|
||||||
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
|
||||||
const byte *recoverableMessage, size_t recoverableMessageLength,
|
|
||||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
|
||||||
byte *representative, size_t representativeBitLength) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! EMSA2, for use with RWSS and RSA_ISO
|
|
||||||
/*! Only the following hash functions are supported by this signature standard:
|
|
||||||
\dontinclude emsa2.h
|
|
||||||
\skip EMSA2HashId can be instantiated
|
|
||||||
\until end of list
|
|
||||||
*/
|
|
||||||
struct P1363_EMSA2 : public SignatureStandard
|
|
||||||
{
|
|
||||||
typedef EMSA2Pad SignatureMessageEncodingMethod;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,112 +0,0 @@
|
||||||
// eprecomp.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "eprecomp.h"
|
|
||||||
#include "asn.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::SetBase(const DL_GroupPrecomputation<Element> &group, const Element &i_base)
|
|
||||||
{
|
|
||||||
m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base;
|
|
||||||
|
|
||||||
if (m_bases.empty() || !(m_base == m_bases[0]))
|
|
||||||
{
|
|
||||||
m_bases.resize(1);
|
|
||||||
m_bases[0] = m_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (group.NeedConversions())
|
|
||||||
m_base = i_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage)
|
|
||||||
{
|
|
||||||
assert(m_bases.size() > 0);
|
|
||||||
assert(storage <= maxExpBits);
|
|
||||||
|
|
||||||
if (storage > 1)
|
|
||||||
{
|
|
||||||
m_windowSize = (maxExpBits+storage-1)/storage;
|
|
||||||
m_exponentBase = Integer::Power2(m_windowSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bases.resize(storage);
|
|
||||||
for (unsigned i=1; i<storage; i++)
|
|
||||||
m_bases[i] = group.GetGroup().ScalarMultiply(m_bases[i-1], m_exponentBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
word32 version;
|
|
||||||
BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
|
|
||||||
m_exponentBase.BERDecode(seq);
|
|
||||||
m_windowSize = m_exponentBase.BitCount() - 1;
|
|
||||||
m_bases.clear();
|
|
||||||
while (!seq.EndReached())
|
|
||||||
m_bases.push_back(group.BERDecodeElement(seq));
|
|
||||||
if (!m_bases.empty() && group.NeedConversions())
|
|
||||||
m_base = group.ConvertOut(m_bases[0]);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
DEREncodeUnsigned<word32>(seq, 1); // version
|
|
||||||
m_exponentBase.DEREncode(seq);
|
|
||||||
for (unsigned i=0; i<m_bases.size(); i++)
|
|
||||||
group.DEREncodeElement(seq, m_bases[i]);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::PrepareCascade(const DL_GroupPrecomputation<Element> &i_group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const
|
|
||||||
{
|
|
||||||
const AbstractGroup<T> &group = i_group.GetGroup();
|
|
||||||
|
|
||||||
Integer r, q, e = exponent;
|
|
||||||
bool fastNegate = group.InversionIsFast() && m_windowSize > 1;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i=0; i+1<m_bases.size(); i++)
|
|
||||||
{
|
|
||||||
Integer::DivideByPowerOf2(r, q, e, m_windowSize);
|
|
||||||
std::swap(q, e);
|
|
||||||
if (fastNegate && r.GetBit(m_windowSize-1))
|
|
||||||
{
|
|
||||||
++e;
|
|
||||||
eb.push_back(BaseAndExponent<Element>(group.Inverse(m_bases[i]), m_exponentBase - r));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
eb.push_back(BaseAndExponent<Element>(m_bases[i], r));
|
|
||||||
}
|
|
||||||
eb.push_back(BaseAndExponent<Element>(m_bases[i], e));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T DL_FixedBasePrecomputationImpl<T>::Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const
|
|
||||||
{
|
|
||||||
std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
|
|
||||||
eb.reserve(m_bases.size());
|
|
||||||
PrepareCascade(group, eb, exponent);
|
|
||||||
return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T
|
|
||||||
DL_FixedBasePrecomputationImpl<T>::CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent,
|
|
||||||
const DL_FixedBasePrecomputation<T> &i_pc2, const Integer &exponent2) const
|
|
||||||
{
|
|
||||||
std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
|
|
||||||
const DL_FixedBasePrecomputationImpl<T> &pc2 = static_cast<const DL_FixedBasePrecomputationImpl<T> &>(i_pc2);
|
|
||||||
eb.reserve(m_bases.size() + pc2.m_bases.size());
|
|
||||||
PrepareCascade(group, eb, exponent);
|
|
||||||
pc2.PrepareCascade(group, eb, exponent2);
|
|
||||||
return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,75 +0,0 @@
|
||||||
#ifndef CRYPTOPP_EPRECOMP_H
|
|
||||||
#define CRYPTOPP_EPRECOMP_H
|
|
||||||
|
|
||||||
#include "integer.h"
|
|
||||||
#include "algebra.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class DL_GroupPrecomputation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
virtual bool NeedConversions() const {return false;}
|
|
||||||
virtual Element ConvertIn(const Element &v) const {return v;}
|
|
||||||
virtual Element ConvertOut(const Element &v) const {return v;}
|
|
||||||
virtual const AbstractGroup<Element> & GetGroup() const =0;
|
|
||||||
virtual Element BERDecodeElement(BufferedTransformation &bt) const =0;
|
|
||||||
virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class DL_FixedBasePrecomputation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
virtual bool IsInitialized() const =0;
|
|
||||||
virtual void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base) =0;
|
|
||||||
virtual const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const =0;
|
|
||||||
virtual void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage) =0;
|
|
||||||
virtual void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) =0;
|
|
||||||
virtual void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const =0;
|
|
||||||
virtual Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const =0;
|
|
||||||
virtual Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T Element;
|
|
||||||
|
|
||||||
DL_FixedBasePrecomputationImpl() : m_windowSize(0) {}
|
|
||||||
|
|
||||||
// DL_FixedBasePrecomputation
|
|
||||||
bool IsInitialized() const
|
|
||||||
{return !m_bases.empty();}
|
|
||||||
void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base);
|
|
||||||
const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const
|
|
||||||
{return group.NeedConversions() ? m_base : m_bases[0];}
|
|
||||||
void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage);
|
|
||||||
void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation);
|
|
||||||
void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const;
|
|
||||||
Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
|
|
||||||
Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void PrepareCascade(const DL_GroupPrecomputation<Element> &group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const;
|
|
||||||
|
|
||||||
Element m_base;
|
|
||||||
unsigned int m_windowSize;
|
|
||||||
Integer m_exponentBase; // what base to represent the exponent in
|
|
||||||
std::vector<Element> m_bases; // precalculated bases
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
|
|
||||||
#include "eprecomp.cpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,210 +0,0 @@
|
||||||
// esign.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "esign.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "modarith.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
#include "sha.h"
|
|
||||||
#include "algparam.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void ESIGN_TestInstantiations()
|
|
||||||
{
|
|
||||||
ESIGN<SHA>::Verifier x1(1, 1);
|
|
||||||
ESIGN<SHA>::Signer x2(NullRNG(), 1);
|
|
||||||
ESIGN<SHA>::Verifier x3(x2);
|
|
||||||
ESIGN<SHA>::Verifier x4(x2.GetKey());
|
|
||||||
ESIGN<SHA>::Verifier x5(x3);
|
|
||||||
ESIGN<SHA>::Signer x6 = x2;
|
|
||||||
|
|
||||||
x6 = x2;
|
|
||||||
x3 = ESIGN<SHA>::Verifier(x2);
|
|
||||||
x4 = x2.GetKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESIGNFunction::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
m_n.BERDecode(seq);
|
|
||||||
m_e.BERDecode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESIGNFunction::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
m_n.DEREncode(seq);
|
|
||||||
m_e.DEREncode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer ESIGNFunction::ApplyFunction(const Integer &x) const
|
|
||||||
{
|
|
||||||
DoQuickSanityCheck();
|
|
||||||
return STDMIN(a_exp_b_mod_c(x, m_e, m_n) >> (2*GetK()+2), MaxImage());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
bool pass = true;
|
|
||||||
pass = pass && m_n > Integer::One() && m_n.IsOdd();
|
|
||||||
pass = pass && m_e >= 8 && m_e < m_n;
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
return GetValueHelper(this, name, valueType, pValue).Assignable()
|
|
||||||
CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
|
|
||||||
CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESIGNFunction::AssignFrom(const NameValuePairs &source)
|
|
||||||
{
|
|
||||||
AssignFromHelper(this, source)
|
|
||||||
CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
|
|
||||||
CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
// *****************************************************************************
|
|
||||||
|
|
||||||
void InvertibleESIGNFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶m)
|
|
||||||
{
|
|
||||||
int modulusSize = 1023*2;
|
|
||||||
param.GetIntValue("ModulusSize", modulusSize) || param.GetIntValue("KeySize", modulusSize);
|
|
||||||
|
|
||||||
if (modulusSize < 24)
|
|
||||||
throw InvalidArgument("InvertibleESIGNFunction: specified modulus size is too small");
|
|
||||||
|
|
||||||
if (modulusSize % 3 != 0)
|
|
||||||
throw InvalidArgument("InvertibleESIGNFunction: modulus size must be divisible by 3");
|
|
||||||
|
|
||||||
m_e = param.GetValueWithDefault("PublicExponent", Integer(32));
|
|
||||||
|
|
||||||
if (m_e < 8)
|
|
||||||
throw InvalidArgument("InvertibleESIGNFunction: public exponents less than 8 may not be secure");
|
|
||||||
|
|
||||||
// VC70 workaround: putting these after primeParam causes overlapped stack allocation
|
|
||||||
ConstByteArrayParameter seedParam;
|
|
||||||
SecByteBlock seed;
|
|
||||||
|
|
||||||
const Integer minP = Integer(204) << (modulusSize/3-8);
|
|
||||||
const Integer maxP = Integer::Power2(modulusSize/3)-1;
|
|
||||||
AlgorithmParameters primeParam = MakeParameters("Min", minP)("Max", maxP)("RandomNumberType", Integer::PRIME);
|
|
||||||
|
|
||||||
if (param.GetValue("Seed", seedParam))
|
|
||||||
{
|
|
||||||
seed.resize(seedParam.size() + 4);
|
|
||||||
memcpy(seed + 4, seedParam.begin(), seedParam.size());
|
|
||||||
|
|
||||||
PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)0);
|
|
||||||
m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
|
|
||||||
PutWord(false, BIG_ENDIAN_ORDER, seed, (word32)1);
|
|
||||||
m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("Seed", ConstByteArrayParameter(seed))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_p.GenerateRandom(rng, primeParam);
|
|
||||||
m_q.GenerateRandom(rng, primeParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_n = m_p * m_p * m_q;
|
|
||||||
|
|
||||||
assert(m_n.BitCount() == modulusSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InvertibleESIGNFunction::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder privateKey(bt);
|
|
||||||
m_n.BERDecode(privateKey);
|
|
||||||
m_e.BERDecode(privateKey);
|
|
||||||
m_p.BERDecode(privateKey);
|
|
||||||
m_q.BERDecode(privateKey);
|
|
||||||
privateKey.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InvertibleESIGNFunction::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder privateKey(bt);
|
|
||||||
m_n.DEREncode(privateKey);
|
|
||||||
m_e.DEREncode(privateKey);
|
|
||||||
m_p.DEREncode(privateKey);
|
|
||||||
m_q.DEREncode(privateKey);
|
|
||||||
privateKey.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer InvertibleESIGNFunction::CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
|
|
||||||
{
|
|
||||||
DoQuickSanityCheck();
|
|
||||||
|
|
||||||
Integer pq = m_p * m_q;
|
|
||||||
Integer p2 = m_p * m_p;
|
|
||||||
Integer r, z, re, a, w0, w1;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
r.Randomize(rng, Integer::Zero(), pq);
|
|
||||||
z = x << (2*GetK()+2);
|
|
||||||
re = a_exp_b_mod_c(r, m_e, m_n);
|
|
||||||
a = (z - re) % m_n;
|
|
||||||
Integer::Divide(w1, w0, a, pq);
|
|
||||||
if (w1.NotZero())
|
|
||||||
{
|
|
||||||
++w0;
|
|
||||||
w1 = pq - w1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((w1 >> 2*GetK()+1).IsPositive());
|
|
||||||
|
|
||||||
ModularArithmetic modp(m_p);
|
|
||||||
Integer t = modp.Divide(w0 * r % m_p, m_e * re % m_p);
|
|
||||||
Integer s = r + t*pq;
|
|
||||||
assert(s < m_n);
|
|
||||||
/*
|
|
||||||
using namespace std;
|
|
||||||
cout << "f = " << x << endl;
|
|
||||||
cout << "r = " << r << endl;
|
|
||||||
cout << "z = " << z << endl;
|
|
||||||
cout << "a = " << a << endl;
|
|
||||||
cout << "w0 = " << w0 << endl;
|
|
||||||
cout << "w1 = " << w1 << endl;
|
|
||||||
cout << "t = " << t << endl;
|
|
||||||
cout << "s = " << s << endl;
|
|
||||||
*/
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvertibleESIGNFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
bool pass = ESIGNFunction::Validate(rng, level);
|
|
||||||
pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
|
|
||||||
pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
|
|
||||||
pass = pass && m_p.BitCount() == m_q.BitCount();
|
|
||||||
if (level >= 1)
|
|
||||||
pass = pass && m_p * m_p * m_q == m_n;
|
|
||||||
if (level >= 2)
|
|
||||||
pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InvertibleESIGNFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
return GetValueHelper<ESIGNFunction>(this, name, valueType, pValue).Assignable()
|
|
||||||
CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
|
|
||||||
CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InvertibleESIGNFunction::AssignFrom(const NameValuePairs &source)
|
|
||||||
{
|
|
||||||
AssignFromHelper<ESIGNFunction>(this, source)
|
|
||||||
CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
|
|
||||||
CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,128 +0,0 @@
|
||||||
#ifndef CRYPTOPP_ESIGN_H
|
|
||||||
#define CRYPTOPP_ESIGN_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
This file contains classes that implement the
|
|
||||||
ESIGN signature schemes as defined in IEEE P1363a.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pubkey.h"
|
|
||||||
#include "integer.h"
|
|
||||||
#include "asn.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class ESIGNFunction : public TrapdoorFunction, public ASN1CryptoMaterial<PublicKey>
|
|
||||||
{
|
|
||||||
typedef ESIGNFunction ThisClass;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Initialize(const Integer &n, const Integer &e)
|
|
||||||
{m_n = n; m_e = e;}
|
|
||||||
|
|
||||||
// PublicKey
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
// CryptoMaterial
|
|
||||||
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
void AssignFrom(const NameValuePairs &source);
|
|
||||||
|
|
||||||
// TrapdoorFunction
|
|
||||||
Integer ApplyFunction(const Integer &x) const;
|
|
||||||
Integer PreimageBound() const {return m_n;}
|
|
||||||
Integer ImageBound() const {return Integer::Power2(GetK());}
|
|
||||||
|
|
||||||
// non-derived
|
|
||||||
const Integer & GetModulus() const {return m_n;}
|
|
||||||
const Integer & GetPublicExponent() const {return m_e;}
|
|
||||||
|
|
||||||
void SetModulus(const Integer &n) {m_n = n;}
|
|
||||||
void SetPublicExponent(const Integer &e) {m_e = e;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
unsigned int GetK() const {return m_n.BitCount()/3-1;}
|
|
||||||
|
|
||||||
Integer m_n, m_e;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class InvertibleESIGNFunction : public ESIGNFunction, public RandomizedTrapdoorFunctionInverse, public PrivateKey
|
|
||||||
{
|
|
||||||
typedef InvertibleESIGNFunction ThisClass;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Initialize(const Integer &n, const Integer &e, const Integer &p, const Integer &q)
|
|
||||||
{m_n = n; m_e = e; m_p = p; m_q = q;}
|
|
||||||
// generate a random private key
|
|
||||||
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
|
|
||||||
{GenerateRandomWithKeySize(rng, modulusBits);}
|
|
||||||
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const;
|
|
||||||
|
|
||||||
// GeneratibleCryptoMaterial
|
|
||||||
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
void AssignFrom(const NameValuePairs &source);
|
|
||||||
/*! parameters: (ModulusSize) */
|
|
||||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
|
|
||||||
|
|
||||||
const Integer& GetPrime1() const {return m_p;}
|
|
||||||
const Integer& GetPrime2() const {return m_q;}
|
|
||||||
|
|
||||||
void SetPrime1(const Integer &p) {m_p = p;}
|
|
||||||
void SetPrime2(const Integer &q) {m_q = q;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Integer m_p, m_q;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class T>
|
|
||||||
class EMSA5Pad : public PK_DeterministicSignatureMessageEncodingMethod
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char *StaticAlgorithmName() {return "EMSA5";}
|
|
||||||
|
|
||||||
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
|
||||||
const byte *recoverableMessage, size_t recoverableMessageLength,
|
|
||||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
|
||||||
byte *representative, size_t representativeBitLength) const
|
|
||||||
{
|
|
||||||
SecByteBlock digest(hash.DigestSize());
|
|
||||||
hash.Final(digest);
|
|
||||||
size_t representativeByteLength = BitsToBytes(representativeBitLength);
|
|
||||||
T mgf;
|
|
||||||
mgf.GenerateAndMask(hash, representative, representativeByteLength, digest, digest.size(), false);
|
|
||||||
if (representativeBitLength % 8 != 0)
|
|
||||||
representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! EMSA5, for use with ESIGN
|
|
||||||
struct P1363_EMSA5 : public SignatureStandard
|
|
||||||
{
|
|
||||||
typedef EMSA5Pad<P1363_MGF1> SignatureMessageEncodingMethod;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ESIGN_Keys
|
|
||||||
{
|
|
||||||
static std::string StaticAlgorithmName() {return "ESIGN";}
|
|
||||||
typedef ESIGNFunction PublicKey;
|
|
||||||
typedef InvertibleESIGNFunction PrivateKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! ESIGN, as defined in IEEE P1363a
|
|
||||||
template <class H, class STANDARD = P1363_EMSA5>
|
|
||||||
struct ESIGN : public TF_SS<STANDARD, H, ESIGN_Keys>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,136 +0,0 @@
|
||||||
#ifndef CRYPTOPP_OBJFACT_H
|
|
||||||
#define CRYPTOPP_OBJFACT_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class AbstractClass>
|
|
||||||
class ObjectFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~ObjectFactory () {}
|
|
||||||
virtual AbstractClass * CreateObject() const =0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class AbstractClass, class ConcreteClass>
|
|
||||||
class DefaultObjectFactory : public ObjectFactory<AbstractClass>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AbstractClass * CreateObject() const
|
|
||||||
{
|
|
||||||
return new ConcreteClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class AbstractClass, int instance=0>
|
|
||||||
class ObjectFactoryRegistry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class FactoryNotFound : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FactoryNotFound(const char *name) : Exception(OTHER_ERROR, std::string("ObjectFactoryRegistry: could not find factory for algorithm ") + name) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
~ObjectFactoryRegistry()
|
|
||||||
{
|
|
||||||
for (CPP_TYPENAME Map::iterator i = m_map.begin(); i != m_map.end(); ++i)
|
|
||||||
{
|
|
||||||
delete (ObjectFactory<AbstractClass> *)i->second;
|
|
||||||
i->second = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterFactory(const std::string &name, ObjectFactory<AbstractClass> *factory)
|
|
||||||
{
|
|
||||||
m_map[name] = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ObjectFactory<AbstractClass> * GetFactory(const char *name) const
|
|
||||||
{
|
|
||||||
CPP_TYPENAME Map::const_iterator i = m_map.find(name);
|
|
||||||
return i == m_map.end() ? NULL : (ObjectFactory<AbstractClass> *)i->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractClass *CreateObject(const char *name) const
|
|
||||||
{
|
|
||||||
const ObjectFactory<AbstractClass> *factory = GetFactory(name);
|
|
||||||
if (!factory)
|
|
||||||
throw FactoryNotFound(name);
|
|
||||||
return factory->CreateObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a vector containing the factory names. This is easier than returning an iterator.
|
|
||||||
// from Andrew Pitonyak
|
|
||||||
std::vector<std::string> GetFactoryNames() const
|
|
||||||
{
|
|
||||||
std::vector<std::string> names;
|
|
||||||
CPP_TYPENAME Map::const_iterator iter;
|
|
||||||
for (iter = m_map.begin(); iter != m_map.end(); ++iter)
|
|
||||||
names.push_back(iter->first);
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRYPTOPP_NOINLINE static ObjectFactoryRegistry<AbstractClass, instance> & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// use void * instead of ObjectFactory<AbstractClass> * to save code size
|
|
||||||
typedef std::map<std::string, void *> Map;
|
|
||||||
Map m_map;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class AbstractClass, int instance>
|
|
||||||
ObjectFactoryRegistry<AbstractClass, instance> & ObjectFactoryRegistry<AbstractClass, instance>::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT)
|
|
||||||
{
|
|
||||||
static ObjectFactoryRegistry<AbstractClass, instance> s_registry;
|
|
||||||
return s_registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class AbstractClass, class ConcreteClass, int instance = 0>
|
|
||||||
struct RegisterDefaultFactoryFor {
|
|
||||||
RegisterDefaultFactoryFor(const char *name=NULL)
|
|
||||||
{
|
|
||||||
// BCB2006 workaround
|
|
||||||
std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName());
|
|
||||||
ObjectFactoryRegistry<AbstractClass, instance>::Registry().
|
|
||||||
RegisterFactory(n, new DefaultObjectFactory<AbstractClass, ConcreteClass>);
|
|
||||||
}};
|
|
||||||
|
|
||||||
template <class SchemeClass>
|
|
||||||
void RegisterAsymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
|
|
||||||
{
|
|
||||||
RegisterDefaultFactoryFor<PK_Encryptor, CPP_TYPENAME SchemeClass::Encryptor>((const char *)name);
|
|
||||||
RegisterDefaultFactoryFor<PK_Decryptor, CPP_TYPENAME SchemeClass::Decryptor>((const char *)name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class SchemeClass>
|
|
||||||
void RegisterSignatureSchemeDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
|
|
||||||
{
|
|
||||||
RegisterDefaultFactoryFor<PK_Signer, CPP_TYPENAME SchemeClass::Signer>((const char *)name);
|
|
||||||
RegisterDefaultFactoryFor<PK_Verifier, CPP_TYPENAME SchemeClass::Verifier>((const char *)name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class SchemeClass>
|
|
||||||
void RegisterSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
|
|
||||||
{
|
|
||||||
RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
|
|
||||||
RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class SchemeClass>
|
|
||||||
void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
|
|
||||||
{
|
|
||||||
RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
|
|
||||||
RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,259 +0,0 @@
|
||||||
// files.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "files.h"
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void Files_TestInstantiations()
|
|
||||||
{
|
|
||||||
FileStore f0;
|
|
||||||
FileSource f1;
|
|
||||||
FileSink f2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void FileStore::StoreInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
m_waiting = false;
|
|
||||||
m_stream = NULL;
|
|
||||||
m_file.release();
|
|
||||||
|
|
||||||
const char *fileName = NULL;
|
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
|
|
||||||
const wchar_t *fileNameWide = NULL;
|
|
||||||
if (!parameters.GetValue(Name::InputFileNameWide(), fileNameWide))
|
|
||||||
#endif
|
|
||||||
if (!parameters.GetValue(Name::InputFileName(), fileName))
|
|
||||||
{
|
|
||||||
parameters.GetValue(Name::InputStreamPointer(), m_stream);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? ios::binary : ios::openmode(0);
|
|
||||||
m_file.reset(new std::ifstream);
|
|
||||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
|
||||||
std::string narrowed;
|
|
||||||
if (fileNameWide)
|
|
||||||
fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
|
|
||||||
#endif
|
|
||||||
#if _MSC_VER >= 1400
|
|
||||||
if (fileNameWide)
|
|
||||||
{
|
|
||||||
m_file->open(fileNameWide, ios::in | binary);
|
|
||||||
if (!*m_file)
|
|
||||||
throw OpenErr(StringNarrow(fileNameWide, false));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (fileName)
|
|
||||||
{
|
|
||||||
m_file->open(fileName, ios::in | binary);
|
|
||||||
if (!*m_file)
|
|
||||||
throw OpenErr(fileName);
|
|
||||||
}
|
|
||||||
m_stream = m_file.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
lword FileStore::MaxRetrievable() const
|
|
||||||
{
|
|
||||||
if (!m_stream)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
streampos current = m_stream->tellg();
|
|
||||||
streampos end = m_stream->seekg(0, ios::end).tellg();
|
|
||||||
m_stream->seekg(current);
|
|
||||||
return end-current;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
|
|
||||||
{
|
|
||||||
if (!m_stream)
|
|
||||||
{
|
|
||||||
transferBytes = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
lword size=transferBytes;
|
|
||||||
transferBytes = 0;
|
|
||||||
|
|
||||||
if (m_waiting)
|
|
||||||
goto output;
|
|
||||||
|
|
||||||
while (size && m_stream->good())
|
|
||||||
{
|
|
||||||
{
|
|
||||||
size_t spaceSize = 1024;
|
|
||||||
m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(0)-1, size), spaceSize);
|
|
||||||
|
|
||||||
m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize));
|
|
||||||
}
|
|
||||||
m_len = (size_t)m_stream->gcount();
|
|
||||||
size_t blockedBytes;
|
|
||||||
output:
|
|
||||||
blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
|
|
||||||
m_waiting = blockedBytes > 0;
|
|
||||||
if (m_waiting)
|
|
||||||
return blockedBytes;
|
|
||||||
size -= m_len;
|
|
||||||
transferBytes += m_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_stream->good() && !m_stream->eof())
|
|
||||||
throw ReadErr();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
|
|
||||||
{
|
|
||||||
if (!m_stream)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (begin == 0 && end == 1)
|
|
||||||
{
|
|
||||||
int result = m_stream->peek();
|
|
||||||
if (result == char_traits<char>::eof())
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking);
|
|
||||||
begin += 1-blockedBytes;
|
|
||||||
return blockedBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: figure out what happens on cin
|
|
||||||
streampos current = m_stream->tellg();
|
|
||||||
streampos endPosition = m_stream->seekg(0, ios::end).tellg();
|
|
||||||
streampos newPosition = current + (streamoff)begin;
|
|
||||||
|
|
||||||
if (newPosition >= endPosition)
|
|
||||||
{
|
|
||||||
m_stream->seekg(current);
|
|
||||||
return 0; // don't try to seek beyond the end of file
|
|
||||||
}
|
|
||||||
m_stream->seekg(newPosition);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
assert(!m_waiting);
|
|
||||||
lword copyMax = end-begin;
|
|
||||||
size_t blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
|
|
||||||
begin += copyMax;
|
|
||||||
if (blockedBytes)
|
|
||||||
{
|
|
||||||
const_cast<FileStore *>(this)->m_waiting = false;
|
|
||||||
return blockedBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
m_stream->clear();
|
|
||||||
m_stream->seekg(current);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
m_stream->clear();
|
|
||||||
m_stream->seekg(current);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
lword FileStore::Skip(lword skipMax)
|
|
||||||
{
|
|
||||||
if (!m_stream)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
lword oldPos = m_stream->tellg();
|
|
||||||
std::istream::off_type offset;
|
|
||||||
if (!SafeConvert(skipMax, offset))
|
|
||||||
throw InvalidArgument("FileStore: maximum seek offset exceeded");
|
|
||||||
m_stream->seekg(offset, ios::cur);
|
|
||||||
return (lword)m_stream->tellg() - oldPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileSink::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
m_stream = NULL;
|
|
||||||
m_file.release();
|
|
||||||
|
|
||||||
const char *fileName = NULL;
|
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
|
|
||||||
const wchar_t *fileNameWide = NULL;
|
|
||||||
if (!parameters.GetValue(Name::OutputFileNameWide(), fileNameWide))
|
|
||||||
#endif
|
|
||||||
if (!parameters.GetValue(Name::OutputFileName(), fileName))
|
|
||||||
{
|
|
||||||
parameters.GetValue(Name::OutputStreamPointer(), m_stream);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? ios::binary : ios::openmode(0);
|
|
||||||
m_file.reset(new std::ofstream);
|
|
||||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
|
||||||
std::string narrowed;
|
|
||||||
if (fileNameWide)
|
|
||||||
fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
|
|
||||||
#endif
|
|
||||||
#if _MSC_VER >= 1400
|
|
||||||
if (fileNameWide)
|
|
||||||
{
|
|
||||||
m_file->open(fileNameWide, ios::out | ios::trunc | binary);
|
|
||||||
if (!*m_file)
|
|
||||||
throw OpenErr(StringNarrow(fileNameWide, false));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (fileName)
|
|
||||||
{
|
|
||||||
m_file->open(fileName, ios::out | ios::trunc | binary);
|
|
||||||
if (!*m_file)
|
|
||||||
throw OpenErr(fileName);
|
|
||||||
}
|
|
||||||
m_stream = m_file.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
|
|
||||||
{
|
|
||||||
if (!m_stream)
|
|
||||||
throw Err("FileSink: output stream not opened");
|
|
||||||
|
|
||||||
m_stream->flush();
|
|
||||||
if (!m_stream->good())
|
|
||||||
throw WriteErr();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
if (!m_stream)
|
|
||||||
throw Err("FileSink: output stream not opened");
|
|
||||||
|
|
||||||
while (length > 0)
|
|
||||||
{
|
|
||||||
std::streamsize size;
|
|
||||||
if (!SafeConvert(length, size))
|
|
||||||
size = numeric_limits<std::streamsize>::max();
|
|
||||||
m_stream->write((const char *)inString, size);
|
|
||||||
inString += size;
|
|
||||||
length -= (size_t)size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messageEnd)
|
|
||||||
m_stream->flush();
|
|
||||||
|
|
||||||
if (!m_stream->good())
|
|
||||||
throw WriteErr();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,112 +0,0 @@
|
||||||
#ifndef CRYPTOPP_FILES_H
|
|
||||||
#define CRYPTOPP_FILES_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "filters.h"
|
|
||||||
#include "argnames.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! file-based implementation of Store interface
|
|
||||||
class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Err : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Err(const std::string &s) : Exception(IO_ERROR, s) {}
|
|
||||||
};
|
|
||||||
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}};
|
|
||||||
class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}};
|
|
||||||
|
|
||||||
FileStore() : m_stream(NULL) {}
|
|
||||||
FileStore(std::istream &in)
|
|
||||||
{StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));}
|
|
||||||
FileStore(const char *filename)
|
|
||||||
{StoreInitialize(MakeParameters(Name::InputFileName(), filename));}
|
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
|
|
||||||
//! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
|
|
||||||
FileStore(const wchar_t *filename)
|
|
||||||
{StoreInitialize(MakeParameters(Name::InputFileNameWide(), filename));}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::istream* GetStream() {return m_stream;}
|
|
||||||
|
|
||||||
lword MaxRetrievable() const;
|
|
||||||
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
|
||||||
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
|
|
||||||
lword Skip(lword skipMax=ULONG_MAX);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void StoreInitialize(const NameValuePairs ¶meters);
|
|
||||||
|
|
||||||
member_ptr<std::ifstream> m_file;
|
|
||||||
std::istream *m_stream;
|
|
||||||
byte *m_space;
|
|
||||||
size_t m_len;
|
|
||||||
bool m_waiting;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! file-based implementation of Source interface
|
|
||||||
class CRYPTOPP_DLL FileSource : public SourceTemplate<FileStore>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef FileStore::Err Err;
|
|
||||||
typedef FileStore::OpenErr OpenErr;
|
|
||||||
typedef FileStore::ReadErr ReadErr;
|
|
||||||
|
|
||||||
FileSource(BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<FileStore>(attachment) {}
|
|
||||||
FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));}
|
|
||||||
FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
|
|
||||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));}
|
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
|
|
||||||
//! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
|
|
||||||
FileSource(const wchar_t *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
|
|
||||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileNameWide(), filename)(Name::InputBinaryMode(), binary));}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::istream* GetStream() {return m_store.GetStream();}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! file-based implementation of Sink interface
|
|
||||||
class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Err : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Err(const std::string &s) : Exception(IO_ERROR, s) {}
|
|
||||||
};
|
|
||||||
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}};
|
|
||||||
class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}};
|
|
||||||
|
|
||||||
FileSink() : m_stream(NULL) {}
|
|
||||||
FileSink(std::ostream &out)
|
|
||||||
{IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));}
|
|
||||||
FileSink(const char *filename, bool binary=true)
|
|
||||||
{IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)(Name::OutputBinaryMode(), binary));}
|
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
|
|
||||||
//! specify file with Unicode name. On non-Windows OS, this function assumes that setlocale() has been called.
|
|
||||||
FileSink(const wchar_t *filename, bool binary=true)
|
|
||||||
{IsolatedInitialize(MakeParameters(Name::OutputFileNameWide(), filename)(Name::OutputBinaryMode(), binary));}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::ostream* GetStream() {return m_stream;}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
|
|
||||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
|
||||||
|
|
||||||
private:
|
|
||||||
member_ptr<std::ofstream> m_file;
|
|
||||||
std::ostream *m_stream;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,810 +0,0 @@
|
||||||
#ifndef CRYPTOPP_FILTERS_H
|
|
||||||
#define CRYPTOPP_FILTERS_H
|
|
||||||
|
|
||||||
//! \file
|
|
||||||
|
|
||||||
#include "simple.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "smartptr.h"
|
|
||||||
#include "queue.h"
|
|
||||||
#include "algparam.h"
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
/// provides an implementation of BufferedTransformation's attachment interface
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Filter(BufferedTransformation *attachment = NULL);
|
|
||||||
|
|
||||||
bool Attachable() {return true;}
|
|
||||||
BufferedTransformation *AttachedTransformation();
|
|
||||||
const BufferedTransformation *AttachedTransformation() const;
|
|
||||||
void Detach(BufferedTransformation *newAttachment = NULL);
|
|
||||||
|
|
||||||
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
|
||||||
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
|
|
||||||
|
|
||||||
void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
|
||||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
|
|
||||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BufferedTransformation * NewDefaultAttachment() const;
|
|
||||||
void Insert(Filter *nextFilter); // insert filter after this one
|
|
||||||
|
|
||||||
virtual bool ShouldPropagateMessageEnd() const {return true;}
|
|
||||||
virtual bool ShouldPropagateMessageSeriesEnd() const {return true;}
|
|
||||||
|
|
||||||
void PropagateInitialize(const NameValuePairs ¶meters, int propagation);
|
|
||||||
|
|
||||||
size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
|
|
||||||
size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
|
|
||||||
bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
|
|
||||||
bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
|
|
||||||
bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
|
|
||||||
|
|
||||||
private:
|
|
||||||
member_ptr<BufferedTransformation> m_attachment;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t m_inputPosition;
|
|
||||||
int m_continueAt;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CRYPTOPP_DLL FilterPutSpaceHelper
|
|
||||||
{
|
|
||||||
// desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace
|
|
||||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize)
|
|
||||||
{
|
|
||||||
assert(desiredSize >= minSize && bufferSize >= minSize);
|
|
||||||
if (m_tempSpace.size() < minSize)
|
|
||||||
{
|
|
||||||
byte *result = target.ChannelCreatePutSpace(channel, desiredSize);
|
|
||||||
if (desiredSize >= minSize)
|
|
||||||
{
|
|
||||||
bufferSize = desiredSize;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
m_tempSpace.New(bufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferSize = m_tempSpace.size();
|
|
||||||
return m_tempSpace.begin();
|
|
||||||
}
|
|
||||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize)
|
|
||||||
{return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
|
|
||||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize)
|
|
||||||
{return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
|
|
||||||
SecByteBlock m_tempSpace;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! measure how many byte and messages pass through, also serves as valve
|
|
||||||
class CRYPTOPP_DLL MeterFilter : public Bufferless<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true)
|
|
||||||
: m_transparent(transparent) {Detach(attachment); ResetMeter();}
|
|
||||||
|
|
||||||
void SetTransparent(bool transparent) {m_transparent = transparent;}
|
|
||||||
void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true);
|
|
||||||
void ResetMeter();
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters) {ResetMeter();}
|
|
||||||
|
|
||||||
lword GetCurrentMessageBytes() const {return m_currentMessageBytes;}
|
|
||||||
lword GetTotalBytes() {return m_totalBytes;}
|
|
||||||
unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;}
|
|
||||||
unsigned int GetTotalMessages() {return m_totalMessages;}
|
|
||||||
unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;}
|
|
||||||
|
|
||||||
byte * CreatePutSpace(size_t &size)
|
|
||||||
{return AttachedTransformation()->CreatePutSpace(size);}
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking);
|
|
||||||
bool IsolatedMessageSeriesEnd(bool blocking);
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable);
|
|
||||||
bool ShouldPropagateMessageEnd() const {return m_transparent;}
|
|
||||||
bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;}
|
|
||||||
|
|
||||||
struct MessageRange
|
|
||||||
{
|
|
||||||
inline bool operator<(const MessageRange &b) const // BCB2006 workaround: this has to be a member function
|
|
||||||
{return message < b.message || (message == b.message && position < b.position);}
|
|
||||||
unsigned int message; lword position; lword size;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool m_transparent;
|
|
||||||
lword m_currentMessageBytes, m_totalBytes;
|
|
||||||
unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries;
|
|
||||||
std::deque<MessageRange> m_rangesToSkip;
|
|
||||||
byte *m_begin;
|
|
||||||
size_t m_length;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL TransparentFilter : public MeterFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL OpaqueFilter : public MeterFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! FilterWithBufferedInput divides up the input stream into
|
|
||||||
a first block, a number of middle blocks, and a last block.
|
|
||||||
First and last blocks are optional, and middle blocks may
|
|
||||||
be a stream instead (i.e. blockSize == 1).
|
|
||||||
*/
|
|
||||||
class CRYPTOPP_DLL FilterWithBufferedInput : public Filter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FilterWithBufferedInput(BufferedTransformation *attachment);
|
|
||||||
//! firstSize and lastSize may be 0, blockSize must be at least 1
|
|
||||||
FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment);
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
return PutMaybeModifiable(const_cast<byte *>(inString), length, messageEnd, blocking, false);
|
|
||||||
}
|
|
||||||
size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
return PutMaybeModifiable(inString, length, messageEnd, blocking, true);
|
|
||||||
}
|
|
||||||
/*! calls ForceNextPut() if hardFlush is true */
|
|
||||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
|
||||||
|
|
||||||
/*! The input buffer may contain more than blockSize bytes if lastSize != 0.
|
|
||||||
ForceNextPut() forces a call to NextPut() if this is the case.
|
|
||||||
*/
|
|
||||||
void ForceNextPut();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool DidFirstPut() {return m_firstInputDone;}
|
|
||||||
|
|
||||||
virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
|
|
||||||
{InitializeDerived(parameters);}
|
|
||||||
virtual void InitializeDerived(const NameValuePairs ¶meters) {}
|
|
||||||
// FirstPut() is called if (firstSize != 0 and totalLength >= firstSize)
|
|
||||||
// or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received))
|
|
||||||
virtual void FirstPut(const byte *inString) =0;
|
|
||||||
// NextPut() is called if totalLength >= firstSize+blockSize+lastSize
|
|
||||||
virtual void NextPutSingle(const byte *inString) {assert(false);}
|
|
||||||
// Same as NextPut() except length can be a multiple of blockSize
|
|
||||||
// Either NextPut() or NextPutMultiple() must be overriden
|
|
||||||
virtual void NextPutMultiple(const byte *inString, size_t length);
|
|
||||||
// Same as NextPutMultiple(), but inString can be modified
|
|
||||||
virtual void NextPutModifiable(byte *inString, size_t length)
|
|
||||||
{NextPutMultiple(inString, length);}
|
|
||||||
// LastPut() is always called
|
|
||||||
// if totalLength < firstSize then length == totalLength
|
|
||||||
// else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
|
|
||||||
// else lastSize <= length < lastSize+blockSize
|
|
||||||
virtual void LastPut(const byte *inString, size_t length) =0;
|
|
||||||
virtual void FlushDerived() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable);
|
|
||||||
void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable)
|
|
||||||
{
|
|
||||||
if (modifiable) NextPutModifiable(inString, length);
|
|
||||||
else NextPutMultiple(inString, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function should no longer be used, put this here to cause a compiler error
|
|
||||||
// if someone tries to override NextPut().
|
|
||||||
virtual int NextPut(const byte *inString, size_t length) {assert(false); return 0;}
|
|
||||||
|
|
||||||
class BlockQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void ResetQueue(size_t blockSize, size_t maxBlocks);
|
|
||||||
byte *GetBlock();
|
|
||||||
byte *GetContigousBlocks(size_t &numberOfBytes);
|
|
||||||
size_t GetAll(byte *outString);
|
|
||||||
void Put(const byte *inString, size_t length);
|
|
||||||
size_t CurrentSize() const {return m_size;}
|
|
||||||
size_t MaxSize() const {return m_buffer.size();}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SecByteBlock m_buffer;
|
|
||||||
size_t m_blockSize, m_maxBlocks, m_size;
|
|
||||||
byte *m_begin;
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t m_firstSize, m_blockSize, m_lastSize;
|
|
||||||
bool m_firstInputDone;
|
|
||||||
BlockQueue m_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL FilterWithInputQueue : public Filter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FilterWithInputQueue(BufferedTransformation *attachment=NULL) : Filter(attachment) {}
|
|
||||||
|
|
||||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
if (!blocking)
|
|
||||||
throw BlockingInputOnly("FilterWithInputQueue");
|
|
||||||
|
|
||||||
m_inQueue.Put(inString, length);
|
|
||||||
if (messageEnd)
|
|
||||||
{
|
|
||||||
IsolatedMessageEnd(blocking);
|
|
||||||
Output(0, NULL, 0, messageEnd, blocking);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool IsolatedMessageEnd(bool blocking) =0;
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters) {m_inQueue.Clear();}
|
|
||||||
|
|
||||||
ByteQueue m_inQueue;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlockPaddingSchemeDef
|
|
||||||
{
|
|
||||||
enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed
|
|
||||||
class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode),
|
|
||||||
otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes).
|
|
||||||
See http://www.weidai.com/scan-mirror/csp.html for details of the padding schemes. */
|
|
||||||
StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool allowAuthenticatedSymmetricCipher = false);
|
|
||||||
|
|
||||||
std::string AlgorithmName() const {return m_cipher.AlgorithmName();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
|
|
||||||
void FirstPut(const byte *inString);
|
|
||||||
void NextPutMultiple(const byte *inString, size_t length);
|
|
||||||
void NextPutModifiable(byte *inString, size_t length);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding);
|
|
||||||
|
|
||||||
StreamTransformation &m_cipher;
|
|
||||||
BlockPaddingScheme m_padding;
|
|
||||||
unsigned int m_optimalBufferSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
|
||||||
typedef StreamTransformationFilter StreamCipherFilter;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! Filter Wrapper for HashTransformation
|
|
||||||
class CRYPTOPP_DLL HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL);
|
|
||||||
|
|
||||||
std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);}
|
|
||||||
|
|
||||||
private:
|
|
||||||
HashTransformation &m_hashModule;
|
|
||||||
bool m_putMessage;
|
|
||||||
unsigned int m_digestSize;
|
|
||||||
byte *m_space;
|
|
||||||
std::string m_messagePutChannel, m_hashPutChannel;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Filter Wrapper for HashTransformation
|
|
||||||
class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class HashVerificationFailed : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HashVerificationFailed()
|
|
||||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Flags {HASH_AT_END=0, HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT};
|
|
||||||
HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1);
|
|
||||||
|
|
||||||
std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
|
|
||||||
bool GetLastResult() const {return m_verified;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
|
|
||||||
void FirstPut(const byte *inString);
|
|
||||||
void NextPutMultiple(const byte *inString, size_t length);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class AuthenticatedDecryptionFilter;
|
|
||||||
|
|
||||||
HashTransformation &m_hashModule;
|
|
||||||
word32 m_flags;
|
|
||||||
unsigned int m_digestSize;
|
|
||||||
bool m_verified;
|
|
||||||
SecByteBlock m_expectedHash;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef HashVerificationFilter HashVerifier; // for backwards compatibility
|
|
||||||
|
|
||||||
//! Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
|
|
||||||
/*! Additional authenticated data should be given in channel "AAD". If putAAD is true, AAD will be Put() to the attached BufferedTransformation in channel "AAD". */
|
|
||||||
class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*! See StreamTransformationFilter for documentation on BlockPaddingScheme */
|
|
||||||
AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING);
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
|
|
||||||
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
HashFilter m_hf;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
|
|
||||||
/*! Additional authenticated data should be given in channel "AAD". */
|
|
||||||
class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Flags {MAC_AT_END=0, MAC_AT_BEGIN=1, THROW_EXCEPTION=16, DEFAULT_FLAGS = THROW_EXCEPTION};
|
|
||||||
|
|
||||||
/*! See StreamTransformationFilter for documentation on BlockPaddingScheme */
|
|
||||||
AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING);
|
|
||||||
|
|
||||||
std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();}
|
|
||||||
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
|
|
||||||
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
bool GetLastResult() const {return m_hashVerifier.GetLastResult();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
|
|
||||||
void FirstPut(const byte *inString);
|
|
||||||
void NextPutMultiple(const byte *inString, size_t length);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
HashVerificationFilter m_hashVerifier;
|
|
||||||
StreamTransformationFilter m_streamFilter;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Filter Wrapper for PK_Signer
|
|
||||||
class CRYPTOPP_DLL SignerFilter : public Unflushable<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false)
|
|
||||||
: m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);}
|
|
||||||
|
|
||||||
std::string AlgorithmName() const {return m_signer.AlgorithmName();}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
private:
|
|
||||||
RandomNumberGenerator &m_rng;
|
|
||||||
const PK_Signer &m_signer;
|
|
||||||
member_ptr<PK_MessageAccumulator> m_messageAccumulator;
|
|
||||||
bool m_putMessage;
|
|
||||||
SecByteBlock m_buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Filter Wrapper for PK_Verifier
|
|
||||||
class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class SignatureVerificationFailed : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SignatureVerificationFailed()
|
|
||||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Flags {SIGNATURE_AT_END=0, SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT};
|
|
||||||
SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
|
|
||||||
|
|
||||||
std::string AlgorithmName() const {return m_verifier.AlgorithmName();}
|
|
||||||
|
|
||||||
bool GetLastResult() const {return m_verified;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
|
|
||||||
void FirstPut(const byte *inString);
|
|
||||||
void NextPutMultiple(const byte *inString, size_t length);
|
|
||||||
void LastPut(const byte *inString, size_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const PK_Verifier &m_verifier;
|
|
||||||
member_ptr<PK_MessageAccumulator> m_messageAccumulator;
|
|
||||||
word32 m_flags;
|
|
||||||
SecByteBlock m_signature;
|
|
||||||
bool m_verified;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility
|
|
||||||
|
|
||||||
//! Redirect input to another BufferedTransformation without owning it
|
|
||||||
class CRYPTOPP_DLL Redirector : public CustomSignalPropagation<Sink>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Behavior
|
|
||||||
{
|
|
||||||
DATA_ONLY = 0x00,
|
|
||||||
PASS_SIGNALS = 0x01,
|
|
||||||
PASS_WAIT_OBJECTS = 0x02,
|
|
||||||
PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS
|
|
||||||
};
|
|
||||||
|
|
||||||
Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {}
|
|
||||||
Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING)
|
|
||||||
: m_target(&target), m_behavior(behavior) {}
|
|
||||||
|
|
||||||
void Redirect(BufferedTransformation &target) {m_target = ⌖}
|
|
||||||
void StopRedirection() {m_target = NULL;}
|
|
||||||
|
|
||||||
Behavior GetBehavior() {return (Behavior) m_behavior;}
|
|
||||||
void SetBehavior(Behavior behavior) {m_behavior=behavior;}
|
|
||||||
bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;}
|
|
||||||
void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; }
|
|
||||||
bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;}
|
|
||||||
void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; }
|
|
||||||
|
|
||||||
bool CanModifyInput() const
|
|
||||||
{return m_target ? m_target->CanModifyInput() : false;}
|
|
||||||
|
|
||||||
void Initialize(const NameValuePairs ¶meters, int propagation);
|
|
||||||
byte * CreatePutSpace(size_t &size)
|
|
||||||
{return m_target ? m_target->CreatePutSpace(size) : (byte *)(size=0, NULL);}
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_target ? m_target->Put2(begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
|
|
||||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
|
||||||
{return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;}
|
|
||||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
|
||||||
{return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;}
|
|
||||||
|
|
||||||
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
|
|
||||||
{return m_target ? m_target->ChannelCreatePutSpace(channel, size) : (byte *)(size=0, NULL);}
|
|
||||||
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
|
|
||||||
size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
|
|
||||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
|
|
||||||
{return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
|
|
||||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
|
|
||||||
{return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
|
|
||||||
|
|
||||||
unsigned int GetMaxWaitObjectCount() const
|
|
||||||
{ return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; }
|
|
||||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
|
||||||
{ if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
BufferedTransformation *m_target;
|
|
||||||
word32 m_behavior;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used By ProxyFilter
|
|
||||||
class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation<Sink>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
|
|
||||||
|
|
||||||
bool GetPassSignal() const {return m_passSignal;}
|
|
||||||
void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
|
|
||||||
|
|
||||||
byte * CreatePutSpace(size_t &size)
|
|
||||||
{return m_owner.AttachedTransformation()->CreatePutSpace(size);}
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
|
||||||
size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
|
||||||
void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1)
|
|
||||||
{if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);}
|
|
||||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
|
||||||
{return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;}
|
|
||||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
|
||||||
{return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;}
|
|
||||||
|
|
||||||
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
|
|
||||||
{return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);}
|
|
||||||
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
|
||||||
size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
|
||||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
|
|
||||||
{return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
|
|
||||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
|
|
||||||
{return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BufferedTransformation &m_owner;
|
|
||||||
bool m_passSignal;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Base class for Filter classes that are proxies for a chain of other filters.
|
|
||||||
class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment);
|
|
||||||
|
|
||||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
|
||||||
|
|
||||||
void SetFilter(Filter *filter);
|
|
||||||
void NextPutMultiple(const byte *s, size_t len);
|
|
||||||
void NextPutModifiable(byte *inString, size_t length);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
member_ptr<BufferedTransformation> m_filter;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! simple proxy filter that doesn't modify the underlying filter's input or output
|
|
||||||
class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment)
|
|
||||||
: ProxyFilter(filter, 0, 0, attachment) {}
|
|
||||||
|
|
||||||
void FirstPut(const byte *) {}
|
|
||||||
void LastPut(const byte *, size_t) {m_filter->MessageEnd();}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! proxy for the filter created by PK_Encryptor::CreateEncryptionFilter
|
|
||||||
/*! This class is here just to provide symmetry with VerifierFilter. */
|
|
||||||
class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL)
|
|
||||||
: SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! proxy for the filter created by PK_Decryptor::CreateDecryptionFilter
|
|
||||||
/*! This class is here just to provide symmetry with SignerFilter. */
|
|
||||||
class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL)
|
|
||||||
: SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Append input to a string object
|
|
||||||
template <class T>
|
|
||||||
class StringSinkTemplate : public Bufferless<Sink>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// VC60 workaround: no T::char_type
|
|
||||||
typedef typename T::traits_type::char_type char_type;
|
|
||||||
|
|
||||||
StringSinkTemplate(T &output)
|
|
||||||
: m_output(&output) {assert(sizeof(output[0])==1);}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
|
|
||||||
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
|
||||||
{
|
|
||||||
if (length > 0)
|
|
||||||
{
|
|
||||||
typename T::size_type size = m_output->size();
|
|
||||||
if (length < size && size + length > m_output->capacity())
|
|
||||||
m_output->reserve(2*size);
|
|
||||||
m_output->append((const char_type *)begin, (const char_type *)begin+length);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T *m_output;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Append input to an std::string
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate<std::string>;
|
|
||||||
typedef StringSinkTemplate<std::string> StringSink;
|
|
||||||
|
|
||||||
//! incorporates input into RNG as additional entropy
|
|
||||||
class RandomNumberSink : public Bufferless<Sink>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RandomNumberSink()
|
|
||||||
: m_rng(NULL) {}
|
|
||||||
|
|
||||||
RandomNumberSink(RandomNumberGenerator &rng)
|
|
||||||
: m_rng(&rng) {}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
private:
|
|
||||||
RandomNumberGenerator *m_rng;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Copy input to a memory buffer
|
|
||||||
class CRYPTOPP_DLL ArraySink : public Bufferless<Sink>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) {IsolatedInitialize(parameters);}
|
|
||||||
ArraySink(byte *buf, size_t size) : m_buf(buf), m_size(size), m_total(0) {}
|
|
||||||
|
|
||||||
size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);}
|
|
||||||
lword TotalPutLength() {return m_total;}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
byte * CreatePutSpace(size_t &size);
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
byte *m_buf;
|
|
||||||
size_t m_size;
|
|
||||||
lword m_total;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Xor input to a memory buffer
|
|
||||||
class CRYPTOPP_DLL ArrayXorSink : public ArraySink
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ArrayXorSink(byte *buf, size_t size)
|
|
||||||
: ArraySink(buf, size) {}
|
|
||||||
|
|
||||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
|
||||||
byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! string-based implementation of Store interface
|
|
||||||
class StringStore : public Store
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringStore(const char *string = NULL)
|
|
||||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
|
||||||
StringStore(const byte *string, size_t length)
|
|
||||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
|
|
||||||
template <class T> StringStore(const T &string)
|
|
||||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
|
||||||
|
|
||||||
CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
|
||||||
CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
CRYPTOPP_DLL void StoreInitialize(const NameValuePairs ¶meters);
|
|
||||||
|
|
||||||
const byte *m_store;
|
|
||||||
size_t m_length, m_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! RNG-based implementation of Source interface
|
|
||||||
class CRYPTOPP_DLL RandomNumberStore : public Store
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RandomNumberStore()
|
|
||||||
: m_rng(NULL), m_length(0), m_count(0) {}
|
|
||||||
|
|
||||||
RandomNumberStore(RandomNumberGenerator &rng, lword length)
|
|
||||||
: m_rng(&rng), m_length(length), m_count(0) {}
|
|
||||||
|
|
||||||
bool AnyRetrievable() const {return MaxRetrievable() != 0;}
|
|
||||||
lword MaxRetrievable() const {return m_length-m_count;}
|
|
||||||
|
|
||||||
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
|
||||||
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
|
|
||||||
{
|
|
||||||
throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void StoreInitialize(const NameValuePairs ¶meters);
|
|
||||||
|
|
||||||
RandomNumberGenerator *m_rng;
|
|
||||||
lword m_length, m_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! empty store
|
|
||||||
class CRYPTOPP_DLL NullStore : public Store
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NullStore(lword size = ULONG_MAX) : m_size(size) {}
|
|
||||||
void StoreInitialize(const NameValuePairs ¶meters) {}
|
|
||||||
lword MaxRetrievable() const {return m_size;}
|
|
||||||
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
|
||||||
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
lword m_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! A Filter that pumps data into its attachment as input
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting<Filter>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Source(BufferedTransformation *attachment = NULL)
|
|
||||||
{Source::Detach(attachment);}
|
|
||||||
|
|
||||||
lword Pump(lword pumpMax=size_t(0)-1)
|
|
||||||
{Pump2(pumpMax); return pumpMax;}
|
|
||||||
unsigned int PumpMessages(unsigned int count=UINT_MAX)
|
|
||||||
{PumpMessages2(count); return count;}
|
|
||||||
void PumpAll()
|
|
||||||
{PumpAll2();}
|
|
||||||
virtual size_t Pump2(lword &byteCount, bool blocking=true) =0;
|
|
||||||
virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
|
|
||||||
virtual size_t PumpAll2(bool blocking=true);
|
|
||||||
virtual bool SourceExhausted() const =0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
IsolatedInitialize(parameters);
|
|
||||||
if (pumpAll)
|
|
||||||
PumpAll();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Turn a Store into a Source
|
|
||||||
template <class T>
|
|
||||||
class SourceTemplate : public Source
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SourceTemplate<T>(BufferedTransformation *attachment)
|
|
||||||
: Source(attachment) {}
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{m_store.IsolatedInitialize(parameters);}
|
|
||||||
size_t Pump2(lword &byteCount, bool blocking=true)
|
|
||||||
{return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);}
|
|
||||||
size_t PumpMessages2(unsigned int &messageCount, bool blocking=true)
|
|
||||||
{return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);}
|
|
||||||
size_t PumpAll2(bool blocking=true)
|
|
||||||
{return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);}
|
|
||||||
bool SourceExhausted() const
|
|
||||||
{return !m_store.AnyRetrievable() && !m_store.AnyMessages();}
|
|
||||||
void SetAutoSignalPropagation(int propagation)
|
|
||||||
{m_store.SetAutoSignalPropagation(propagation);}
|
|
||||||
int GetAutoSignalPropagation() const
|
|
||||||
{return m_store.GetAutoSignalPropagation();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T m_store;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! string-based implementation of Source interface
|
|
||||||
class CRYPTOPP_DLL StringSource : public SourceTemplate<StringStore>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringSource(BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<StringStore>(attachment) {}
|
|
||||||
//! zero terminated string as source
|
|
||||||
StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
|
||||||
//! binary byte array as source
|
|
||||||
StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
|
|
||||||
//! std::string as source
|
|
||||||
StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! use the third constructor for an array source
|
|
||||||
typedef StringSource ArraySource;
|
|
||||||
|
|
||||||
//! RNG-based implementation of Source interface
|
|
||||||
class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate<RandomNumberStore>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL)
|
|
||||||
: SourceTemplate<RandomNumberStore>(attachment)
|
|
||||||
{SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));}
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,84 +0,0 @@
|
||||||
// fips140.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "fips140.h"
|
|
||||||
#include "trdlocal.h" // needs to be included last for cygwin
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
// Define this to 1 to turn on FIPS 140-2 compliance features, including additional tests during
|
|
||||||
// startup, random number generation, and key generation. These tests may affect performance.
|
|
||||||
#ifndef CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
|
||||||
#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(THREADS_AVAILABLE))
|
|
||||||
#error FIPS 140-2 compliance requires the availability of thread local storage.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE))
|
|
||||||
#error FIPS 140-2 compliance requires the availability of OS provided RNG.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PowerUpSelfTestStatus g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE;
|
|
||||||
|
|
||||||
bool FIPS_140_2_ComplianceEnabled()
|
|
||||||
{
|
|
||||||
return CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimulatePowerUpSelfTestFailure()
|
|
||||||
{
|
|
||||||
g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus()
|
|
||||||
{
|
|
||||||
return g_powerUpSelfTestStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
|
||||||
ThreadLocalStorage & AccessPowerUpSelfTestInProgress()
|
|
||||||
{
|
|
||||||
static ThreadLocalStorage selfTestInProgress;
|
|
||||||
return selfTestInProgress;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool PowerUpSelfTestInProgressOnThisThread()
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
|
||||||
return AccessPowerUpSelfTestInProgress().GetValue() != NULL;
|
|
||||||
#else
|
|
||||||
assert(false); // should not be called
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress)
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
|
||||||
AccessPowerUpSelfTestInProgress().SetValue((void *)inProgress);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor)
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
|
||||||
EncryptionPairwiseConsistencyTest(encryptor, decryptor);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier)
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
|
||||||
SignaturePairwiseConsistencyTest(signer, verifier);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,59 +0,0 @@
|
||||||
#ifndef CRYPTOPP_FIPS140_H
|
|
||||||
#define CRYPTOPP_FIPS140_H
|
|
||||||
|
|
||||||
/*! \file
|
|
||||||
FIPS 140 related functions and classes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! exception thrown when a crypto algorithm is used after a self test fails
|
|
||||||
class CRYPTOPP_DLL SelfTestFailure : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! returns whether FIPS 140-2 compliance features were enabled at compile time
|
|
||||||
CRYPTOPP_DLL bool CRYPTOPP_API FIPS_140_2_ComplianceEnabled();
|
|
||||||
|
|
||||||
//! enum values representing status of the power-up self test
|
|
||||||
enum PowerUpSelfTestStatus {POWER_UP_SELF_TEST_NOT_DONE, POWER_UP_SELF_TEST_FAILED, POWER_UP_SELF_TEST_PASSED};
|
|
||||||
|
|
||||||
//! perform the power-up self test, and set the self test status
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac);
|
|
||||||
|
|
||||||
//! perform the power-up self test using the filename of this DLL and the embedded module MAC
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest();
|
|
||||||
|
|
||||||
//! set the power-up self test status to POWER_UP_SELF_TEST_FAILED
|
|
||||||
CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure();
|
|
||||||
|
|
||||||
//! return the current power-up self test status
|
|
||||||
CRYPTOPP_DLL PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus();
|
|
||||||
|
|
||||||
typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)();
|
|
||||||
|
|
||||||
CRYPTOPP_DLL MessageAuthenticationCode * CRYPTOPP_API NewIntegrityCheckingMAC();
|
|
||||||
|
|
||||||
CRYPTOPP_DLL bool CRYPTOPP_API IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac = NULL, unsigned long *pMacFileLocation = NULL);
|
|
||||||
|
|
||||||
// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test
|
|
||||||
bool PowerUpSelfTestInProgressOnThisThread();
|
|
||||||
|
|
||||||
void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress);
|
|
||||||
|
|
||||||
void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier);
|
|
||||||
void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
|
|
||||||
|
|
||||||
void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier);
|
|
||||||
void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
|
|
||||||
|
|
||||||
#define CRYPTOPP_DUMMY_DLL_MAC "MAC_51f34b8db820ae8"
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,67 +0,0 @@
|
||||||
#ifndef CRYPTOPP_FLTRIMPL_H
|
|
||||||
#define CRYPTOPP_FLTRIMPL_H
|
|
||||||
|
|
||||||
#define FILTER_BEGIN \
|
|
||||||
switch (m_continueAt) \
|
|
||||||
{ \
|
|
||||||
case 0: \
|
|
||||||
m_inputPosition = 0;
|
|
||||||
|
|
||||||
#define FILTER_END_NO_MESSAGE_END_NO_RETURN \
|
|
||||||
break; \
|
|
||||||
default: \
|
|
||||||
assert(false); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FILTER_END_NO_MESSAGE_END \
|
|
||||||
FILTER_END_NO_MESSAGE_END_NO_RETURN \
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define FILTER_END \
|
|
||||||
case -1: \
|
|
||||||
if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \
|
|
||||||
return 1; \
|
|
||||||
FILTER_END_NO_MESSAGE_END
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \
|
|
||||||
{\
|
|
||||||
case site: \
|
|
||||||
statement; \
|
|
||||||
if (Output(site, output, length, messageEnd, blocking, channel)) \
|
|
||||||
return STDMAX(size_t(1), length-m_inputPosition);\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \
|
|
||||||
FILTER_OUTPUT3(site, statement, output, length, messageEnd, DEFAULT_CHANNEL)
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT(site, output, length, messageEnd) \
|
|
||||||
FILTER_OUTPUT2(site, 0, output, length, messageEnd)
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT_BYTE(site, output) \
|
|
||||||
FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0)
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT2_MODIFIABLE(site, statement, output, length, messageEnd) \
|
|
||||||
{\
|
|
||||||
case site: \
|
|
||||||
statement; \
|
|
||||||
if (OutputModifiable(site, output, length, messageEnd, blocking)) \
|
|
||||||
return STDMAX(size_t(1), length-m_inputPosition);\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT_MODIFIABLE(site, output, length, messageEnd) \
|
|
||||||
FILTER_OUTPUT2_MODIFIABLE(site, 0, output, length, messageEnd)
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, statement, output, length, messageEnd, modifiable) \
|
|
||||||
{\
|
|
||||||
case site: \
|
|
||||||
statement; \
|
|
||||||
if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking)) \
|
|
||||||
return STDMAX(size_t(1), length-m_inputPosition);\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable) \
|
|
||||||
FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable)
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,828 +0,0 @@
|
||||||
// gcm.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM gcm.cpp" to generate MASM code
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
#ifndef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
|
|
||||||
#include "gcm.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
word16 GCM_Base::s_reductionTable[256];
|
|
||||||
volatile bool GCM_Base::s_reductionTableInitialized = false;
|
|
||||||
|
|
||||||
void GCM_Base::GCTR::IncrementCounterBy256()
|
|
||||||
{
|
|
||||||
IncrementCounterByOne(m_counterArray+BlockSize()-4, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// preserved for testing
|
|
||||||
void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)
|
|
||||||
{
|
|
||||||
word64 Z0=0, Z1=0, V0, V1;
|
|
||||||
|
|
||||||
typedef BlockGetAndPut<word64, BigEndian> Block;
|
|
||||||
Block::Get(a)(V0)(V1);
|
|
||||||
|
|
||||||
for (int i=0; i<16; i++)
|
|
||||||
{
|
|
||||||
for (int j=0x80; j!=0; j>>=1)
|
|
||||||
{
|
|
||||||
int x = b[i] & j;
|
|
||||||
Z0 ^= x ? V0 : 0;
|
|
||||||
Z1 ^= x ? V1 : 0;
|
|
||||||
x = (int)V1 & 1;
|
|
||||||
V1 = (V1>>1) | (V0<<63);
|
|
||||||
V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Block::Put(NULL, c)(Z0)(Z1);
|
|
||||||
}
|
|
||||||
|
|
||||||
__m128i _mm_clmulepi64_si128(const __m128i &a, const __m128i &b, int i)
|
|
||||||
{
|
|
||||||
word64 A[1] = {ByteReverse(((word64*)&a)[i&1])};
|
|
||||||
word64 B[1] = {ByteReverse(((word64*)&b)[i>>4])};
|
|
||||||
|
|
||||||
PolynomialMod2 pa((byte *)A, 8);
|
|
||||||
PolynomialMod2 pb((byte *)B, 8);
|
|
||||||
PolynomialMod2 c = pa*pb;
|
|
||||||
|
|
||||||
__m128i output;
|
|
||||||
for (int i=0; i<16; i++)
|
|
||||||
((byte *)&output)[i] = c.GetByte(i);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
|
||||||
inline static void SSE2_Xor16(byte *a, const byte *b, const byte *c)
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
|
||||||
*(__m128i *)a = _mm_xor_si128(*(__m128i *)b, *(__m128i *)c);
|
|
||||||
#else
|
|
||||||
asm ("movdqa %1, %%xmm0; pxor %2, %%xmm0; movdqa %%xmm0, %0;" : "=m" (a[0]) : "m"(b[0]), "m"(c[0]));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline static void Xor16(byte *a, const byte *b, const byte *c)
|
|
||||||
{
|
|
||||||
((word64 *)a)[0] = ((word64 *)b)[0] ^ ((word64 *)c)[0];
|
|
||||||
((word64 *)a)[1] = ((word64 *)b)[1] ^ ((word64 *)c)[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
|
||||||
static CRYPTOPP_ALIGN_DATA(16) const word64 s_clmulConstants64[] = {
|
|
||||||
W64LIT(0xe100000000000000), W64LIT(0xc200000000000000),
|
|
||||||
W64LIT(0x08090a0b0c0d0e0f), W64LIT(0x0001020304050607),
|
|
||||||
W64LIT(0x0001020304050607), W64LIT(0x08090a0b0c0d0e0f)};
|
|
||||||
static const __m128i *s_clmulConstants = (const __m128i *)s_clmulConstants64;
|
|
||||||
static const unsigned int s_clmulTableSizeInBlocks = 8;
|
|
||||||
|
|
||||||
inline __m128i CLMUL_Reduce(__m128i c0, __m128i c1, __m128i c2, const __m128i &r)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
The polynomial to be reduced is c0 * x^128 + c1 * x^64 + c2. c0t below refers to the most
|
|
||||||
significant half of c0 as a polynomial, which, due to GCM's bit reflection, are in the
|
|
||||||
rightmost bit positions, and the lowest byte addresses.
|
|
||||||
|
|
||||||
c1 ^= c0t * 0xc200000000000000
|
|
||||||
c2t ^= c0t
|
|
||||||
t = shift (c1t ^ c0b) left 1 bit
|
|
||||||
c2 ^= t * 0xe100000000000000
|
|
||||||
c2t ^= c1b
|
|
||||||
shift c2 left 1 bit and xor in lowest bit of c1t
|
|
||||||
*/
|
|
||||||
#if 0 // MSVC 2010 workaround: see http://connect.microsoft.com/VisualStudio/feedback/details/575301
|
|
||||||
c2 = _mm_xor_si128(c2, _mm_move_epi64(c0));
|
|
||||||
#else
|
|
||||||
c1 = _mm_xor_si128(c1, _mm_slli_si128(c0, 8));
|
|
||||||
#endif
|
|
||||||
c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(c0, r, 0x10));
|
|
||||||
c0 = _mm_srli_si128(c0, 8);
|
|
||||||
c0 = _mm_xor_si128(c0, c1);
|
|
||||||
c0 = _mm_slli_epi64(c0, 1);
|
|
||||||
c0 = _mm_clmulepi64_si128(c0, r, 0);
|
|
||||||
c2 = _mm_xor_si128(c2, c0);
|
|
||||||
c2 = _mm_xor_si128(c2, _mm_srli_si128(c1, 8));
|
|
||||||
c1 = _mm_unpacklo_epi64(c1, c2);
|
|
||||||
c1 = _mm_srli_epi64(c1, 63);
|
|
||||||
c2 = _mm_slli_epi64(c2, 1);
|
|
||||||
return _mm_xor_si128(c2, c1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline __m128i CLMUL_GF_Mul(const __m128i &x, const __m128i &h, const __m128i &r)
|
|
||||||
{
|
|
||||||
__m128i c0 = _mm_clmulepi64_si128(x,h,0);
|
|
||||||
__m128i c1 = _mm_xor_si128(_mm_clmulepi64_si128(x,h,1), _mm_clmulepi64_si128(x,h,0x10));
|
|
||||||
__m128i c2 = _mm_clmulepi64_si128(x,h,0x11);
|
|
||||||
|
|
||||||
return CLMUL_Reduce(c0, c1, c2, r);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms)
|
|
||||||
{
|
|
||||||
BlockCipher &blockCipher = AccessBlockCipher();
|
|
||||||
blockCipher.SetKey(userKey, keylength, params);
|
|
||||||
|
|
||||||
if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
|
|
||||||
throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
|
|
||||||
|
|
||||||
int tableSize, i, j, k;
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
|
||||||
if (HasCLMUL())
|
|
||||||
{
|
|
||||||
params.GetIntValue(Name::TableSize(), tableSize); // avoid "parameter not used" error
|
|
||||||
tableSize = s_clmulTableSizeInBlocks * REQUIRED_BLOCKSIZE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (params.GetIntValue(Name::TableSize(), tableSize))
|
|
||||||
tableSize = (tableSize >= 64*1024) ? 64*1024 : 2*1024;
|
|
||||||
else
|
|
||||||
tableSize = (GetTablesOption() == GCM_64K_Tables) ? 64*1024 : 2*1024;
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1300 && _MSC_VER < 1400)
|
|
||||||
// VC 2003 workaround: compiler generates bad code for 64K tables
|
|
||||||
tableSize = 2*1024;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
m_buffer.resize(3*REQUIRED_BLOCKSIZE + tableSize);
|
|
||||||
byte *table = MulTable();
|
|
||||||
byte *hashKey = HashKey();
|
|
||||||
memset(hashKey, 0, REQUIRED_BLOCKSIZE);
|
|
||||||
blockCipher.ProcessBlock(hashKey);
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
|
||||||
if (HasCLMUL())
|
|
||||||
{
|
|
||||||
const __m128i r = s_clmulConstants[0];
|
|
||||||
__m128i h0 = _mm_shuffle_epi8(_mm_load_si128((__m128i *)hashKey), s_clmulConstants[1]);
|
|
||||||
__m128i h = h0;
|
|
||||||
|
|
||||||
for (i=0; i<tableSize; i+=32)
|
|
||||||
{
|
|
||||||
__m128i h1 = CLMUL_GF_Mul(h, h0, r);
|
|
||||||
_mm_storel_epi64((__m128i *)(table+i), h);
|
|
||||||
_mm_storeu_si128((__m128i *)(table+i+16), h1);
|
|
||||||
_mm_storeu_si128((__m128i *)(table+i+8), h);
|
|
||||||
_mm_storel_epi64((__m128i *)(table+i+8), h1);
|
|
||||||
h = CLMUL_GF_Mul(h1, h0, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
word64 V0, V1;
|
|
||||||
typedef BlockGetAndPut<word64, BigEndian> Block;
|
|
||||||
Block::Get(hashKey)(V0)(V1);
|
|
||||||
|
|
||||||
if (tableSize == 64*1024)
|
|
||||||
{
|
|
||||||
for (i=0; i<128; i++)
|
|
||||||
{
|
|
||||||
k = i%8;
|
|
||||||
Block::Put(NULL, table+(i/8)*256*16+(size_t(1)<<(11-k)))(V0)(V1);
|
|
||||||
|
|
||||||
int x = (int)V1 & 1;
|
|
||||||
V1 = (V1>>1) | (V0<<63);
|
|
||||||
V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<16; i++)
|
|
||||||
{
|
|
||||||
memset(table+i*256*16, 0, 16);
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
|
||||||
if (HasSSE2())
|
|
||||||
for (j=2; j<=0x80; j*=2)
|
|
||||||
for (k=1; k<j; k++)
|
|
||||||
SSE2_Xor16(table+i*256*16+(j+k)*16, table+i*256*16+j*16, table+i*256*16+k*16);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
for (j=2; j<=0x80; j*=2)
|
|
||||||
for (k=1; k<j; k++)
|
|
||||||
Xor16(table+i*256*16+(j+k)*16, table+i*256*16+j*16, table+i*256*16+k*16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!s_reductionTableInitialized)
|
|
||||||
{
|
|
||||||
s_reductionTable[0] = 0;
|
|
||||||
word16 x = 0x01c2;
|
|
||||||
s_reductionTable[1] = ByteReverse(x);
|
|
||||||
for (int i=2; i<=0x80; i*=2)
|
|
||||||
{
|
|
||||||
x <<= 1;
|
|
||||||
s_reductionTable[i] = ByteReverse(x);
|
|
||||||
for (int j=1; j<i; j++)
|
|
||||||
s_reductionTable[i+j] = s_reductionTable[i] ^ s_reductionTable[j];
|
|
||||||
}
|
|
||||||
s_reductionTableInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<128-24; i++)
|
|
||||||
{
|
|
||||||
k = i%32;
|
|
||||||
if (k < 4)
|
|
||||||
Block::Put(NULL, table+1024+(i/32)*256+(size_t(1)<<(7-k)))(V0)(V1);
|
|
||||||
else if (k < 8)
|
|
||||||
Block::Put(NULL, table+(i/32)*256+(size_t(1)<<(11-k)))(V0)(V1);
|
|
||||||
|
|
||||||
int x = (int)V1 & 1;
|
|
||||||
V1 = (V1>>1) | (V0<<63);
|
|
||||||
V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<4; i++)
|
|
||||||
{
|
|
||||||
memset(table+i*256, 0, 16);
|
|
||||||
memset(table+1024+i*256, 0, 16);
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
|
||||||
if (HasSSE2())
|
|
||||||
for (j=2; j<=8; j*=2)
|
|
||||||
for (k=1; k<j; k++)
|
|
||||||
{
|
|
||||||
SSE2_Xor16(table+i*256+(j+k)*16, table+i*256+j*16, table+i*256+k*16);
|
|
||||||
SSE2_Xor16(table+1024+i*256+(j+k)*16, table+1024+i*256+j*16, table+1024+i*256+k*16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
for (j=2; j<=8; j*=2)
|
|
||||||
for (k=1; k<j; k++)
|
|
||||||
{
|
|
||||||
Xor16(table+i*256+(j+k)*16, table+i*256+j*16, table+i*256+k*16);
|
|
||||||
Xor16(table+1024+i*256+(j+k)*16, table+1024+i*256+j*16, table+1024+i*256+k*16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GCM_Base::ReverseHashBufferIfNeeded()
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
|
||||||
if (HasCLMUL())
|
|
||||||
{
|
|
||||||
__m128i &x = *(__m128i *)HashBuffer();
|
|
||||||
x = _mm_shuffle_epi8(x, s_clmulConstants[1]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCM_Base::Resync(const byte *iv, size_t len)
|
|
||||||
{
|
|
||||||
BlockCipher &cipher = AccessBlockCipher();
|
|
||||||
byte *hashBuffer = HashBuffer();
|
|
||||||
|
|
||||||
if (len == 12)
|
|
||||||
{
|
|
||||||
memcpy(hashBuffer, iv, len);
|
|
||||||
memset(hashBuffer+len, 0, 3);
|
|
||||||
hashBuffer[len+3] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size_t origLen = len;
|
|
||||||
memset(hashBuffer, 0, HASH_BLOCKSIZE);
|
|
||||||
|
|
||||||
if (len >= HASH_BLOCKSIZE)
|
|
||||||
{
|
|
||||||
len = GCM_Base::AuthenticateBlocks(iv, len);
|
|
||||||
iv += (origLen - len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
memcpy(m_buffer, iv, len);
|
|
||||||
memset(m_buffer+len, 0, HASH_BLOCKSIZE-len);
|
|
||||||
GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
PutBlock<word64, BigEndian, true>(NULL, m_buffer)(0)(origLen*8);
|
|
||||||
GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
|
|
||||||
|
|
||||||
ReverseHashBufferIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_state >= State_IVSet)
|
|
||||||
m_ctr.Resynchronize(hashBuffer, REQUIRED_BLOCKSIZE);
|
|
||||||
else
|
|
||||||
m_ctr.SetCipherWithIV(cipher, hashBuffer);
|
|
||||||
|
|
||||||
m_ctr.Seek(HASH_BLOCKSIZE);
|
|
||||||
|
|
||||||
memset(hashBuffer, 0, HASH_BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GCM_Base::OptimalDataAlignment() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
|
|
||||||
HasSSE2() ? 16 :
|
|
||||||
#endif
|
|
||||||
GetBlockCipher().OptimalDataAlignment();
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
|
|
||||||
|
|
||||||
#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_X64_MASM_AVAILABLE
|
|
||||||
extern "C" {
|
|
||||||
void GCM_AuthenticateBlocks_2K(const byte *data, size_t blocks, word64 *hashBuffer, const word16 *reductionTable);
|
|
||||||
void GCM_AuthenticateBlocks_64K(const byte *data, size_t blocks, word64 *hashBuffer);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
|
|
||||||
size_t GCM_Base::AuthenticateBlocks(const byte *data, size_t len)
|
|
||||||
{
|
|
||||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
|
||||||
if (HasCLMUL())
|
|
||||||
{
|
|
||||||
const __m128i *table = (const __m128i *)MulTable();
|
|
||||||
__m128i x = _mm_load_si128((__m128i *)HashBuffer());
|
|
||||||
const __m128i r = s_clmulConstants[0], bswapMask = s_clmulConstants[1], bswapMask2 = s_clmulConstants[2];
|
|
||||||
|
|
||||||
while (len >= 16)
|
|
||||||
{
|
|
||||||
size_t s = UnsignedMin(len/16, s_clmulTableSizeInBlocks), i=0;
|
|
||||||
__m128i d, d2 = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)(data+(s-1)*16)), bswapMask2);;
|
|
||||||
__m128i c0 = _mm_setzero_si128();
|
|
||||||
__m128i c1 = _mm_setzero_si128();
|
|
||||||
__m128i c2 = _mm_setzero_si128();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
__m128i h0 = _mm_load_si128(table+i);
|
|
||||||
__m128i h1 = _mm_load_si128(table+i+1);
|
|
||||||
__m128i h01 = _mm_xor_si128(h0, h1);
|
|
||||||
|
|
||||||
if (++i == s)
|
|
||||||
{
|
|
||||||
d = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)data), bswapMask);
|
|
||||||
d = _mm_xor_si128(d, x);
|
|
||||||
c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d, h0, 0));
|
|
||||||
c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d, h1, 1));
|
|
||||||
d = _mm_xor_si128(d, _mm_shuffle_epi32(d, _MM_SHUFFLE(1, 0, 3, 2)));
|
|
||||||
c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d, h01, 0));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)(data+(s-i)*16-8)), bswapMask2);
|
|
||||||
c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d2, h0, 1));
|
|
||||||
c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d, h1, 1));
|
|
||||||
d2 = _mm_xor_si128(d2, d);
|
|
||||||
c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d2, h01, 1));
|
|
||||||
|
|
||||||
if (++i == s)
|
|
||||||
{
|
|
||||||
d = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)data), bswapMask);
|
|
||||||
d = _mm_xor_si128(d, x);
|
|
||||||
c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d, h0, 0x10));
|
|
||||||
c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d, h1, 0x11));
|
|
||||||
d = _mm_xor_si128(d, _mm_shuffle_epi32(d, _MM_SHUFFLE(1, 0, 3, 2)));
|
|
||||||
c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d, h01, 0x10));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
d2 = _mm_shuffle_epi8(_mm_loadu_si128((const __m128i *)(data+(s-i)*16-8)), bswapMask);
|
|
||||||
c0 = _mm_xor_si128(c0, _mm_clmulepi64_si128(d, h0, 0x10));
|
|
||||||
c2 = _mm_xor_si128(c2, _mm_clmulepi64_si128(d2, h1, 0x10));
|
|
||||||
d = _mm_xor_si128(d, d2);
|
|
||||||
c1 = _mm_xor_si128(c1, _mm_clmulepi64_si128(d, h01, 0x10));
|
|
||||||
}
|
|
||||||
data += s*16;
|
|
||||||
len -= s*16;
|
|
||||||
|
|
||||||
c1 = _mm_xor_si128(_mm_xor_si128(c1, c0), c2);
|
|
||||||
x = CLMUL_Reduce(c0, c1, c2, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
_mm_store_si128((__m128i *)HashBuffer(), x);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef BlockGetAndPut<word64, NativeByteOrder> Block;
|
|
||||||
word64 *hashBuffer = (word64 *)HashBuffer();
|
|
||||||
|
|
||||||
switch (2*(m_buffer.size()>=64*1024)
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
|
|
||||||
+ HasSSE2()
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
case 0: // non-SSE2 and 2K tables
|
|
||||||
{
|
|
||||||
byte *table = MulTable();
|
|
||||||
word64 x0 = hashBuffer[0], x1 = hashBuffer[1];
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
word64 y0, y1, a0, a1, b0, b1, c0, c1, d0, d1;
|
|
||||||
Block::Get(data)(y0)(y1);
|
|
||||||
x0 ^= y0;
|
|
||||||
x1 ^= y1;
|
|
||||||
|
|
||||||
data += HASH_BLOCKSIZE;
|
|
||||||
len -= HASH_BLOCKSIZE;
|
|
||||||
|
|
||||||
#define READ_TABLE_WORD64_COMMON(a, b, c, d) *(word64 *)(table+(a*1024)+(b*256)+c+d*8)
|
|
||||||
|
|
||||||
#ifdef IS_LITTLE_ENDIAN
|
|
||||||
#if CRYPTOPP_BOOL_SLOW_WORD64
|
|
||||||
word32 z0 = (word32)x0;
|
|
||||||
word32 z1 = (word32)(x0>>32);
|
|
||||||
word32 z2 = (word32)x1;
|
|
||||||
word32 z3 = (word32)(x1>>32);
|
|
||||||
#define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, (d?(z##c>>((d?d-1:0)*4))&0xf0:(z##c&0xf)<<4), e)
|
|
||||||
#else
|
|
||||||
#define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, ((d+8*b)?(x##a>>(((d+8*b)?(d+8*b)-1:1)*4))&0xf0:(x##a&0xf)<<4), e)
|
|
||||||
#endif
|
|
||||||
#define GF_MOST_SIG_8BITS(a) (a##1 >> 7*8)
|
|
||||||
#define GF_SHIFT_8(a) a##1 = (a##1 << 8) ^ (a##0 >> 7*8); a##0 <<= 8;
|
|
||||||
#else
|
|
||||||
#define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((1-d%2), c, ((15-d-8*b)?(x##a>>(((15-d-8*b)?(15-d-8*b)-1:0)*4))&0xf0:(x##a&0xf)<<4), e)
|
|
||||||
#define GF_MOST_SIG_8BITS(a) (a##1 & 0xff)
|
|
||||||
#define GF_SHIFT_8(a) a##1 = (a##1 >> 8) ^ (a##0 << 7*8); a##0 >>= 8;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GF_MUL_32BY128(op, a, b, c) \
|
|
||||||
a0 op READ_TABLE_WORD64(a, b, c, 0, 0) ^ READ_TABLE_WORD64(a, b, c, 1, 0);\
|
|
||||||
a1 op READ_TABLE_WORD64(a, b, c, 0, 1) ^ READ_TABLE_WORD64(a, b, c, 1, 1);\
|
|
||||||
b0 op READ_TABLE_WORD64(a, b, c, 2, 0) ^ READ_TABLE_WORD64(a, b, c, 3, 0);\
|
|
||||||
b1 op READ_TABLE_WORD64(a, b, c, 2, 1) ^ READ_TABLE_WORD64(a, b, c, 3, 1);\
|
|
||||||
c0 op READ_TABLE_WORD64(a, b, c, 4, 0) ^ READ_TABLE_WORD64(a, b, c, 5, 0);\
|
|
||||||
c1 op READ_TABLE_WORD64(a, b, c, 4, 1) ^ READ_TABLE_WORD64(a, b, c, 5, 1);\
|
|
||||||
d0 op READ_TABLE_WORD64(a, b, c, 6, 0) ^ READ_TABLE_WORD64(a, b, c, 7, 0);\
|
|
||||||
d1 op READ_TABLE_WORD64(a, b, c, 6, 1) ^ READ_TABLE_WORD64(a, b, c, 7, 1);\
|
|
||||||
|
|
||||||
GF_MUL_32BY128(=, 0, 0, 0)
|
|
||||||
GF_MUL_32BY128(^=, 0, 1, 1)
|
|
||||||
GF_MUL_32BY128(^=, 1, 0, 2)
|
|
||||||
GF_MUL_32BY128(^=, 1, 1, 3)
|
|
||||||
|
|
||||||
word32 r = (word32)s_reductionTable[GF_MOST_SIG_8BITS(d)] << 16;
|
|
||||||
GF_SHIFT_8(d)
|
|
||||||
c0 ^= d0; c1 ^= d1;
|
|
||||||
r ^= (word32)s_reductionTable[GF_MOST_SIG_8BITS(c)] << 8;
|
|
||||||
GF_SHIFT_8(c)
|
|
||||||
b0 ^= c0; b1 ^= c1;
|
|
||||||
r ^= s_reductionTable[GF_MOST_SIG_8BITS(b)];
|
|
||||||
GF_SHIFT_8(b)
|
|
||||||
a0 ^= b0; a1 ^= b1;
|
|
||||||
a0 ^= ConditionalByteReverse<word64>(LITTLE_ENDIAN_ORDER, r);
|
|
||||||
x0 = a0; x1 = a1;
|
|
||||||
}
|
|
||||||
while (len >= HASH_BLOCKSIZE);
|
|
||||||
|
|
||||||
hashBuffer[0] = x0; hashBuffer[1] = x1;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2: // non-SSE2 and 64K tables
|
|
||||||
{
|
|
||||||
byte *table = MulTable();
|
|
||||||
word64 x0 = hashBuffer[0], x1 = hashBuffer[1];
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
word64 y0, y1, a0, a1;
|
|
||||||
Block::Get(data)(y0)(y1);
|
|
||||||
x0 ^= y0;
|
|
||||||
x1 ^= y1;
|
|
||||||
|
|
||||||
data += HASH_BLOCKSIZE;
|
|
||||||
len -= HASH_BLOCKSIZE;
|
|
||||||
|
|
||||||
#undef READ_TABLE_WORD64_COMMON
|
|
||||||
#undef READ_TABLE_WORD64
|
|
||||||
|
|
||||||
#define READ_TABLE_WORD64_COMMON(a, c, d) *(word64 *)(table+(a)*256*16+(c)+(d)*8)
|
|
||||||
|
|
||||||
#ifdef IS_LITTLE_ENDIAN
|
|
||||||
#if CRYPTOPP_BOOL_SLOW_WORD64
|
|
||||||
word32 z0 = (word32)x0;
|
|
||||||
word32 z1 = (word32)(x0>>32);
|
|
||||||
word32 z2 = (word32)x1;
|
|
||||||
word32 z3 = (word32)(x1>>32);
|
|
||||||
#define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, (d?(z##c>>((d?d:1)*8-4))&0xff0:(z##c&0xff)<<4), e)
|
|
||||||
#else
|
|
||||||
#define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((d+4*(c%2))?(x##b>>(((d+4*(c%2))?(d+4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((7-d-4*(c%2))?(x##b>>(((7-d-4*(c%2))?(7-d-4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GF_MUL_8BY128(op, b, c, d) \
|
|
||||||
a0 op READ_TABLE_WORD64(b, c, d, 0);\
|
|
||||||
a1 op READ_TABLE_WORD64(b, c, d, 1);\
|
|
||||||
|
|
||||||
GF_MUL_8BY128(=, 0, 0, 0)
|
|
||||||
GF_MUL_8BY128(^=, 0, 0, 1)
|
|
||||||
GF_MUL_8BY128(^=, 0, 0, 2)
|
|
||||||
GF_MUL_8BY128(^=, 0, 0, 3)
|
|
||||||
GF_MUL_8BY128(^=, 0, 1, 0)
|
|
||||||
GF_MUL_8BY128(^=, 0, 1, 1)
|
|
||||||
GF_MUL_8BY128(^=, 0, 1, 2)
|
|
||||||
GF_MUL_8BY128(^=, 0, 1, 3)
|
|
||||||
GF_MUL_8BY128(^=, 1, 2, 0)
|
|
||||||
GF_MUL_8BY128(^=, 1, 2, 1)
|
|
||||||
GF_MUL_8BY128(^=, 1, 2, 2)
|
|
||||||
GF_MUL_8BY128(^=, 1, 2, 3)
|
|
||||||
GF_MUL_8BY128(^=, 1, 3, 0)
|
|
||||||
GF_MUL_8BY128(^=, 1, 3, 1)
|
|
||||||
GF_MUL_8BY128(^=, 1, 3, 2)
|
|
||||||
GF_MUL_8BY128(^=, 1, 3, 3)
|
|
||||||
|
|
||||||
x0 = a0; x1 = a1;
|
|
||||||
}
|
|
||||||
while (len >= HASH_BLOCKSIZE);
|
|
||||||
|
|
||||||
hashBuffer[0] = x0; hashBuffer[1] = x1;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
|
|
||||||
#ifdef CRYPTOPP_X64_MASM_AVAILABLE
|
|
||||||
case 1: // SSE2 and 2K tables
|
|
||||||
GCM_AuthenticateBlocks_2K(data, len/16, hashBuffer, s_reductionTable);
|
|
||||||
return len % 16;
|
|
||||||
case 3: // SSE2 and 64K tables
|
|
||||||
GCM_AuthenticateBlocks_64K(data, len/16, hashBuffer);
|
|
||||||
return len % 16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
|
||||||
case 1: // SSE2 and 2K tables
|
|
||||||
{
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__
|
|
||||||
(
|
|
||||||
".intel_syntax noprefix;"
|
|
||||||
#elif defined(CRYPTOPP_GENERATE_X64_MASM)
|
|
||||||
ALIGN 8
|
|
||||||
GCM_AuthenticateBlocks_2K PROC FRAME
|
|
||||||
rex_push_reg rsi
|
|
||||||
push_reg rdi
|
|
||||||
push_reg rbx
|
|
||||||
.endprolog
|
|
||||||
mov rsi, r8
|
|
||||||
mov r11, r9
|
|
||||||
#else
|
|
||||||
AS2( mov WORD_REG(cx), data )
|
|
||||||
AS2( mov WORD_REG(dx), len )
|
|
||||||
AS2( mov WORD_REG(si), hashBuffer )
|
|
||||||
AS2( shr WORD_REG(dx), 4 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AS_PUSH_IF86( bx)
|
|
||||||
AS_PUSH_IF86( bp)
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
AS2( mov AS_REG_7, WORD_REG(di))
|
|
||||||
#elif CRYPTOPP_BOOL_X86
|
|
||||||
AS2( lea AS_REG_7, s_reductionTable)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AS2( movdqa xmm0, [WORD_REG(si)] )
|
|
||||||
|
|
||||||
#define MUL_TABLE_0 WORD_REG(si) + 32
|
|
||||||
#define MUL_TABLE_1 WORD_REG(si) + 32 + 1024
|
|
||||||
#define RED_TABLE AS_REG_7
|
|
||||||
|
|
||||||
ASL(0)
|
|
||||||
AS2( movdqu xmm4, [WORD_REG(cx)] )
|
|
||||||
AS2( pxor xmm0, xmm4 )
|
|
||||||
|
|
||||||
AS2( movd ebx, xmm0 )
|
|
||||||
AS2( mov eax, AS_HEX(f0f0f0f0) )
|
|
||||||
AS2( and eax, ebx )
|
|
||||||
AS2( shl ebx, 4 )
|
|
||||||
AS2( and ebx, AS_HEX(f0f0f0f0) )
|
|
||||||
AS2( movzx edi, ah )
|
|
||||||
AS2( movdqa xmm5, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
|
|
||||||
AS2( movzx edi, al )
|
|
||||||
AS2( movdqa xmm4, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
|
|
||||||
AS2( shr eax, 16 )
|
|
||||||
AS2( movzx edi, ah )
|
|
||||||
AS2( movdqa xmm3, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
|
|
||||||
AS2( movzx edi, al )
|
|
||||||
AS2( movdqa xmm2, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
|
|
||||||
|
|
||||||
#define SSE2_MUL_32BITS(i) \
|
|
||||||
AS2( psrldq xmm0, 4 )\
|
|
||||||
AS2( movd eax, xmm0 )\
|
|
||||||
AS2( and eax, AS_HEX(f0f0f0f0) )\
|
|
||||||
AS2( movzx edi, bh )\
|
|
||||||
AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
|
|
||||||
AS2( movzx edi, bl )\
|
|
||||||
AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
|
|
||||||
AS2( shr ebx, 16 )\
|
|
||||||
AS2( movzx edi, bh )\
|
|
||||||
AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
|
|
||||||
AS2( movzx edi, bl )\
|
|
||||||
AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
|
|
||||||
AS2( movd ebx, xmm0 )\
|
|
||||||
AS2( shl ebx, 4 )\
|
|
||||||
AS2( and ebx, AS_HEX(f0f0f0f0) )\
|
|
||||||
AS2( movzx edi, ah )\
|
|
||||||
AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
|
|
||||||
AS2( movzx edi, al )\
|
|
||||||
AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
|
|
||||||
AS2( shr eax, 16 )\
|
|
||||||
AS2( movzx edi, ah )\
|
|
||||||
AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
|
|
||||||
AS2( movzx edi, al )\
|
|
||||||
AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
|
|
||||||
|
|
||||||
SSE2_MUL_32BITS(1)
|
|
||||||
SSE2_MUL_32BITS(2)
|
|
||||||
SSE2_MUL_32BITS(3)
|
|
||||||
|
|
||||||
AS2( movzx edi, bh )
|
|
||||||
AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
|
|
||||||
AS2( movzx edi, bl )
|
|
||||||
AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
|
|
||||||
AS2( shr ebx, 16 )
|
|
||||||
AS2( movzx edi, bh )
|
|
||||||
AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
|
|
||||||
AS2( movzx edi, bl )
|
|
||||||
AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
|
|
||||||
|
|
||||||
AS2( movdqa xmm0, xmm3 )
|
|
||||||
AS2( pslldq xmm3, 1 )
|
|
||||||
AS2( pxor xmm2, xmm3 )
|
|
||||||
AS2( movdqa xmm1, xmm2 )
|
|
||||||
AS2( pslldq xmm2, 1 )
|
|
||||||
AS2( pxor xmm5, xmm2 )
|
|
||||||
|
|
||||||
AS2( psrldq xmm0, 15 )
|
|
||||||
AS2( movd WORD_REG(di), xmm0 )
|
|
||||||
AS2( movzx eax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
|
|
||||||
AS2( shl eax, 8 )
|
|
||||||
|
|
||||||
AS2( movdqa xmm0, xmm5 )
|
|
||||||
AS2( pslldq xmm5, 1 )
|
|
||||||
AS2( pxor xmm4, xmm5 )
|
|
||||||
|
|
||||||
AS2( psrldq xmm1, 15 )
|
|
||||||
AS2( movd WORD_REG(di), xmm1 )
|
|
||||||
AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
|
|
||||||
AS2( shl eax, 8 )
|
|
||||||
|
|
||||||
AS2( psrldq xmm0, 15 )
|
|
||||||
AS2( movd WORD_REG(di), xmm0 )
|
|
||||||
AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
|
|
||||||
|
|
||||||
AS2( movd xmm0, eax )
|
|
||||||
AS2( pxor xmm0, xmm4 )
|
|
||||||
|
|
||||||
AS2( add WORD_REG(cx), 16 )
|
|
||||||
AS2( sub WORD_REG(dx), 1 )
|
|
||||||
ASJ( jnz, 0, b )
|
|
||||||
AS2( movdqa [WORD_REG(si)], xmm0 )
|
|
||||||
|
|
||||||
AS_POP_IF86( bp)
|
|
||||||
AS_POP_IF86( bx)
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
".att_syntax prefix;"
|
|
||||||
:
|
|
||||||
: "c" (data), "d" (len/16), "S" (hashBuffer), "D" (s_reductionTable)
|
|
||||||
: "memory", "cc", "%eax"
|
|
||||||
#if CRYPTOPP_BOOL_X64
|
|
||||||
, "%ebx", "%r11"
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#elif defined(CRYPTOPP_GENERATE_X64_MASM)
|
|
||||||
pop rbx
|
|
||||||
pop rdi
|
|
||||||
pop rsi
|
|
||||||
ret
|
|
||||||
GCM_AuthenticateBlocks_2K ENDP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return len%16;
|
|
||||||
}
|
|
||||||
case 3: // SSE2 and 64K tables
|
|
||||||
{
|
|
||||||
#ifdef __GNUC__
|
|
||||||
__asm__ __volatile__
|
|
||||||
(
|
|
||||||
".intel_syntax noprefix;"
|
|
||||||
#elif defined(CRYPTOPP_GENERATE_X64_MASM)
|
|
||||||
ALIGN 8
|
|
||||||
GCM_AuthenticateBlocks_64K PROC FRAME
|
|
||||||
rex_push_reg rsi
|
|
||||||
push_reg rdi
|
|
||||||
.endprolog
|
|
||||||
mov rsi, r8
|
|
||||||
#else
|
|
||||||
AS2( mov WORD_REG(cx), data )
|
|
||||||
AS2( mov WORD_REG(dx), len )
|
|
||||||
AS2( mov WORD_REG(si), hashBuffer )
|
|
||||||
AS2( shr WORD_REG(dx), 4 )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AS2( movdqa xmm0, [WORD_REG(si)] )
|
|
||||||
|
|
||||||
#undef MUL_TABLE
|
|
||||||
#define MUL_TABLE(i,j) WORD_REG(si) + 32 + (i*4+j)*256*16
|
|
||||||
|
|
||||||
ASL(1)
|
|
||||||
AS2( movdqu xmm1, [WORD_REG(cx)] )
|
|
||||||
AS2( pxor xmm1, xmm0 )
|
|
||||||
AS2( pxor xmm0, xmm0 )
|
|
||||||
|
|
||||||
#undef SSE2_MUL_32BITS
|
|
||||||
#define SSE2_MUL_32BITS(i) \
|
|
||||||
AS2( movd eax, xmm1 )\
|
|
||||||
AS2( psrldq xmm1, 4 )\
|
|
||||||
AS2( movzx edi, al )\
|
|
||||||
AS2( add WORD_REG(di), WORD_REG(di) )\
|
|
||||||
AS2( pxor xmm0, [MUL_TABLE(i,0) + WORD_REG(di)*8] )\
|
|
||||||
AS2( movzx edi, ah )\
|
|
||||||
AS2( add WORD_REG(di), WORD_REG(di) )\
|
|
||||||
AS2( pxor xmm0, [MUL_TABLE(i,1) + WORD_REG(di)*8] )\
|
|
||||||
AS2( shr eax, 16 )\
|
|
||||||
AS2( movzx edi, al )\
|
|
||||||
AS2( add WORD_REG(di), WORD_REG(di) )\
|
|
||||||
AS2( pxor xmm0, [MUL_TABLE(i,2) + WORD_REG(di)*8] )\
|
|
||||||
AS2( movzx edi, ah )\
|
|
||||||
AS2( add WORD_REG(di), WORD_REG(di) )\
|
|
||||||
AS2( pxor xmm0, [MUL_TABLE(i,3) + WORD_REG(di)*8] )\
|
|
||||||
|
|
||||||
SSE2_MUL_32BITS(0)
|
|
||||||
SSE2_MUL_32BITS(1)
|
|
||||||
SSE2_MUL_32BITS(2)
|
|
||||||
SSE2_MUL_32BITS(3)
|
|
||||||
|
|
||||||
AS2( add WORD_REG(cx), 16 )
|
|
||||||
AS2( sub WORD_REG(dx), 1 )
|
|
||||||
ASJ( jnz, 1, b )
|
|
||||||
AS2( movdqa [WORD_REG(si)], xmm0 )
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
".att_syntax prefix;"
|
|
||||||
:
|
|
||||||
: "c" (data), "d" (len/16), "S" (hashBuffer)
|
|
||||||
: "memory", "cc", "%edi", "%eax"
|
|
||||||
);
|
|
||||||
#elif defined(CRYPTOPP_GENERATE_X64_MASM)
|
|
||||||
pop rdi
|
|
||||||
pop rsi
|
|
||||||
ret
|
|
||||||
GCM_AuthenticateBlocks_64K ENDP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return len%16;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifndef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
}
|
|
||||||
|
|
||||||
return len%16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCM_Base::AuthenticateLastHeaderBlock()
|
|
||||||
{
|
|
||||||
if (m_bufferedDataLength > 0)
|
|
||||||
{
|
|
||||||
memset(m_buffer+m_bufferedDataLength, 0, HASH_BLOCKSIZE-m_bufferedDataLength);
|
|
||||||
m_bufferedDataLength = 0;
|
|
||||||
GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCM_Base::AuthenticateLastConfidentialBlock()
|
|
||||||
{
|
|
||||||
GCM_Base::AuthenticateLastHeaderBlock();
|
|
||||||
PutBlock<word64, BigEndian, true>(NULL, m_buffer)(m_totalHeaderLength*8)(m_totalMessageLength*8);
|
|
||||||
GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
|
|
||||||
{
|
|
||||||
m_ctr.Seek(0);
|
|
||||||
ReverseHashBufferIfNeeded();
|
|
||||||
m_ctr.ProcessData(mac, HashBuffer(), macSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
|
|
||||||
#endif
|
|
|
@ -1,106 +0,0 @@
|
||||||
#ifndef CRYPTOPP_GCM_H
|
|
||||||
#define CRYPTOPP_GCM_H
|
|
||||||
|
|
||||||
#include "authenc.h"
|
|
||||||
#include "modes.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! .
|
|
||||||
enum GCM_TablesOption {GCM_2K_Tables, GCM_64K_Tables};
|
|
||||||
|
|
||||||
//! .
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// AuthenticatedSymmetricCipher
|
|
||||||
std::string AlgorithmName() const
|
|
||||||
{return GetBlockCipher().AlgorithmName() + std::string("/GCM");}
|
|
||||||
size_t MinKeyLength() const
|
|
||||||
{return GetBlockCipher().MinKeyLength();}
|
|
||||||
size_t MaxKeyLength() const
|
|
||||||
{return GetBlockCipher().MaxKeyLength();}
|
|
||||||
size_t DefaultKeyLength() const
|
|
||||||
{return GetBlockCipher().DefaultKeyLength();}
|
|
||||||
size_t GetValidKeyLength(size_t n) const
|
|
||||||
{return GetBlockCipher().GetValidKeyLength(n);}
|
|
||||||
bool IsValidKeyLength(size_t n) const
|
|
||||||
{return GetBlockCipher().IsValidKeyLength(n);}
|
|
||||||
unsigned int OptimalDataAlignment() const;
|
|
||||||
IV_Requirement IVRequirement() const
|
|
||||||
{return UNIQUE_IV;}
|
|
||||||
unsigned int IVSize() const
|
|
||||||
{return 12;}
|
|
||||||
unsigned int MinIVLength() const
|
|
||||||
{return 1;}
|
|
||||||
unsigned int MaxIVLength() const
|
|
||||||
{return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard
|
|
||||||
unsigned int DigestSize() const
|
|
||||||
{return 16;}
|
|
||||||
lword MaxHeaderLength() const
|
|
||||||
{return (W64LIT(1)<<61)-1;}
|
|
||||||
lword MaxMessageLength() const
|
|
||||||
{return ((W64LIT(1)<<39)-256)/8;}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// AuthenticatedSymmetricCipherBase
|
|
||||||
bool AuthenticationIsOnPlaintext() const
|
|
||||||
{return false;}
|
|
||||||
unsigned int AuthenticationBlockSize() const
|
|
||||||
{return HASH_BLOCKSIZE;}
|
|
||||||
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms);
|
|
||||||
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);
|
|
||||||
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
|
|
||||||
|
|
||||||
virtual BlockCipher & AccessBlockCipher() =0;
|
|
||||||
virtual GCM_TablesOption GetTablesOption() const =0;
|
|
||||||
|
|
||||||
const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();};
|
|
||||||
byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
|
|
||||||
byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;}
|
|
||||||
byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;}
|
|
||||||
inline void ReverseHashBufferIfNeeded();
|
|
||||||
|
|
||||||
class CRYPTOPP_DLL GCTR : public CTR_Mode_ExternalCipher::Encryption
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void IncrementCounterBy256();
|
|
||||||
};
|
|
||||||
|
|
||||||
GCTR m_ctr;
|
|
||||||
static word16 s_reductionTable[256];
|
|
||||||
static volatile bool s_reductionTableInitialized;
|
|
||||||
enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16};
|
|
||||||
};
|
|
||||||
|
|
||||||
//! .
|
|
||||||
template <class T_BlockCipher, GCM_TablesOption T_TablesOption, bool T_IsEncryption>
|
|
||||||
class GCM_Final : public GCM_Base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static std::string StaticAlgorithmName()
|
|
||||||
{return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");}
|
|
||||||
bool IsForwardTransformation() const
|
|
||||||
{return T_IsEncryption;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GCM_TablesOption GetTablesOption() const {return T_TablesOption;}
|
|
||||||
BlockCipher & AccessBlockCipher() {return m_cipher;}
|
|
||||||
typename T_BlockCipher::Encryption m_cipher;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://www.cryptolounge.org/wiki/GCM">GCM</a>
|
|
||||||
template <class T_BlockCipher, GCM_TablesOption T_TablesOption=GCM_2K_Tables>
|
|
||||||
struct GCM : public AuthenticatedSymmetricCipherDocumentation
|
|
||||||
{
|
|
||||||
typedef GCM_Final<T_BlockCipher, T_TablesOption, true> Encryption;
|
|
||||||
typedef GCM_Final<T_BlockCipher, T_TablesOption, false> Decryption;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,34 +0,0 @@
|
||||||
// gf256.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "gf256.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
GF256::Element GF256::Multiply(Element a, Element b) const
|
|
||||||
{
|
|
||||||
word result = 0, t = b;
|
|
||||||
|
|
||||||
for (unsigned int i=0; i<8; i++)
|
|
||||||
{
|
|
||||||
result <<= 1;
|
|
||||||
if (result & 0x100)
|
|
||||||
result ^= m_modulus;
|
|
||||||
|
|
||||||
t <<= 1;
|
|
||||||
if (t & 0x100)
|
|
||||||
result ^= a;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (GF256::Element) result;
|
|
||||||
}
|
|
||||||
|
|
||||||
GF256::Element GF256::MultiplicativeInverse(Element a) const
|
|
||||||
{
|
|
||||||
Element result = a;
|
|
||||||
for (int i=1; i<7; i++)
|
|
||||||
result = Multiply(Square(result), a);
|
|
||||||
return Square(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,66 +0,0 @@
|
||||||
#ifndef CRYPTOPP_GF256_H
|
|
||||||
#define CRYPTOPP_GF256_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! GF(256) with polynomial basis
|
|
||||||
class GF256
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef byte Element;
|
|
||||||
typedef int RandomizationParameter;
|
|
||||||
|
|
||||||
GF256(byte modulus) : m_modulus(modulus) {}
|
|
||||||
|
|
||||||
Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const
|
|
||||||
{return rng.GenerateByte();}
|
|
||||||
|
|
||||||
bool Equal(Element a, Element b) const
|
|
||||||
{return a==b;}
|
|
||||||
|
|
||||||
Element Zero() const
|
|
||||||
{return 0;}
|
|
||||||
|
|
||||||
Element Add(Element a, Element b) const
|
|
||||||
{return a^b;}
|
|
||||||
|
|
||||||
Element& Accumulate(Element &a, Element b) const
|
|
||||||
{return a^=b;}
|
|
||||||
|
|
||||||
Element Inverse(Element a) const
|
|
||||||
{return a;}
|
|
||||||
|
|
||||||
Element Subtract(Element a, Element b) const
|
|
||||||
{return a^b;}
|
|
||||||
|
|
||||||
Element& Reduce(Element &a, Element b) const
|
|
||||||
{return a^=b;}
|
|
||||||
|
|
||||||
Element Double(Element a) const
|
|
||||||
{return 0;}
|
|
||||||
|
|
||||||
Element One() const
|
|
||||||
{return 1;}
|
|
||||||
|
|
||||||
Element Multiply(Element a, Element b) const;
|
|
||||||
|
|
||||||
Element Square(Element a) const
|
|
||||||
{return Multiply(a, a);}
|
|
||||||
|
|
||||||
bool IsUnit(Element a) const
|
|
||||||
{return a != 0;}
|
|
||||||
|
|
||||||
Element MultiplicativeInverse(Element a) const;
|
|
||||||
|
|
||||||
Element Divide(Element a, Element b) const
|
|
||||||
{return Multiply(a, MultiplicativeInverse(b));}
|
|
||||||
|
|
||||||
private:
|
|
||||||
word m_modulus;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,99 +0,0 @@
|
||||||
// gf2_32.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "gf2_32.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
GF2_32::Element GF2_32::Multiply(Element a, Element b) const
|
|
||||||
{
|
|
||||||
word32 table[4];
|
|
||||||
table[0] = 0;
|
|
||||||
table[1] = m_modulus;
|
|
||||||
if (a & 0x80000000)
|
|
||||||
{
|
|
||||||
table[2] = m_modulus ^ (a<<1);
|
|
||||||
table[3] = a<<1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
table[2] = a<<1;
|
|
||||||
table[3] = m_modulus ^ (a<<1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CRYPTOPP_FAST_ROTATE(32)
|
|
||||||
b = rotrFixed(b, 30U);
|
|
||||||
word32 result = table[b&2];
|
|
||||||
|
|
||||||
for (int i=29; i>=0; --i)
|
|
||||||
{
|
|
||||||
b = rotlFixed(b, 1U);
|
|
||||||
result = (result<<1) ^ table[(b&2) + (result>>31)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (b&1) ? result ^ a : result;
|
|
||||||
#else
|
|
||||||
word32 result = table[(b>>30) & 2];
|
|
||||||
|
|
||||||
for (int i=29; i>=0; --i)
|
|
||||||
result = (result<<1) ^ table[((b>>i)&2) + (result>>31)];
|
|
||||||
|
|
||||||
return (b&1) ? result ^ a : result;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
GF2_32::Element GF2_32::MultiplicativeInverse(Element a) const
|
|
||||||
{
|
|
||||||
if (a <= 1) // 1 is a special case
|
|
||||||
return a;
|
|
||||||
|
|
||||||
// warning - don't try to adapt this algorithm for another situation
|
|
||||||
word32 g0=m_modulus, g1=a, g2=a;
|
|
||||||
word32 v0=0, v1=1, v2=1;
|
|
||||||
|
|
||||||
assert(g1);
|
|
||||||
|
|
||||||
while (!(g2 & 0x80000000))
|
|
||||||
{
|
|
||||||
g2 <<= 1;
|
|
||||||
v2 <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
g2 <<= 1;
|
|
||||||
v2 <<= 1;
|
|
||||||
|
|
||||||
g0 ^= g2;
|
|
||||||
v0 ^= v2;
|
|
||||||
|
|
||||||
while (g0 != 1)
|
|
||||||
{
|
|
||||||
if (g1 < g0 || ((g0^g1) < g0 && (g0^g1) < g1))
|
|
||||||
{
|
|
||||||
assert(BitPrecision(g1) <= BitPrecision(g0));
|
|
||||||
g2 = g1;
|
|
||||||
v2 = v1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(BitPrecision(g1) > BitPrecision(g0));
|
|
||||||
g2 = g0; g0 = g1; g1 = g2;
|
|
||||||
v2 = v0; v0 = v1; v1 = v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((g0^g2) >= g2)
|
|
||||||
{
|
|
||||||
assert(BitPrecision(g0) > BitPrecision(g2));
|
|
||||||
g2 <<= 1;
|
|
||||||
v2 <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(BitPrecision(g0) == BitPrecision(g2));
|
|
||||||
g0 ^= g2;
|
|
||||||
v0 ^= v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return v0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,66 +0,0 @@
|
||||||
#ifndef CRYPTOPP_GF2_32_H
|
|
||||||
#define CRYPTOPP_GF2_32_H
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! GF(2^32) with polynomial basis
|
|
||||||
class GF2_32
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef word32 Element;
|
|
||||||
typedef int RandomizationParameter;
|
|
||||||
|
|
||||||
GF2_32(word32 modulus=0x0000008D) : m_modulus(modulus) {}
|
|
||||||
|
|
||||||
Element RandomElement(RandomNumberGenerator &rng, int ignored = 0) const
|
|
||||||
{return rng.GenerateWord32();}
|
|
||||||
|
|
||||||
bool Equal(Element a, Element b) const
|
|
||||||
{return a==b;}
|
|
||||||
|
|
||||||
Element Identity() const
|
|
||||||
{return 0;}
|
|
||||||
|
|
||||||
Element Add(Element a, Element b) const
|
|
||||||
{return a^b;}
|
|
||||||
|
|
||||||
Element& Accumulate(Element &a, Element b) const
|
|
||||||
{return a^=b;}
|
|
||||||
|
|
||||||
Element Inverse(Element a) const
|
|
||||||
{return a;}
|
|
||||||
|
|
||||||
Element Subtract(Element a, Element b) const
|
|
||||||
{return a^b;}
|
|
||||||
|
|
||||||
Element& Reduce(Element &a, Element b) const
|
|
||||||
{return a^=b;}
|
|
||||||
|
|
||||||
Element Double(Element a) const
|
|
||||||
{return 0;}
|
|
||||||
|
|
||||||
Element MultiplicativeIdentity() const
|
|
||||||
{return 1;}
|
|
||||||
|
|
||||||
Element Multiply(Element a, Element b) const;
|
|
||||||
|
|
||||||
Element Square(Element a) const
|
|
||||||
{return Multiply(a, a);}
|
|
||||||
|
|
||||||
bool IsUnit(Element a) const
|
|
||||||
{return a != 0;}
|
|
||||||
|
|
||||||
Element MultiplicativeInverse(Element a) const;
|
|
||||||
|
|
||||||
Element Divide(Element a, Element b) const
|
|
||||||
{return Multiply(a, MultiplicativeInverse(b));}
|
|
||||||
|
|
||||||
private:
|
|
||||||
word32 m_modulus;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,882 +0,0 @@
|
||||||
// gf2n.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "gf2n.h"
|
|
||||||
#include "algebra.h"
|
|
||||||
#include "words.h"
|
|
||||||
#include "randpool.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "oids.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
PolynomialMod2::PolynomialMod2()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2::PolynomialMod2(word value, size_t bitLength)
|
|
||||||
: reg(BitsToWords(bitLength))
|
|
||||||
{
|
|
||||||
assert(value==0 || reg.size()>0);
|
|
||||||
|
|
||||||
if (reg.size() > 0)
|
|
||||||
{
|
|
||||||
reg[0] = value;
|
|
||||||
SetWords(reg+1, 0, reg.size()-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2::PolynomialMod2(const PolynomialMod2& t)
|
|
||||||
: reg(t.reg.size())
|
|
||||||
{
|
|
||||||
CopyWords(reg, t.reg, reg.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits)
|
|
||||||
{
|
|
||||||
const size_t nbytes = nbits/8 + 1;
|
|
||||||
SecByteBlock buf(nbytes);
|
|
||||||
rng.GenerateBlock(buf, nbytes);
|
|
||||||
buf[0] = (byte)Crop(buf[0], nbits % 8);
|
|
||||||
Decode(buf, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength)
|
|
||||||
{
|
|
||||||
PolynomialMod2 result((word)0, bitLength);
|
|
||||||
SetWords(result.reg, ~(word)0, result.reg.size());
|
|
||||||
if (bitLength%WORD_BITS)
|
|
||||||
result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::SetBit(size_t n, int value)
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
reg.CleanGrow(n/WORD_BITS + 1);
|
|
||||||
reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (n/WORD_BITS < reg.size())
|
|
||||||
reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte PolynomialMod2::GetByte(size_t n) const
|
|
||||||
{
|
|
||||||
if (n/WORD_SIZE >= reg.size())
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::SetByte(size_t n, byte value)
|
|
||||||
{
|
|
||||||
reg.CleanGrow(BytesToWords(n+1));
|
|
||||||
reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
|
|
||||||
reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Monomial(size_t i)
|
|
||||||
{
|
|
||||||
PolynomialMod2 r((word)0, i+1);
|
|
||||||
r.SetBit(i);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2)
|
|
||||||
{
|
|
||||||
PolynomialMod2 r((word)0, t0+1);
|
|
||||||
r.SetBit(t0);
|
|
||||||
r.SetBit(t1);
|
|
||||||
r.SetBit(t2);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4)
|
|
||||||
{
|
|
||||||
PolynomialMod2 r((word)0, t0+1);
|
|
||||||
r.SetBit(t0);
|
|
||||||
r.SetBit(t1);
|
|
||||||
r.SetBit(t2);
|
|
||||||
r.SetBit(t3);
|
|
||||||
r.SetBit(t4);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <word i>
|
|
||||||
struct NewPolynomialMod2
|
|
||||||
{
|
|
||||||
PolynomialMod2 * operator()() const
|
|
||||||
{
|
|
||||||
return new PolynomialMod2(i);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const PolynomialMod2 &PolynomialMod2::Zero()
|
|
||||||
{
|
|
||||||
return Singleton<PolynomialMod2>().Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
const PolynomialMod2 &PolynomialMod2::One()
|
|
||||||
{
|
|
||||||
return Singleton<PolynomialMod2, NewPolynomialMod2<1> >().Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::Decode(const byte *input, size_t inputLen)
|
|
||||||
{
|
|
||||||
StringStore store(input, inputLen);
|
|
||||||
Decode(store, inputLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::Encode(byte *output, size_t outputLen) const
|
|
||||||
{
|
|
||||||
ArraySink sink(output, outputLen);
|
|
||||||
Encode(sink, outputLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen)
|
|
||||||
{
|
|
||||||
reg.CleanNew(BytesToWords(inputLen));
|
|
||||||
|
|
||||||
for (size_t i=inputLen; i > 0; i--)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
bt.Get(b);
|
|
||||||
reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const
|
|
||||||
{
|
|
||||||
for (size_t i=outputLen; i > 0; i--)
|
|
||||||
bt.Put(GetByte(i-1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const
|
|
||||||
{
|
|
||||||
DERGeneralEncoder enc(bt, OCTET_STRING);
|
|
||||||
Encode(enc, length);
|
|
||||||
enc.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length)
|
|
||||||
{
|
|
||||||
BERGeneralDecoder dec(bt, OCTET_STRING);
|
|
||||||
if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
|
|
||||||
BERDecodeError();
|
|
||||||
Decode(dec, length);
|
|
||||||
dec.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int PolynomialMod2::WordCount() const
|
|
||||||
{
|
|
||||||
return (unsigned int)CountWords(reg, reg.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int PolynomialMod2::ByteCount() const
|
|
||||||
{
|
|
||||||
unsigned wordCount = WordCount();
|
|
||||||
if (wordCount)
|
|
||||||
return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int PolynomialMod2::BitCount() const
|
|
||||||
{
|
|
||||||
unsigned wordCount = WordCount();
|
|
||||||
if (wordCount)
|
|
||||||
return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int PolynomialMod2::Parity() const
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
word temp=0;
|
|
||||||
for (i=0; i<reg.size(); i++)
|
|
||||||
temp ^= reg[i];
|
|
||||||
return CryptoPP::Parity(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2& PolynomialMod2::operator=(const PolynomialMod2& t)
|
|
||||||
{
|
|
||||||
reg.Assign(t.reg);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2& PolynomialMod2::operator^=(const PolynomialMod2& t)
|
|
||||||
{
|
|
||||||
reg.CleanGrow(t.reg.size());
|
|
||||||
XorWords(reg, t.reg, t.reg.size());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Xor(const PolynomialMod2 &b) const
|
|
||||||
{
|
|
||||||
if (b.reg.size() >= reg.size())
|
|
||||||
{
|
|
||||||
PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS);
|
|
||||||
XorWords(result.reg, reg, b.reg, reg.size());
|
|
||||||
CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PolynomialMod2 result((word)0, reg.size()*WORD_BITS);
|
|
||||||
XorWords(result.reg, reg, b.reg, b.reg.size());
|
|
||||||
CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const
|
|
||||||
{
|
|
||||||
PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size()));
|
|
||||||
AndWords(result.reg, reg, b.reg, result.reg.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const
|
|
||||||
{
|
|
||||||
PolynomialMod2 result((word)0, BitCount() + b.BitCount());
|
|
||||||
|
|
||||||
for (int i=b.Degree(); i>=0; i--)
|
|
||||||
{
|
|
||||||
result <<= 1;
|
|
||||||
if (b[i])
|
|
||||||
XorWords(result.reg, reg, reg.size());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Squared() const
|
|
||||||
{
|
|
||||||
static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85};
|
|
||||||
|
|
||||||
PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS);
|
|
||||||
|
|
||||||
for (unsigned i=0; i<reg.size(); i++)
|
|
||||||
{
|
|
||||||
unsigned j;
|
|
||||||
|
|
||||||
for (j=0; j<WORD_BITS; j+=8)
|
|
||||||
result.reg[2*i] |= map[(reg[i] >> (j/2)) % 16] << j;
|
|
||||||
|
|
||||||
for (j=0; j<WORD_BITS; j+=8)
|
|
||||||
result.reg[2*i+1] |= map[(reg[i] >> (j/2 + WORD_BITS/2)) % 16] << j;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 "ient,
|
|
||||||
const PolynomialMod2 ÷nd, const PolynomialMod2 &divisor)
|
|
||||||
{
|
|
||||||
if (!divisor)
|
|
||||||
throw PolynomialMod2::DivideByZero();
|
|
||||||
|
|
||||||
int degree = divisor.Degree();
|
|
||||||
remainder.reg.CleanNew(BitsToWords(degree+1));
|
|
||||||
if (dividend.BitCount() >= divisor.BitCount())
|
|
||||||
quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1));
|
|
||||||
else
|
|
||||||
quotient.reg.CleanNew(0);
|
|
||||||
|
|
||||||
for (int i=dividend.Degree(); i>=0; i--)
|
|
||||||
{
|
|
||||||
remainder <<= 1;
|
|
||||||
remainder.reg[0] |= dividend[i];
|
|
||||||
if (remainder[degree])
|
|
||||||
{
|
|
||||||
remainder -= divisor;
|
|
||||||
quotient.SetBit(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const
|
|
||||||
{
|
|
||||||
PolynomialMod2 remainder, quotient;
|
|
||||||
PolynomialMod2::Divide(remainder, quotient, *this, b);
|
|
||||||
return quotient;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const
|
|
||||||
{
|
|
||||||
PolynomialMod2 remainder, quotient;
|
|
||||||
PolynomialMod2::Divide(remainder, quotient, *this, b);
|
|
||||||
return remainder;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n)
|
|
||||||
{
|
|
||||||
if (!reg.size())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
word u;
|
|
||||||
word carry=0;
|
|
||||||
word *r=reg;
|
|
||||||
|
|
||||||
if (n==1) // special case code for most frequent case
|
|
||||||
{
|
|
||||||
i = (int)reg.size();
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
u = *r;
|
|
||||||
*r = (u << 1) | carry;
|
|
||||||
carry = u >> (WORD_BITS-1);
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (carry)
|
|
||||||
{
|
|
||||||
reg.Grow(reg.size()+1);
|
|
||||||
reg[reg.size()-1] = carry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
int shiftWords = n / WORD_BITS;
|
|
||||||
int shiftBits = n % WORD_BITS;
|
|
||||||
|
|
||||||
if (shiftBits)
|
|
||||||
{
|
|
||||||
i = (int)reg.size();
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
u = *r;
|
|
||||||
*r = (u << shiftBits) | carry;
|
|
||||||
carry = u >> (WORD_BITS-shiftBits);
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (carry)
|
|
||||||
{
|
|
||||||
reg.Grow(reg.size()+shiftWords+1);
|
|
||||||
reg[reg.size()-1] = carry;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
reg.Grow(reg.size()+shiftWords);
|
|
||||||
|
|
||||||
if (shiftWords)
|
|
||||||
{
|
|
||||||
for (i = (int)reg.size()-1; i>=shiftWords; i--)
|
|
||||||
reg[i] = reg[i-shiftWords];
|
|
||||||
for (; i>=0; i--)
|
|
||||||
reg[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n)
|
|
||||||
{
|
|
||||||
if (!reg.size())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
int shiftWords = n / WORD_BITS;
|
|
||||||
int shiftBits = n % WORD_BITS;
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
word u;
|
|
||||||
word carry=0;
|
|
||||||
word *r=reg+reg.size()-1;
|
|
||||||
|
|
||||||
if (shiftBits)
|
|
||||||
{
|
|
||||||
i = reg.size();
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
u = *r;
|
|
||||||
*r = (u >> shiftBits) | carry;
|
|
||||||
carry = u << (WORD_BITS-shiftBits);
|
|
||||||
r--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shiftWords)
|
|
||||||
{
|
|
||||||
for (i=0; i<reg.size()-shiftWords; i++)
|
|
||||||
reg[i] = reg[i+shiftWords];
|
|
||||||
for (; i<reg.size(); i++)
|
|
||||||
reg[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::operator<<(unsigned int n) const
|
|
||||||
{
|
|
||||||
PolynomialMod2 result(*this);
|
|
||||||
return result<<=n;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::operator>>(unsigned int n) const
|
|
||||||
{
|
|
||||||
PolynomialMod2 result(*this);
|
|
||||||
return result>>=n;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PolynomialMod2::operator!() const
|
|
||||||
{
|
|
||||||
for (unsigned i=0; i<reg.size(); i++)
|
|
||||||
if (reg[i]) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PolynomialMod2::Equals(const PolynomialMod2 &rhs) const
|
|
||||||
{
|
|
||||||
size_t i, smallerSize = STDMIN(reg.size(), rhs.reg.size());
|
|
||||||
|
|
||||||
for (i=0; i<smallerSize; i++)
|
|
||||||
if (reg[i] != rhs.reg[i]) return false;
|
|
||||||
|
|
||||||
for (i=smallerSize; i<reg.size(); i++)
|
|
||||||
if (reg[i] != 0) return false;
|
|
||||||
|
|
||||||
for (i=smallerSize; i<rhs.reg.size(); i++)
|
|
||||||
if (rhs.reg[i] != 0) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a)
|
|
||||||
{
|
|
||||||
// Get relevant conversion specifications from ostream.
|
|
||||||
long f = out.flags() & std::ios::basefield; // Get base digits.
|
|
||||||
int bits, block;
|
|
||||||
char suffix;
|
|
||||||
switch(f)
|
|
||||||
{
|
|
||||||
case std::ios::oct :
|
|
||||||
bits = 3;
|
|
||||||
block = 4;
|
|
||||||
suffix = 'o';
|
|
||||||
break;
|
|
||||||
case std::ios::hex :
|
|
||||||
bits = 4;
|
|
||||||
block = 2;
|
|
||||||
suffix = 'h';
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
bits = 1;
|
|
||||||
block = 8;
|
|
||||||
suffix = 'b';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!a)
|
|
||||||
return out << '0' << suffix;
|
|
||||||
|
|
||||||
SecBlock<char> s(a.BitCount()/bits+1);
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
static const char upper[]="0123456789ABCDEF";
|
|
||||||
static const char lower[]="0123456789abcdef";
|
|
||||||
const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
|
|
||||||
|
|
||||||
for (i=0; i*bits < a.BitCount(); i++)
|
|
||||||
{
|
|
||||||
int digit=0;
|
|
||||||
for (int j=0; j<bits; j++)
|
|
||||||
digit |= a[i*bits+j] << j;
|
|
||||||
s[i]=vec[digit];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
out << s[i];
|
|
||||||
if (i && (i%block)==0)
|
|
||||||
out << ',';
|
|
||||||
}
|
|
||||||
|
|
||||||
return out << suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::Gcd(const PolynomialMod2 &a, const PolynomialMod2 &b)
|
|
||||||
{
|
|
||||||
return EuclideanDomainOf<PolynomialMod2>().Gcd(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const
|
|
||||||
{
|
|
||||||
typedef EuclideanDomainOf<PolynomialMod2> Domain;
|
|
||||||
return QuotientRing<Domain>(Domain(), modulus).MultiplicativeInverse(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PolynomialMod2::IsIrreducible() const
|
|
||||||
{
|
|
||||||
signed int d = Degree();
|
|
||||||
if (d <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
PolynomialMod2 t(2), u(t);
|
|
||||||
for (int i=1; i<=d/2; i++)
|
|
||||||
{
|
|
||||||
u = u.Squared()%(*this);
|
|
||||||
if (!Gcd(u+t, *this).IsUnit())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
GF2NP::GF2NP(const PolynomialMod2 &modulus)
|
|
||||||
: QuotientRing<EuclideanDomainOf<PolynomialMod2> >(EuclideanDomainOf<PolynomialMod2>(), modulus), m(modulus.Degree())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GF2NP::Element GF2NP::SquareRoot(const Element &a) const
|
|
||||||
{
|
|
||||||
Element r = a;
|
|
||||||
for (unsigned int i=1; i<m; i++)
|
|
||||||
r = Square(r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
GF2NP::Element GF2NP::HalfTrace(const Element &a) const
|
|
||||||
{
|
|
||||||
assert(m%2 == 1);
|
|
||||||
Element h = a;
|
|
||||||
for (unsigned int i=1; i<=(m-1)/2; i++)
|
|
||||||
h = Add(Square(Square(h)), a);
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
GF2NP::Element GF2NP::SolveQuadraticEquation(const Element &a) const
|
|
||||||
{
|
|
||||||
if (m%2 == 0)
|
|
||||||
{
|
|
||||||
Element z, w;
|
|
||||||
RandomPool rng;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Element p((RandomNumberGenerator &)rng, m);
|
|
||||||
z = PolynomialMod2::Zero();
|
|
||||||
w = p;
|
|
||||||
for (unsigned int i=1; i<=m-1; i++)
|
|
||||||
{
|
|
||||||
w = Square(w);
|
|
||||||
z = Square(z);
|
|
||||||
Accumulate(z, Multiply(w, a));
|
|
||||||
Accumulate(w, p);
|
|
||||||
}
|
|
||||||
} while (w.IsZero());
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return HalfTrace(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************************************
|
|
||||||
|
|
||||||
GF2NT::GF2NT(unsigned int t0, unsigned int t1, unsigned int t2)
|
|
||||||
: GF2NP(PolynomialMod2::Trinomial(t0, t1, t2))
|
|
||||||
, t0(t0), t1(t1)
|
|
||||||
, result((word)0, m)
|
|
||||||
{
|
|
||||||
assert(t0 > t1 && t1 > t2 && t2==0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const
|
|
||||||
{
|
|
||||||
if (t0-t1 < WORD_BITS)
|
|
||||||
return GF2NP::MultiplicativeInverse(a);
|
|
||||||
|
|
||||||
SecWordBlock T(m_modulus.reg.size() * 4);
|
|
||||||
word *b = T;
|
|
||||||
word *c = T+m_modulus.reg.size();
|
|
||||||
word *f = T+2*m_modulus.reg.size();
|
|
||||||
word *g = T+3*m_modulus.reg.size();
|
|
||||||
size_t bcLen=1, fgLen=m_modulus.reg.size();
|
|
||||||
unsigned int k=0;
|
|
||||||
|
|
||||||
SetWords(T, 0, 3*m_modulus.reg.size());
|
|
||||||
b[0]=1;
|
|
||||||
assert(a.reg.size() <= m_modulus.reg.size());
|
|
||||||
CopyWords(f, a.reg, a.reg.size());
|
|
||||||
CopyWords(g, m_modulus.reg, m_modulus.reg.size());
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
word t=f[0];
|
|
||||||
while (!t)
|
|
||||||
{
|
|
||||||
ShiftWordsRightByWords(f, fgLen, 1);
|
|
||||||
if (c[bcLen-1])
|
|
||||||
bcLen++;
|
|
||||||
assert(bcLen <= m_modulus.reg.size());
|
|
||||||
ShiftWordsLeftByWords(c, bcLen, 1);
|
|
||||||
k+=WORD_BITS;
|
|
||||||
t=f[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int i=0;
|
|
||||||
while (t%2 == 0)
|
|
||||||
{
|
|
||||||
t>>=1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
k+=i;
|
|
||||||
|
|
||||||
if (t==1 && CountWords(f, fgLen)==1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i==1)
|
|
||||||
{
|
|
||||||
ShiftWordsRightByBits(f, fgLen, 1);
|
|
||||||
t=ShiftWordsLeftByBits(c, bcLen, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ShiftWordsRightByBits(f, fgLen, i);
|
|
||||||
t=ShiftWordsLeftByBits(c, bcLen, i);
|
|
||||||
}
|
|
||||||
if (t)
|
|
||||||
{
|
|
||||||
c[bcLen] = t;
|
|
||||||
bcLen++;
|
|
||||||
assert(bcLen <= m_modulus.reg.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f[fgLen-1]==0 && g[fgLen-1]==0)
|
|
||||||
fgLen--;
|
|
||||||
|
|
||||||
if (f[fgLen-1] < g[fgLen-1])
|
|
||||||
{
|
|
||||||
std::swap(f, g);
|
|
||||||
std::swap(b, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
XorWords(f, g, fgLen);
|
|
||||||
XorWords(b, c, bcLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (k >= WORD_BITS)
|
|
||||||
{
|
|
||||||
word temp = b[0];
|
|
||||||
// right shift b
|
|
||||||
for (unsigned i=0; i+1<BitsToWords(m); i++)
|
|
||||||
b[i] = b[i+1];
|
|
||||||
b[BitsToWords(m)-1] = 0;
|
|
||||||
|
|
||||||
if (t1 < WORD_BITS)
|
|
||||||
for (unsigned int j=0; j<WORD_BITS-t1; j++)
|
|
||||||
temp ^= ((temp >> j) & 1) << (t1 + j);
|
|
||||||
else
|
|
||||||
b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
|
|
||||||
|
|
||||||
if (t1 % WORD_BITS)
|
|
||||||
b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
|
|
||||||
|
|
||||||
if (t0%WORD_BITS)
|
|
||||||
{
|
|
||||||
b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
|
|
||||||
b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
b[t0/WORD_BITS-1] ^= temp;
|
|
||||||
|
|
||||||
k -= WORD_BITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k)
|
|
||||||
{
|
|
||||||
word temp = b[0] << (WORD_BITS - k);
|
|
||||||
ShiftWordsRightByBits(b, BitsToWords(m), k);
|
|
||||||
|
|
||||||
if (t1 < WORD_BITS)
|
|
||||||
for (unsigned int j=0; j<WORD_BITS-t1; j++)
|
|
||||||
temp ^= ((temp >> j) & 1) << (t1 + j);
|
|
||||||
else
|
|
||||||
b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
|
|
||||||
|
|
||||||
if (t1 % WORD_BITS)
|
|
||||||
b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
|
|
||||||
|
|
||||||
if (t0%WORD_BITS)
|
|
||||||
{
|
|
||||||
b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
|
|
||||||
b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
b[t0/WORD_BITS-1] ^= temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
CopyWords(result.reg.begin(), b, result.reg.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
size_t aSize = STDMIN(a.reg.size(), result.reg.size());
|
|
||||||
Element r((word)0, m);
|
|
||||||
|
|
||||||
for (int i=m-1; i>=0; i--)
|
|
||||||
{
|
|
||||||
if (r[m-1])
|
|
||||||
{
|
|
||||||
ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
|
|
||||||
XorWords(r.reg.begin(), m_modulus.reg, r.reg.size());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
|
|
||||||
|
|
||||||
if (b[i])
|
|
||||||
XorWords(r.reg.begin(), a.reg, aSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m%WORD_BITS)
|
|
||||||
r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS);
|
|
||||||
|
|
||||||
CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const GF2NT::Element& GF2NT::Reduced(const Element &a) const
|
|
||||||
{
|
|
||||||
if (t0-t1 < WORD_BITS)
|
|
||||||
return m_domain.Mod(a, m_modulus);
|
|
||||||
|
|
||||||
SecWordBlock b(a.reg);
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
for (i=b.size()-1; i>=BitsToWords(t0); i--)
|
|
||||||
{
|
|
||||||
word temp = b[i];
|
|
||||||
|
|
||||||
if (t0%WORD_BITS)
|
|
||||||
{
|
|
||||||
b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
|
|
||||||
b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
b[i-t0/WORD_BITS] ^= temp;
|
|
||||||
|
|
||||||
if ((t0-t1)%WORD_BITS)
|
|
||||||
{
|
|
||||||
b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
|
|
||||||
b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
b[i-(t0-t1)/WORD_BITS] ^= temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i==BitsToWords(t0)-1 && t0%WORD_BITS)
|
|
||||||
{
|
|
||||||
word mask = ((word)1<<(t0%WORD_BITS))-1;
|
|
||||||
word temp = b[i] & ~mask;
|
|
||||||
b[i] &= mask;
|
|
||||||
|
|
||||||
b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
|
|
||||||
|
|
||||||
if ((t0-t1)%WORD_BITS)
|
|
||||||
{
|
|
||||||
b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
|
|
||||||
if ((t0-t1)%WORD_BITS > t0%WORD_BITS)
|
|
||||||
b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
|
|
||||||
else
|
|
||||||
assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
b[i-(t0-t1)/WORD_BITS] ^= temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWords(result.reg.begin(), 0, result.reg.size());
|
|
||||||
CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const
|
|
||||||
{
|
|
||||||
a.DEREncodeAsOctetString(out, MaxElementByteLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const
|
|
||||||
{
|
|
||||||
a.BERDecodeAsOctetString(in, MaxElementByteLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GF2NT::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
ASN1::characteristic_two_field().DEREncode(seq);
|
|
||||||
DERSequenceEncoder parameters(seq);
|
|
||||||
DEREncodeUnsigned(parameters, m);
|
|
||||||
ASN1::tpBasis().DEREncode(parameters);
|
|
||||||
DEREncodeUnsigned(parameters, t1);
|
|
||||||
parameters.MessageEnd();
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GF2NPP::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
ASN1::characteristic_two_field().DEREncode(seq);
|
|
||||||
DERSequenceEncoder parameters(seq);
|
|
||||||
DEREncodeUnsigned(parameters, m);
|
|
||||||
ASN1::ppBasis().DEREncode(parameters);
|
|
||||||
DERSequenceEncoder pentanomial(parameters);
|
|
||||||
DEREncodeUnsigned(pentanomial, t3);
|
|
||||||
DEREncodeUnsigned(pentanomial, t2);
|
|
||||||
DEREncodeUnsigned(pentanomial, t1);
|
|
||||||
pentanomial.MessageEnd();
|
|
||||||
parameters.MessageEnd();
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
// VC60 workaround: auto_ptr lacks reset()
|
|
||||||
member_ptr<GF2NP> result;
|
|
||||||
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
if (OID(seq) != ASN1::characteristic_two_field())
|
|
||||||
BERDecodeError();
|
|
||||||
BERSequenceDecoder parameters(seq);
|
|
||||||
unsigned int m;
|
|
||||||
BERDecodeUnsigned(parameters, m);
|
|
||||||
OID oid(parameters);
|
|
||||||
if (oid == ASN1::tpBasis())
|
|
||||||
{
|
|
||||||
unsigned int t1;
|
|
||||||
BERDecodeUnsigned(parameters, t1);
|
|
||||||
result.reset(new GF2NT(m, t1, 0));
|
|
||||||
}
|
|
||||||
else if (oid == ASN1::ppBasis())
|
|
||||||
{
|
|
||||||
unsigned int t1, t2, t3;
|
|
||||||
BERSequenceDecoder pentanomial(parameters);
|
|
||||||
BERDecodeUnsigned(pentanomial, t3);
|
|
||||||
BERDecodeUnsigned(pentanomial, t2);
|
|
||||||
BERDecodeUnsigned(pentanomial, t1);
|
|
||||||
pentanomial.MessageEnd();
|
|
||||||
result.reset(new GF2NPP(m, t3, t2, t1, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BERDecodeError();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
parameters.MessageEnd();
|
|
||||||
seq.MessageEnd();
|
|
||||||
|
|
||||||
return result.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,369 +0,0 @@
|
||||||
#ifndef CRYPTOPP_GF2N_H
|
|
||||||
#define CRYPTOPP_GF2N_H
|
|
||||||
|
|
||||||
/*! \file */
|
|
||||||
|
|
||||||
#include "cryptlib.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "algebra.h"
|
|
||||||
|
|
||||||
#include <iosfwd>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Polynomial with Coefficients in GF(2)
|
|
||||||
/*! \nosubgrouping */
|
|
||||||
class CRYPTOPP_DLL PolynomialMod2
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS
|
|
||||||
//@{
|
|
||||||
//! divide by zero exception
|
|
||||||
class DivideByZero : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef unsigned int RandomizationParameter;
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name CREATORS
|
|
||||||
//@{
|
|
||||||
//! creates the zero polynomial
|
|
||||||
PolynomialMod2();
|
|
||||||
//! copy constructor
|
|
||||||
PolynomialMod2(const PolynomialMod2& t);
|
|
||||||
|
|
||||||
//! convert from word
|
|
||||||
/*! value should be encoded with the least significant bit as coefficient to x^0
|
|
||||||
and most significant bit as coefficient to x^(WORD_BITS-1)
|
|
||||||
bitLength denotes how much memory to allocate initially
|
|
||||||
*/
|
|
||||||
PolynomialMod2(word value, size_t bitLength=WORD_BITS);
|
|
||||||
|
|
||||||
//! convert from big-endian byte array
|
|
||||||
PolynomialMod2(const byte *encodedPoly, size_t byteCount)
|
|
||||||
{Decode(encodedPoly, byteCount);}
|
|
||||||
|
|
||||||
//! convert from big-endian form stored in a BufferedTransformation
|
|
||||||
PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount)
|
|
||||||
{Decode(encodedPoly, byteCount);}
|
|
||||||
|
|
||||||
//! create a random polynomial uniformly distributed over all polynomials with degree less than bitcount
|
|
||||||
PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount)
|
|
||||||
{Randomize(rng, bitcount);}
|
|
||||||
|
|
||||||
//! return x^i
|
|
||||||
static PolynomialMod2 CRYPTOPP_API Monomial(size_t i);
|
|
||||||
//! return x^t0 + x^t1 + x^t2
|
|
||||||
static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2);
|
|
||||||
//! return x^t0 + x^t1 + x^t2 + x^t3 + x^t4
|
|
||||||
static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4);
|
|
||||||
//! return x^(n-1) + ... + x + 1
|
|
||||||
static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n);
|
|
||||||
|
|
||||||
//!
|
|
||||||
static const PolynomialMod2 & CRYPTOPP_API Zero();
|
|
||||||
//!
|
|
||||||
static const PolynomialMod2 & CRYPTOPP_API One();
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name ENCODE/DECODE
|
|
||||||
//@{
|
|
||||||
//! minimum number of bytes to encode this polynomial
|
|
||||||
/*! MinEncodedSize of 0 is 1 */
|
|
||||||
unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());}
|
|
||||||
|
|
||||||
//! encode in big-endian format
|
|
||||||
/*! if outputLen < MinEncodedSize, the most significant bytes will be dropped
|
|
||||||
if outputLen > MinEncodedSize, the most significant bytes will be padded
|
|
||||||
*/
|
|
||||||
void Encode(byte *output, size_t outputLen) const;
|
|
||||||
//!
|
|
||||||
void Encode(BufferedTransformation &bt, size_t outputLen) const;
|
|
||||||
|
|
||||||
//!
|
|
||||||
void Decode(const byte *input, size_t inputLen);
|
|
||||||
//!
|
|
||||||
//* Precondition: bt.MaxRetrievable() >= inputLen
|
|
||||||
void Decode(BufferedTransformation &bt, size_t inputLen);
|
|
||||||
|
|
||||||
//! encode value as big-endian octet string
|
|
||||||
void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const;
|
|
||||||
//! decode value as big-endian octet string
|
|
||||||
void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name ACCESSORS
|
|
||||||
//@{
|
|
||||||
//! number of significant bits = Degree() + 1
|
|
||||||
unsigned int BitCount() const;
|
|
||||||
//! number of significant bytes = ceiling(BitCount()/8)
|
|
||||||
unsigned int ByteCount() const;
|
|
||||||
//! number of significant words = ceiling(ByteCount()/sizeof(word))
|
|
||||||
unsigned int WordCount() const;
|
|
||||||
|
|
||||||
//! return the n-th bit, n=0 being the least significant bit
|
|
||||||
bool GetBit(size_t n) const {return GetCoefficient(n)!=0;}
|
|
||||||
//! return the n-th byte
|
|
||||||
byte GetByte(size_t n) const;
|
|
||||||
|
|
||||||
//! the zero polynomial will return a degree of -1
|
|
||||||
signed int Degree() const {return BitCount()-1;}
|
|
||||||
//! degree + 1
|
|
||||||
unsigned int CoefficientCount() const {return BitCount();}
|
|
||||||
//! return coefficient for x^i
|
|
||||||
int GetCoefficient(size_t i) const
|
|
||||||
{return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;}
|
|
||||||
//! return coefficient for x^i
|
|
||||||
int operator[](unsigned int i) const {return GetCoefficient(i);}
|
|
||||||
|
|
||||||
//!
|
|
||||||
bool IsZero() const {return !*this;}
|
|
||||||
//!
|
|
||||||
bool Equals(const PolynomialMod2 &rhs) const;
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name MANIPULATORS
|
|
||||||
//@{
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator=(const PolynomialMod2& t);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator&=(const PolynomialMod2& t);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator^=(const PolynomialMod2& t);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator+=(const PolynomialMod2& t) {return *this ^= t;}
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator-=(const PolynomialMod2& t) {return *this ^= t;}
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator*=(const PolynomialMod2& t);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator/=(const PolynomialMod2& t);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator%=(const PolynomialMod2& t);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator<<=(unsigned int);
|
|
||||||
//!
|
|
||||||
PolynomialMod2& operator>>=(unsigned int);
|
|
||||||
|
|
||||||
//!
|
|
||||||
void Randomize(RandomNumberGenerator &rng, size_t bitcount);
|
|
||||||
|
|
||||||
//!
|
|
||||||
void SetBit(size_t i, int value = 1);
|
|
||||||
//! set the n-th byte to value
|
|
||||||
void SetByte(size_t n, byte value);
|
|
||||||
|
|
||||||
//!
|
|
||||||
void SetCoefficient(size_t i, int value) {SetBit(i, value);}
|
|
||||||
|
|
||||||
//!
|
|
||||||
void swap(PolynomialMod2 &a) {reg.swap(a.reg);}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name UNARY OPERATORS
|
|
||||||
//@{
|
|
||||||
//!
|
|
||||||
bool operator!() const;
|
|
||||||
//!
|
|
||||||
PolynomialMod2 operator+() const {return *this;}
|
|
||||||
//!
|
|
||||||
PolynomialMod2 operator-() const {return *this;}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name BINARY OPERATORS
|
|
||||||
//@{
|
|
||||||
//!
|
|
||||||
PolynomialMod2 And(const PolynomialMod2 &b) const;
|
|
||||||
//!
|
|
||||||
PolynomialMod2 Xor(const PolynomialMod2 &b) const;
|
|
||||||
//!
|
|
||||||
PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);}
|
|
||||||
//!
|
|
||||||
PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);}
|
|
||||||
//!
|
|
||||||
PolynomialMod2 Times(const PolynomialMod2 &b) const;
|
|
||||||
//!
|
|
||||||
PolynomialMod2 DividedBy(const PolynomialMod2 &b) const;
|
|
||||||
//!
|
|
||||||
PolynomialMod2 Modulo(const PolynomialMod2 &b) const;
|
|
||||||
|
|
||||||
//!
|
|
||||||
PolynomialMod2 operator>>(unsigned int n) const;
|
|
||||||
//!
|
|
||||||
PolynomialMod2 operator<<(unsigned int n) const;
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name OTHER ARITHMETIC FUNCTIONS
|
|
||||||
//@{
|
|
||||||
//! sum modulo 2 of all coefficients
|
|
||||||
unsigned int Parity() const;
|
|
||||||
|
|
||||||
//! check for irreducibility
|
|
||||||
bool IsIrreducible() const;
|
|
||||||
|
|
||||||
//! is always zero since we're working modulo 2
|
|
||||||
PolynomialMod2 Doubled() const {return Zero();}
|
|
||||||
//!
|
|
||||||
PolynomialMod2 Squared() const;
|
|
||||||
|
|
||||||
//! only 1 is a unit
|
|
||||||
bool IsUnit() const {return Equals(One());}
|
|
||||||
//! return inverse if *this is a unit, otherwise return 0
|
|
||||||
PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();}
|
|
||||||
|
|
||||||
//! greatest common divisor
|
|
||||||
static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n);
|
|
||||||
//! calculate multiplicative inverse of *this mod n
|
|
||||||
PolynomialMod2 InverseMod(const PolynomialMod2 &) const;
|
|
||||||
|
|
||||||
//! calculate r and q such that (a == d*q + r) && (deg(r) < deg(d))
|
|
||||||
static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//! \name INPUT/OUTPUT
|
|
||||||
//@{
|
|
||||||
//!
|
|
||||||
friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class GF2NT;
|
|
||||||
|
|
||||||
SecWordBlock reg;
|
|
||||||
};
|
|
||||||
|
|
||||||
//!
|
|
||||||
inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
|
|
||||||
{return a.Equals(b);}
|
|
||||||
//!
|
|
||||||
inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
|
|
||||||
{return !(a==b);}
|
|
||||||
//! compares degree
|
|
||||||
inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
|
|
||||||
{return a.Degree() > b.Degree();}
|
|
||||||
//! compares degree
|
|
||||||
inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
|
|
||||||
{return a.Degree() >= b.Degree();}
|
|
||||||
//! compares degree
|
|
||||||
inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
|
|
||||||
{return a.Degree() < b.Degree();}
|
|
||||||
//! compares degree
|
|
||||||
inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b)
|
|
||||||
{return a.Degree() <= b.Degree();}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);}
|
|
||||||
//!
|
|
||||||
inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);}
|
|
||||||
|
|
||||||
// CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations,
|
|
||||||
// but before the use of QuotientRing<EuclideanDomainOf<PolynomialMod2> > for VC .NET 2003
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup<PolynomialMod2>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing<PolynomialMod2>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain<PolynomialMod2>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf<PolynomialMod2>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing<EuclideanDomainOf<PolynomialMod2> >;
|
|
||||||
|
|
||||||
//! GF(2^n) with Polynomial Basis
|
|
||||||
class CRYPTOPP_DLL GF2NP : public QuotientRing<EuclideanDomainOf<PolynomialMod2> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GF2NP(const PolynomialMod2 &modulus);
|
|
||||||
|
|
||||||
virtual GF2NP * Clone() const {return new GF2NP(*this);}
|
|
||||||
virtual void DEREncode(BufferedTransformation &bt) const
|
|
||||||
{assert(false);} // no ASN.1 syntax yet for general polynomial basis
|
|
||||||
|
|
||||||
void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
|
|
||||||
void BERDecodeElement(BufferedTransformation &in, Element &a) const;
|
|
||||||
|
|
||||||
bool Equal(const Element &a, const Element &b) const
|
|
||||||
{assert(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);}
|
|
||||||
|
|
||||||
bool IsUnit(const Element &a) const
|
|
||||||
{assert(a.Degree() < m_modulus.Degree()); return !!a;}
|
|
||||||
|
|
||||||
unsigned int MaxElementBitLength() const
|
|
||||||
{return m;}
|
|
||||||
|
|
||||||
unsigned int MaxElementByteLength() const
|
|
||||||
{return (unsigned int)BitsToBytes(MaxElementBitLength());}
|
|
||||||
|
|
||||||
Element SquareRoot(const Element &a) const;
|
|
||||||
|
|
||||||
Element HalfTrace(const Element &a) const;
|
|
||||||
|
|
||||||
// returns z such that z^2 + z == a
|
|
||||||
Element SolveQuadraticEquation(const Element &a) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
unsigned int m;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! GF(2^n) with Trinomial Basis
|
|
||||||
class CRYPTOPP_DLL GF2NT : public GF2NP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2
|
|
||||||
GF2NT(unsigned int t0, unsigned int t1, unsigned int t2);
|
|
||||||
|
|
||||||
GF2NP * Clone() const {return new GF2NT(*this);}
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
const Element& Multiply(const Element &a, const Element &b) const;
|
|
||||||
|
|
||||||
const Element& Square(const Element &a) const
|
|
||||||
{return Reduced(a.Squared());}
|
|
||||||
|
|
||||||
const Element& MultiplicativeInverse(const Element &a) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const Element& Reduced(const Element &a) const;
|
|
||||||
|
|
||||||
unsigned int t0, t1;
|
|
||||||
mutable PolynomialMod2 result;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! GF(2^n) with Pentanomial Basis
|
|
||||||
class CRYPTOPP_DLL GF2NPP : public GF2NP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4
|
|
||||||
GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4)
|
|
||||||
: GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t0(t0), t1(t1), t2(t2), t3(t3) {}
|
|
||||||
|
|
||||||
GF2NP * Clone() const {return new GF2NPP(*this);}
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int t0, t1, t2, t3;
|
|
||||||
};
|
|
||||||
|
|
||||||
// construct new GF2NP from the ASN.1 sequence Characteristic-two
|
|
||||||
CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt);
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#ifndef __BORLANDC__
|
|
||||||
NAMESPACE_BEGIN(std)
|
|
||||||
template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b)
|
|
||||||
{
|
|
||||||
a.swap(b);
|
|
||||||
}
|
|
||||||
NAMESPACE_END
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,273 +0,0 @@
|
||||||
// dsa.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "gfpcrypt.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "oids.h"
|
|
||||||
#include "nbtheory.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void TestInstantiations_gfpcrypt()
|
|
||||||
{
|
|
||||||
GDSA<SHA>::Signer test;
|
|
||||||
GDSA<SHA>::Verifier test1;
|
|
||||||
DSA::Signer test5(NullRNG(), 100);
|
|
||||||
DSA::Signer test2(test5);
|
|
||||||
NR<SHA>::Signer test3;
|
|
||||||
NR<SHA>::Verifier test4;
|
|
||||||
DLIES<>::Encryptor test6;
|
|
||||||
DLIES<>::Decryptor test7;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
|
|
||||||
{
|
|
||||||
Integer p, q, g;
|
|
||||||
|
|
||||||
if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
|
|
||||||
{
|
|
||||||
q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
|
|
||||||
Initialize(p, q, g);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int modulusSize = 1024, defaultSubgroupOrderSize;
|
|
||||||
alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
|
|
||||||
|
|
||||||
switch (modulusSize)
|
|
||||||
{
|
|
||||||
case 1024:
|
|
||||||
defaultSubgroupOrderSize = 160;
|
|
||||||
break;
|
|
||||||
case 2048:
|
|
||||||
defaultSubgroupOrderSize = 224;
|
|
||||||
break;
|
|
||||||
case 3072:
|
|
||||||
defaultSubgroupOrderSize = 256;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw InvalidArgument("DSA: not a valid prime length");
|
|
||||||
}
|
|
||||||
|
|
||||||
DL_GroupParameters_GFP::GenerateRandom(rng, CombinedNameValuePairs(alg, MakeParameters(Name::SubgroupOrderSize(), defaultSubgroupOrderSize, false)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level);
|
|
||||||
int pSize = GetModulus().BitCount(), qSize = GetSubgroupOrder().BitCount();
|
|
||||||
pass = pass && ((pSize==1024 && qSize==160) || (pSize==2048 && qSize==224) || (pSize==2048 && qSize==256) || (pSize==3072 && qSize==256));
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
|
||||||
const byte *recoverableMessage, size_t recoverableMessageLength,
|
|
||||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
|
||||||
byte *representative, size_t representativeBitLength) const
|
|
||||||
{
|
|
||||||
assert(recoverableMessageLength == 0);
|
|
||||||
assert(hashIdentifier.second == 0);
|
|
||||||
const size_t representativeByteLength = BitsToBytes(representativeBitLength);
|
|
||||||
const size_t digestSize = hash.DigestSize();
|
|
||||||
const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
|
|
||||||
|
|
||||||
memset(representative, 0, paddingLength);
|
|
||||||
hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
|
|
||||||
|
|
||||||
if (digestSize*8 > representativeBitLength)
|
|
||||||
{
|
|
||||||
Integer h(representative, representativeByteLength);
|
|
||||||
h >>= representativeByteLength*8 - representativeBitLength;
|
|
||||||
h.Encode(representative, representativeByteLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_SignatureMessageEncodingMethod_NR::ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
|
||||||
const byte *recoverableMessage, size_t recoverableMessageLength,
|
|
||||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
|
||||||
byte *representative, size_t representativeBitLength) const
|
|
||||||
{
|
|
||||||
assert(recoverableMessageLength == 0);
|
|
||||||
assert(hashIdentifier.second == 0);
|
|
||||||
const size_t representativeByteLength = BitsToBytes(representativeBitLength);
|
|
||||||
const size_t digestSize = hash.DigestSize();
|
|
||||||
const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize);
|
|
||||||
|
|
||||||
memset(representative, 0, paddingLength);
|
|
||||||
hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize));
|
|
||||||
|
|
||||||
if (digestSize*8 >= representativeBitLength)
|
|
||||||
{
|
|
||||||
Integer h(representative, representativeByteLength);
|
|
||||||
h >>= representativeByteLength*8 - representativeBitLength + 1;
|
|
||||||
h.Encode(representative, representativeByteLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
|
|
||||||
{
|
|
||||||
const Integer &p = GetModulus(), &q = GetSubgroupOrder();
|
|
||||||
|
|
||||||
bool pass = true;
|
|
||||||
pass = pass && p > Integer::One() && p.IsOdd();
|
|
||||||
pass = pass && q > Integer::One() && q.IsOdd();
|
|
||||||
|
|
||||||
if (level >= 1)
|
|
||||||
pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero();
|
|
||||||
if (level >= 2)
|
|
||||||
pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2);
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation<Integer> *gpc) const
|
|
||||||
{
|
|
||||||
const Integer &p = GetModulus(), &q = GetSubgroupOrder();
|
|
||||||
|
|
||||||
bool pass = true;
|
|
||||||
pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative();
|
|
||||||
pass = pass && g < p && !IsIdentity(g);
|
|
||||||
|
|
||||||
if (level >= 1)
|
|
||||||
{
|
|
||||||
if (gpc)
|
|
||||||
pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g;
|
|
||||||
}
|
|
||||||
if (level >= 2)
|
|
||||||
{
|
|
||||||
if (GetFieldType() == 2)
|
|
||||||
pass = pass && Jacobi(g*g-4, p)==-1;
|
|
||||||
|
|
||||||
// verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly
|
|
||||||
// and at most 1 bit is leaked if it's false
|
|
||||||
bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable();
|
|
||||||
|
|
||||||
if (fullValidate && pass)
|
|
||||||
{
|
|
||||||
Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q);
|
|
||||||
pass = pass && IsIdentity(gp);
|
|
||||||
}
|
|
||||||
else if (GetFieldType() == 1)
|
|
||||||
pass = pass && Jacobi(g, p) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
|
|
||||||
{
|
|
||||||
Integer p, q, g;
|
|
||||||
|
|
||||||
if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g))
|
|
||||||
{
|
|
||||||
q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int modulusSize, subgroupOrderSize;
|
|
||||||
|
|
||||||
if (!alg.GetIntValue("ModulusSize", modulusSize))
|
|
||||||
modulusSize = alg.GetIntValueWithDefault("KeySize", 2048);
|
|
||||||
|
|
||||||
if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize))
|
|
||||||
subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize);
|
|
||||||
|
|
||||||
PrimeAndGenerator pg;
|
|
||||||
pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize);
|
|
||||||
p = pg.Prime();
|
|
||||||
q = pg.SubPrime();
|
|
||||||
g = pg.Generator();
|
|
||||||
}
|
|
||||||
|
|
||||||
Initialize(p, q, g);
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const
|
|
||||||
{
|
|
||||||
Integer g(encoded, GetModulus().ByteCount());
|
|
||||||
if (!ValidateElement(1, g, NULL))
|
|
||||||
throw DL_BadElement();
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder parameters(bt);
|
|
||||||
Integer p(parameters);
|
|
||||||
Integer q(parameters);
|
|
||||||
Integer g;
|
|
||||||
if (parameters.EndReached())
|
|
||||||
{
|
|
||||||
g = q;
|
|
||||||
q = ComputeGroupOrder(p) / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
g.BERDecode(parameters);
|
|
||||||
parameters.MessageEnd();
|
|
||||||
|
|
||||||
SetModulusAndSubgroupGenerator(p, g);
|
|
||||||
SetSubgroupOrder(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder parameters(bt);
|
|
||||||
GetModulus().DEREncode(parameters);
|
|
||||||
m_q.DEREncode(parameters);
|
|
||||||
GetSubgroupGenerator().DEREncode(parameters);
|
|
||||||
parameters.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
return GetValueHelper<DL_GroupParameters<Element> >(this, name, valueType, pValue)
|
|
||||||
CRYPTOPP_GET_FUNCTION_ENTRY(Modulus);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source)
|
|
||||||
{
|
|
||||||
AssignFromHelper(this, source)
|
|
||||||
CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator)
|
|
||||||
CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const
|
|
||||||
{
|
|
||||||
return ASN1::id_dsa();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
|
|
||||||
{
|
|
||||||
ModularArithmetic ma(GetModulus());
|
|
||||||
ma.SimultaneousExponentiate(results, base, exponents, exponentsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const
|
|
||||||
{
|
|
||||||
return a_times_b_mod_c(a, b, GetModulus());
|
|
||||||
}
|
|
||||||
|
|
||||||
DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const
|
|
||||||
{
|
|
||||||
ModularArithmetic ma(GetModulus());
|
|
||||||
return ma.CascadeExponentiate(element1, exponent1, element2, exponent2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const
|
|
||||||
{
|
|
||||||
return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount())));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const
|
|
||||||
{
|
|
||||||
return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,528 +0,0 @@
|
||||||
#ifndef CRYPTOPP_GFPCRYPT_H
|
|
||||||
#define CRYPTOPP_GFPCRYPT_H
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
Implementation of schemes based on DL over GF(p)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pubkey.h"
|
|
||||||
#include "modexppc.h"
|
|
||||||
#include "sha.h"
|
|
||||||
#include "algparam.h"
|
|
||||||
#include "asn.h"
|
|
||||||
#include "smartptr.h"
|
|
||||||
#include "hmac.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> >
|
|
||||||
{
|
|
||||||
typedef DL_GroupParameters_IntegerBased ThisClass;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Initialize(const DL_GroupParameters_IntegerBased ¶ms)
|
|
||||||
{Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
|
|
||||||
void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
|
|
||||||
{GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
|
|
||||||
void Initialize(const Integer &p, const Integer &g)
|
|
||||||
{SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
|
|
||||||
void Initialize(const Integer &p, const Integer &q, const Integer &g)
|
|
||||||
{SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
|
|
||||||
|
|
||||||
// ASN1Object interface
|
|
||||||
void BERDecode(BufferedTransformation &bt);
|
|
||||||
void DEREncode(BufferedTransformation &bt) const;
|
|
||||||
|
|
||||||
// GeneratibleCryptoMaterial interface
|
|
||||||
/*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
|
|
||||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
|
||||||
void AssignFrom(const NameValuePairs &source);
|
|
||||||
|
|
||||||
// DL_GroupParameters
|
|
||||||
const Integer & GetSubgroupOrder() const {return m_q;}
|
|
||||||
Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
|
|
||||||
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
|
|
||||||
bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
|
|
||||||
bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
|
|
||||||
void EncodeElement(bool reversible, const Element &element, byte *encoded) const
|
|
||||||
{element.Encode(encoded, GetModulus().ByteCount());}
|
|
||||||
unsigned int GetEncodedElementSize(bool reversible) const {return GetModulus().ByteCount();}
|
|
||||||
Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
|
|
||||||
Integer ConvertElementToInteger(const Element &element) const
|
|
||||||
{return element;}
|
|
||||||
Integer GetMaxExponent() const;
|
|
||||||
static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
|
|
||||||
|
|
||||||
OID GetAlgorithmID() const;
|
|
||||||
|
|
||||||
virtual const Integer & GetModulus() const =0;
|
|
||||||
virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
|
|
||||||
|
|
||||||
void SetSubgroupOrder(const Integer &q)
|
|
||||||
{m_q = q; ParametersChanged();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Integer ComputeGroupOrder(const Integer &modulus) const
|
|
||||||
{return modulus-(GetFieldType() == 1 ? 1 : -1);}
|
|
||||||
|
|
||||||
// GF(p) = 1, GF(p^2) = 2
|
|
||||||
virtual int GetFieldType() const =0;
|
|
||||||
virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Integer m_q;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> >
|
|
||||||
class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
|
|
||||||
{
|
|
||||||
typedef DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> ThisClass;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename GROUP_PRECOMP::Element Element;
|
|
||||||
|
|
||||||
// GeneratibleCryptoMaterial interface
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
|
|
||||||
|
|
||||||
void AssignFrom(const NameValuePairs &source)
|
|
||||||
{AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
|
|
||||||
|
|
||||||
// DL_GroupParameters
|
|
||||||
const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
|
|
||||||
DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
|
|
||||||
|
|
||||||
// IntegerGroupParameters
|
|
||||||
const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
|
|
||||||
const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
|
|
||||||
|
|
||||||
void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together
|
|
||||||
{this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
|
|
||||||
|
|
||||||
// non-inherited
|
|
||||||
bool operator==(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
|
|
||||||
{return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
|
|
||||||
bool operator!=(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
|
|
||||||
{return !operator==(rhs);}
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>;
|
|
||||||
|
|
||||||
//! GF(p) group parameters
|
|
||||||
class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// DL_GroupParameters
|
|
||||||
bool IsIdentity(const Integer &element) const {return element == Integer::One();}
|
|
||||||
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
|
||||||
|
|
||||||
// NameValuePairs interface
|
|
||||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
|
||||||
{
|
|
||||||
return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// used by MQV
|
|
||||||
Element MultiplyElements(const Element &a, const Element &b) const;
|
|
||||||
Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int GetFieldType() const {return 1;}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! GF(p) group parameters that default to same primes
|
|
||||||
class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef NoCofactorMultiplication DefaultCofactorOption;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! GDSA algorithm
|
|
||||||
template <class T>
|
|
||||||
class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
|
|
||||||
|
|
||||||
void Sign(const DL_GroupParameters<T> ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
|
|
||||||
{
|
|
||||||
const Integer &q = params.GetSubgroupOrder();
|
|
||||||
r %= q;
|
|
||||||
Integer kInv = k.InverseMod(q);
|
|
||||||
s = (kInv * (x*r + e)) % q;
|
|
||||||
assert(!!r && !!s);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Verify(const DL_GroupParameters<T> ¶ms, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
|
|
||||||
{
|
|
||||||
const Integer &q = params.GetSubgroupOrder();
|
|
||||||
if (r>=q || r<1 || s>=q || s<1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Integer w = s.InverseMod(q);
|
|
||||||
Integer u1 = (e * w) % q;
|
|
||||||
Integer u2 = (r * w) % q;
|
|
||||||
// verify r == (g^u1 * y^u2 mod p) mod q
|
|
||||||
return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
|
|
||||||
|
|
||||||
//! NR algorithm
|
|
||||||
template <class T>
|
|
||||||
class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";}
|
|
||||||
|
|
||||||
void Sign(const DL_GroupParameters<T> ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
|
|
||||||
{
|
|
||||||
const Integer &q = params.GetSubgroupOrder();
|
|
||||||
r = (r + e) % q;
|
|
||||||
s = (k - x*r) % q;
|
|
||||||
assert(!!r);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Verify(const DL_GroupParameters<T> ¶ms, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
|
|
||||||
{
|
|
||||||
const Integer &q = params.GetSubgroupOrder();
|
|
||||||
if (r>=q || r<1 || s>=q)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// check r == (m_g^s * m_y^r + m) mod m_q
|
|
||||||
return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! DSA public key format is defined in 7.3.3 of RFC 2459. The
|
|
||||||
private key format is defined in 12.9 of PKCS #11 v2.10. */
|
|
||||||
template <class GP>
|
|
||||||
class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &y)
|
|
||||||
{this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
|
|
||||||
void Initialize(const Integer &p, const Integer &g, const Integer &y)
|
|
||||||
{this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
|
|
||||||
void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
|
|
||||||
{this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
|
|
||||||
|
|
||||||
// X509PublicKey
|
|
||||||
void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
|
|
||||||
{this->SetPublicElement(Integer(bt));}
|
|
||||||
void DEREncodePublicKey(BufferedTransformation &bt) const
|
|
||||||
{this->GetPublicElement().DEREncode(bt);}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DL private key (in GF(p) groups)
|
|
||||||
template <class GP>
|
|
||||||
class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
|
|
||||||
{this->GenerateRandomWithKeySize(rng, modulusBits);}
|
|
||||||
void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
|
|
||||||
{this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
|
|
||||||
void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
|
|
||||||
{this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
|
|
||||||
void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &x)
|
|
||||||
{this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
|
|
||||||
void Initialize(const Integer &p, const Integer &g, const Integer &x)
|
|
||||||
{this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
|
|
||||||
void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
|
|
||||||
{this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DL signing/verification keys (in GF(p) groups)
|
|
||||||
struct DL_SignatureKeys_GFP
|
|
||||||
{
|
|
||||||
typedef DL_GroupParameters_GFP GroupParameters;
|
|
||||||
typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
|
|
||||||
typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DL encryption/decryption keys (in GF(p) groups)
|
|
||||||
struct DL_CryptoKeys_GFP
|
|
||||||
{
|
|
||||||
typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
|
|
||||||
typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
|
|
||||||
typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
|
|
||||||
template <class BASE>
|
|
||||||
class DL_PublicKey_GFP_OldFormat : public BASE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
Integer v1(seq);
|
|
||||||
Integer v2(seq);
|
|
||||||
Integer v3(seq);
|
|
||||||
|
|
||||||
if (seq.EndReached())
|
|
||||||
{
|
|
||||||
this->AccessGroupParameters().Initialize(v1, v1/2, v2);
|
|
||||||
this->SetPublicElement(v3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Integer v4(seq);
|
|
||||||
this->AccessGroupParameters().Initialize(v1, v2, v3);
|
|
||||||
this->SetPublicElement(v4);
|
|
||||||
}
|
|
||||||
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
this->GetGroupParameters().GetModulus().DEREncode(seq);
|
|
||||||
if (this->GetGroupParameters().GetCofactor() != 2)
|
|
||||||
this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
|
|
||||||
this->GetGroupParameters().GetGenerator().DEREncode(seq);
|
|
||||||
this->GetPublicElement().DEREncode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
|
|
||||||
template <class BASE>
|
|
||||||
class DL_PrivateKey_GFP_OldFormat : public BASE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void BERDecode(BufferedTransformation &bt)
|
|
||||||
{
|
|
||||||
BERSequenceDecoder seq(bt);
|
|
||||||
Integer v1(seq);
|
|
||||||
Integer v2(seq);
|
|
||||||
Integer v3(seq);
|
|
||||||
Integer v4(seq);
|
|
||||||
|
|
||||||
if (seq.EndReached())
|
|
||||||
{
|
|
||||||
this->AccessGroupParameters().Initialize(v1, v1/2, v2);
|
|
||||||
this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Integer v5(seq);
|
|
||||||
this->AccessGroupParameters().Initialize(v1, v2, v3);
|
|
||||||
this->SetPrivateExponent(v5);
|
|
||||||
}
|
|
||||||
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DEREncode(BufferedTransformation &bt) const
|
|
||||||
{
|
|
||||||
DERSequenceEncoder seq(bt);
|
|
||||||
this->GetGroupParameters().GetModulus().DEREncode(seq);
|
|
||||||
if (this->GetGroupParameters().GetCofactor() != 2)
|
|
||||||
this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
|
|
||||||
this->GetGroupParameters().GetGenerator().DEREncode(seq);
|
|
||||||
this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq);
|
|
||||||
this->GetPrivateExponent().DEREncode(seq);
|
|
||||||
seq.MessageEnd();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
|
|
||||||
template <class H>
|
|
||||||
struct GDSA : public DL_SS<
|
|
||||||
DL_SignatureKeys_GFP,
|
|
||||||
DL_Algorithm_GDSA<Integer>,
|
|
||||||
DL_SignatureMessageEncodingMethod_DSA,
|
|
||||||
H>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#NR">NR</a>
|
|
||||||
template <class H>
|
|
||||||
struct NR : public DL_SS<
|
|
||||||
DL_SignatureKeys_GFP,
|
|
||||||
DL_Algorithm_NR<Integer>,
|
|
||||||
DL_SignatureMessageEncodingMethod_NR,
|
|
||||||
H>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard
|
|
||||||
class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*! also checks that the lengths of p and q are allowed by the DSA standard */
|
|
||||||
bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
|
|
||||||
/*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
|
|
||||||
/*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
|
|
||||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
|
|
||||||
|
|
||||||
static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
|
|
||||||
{return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
|
|
||||||
|
|
||||||
enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class H>
|
|
||||||
class DSA2;
|
|
||||||
|
|
||||||
//! DSA keys
|
|
||||||
struct DL_Keys_DSA
|
|
||||||
{
|
|
||||||
typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
|
|
||||||
typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> > PrivateKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3
|
|
||||||
// class named DSA2 instead of DSA for backwards compatibility (DSA was a non-template class)
|
|
||||||
template <class H>
|
|
||||||
class DSA2 : public DL_SS<
|
|
||||||
DL_Keys_DSA,
|
|
||||||
DL_Algorithm_GDSA<Integer>,
|
|
||||||
DL_SignatureMessageEncodingMethod_DSA,
|
|
||||||
H,
|
|
||||||
DSA2<H> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! DSA with SHA-1, typedef'd for backwards compatibility
|
|
||||||
typedef DSA2<SHA> DSA;
|
|
||||||
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
|
|
||||||
CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> >;
|
|
||||||
|
|
||||||
//! the XOR encryption method, for use with DL-based cryptosystems
|
|
||||||
template <class MAC, bool DHAES_MODE>
|
|
||||||
class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
|
|
||||||
size_t GetSymmetricKeyLength(size_t plaintextLength) const
|
|
||||||
{return plaintextLength + MAC::DEFAULT_KEYLENGTH;}
|
|
||||||
size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
|
|
||||||
{return plaintextLength + MAC::DIGESTSIZE;}
|
|
||||||
size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
|
|
||||||
{return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);}
|
|
||||||
void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
const byte *cipherKey, *macKey;
|
|
||||||
if (DHAES_MODE)
|
|
||||||
{
|
|
||||||
macKey = key;
|
|
||||||
cipherKey = key + MAC::DEFAULT_KEYLENGTH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cipherKey = key;
|
|
||||||
macKey = key + plaintextLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstByteArrayParameter encodingParameters;
|
|
||||||
parameters.GetValue(Name::EncodingParameters(), encodingParameters);
|
|
||||||
|
|
||||||
xorbuf(ciphertext, plaintext, cipherKey, plaintextLength);
|
|
||||||
MAC mac(macKey);
|
|
||||||
mac.Update(ciphertext, plaintextLength);
|
|
||||||
mac.Update(encodingParameters.begin(), encodingParameters.size());
|
|
||||||
if (DHAES_MODE)
|
|
||||||
{
|
|
||||||
byte L[8] = {0,0,0,0};
|
|
||||||
PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
|
|
||||||
mac.Update(L, 8);
|
|
||||||
}
|
|
||||||
mac.Final(ciphertext + plaintextLength);
|
|
||||||
}
|
|
||||||
DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength);
|
|
||||||
const byte *cipherKey, *macKey;
|
|
||||||
if (DHAES_MODE)
|
|
||||||
{
|
|
||||||
macKey = key;
|
|
||||||
cipherKey = key + MAC::DEFAULT_KEYLENGTH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cipherKey = key;
|
|
||||||
macKey = key + plaintextLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstByteArrayParameter encodingParameters;
|
|
||||||
parameters.GetValue(Name::EncodingParameters(), encodingParameters);
|
|
||||||
|
|
||||||
MAC mac(macKey);
|
|
||||||
mac.Update(ciphertext, plaintextLength);
|
|
||||||
mac.Update(encodingParameters.begin(), encodingParameters.size());
|
|
||||||
if (DHAES_MODE)
|
|
||||||
{
|
|
||||||
byte L[8] = {0,0,0,0};
|
|
||||||
PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
|
|
||||||
mac.Update(L, 8);
|
|
||||||
}
|
|
||||||
if (!mac.Verify(ciphertext + plaintextLength))
|
|
||||||
return DecodingResult();
|
|
||||||
|
|
||||||
xorbuf(plaintext, ciphertext, cipherKey, plaintextLength);
|
|
||||||
return DecodingResult(plaintextLength);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! _
|
|
||||||
template <class T, bool DHAES_MODE, class KDF>
|
|
||||||
class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;}
|
|
||||||
void Derive(const DL_GroupParameters<T> ¶ms, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs ¶meters) const
|
|
||||||
{
|
|
||||||
SecByteBlock agreedSecret;
|
|
||||||
if (DHAES_MODE)
|
|
||||||
{
|
|
||||||
agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
|
|
||||||
params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
|
|
||||||
params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
agreedSecret.New(params.GetEncodedElementSize(false));
|
|
||||||
params.EncodeElement(false, agreedElement, agreedSecret);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstByteArrayParameter derivationParameters;
|
|
||||||
parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters);
|
|
||||||
KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Discrete Log Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">DLIES</a>
|
|
||||||
template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
|
|
||||||
struct DLIES
|
|
||||||
: public DL_ES<
|
|
||||||
DL_CryptoKeys_GFP,
|
|
||||||
DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
|
|
||||||
DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
|
|
||||||
DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
|
|
||||||
DLIES<> >
|
|
||||||
{
|
|
||||||
static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,65 +0,0 @@
|
||||||
#ifndef CRYPTOPP_GZIP_H
|
|
||||||
#define CRYPTOPP_GZIP_H
|
|
||||||
|
|
||||||
#include "zdeflate.h"
|
|
||||||
#include "zinflate.h"
|
|
||||||
#include "crc.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
/// GZIP Compression (RFC 1952)
|
|
||||||
class Gzip : public Deflator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Gzip(BufferedTransformation *attachment=NULL, unsigned int deflateLevel=DEFAULT_DEFLATE_LEVEL, unsigned int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true)
|
|
||||||
: Deflator(attachment, deflateLevel, log2WindowSize, detectUncompressible) {}
|
|
||||||
Gzip(const NameValuePairs ¶meters, BufferedTransformation *attachment=NULL)
|
|
||||||
: Deflator(parameters, attachment) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
enum {MAGIC1=0x1f, MAGIC2=0x8b, // flags for the header
|
|
||||||
DEFLATED=8, FAST=4, SLOW=2};
|
|
||||||
|
|
||||||
void WritePrestreamHeader();
|
|
||||||
void ProcessUncompressedData(const byte *string, size_t length);
|
|
||||||
void WritePoststreamTail();
|
|
||||||
|
|
||||||
word32 m_totalLen;
|
|
||||||
CRC32 m_crc;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// GZIP Decompression (RFC 1952)
|
|
||||||
class Gunzip : public Inflator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef Inflator::Err Err;
|
|
||||||
class HeaderErr : public Err {public: HeaderErr() : Err(INVALID_DATA_FORMAT, "Gunzip: header decoding error") {}};
|
|
||||||
class TailErr : public Err {public: TailErr() : Err(INVALID_DATA_FORMAT, "Gunzip: tail too short") {}};
|
|
||||||
class CrcErr : public Err {public: CrcErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: CRC check error") {}};
|
|
||||||
class LengthErr : public Err {public: LengthErr() : Err(DATA_INTEGRITY_CHECK_FAILED, "Gunzip: length check error") {}};
|
|
||||||
|
|
||||||
/*! \param repeat decompress multiple compressed streams in series
|
|
||||||
\param autoSignalPropagation 0 to turn off MessageEnd signal
|
|
||||||
*/
|
|
||||||
Gunzip(BufferedTransformation *attachment = NULL, bool repeat = false, int autoSignalPropagation = -1);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
enum {MAGIC1=0x1f, MAGIC2=0x8b, // flags for the header
|
|
||||||
DEFLATED=8};
|
|
||||||
|
|
||||||
enum FLAG_MASKS {
|
|
||||||
CONTINUED=2, EXTRA_FIELDS=4, FILENAME=8, COMMENTS=16, ENCRYPTED=32};
|
|
||||||
|
|
||||||
unsigned int MaxPrestreamHeaderSize() const {return 1024;}
|
|
||||||
void ProcessPrestreamHeader();
|
|
||||||
void ProcessDecompressedData(const byte *string, size_t length);
|
|
||||||
unsigned int MaxPoststreamTailSize() const {return 8;}
|
|
||||||
void ProcessPoststreamTail();
|
|
||||||
|
|
||||||
word32 m_length;
|
|
||||||
CRC32 m_crc;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,44 +0,0 @@
|
||||||
// hex.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "hex.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
static const byte s_vecUpper[] = "0123456789ABCDEF";
|
|
||||||
static const byte s_vecLower[] = "0123456789abcdef";
|
|
||||||
|
|
||||||
void HexEncoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true);
|
|
||||||
m_filter->Initialize(CombinedNameValuePairs(
|
|
||||||
parameters,
|
|
||||||
MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 4, true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HexDecoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
|
||||||
{
|
|
||||||
BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs(
|
|
||||||
parameters,
|
|
||||||
MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 4, true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const int *HexDecoder::GetDefaultDecodingLookupArray()
|
|
||||||
{
|
|
||||||
static volatile bool s_initialized = false;
|
|
||||||
static int s_array[256];
|
|
||||||
|
|
||||||
if (!s_initialized)
|
|
||||||
{
|
|
||||||
InitializeDecodingLookupArray(s_array, s_vecUpper, 16, true);
|
|
||||||
s_initialized = true;
|
|
||||||
}
|
|
||||||
return s_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef CRYPTOPP_HEX_H
|
|
||||||
#define CRYPTOPP_HEX_H
|
|
||||||
|
|
||||||
#include "basecode.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! Converts given data to base 16
|
|
||||||
class CRYPTOPP_DLL HexEncoder : public SimpleProxyFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HexEncoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
|
|
||||||
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
|
|
||||||
{
|
|
||||||
IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Decode base 16 data back to bytes
|
|
||||||
class CRYPTOPP_DLL HexDecoder : public BaseN_Decoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HexDecoder(BufferedTransformation *attachment = NULL)
|
|
||||||
: BaseN_Decoder(GetDefaultDecodingLookupArray(), 4, attachment) {}
|
|
||||||
|
|
||||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,86 +0,0 @@
|
||||||
// hmac.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
#include "hmac.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
void HMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &)
|
|
||||||
{
|
|
||||||
AssertValidKeyLength(keylength);
|
|
||||||
|
|
||||||
Restart();
|
|
||||||
|
|
||||||
HashTransformation &hash = AccessHash();
|
|
||||||
unsigned int blockSize = hash.BlockSize();
|
|
||||||
|
|
||||||
if (!blockSize)
|
|
||||||
throw InvalidArgument("HMAC: can only be used with a block-based hash function");
|
|
||||||
|
|
||||||
m_buf.resize(2*AccessHash().BlockSize() + AccessHash().DigestSize());
|
|
||||||
|
|
||||||
if (keylength <= blockSize)
|
|
||||||
memcpy(AccessIpad(), userKey, keylength);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AccessHash().CalculateDigest(AccessIpad(), userKey, keylength);
|
|
||||||
keylength = hash.DigestSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(keylength <= blockSize);
|
|
||||||
memset(AccessIpad()+keylength, 0, blockSize-keylength);
|
|
||||||
|
|
||||||
for (unsigned int i=0; i<blockSize; i++)
|
|
||||||
{
|
|
||||||
AccessOpad()[i] = AccessIpad()[i] ^ 0x5c;
|
|
||||||
AccessIpad()[i] ^= 0x36;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HMAC_Base::KeyInnerHash()
|
|
||||||
{
|
|
||||||
assert(!m_innerHashKeyed);
|
|
||||||
HashTransformation &hash = AccessHash();
|
|
||||||
hash.Update(AccessIpad(), hash.BlockSize());
|
|
||||||
m_innerHashKeyed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HMAC_Base::Restart()
|
|
||||||
{
|
|
||||||
if (m_innerHashKeyed)
|
|
||||||
{
|
|
||||||
AccessHash().Restart();
|
|
||||||
m_innerHashKeyed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HMAC_Base::Update(const byte *input, size_t length)
|
|
||||||
{
|
|
||||||
if (!m_innerHashKeyed)
|
|
||||||
KeyInnerHash();
|
|
||||||
AccessHash().Update(input, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HMAC_Base::TruncatedFinal(byte *mac, size_t size)
|
|
||||||
{
|
|
||||||
ThrowIfInvalidTruncatedSize(size);
|
|
||||||
|
|
||||||
HashTransformation &hash = AccessHash();
|
|
||||||
|
|
||||||
if (!m_innerHashKeyed)
|
|
||||||
KeyInnerHash();
|
|
||||||
hash.Final(AccessInnerHash());
|
|
||||||
|
|
||||||
hash.Update(AccessOpad(), hash.BlockSize());
|
|
||||||
hash.Update(AccessInnerHash(), hash.DigestSize());
|
|
||||||
hash.TruncatedFinal(mac, size);
|
|
||||||
|
|
||||||
m_innerHashKeyed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,61 +0,0 @@
|
||||||
// hmac.h - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_HMAC_H
|
|
||||||
#define CRYPTOPP_HMAC_H
|
|
||||||
|
|
||||||
#include "seckey.h"
|
|
||||||
#include "secblock.h"
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HMAC_Base : public VariableKeyLength<16, 0, INT_MAX>, public MessageAuthenticationCode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HMAC_Base() : m_innerHashKeyed(false) {}
|
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms);
|
|
||||||
|
|
||||||
void Restart();
|
|
||||||
void Update(const byte *input, size_t length);
|
|
||||||
void TruncatedFinal(byte *mac, size_t size);
|
|
||||||
unsigned int OptimalBlockSize() const {return const_cast<HMAC_Base*>(this)->AccessHash().OptimalBlockSize();}
|
|
||||||
unsigned int DigestSize() const {return const_cast<HMAC_Base*>(this)->AccessHash().DigestSize();}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual HashTransformation & AccessHash() =0;
|
|
||||||
byte * AccessIpad() {return m_buf;}
|
|
||||||
byte * AccessOpad() {return m_buf + AccessHash().BlockSize();}
|
|
||||||
byte * AccessInnerHash() {return m_buf + 2*AccessHash().BlockSize();}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void KeyInnerHash();
|
|
||||||
|
|
||||||
SecByteBlock m_buf;
|
|
||||||
bool m_innerHashKeyed;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! <a href="http://www.weidai.com/scan-mirror/mac.html#HMAC">HMAC</a>
|
|
||||||
/*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */
|
|
||||||
template <class T>
|
|
||||||
class HMAC : public MessageAuthenticationCodeImpl<HMAC_Base, HMAC<T> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE)
|
|
||||||
CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE)
|
|
||||||
|
|
||||||
HMAC() {}
|
|
||||||
HMAC(const byte *key, size_t length=HMAC_Base::DEFAULT_KEYLENGTH)
|
|
||||||
{this->SetKey(key, length);}
|
|
||||||
|
|
||||||
static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";}
|
|
||||||
std::string AlgorithmName() const {return std::string("HMAC(") + m_hash.AlgorithmName() + ")";}
|
|
||||||
|
|
||||||
private:
|
|
||||||
HashTransformation & AccessHash() {return m_hash;}
|
|
||||||
|
|
||||||
T m_hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,138 +0,0 @@
|
||||||
// hrtimer.cpp - written and placed in the public domain by Wei Dai
|
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "hrtimer.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include <stddef.h> // for NULL
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
#include <windows.h>
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/times.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
double TimerBase::ConvertTo(TimerWord t, Unit unit)
|
|
||||||
{
|
|
||||||
static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
|
|
||||||
|
|
||||||
assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0]));
|
|
||||||
return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerBase::StartTimer()
|
|
||||||
{
|
|
||||||
m_last = m_start = GetCurrentTimerValue();
|
|
||||||
m_started = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
double TimerBase::ElapsedTimeAsDouble()
|
|
||||||
{
|
|
||||||
if (m_stuckAtZero)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (m_started)
|
|
||||||
{
|
|
||||||
TimerWord now = GetCurrentTimerValue();
|
|
||||||
if (m_last < now) // protect against OS bugs where time goes backwards
|
|
||||||
m_last = now;
|
|
||||||
return ConvertTo(m_last - m_start, m_timerUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
StartTimer();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long TimerBase::ElapsedTime()
|
|
||||||
{
|
|
||||||
double elapsed = ElapsedTimeAsDouble();
|
|
||||||
assert(elapsed <= ULONG_MAX);
|
|
||||||
return (unsigned long)elapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerWord Timer::GetCurrentTimerValue()
|
|
||||||
{
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
LARGE_INTEGER now;
|
|
||||||
if (!QueryPerformanceCounter(&now))
|
|
||||||
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
|
|
||||||
return now.QuadPart;
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
timeval now;
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
|
|
||||||
#else
|
|
||||||
return clock();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerWord Timer::TicksPerSecond()
|
|
||||||
{
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
static LARGE_INTEGER freq = {0};
|
|
||||||
if (freq.QuadPart == 0)
|
|
||||||
{
|
|
||||||
if (!QueryPerformanceFrequency(&freq))
|
|
||||||
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
|
|
||||||
}
|
|
||||||
return freq.QuadPart;
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
return 1000000;
|
|
||||||
#else
|
|
||||||
return CLOCKS_PER_SEC;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #ifndef CRYPTOPP_IMPORTS
|
|
||||||
|
|
||||||
TimerWord ThreadUserTimer::GetCurrentTimerValue()
|
|
||||||
{
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
static bool getCurrentThreadImplemented = true;
|
|
||||||
if (getCurrentThreadImplemented)
|
|
||||||
{
|
|
||||||
FILETIME now, ignored;
|
|
||||||
if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
|
|
||||||
{
|
|
||||||
DWORD lastError = GetLastError();
|
|
||||||
if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
getCurrentThreadImplemented = false;
|
|
||||||
goto GetCurrentThreadNotImplemented;
|
|
||||||
}
|
|
||||||
throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
|
|
||||||
}
|
|
||||||
return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
|
|
||||||
}
|
|
||||||
GetCurrentThreadNotImplemented:
|
|
||||||
return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
tms now;
|
|
||||||
times(&now);
|
|
||||||
return now.tms_utime;
|
|
||||||
#else
|
|
||||||
return clock();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerWord ThreadUserTimer::TicksPerSecond()
|
|
||||||
{
|
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
|
||||||
return 10*1000*1000;
|
|
||||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
|
||||||
static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
|
|
||||||
return ticksPerSecond;
|
|
||||||
#else
|
|
||||||
return CLOCKS_PER_SEC;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
|
@ -1,61 +0,0 @@
|
||||||
#ifndef CRYPTOPP_HRTIMER_H
|
|
||||||
#define CRYPTOPP_HRTIMER_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#ifndef HIGHRES_TIMER_AVAILABLE
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
|
||||||
|
|
||||||
#ifdef HIGHRES_TIMER_AVAILABLE
|
|
||||||
typedef word64 TimerWord;
|
|
||||||
#else
|
|
||||||
typedef clock_t TimerWord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! _
|
|
||||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS};
|
|
||||||
TimerBase(Unit unit, bool stuckAtZero) : m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false) {}
|
|
||||||
|
|
||||||
virtual TimerWord GetCurrentTimerValue() =0; // GetCurrentTime is a macro in MSVC 6.0
|
|
||||||
virtual TimerWord TicksPerSecond() =0; // this is not the resolution, just a conversion factor into seconds
|
|
||||||
|
|
||||||
void StartTimer();
|
|
||||||
double ElapsedTimeAsDouble();
|
|
||||||
unsigned long ElapsedTime();
|
|
||||||
|
|
||||||
private:
|
|
||||||
double ConvertTo(TimerWord t, Unit unit);
|
|
||||||
|
|
||||||
Unit m_timerUnit; // HPUX workaround: m_unit is a system macro on HPUX
|
|
||||||
bool m_stuckAtZero, m_started;
|
|
||||||
TimerWord m_start, m_last;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! measure CPU time spent executing instructions of this thread (if supported by OS)
|
|
||||||
/*! /note This only works correctly on Windows NT or later. On Unix it reports process time, and others wall clock time.
|
|
||||||
*/
|
|
||||||
class ThreadUserTimer : public TimerBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
|
|
||||||
TimerWord GetCurrentTimerValue();
|
|
||||||
TimerWord TicksPerSecond();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! high resolution timer
|
|
||||||
class CRYPTOPP_DLL Timer : public TimerBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {}
|
|
||||||
TimerWord GetCurrentTimerValue();
|
|
||||||
TimerWord TicksPerSecond();
|
|
||||||
};
|
|
||||||
|
|
||||||
NAMESPACE_END
|
|
||||||
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue