Implemented 1.3.2 protocol encryption using CryptoPP, up to Client Status packet (http://wiki.vg/Protocol_FAQ step 14)
git-svn-id: http://mc-server.googlecode.com/svn/trunk@808 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
d5f8701f63
commit
539364846a
139
CryptoPP/3way.cpp
Normal file
139
CryptoPP/3way.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
// 3way.cpp - modifed by Wei Dai from Joan Daemen's 3way.c
|
||||
// The original code and all modifications are in the public domain.
|
||||
|
||||
#include "pch.h"
|
||||
#include "3way.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void ThreeWay_TestInstantiations()
|
||||
{
|
||||
ThreeWay::Encryption x1;
|
||||
ThreeWay::Decryption x2;
|
||||
}
|
||||
|
||||
static const word32 START_E = 0x0b0b; // round constant of first encryption round
|
||||
static const word32 START_D = 0xb1b1; // round constant of first decryption round
|
||||
static const word32 RC_MODULUS = 0x11011;
|
||||
|
||||
static inline word32 reverseBits(word32 a)
|
||||
{
|
||||
a = ((a & 0xAAAAAAAA) >> 1) | ((a & 0x55555555) << 1);
|
||||
a = ((a & 0xCCCCCCCC) >> 2) | ((a & 0x33333333) << 2);
|
||||
return ((a & 0xF0F0F0F0) >> 4) | ((a & 0x0F0F0F0F) << 4);
|
||||
}
|
||||
|
||||
#define mu(a0, a1, a2) \
|
||||
{ \
|
||||
a1 = reverseBits(a1); \
|
||||
word32 t = reverseBits(a0); \
|
||||
a0 = reverseBits(a2); \
|
||||
a2 = t; \
|
||||
}
|
||||
|
||||
#define pi_gamma_pi(a0, a1, a2) \
|
||||
{ \
|
||||
word32 b0, b2; \
|
||||
b2 = rotlFixed(a2, 1U); \
|
||||
b0 = rotlFixed(a0, 22U); \
|
||||
a0 = rotlFixed(b0 ^ (a1|(~b2)), 1U); \
|
||||
a2 = rotlFixed(b2 ^ (b0|(~a1)), 22U);\
|
||||
a1 ^= (b2|(~b0)); \
|
||||
}
|
||||
|
||||
// thanks to Paulo Barreto for this optimized theta()
|
||||
#define theta(a0, a1, a2) \
|
||||
{ \
|
||||
word32 b0, b1, c; \
|
||||
c = a0 ^ a1 ^ a2; \
|
||||
c = rotlFixed(c, 16U) ^ rotlFixed(c, 8U); \
|
||||
b0 = (a0 << 24) ^ (a2 >> 8) ^ (a1 << 8) ^ (a0 >> 24); \
|
||||
b1 = (a1 << 24) ^ (a0 >> 8) ^ (a2 << 8) ^ (a1 >> 24); \
|
||||
a0 ^= c ^ b0; \
|
||||
a1 ^= c ^ b1; \
|
||||
a2 ^= c ^ (b0 >> 16) ^ (b1 << 16); \
|
||||
}
|
||||
|
||||
#define rho(a0, a1, a2) \
|
||||
{ \
|
||||
theta(a0, a1, a2); \
|
||||
pi_gamma_pi(a0, a1, a2); \
|
||||
}
|
||||
|
||||
void ThreeWay::Base::UncheckedSetKey(const byte *uk, unsigned int length, const NameValuePairs ¶ms)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
m_rounds = GetRoundsAndThrowIfInvalid(params, this);
|
||||
|
||||
for (unsigned int i=0; i<3; i++)
|
||||
m_k[i] = (word32)uk[4*i+3] | ((word32)uk[4*i+2]<<8) | ((word32)uk[4*i+1]<<16) | ((word32)uk[4*i]<<24);
|
||||
|
||||
if (!IsForwardTransformation())
|
||||
{
|
||||
theta(m_k[0], m_k[1], m_k[2]);
|
||||
mu(m_k[0], m_k[1], m_k[2]);
|
||||
m_k[0] = ByteReverse(m_k[0]);
|
||||
m_k[1] = ByteReverse(m_k[1]);
|
||||
m_k[2] = ByteReverse(m_k[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreeWay::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
||||
|
||||
word32 a0, a1, a2;
|
||||
Block::Get(inBlock)(a0)(a1)(a2);
|
||||
|
||||
word32 rc = START_E;
|
||||
|
||||
for(unsigned i=0; i<m_rounds; i++)
|
||||
{
|
||||
a0 ^= m_k[0] ^ (rc<<16);
|
||||
a1 ^= m_k[1];
|
||||
a2 ^= m_k[2] ^ rc;
|
||||
rho(a0, a1, a2);
|
||||
|
||||
rc <<= 1;
|
||||
if (rc&0x10000) rc ^= 0x11011;
|
||||
}
|
||||
a0 ^= m_k[0] ^ (rc<<16);
|
||||
a1 ^= m_k[1];
|
||||
a2 ^= m_k[2] ^ rc;
|
||||
theta(a0, a1, a2);
|
||||
|
||||
Block::Put(xorBlock, outBlock)(a0)(a1)(a2);
|
||||
}
|
||||
|
||||
void ThreeWay::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
typedef BlockGetAndPut<word32, LittleEndian> Block;
|
||||
|
||||
word32 a0, a1, a2;
|
||||
Block::Get(inBlock)(a0)(a1)(a2);
|
||||
|
||||
word32 rc = START_D;
|
||||
|
||||
mu(a0, a1, a2);
|
||||
for(unsigned i=0; i<m_rounds; i++)
|
||||
{
|
||||
a0 ^= m_k[0] ^ (rc<<16);
|
||||
a1 ^= m_k[1];
|
||||
a2 ^= m_k[2] ^ rc;
|
||||
rho(a0, a1, a2);
|
||||
|
||||
rc <<= 1;
|
||||
if (rc&0x10000) rc ^= 0x11011;
|
||||
}
|
||||
a0 ^= m_k[0] ^ (rc<<16);
|
||||
a1 ^= m_k[1];
|
||||
a2 ^= m_k[2] ^ rc;
|
||||
theta(a0, a1, a2);
|
||||
mu(a0, a1, a2);
|
||||
|
||||
Block::Put(xorBlock, outBlock)(a0)(a1)(a2);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
53
CryptoPP/3way.h
Normal file
53
CryptoPP/3way.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef CRYPTOPP_THREEWAY_H
|
||||
#define CRYPTOPP_THREEWAY_H
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! _
|
||||
struct ThreeWay_Info : public FixedBlockSize<12>, public FixedKeyLength<12>, public VariableRounds<11>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "3-Way";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#3-Way">3-Way</a>
|
||||
class ThreeWay : public ThreeWay_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<ThreeWay_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
||||
|
||||
protected:
|
||||
unsigned int m_rounds;
|
||||
FixedSizeSecBlock<word32, 3> m_k;
|
||||
};
|
||||
|
||||
class CRYPTOPP_NO_VTABLE Enc : public Base
|
||||
{
|
||||
public:
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
};
|
||||
|
||||
class CRYPTOPP_NO_VTABLE Dec : public Base
|
||||
{
|
||||
public:
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
||||
};
|
||||
|
||||
typedef ThreeWay::Encryption ThreeWayEncryption;
|
||||
typedef ThreeWay::Decryption ThreeWayDecryption;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
1634
CryptoPP/Doxyfile
Normal file
1634
CryptoPP/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
62
CryptoPP/License.txt
Normal file
62
CryptoPP/License.txt
Normal file
@ -0,0 +1,62 @@
|
||||
Compilation Copyright (c) 1995-2010 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
|
||||
|
||||
Permission to use, copy, modify, and distribute this compilation for
|
||||
any purpose, including commercial applications, is hereby granted
|
||||
without fee, subject to the following restrictions:
|
||||
|
||||
1. Any copy or modification of this compilation in any form, except
|
||||
in object code form as part of an application software, must include
|
||||
the above copyright notice and this license.
|
||||
|
||||
2. Users of this software agree that any modification or extension
|
||||
they provide to Wei Dai will be considered public domain and not
|
||||
copyrighted unless it includes an explicit copyright notice.
|
||||
|
||||
3. Wei Dai makes no warranty or representation that the operation of the
|
||||
software in this compilation will be error-free, and Wei Dai is under no
|
||||
obligation to provide any services, by way of maintenance, update, or
|
||||
otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS"
|
||||
WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR
|
||||
DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
4. Users will not use Wei Dai or any other contributor's name in any
|
||||
publicity or advertising, without prior written consent in each case.
|
||||
|
||||
5. Export of this software from the United States may require a
|
||||
specific license from the United States Government. It is the
|
||||
responsibility of any person or organization contemplating export
|
||||
to obtain such a license before exporting.
|
||||
|
||||
6. Certain parts of this software may be protected by patents. It
|
||||
is the users' responsibility to obtain the appropriate
|
||||
licenses before using those parts.
|
||||
|
||||
If this compilation is used in object code form in an application
|
||||
software, acknowledgement of the author is not required but would be
|
||||
appreciated. The contribution of any useful modifications or extensions
|
||||
to Wei Dai is not required but would also be appreciated.
|
444
CryptoPP/Readme.txt
Normal file
444
CryptoPP/Readme.txt
Normal file
@ -0,0 +1,444 @@
|
||||
Crypto++: a C++ Class Library of Cryptographic Schemes
|
||||
Version 5.6.1 (8/9/2010, SVN r520)
|
||||
|
||||
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), 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, 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
|
||||
|
||||
Written by Wei Dai
|
77
CryptoPP/adler32.cpp
Normal file
77
CryptoPP/adler32.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
// 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
|
28
CryptoPP/adler32.h
Normal file
28
CryptoPP/adler32.h
Normal file
@ -0,0 +1,28 @@
|
||||
#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
|
16
CryptoPP/aes.h
Normal file
16
CryptoPP/aes.h
Normal file
@ -0,0 +1,16 @@
|
||||
#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
|
340
CryptoPP/algebra.cpp
Normal file
340
CryptoPP/algebra.cpp
Normal file
@ -0,0 +1,340 @@
|
||||
// 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 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 Add(a1, Inverse(b));
|
||||
}
|
||||
|
||||
template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
|
||||
{
|
||||
return a = Add(a, b);
|
||||
}
|
||||
|
||||
template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
|
||||
{
|
||||
return a = Subtract(a, b);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractRing<T>::Square(const Element &a) const
|
||||
{
|
||||
return 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 Multiply(a1, MultiplicativeInverse(b));
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
|
||||
{
|
||||
Element q;
|
||||
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 (!Equal(g[i1], this->Identity()))
|
||||
{
|
||||
g[i2] = 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 (!Equal(g[i1], 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;
|
||||
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 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] = Add(x,y);
|
||||
else
|
||||
{
|
||||
powerTable[2] = Double(x);
|
||||
powerTable[2*tableSize] = 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 = Double(result);
|
||||
if (power1 || power2)
|
||||
Accumulate(result, powerTable[(power2<<w) + power1]);
|
||||
}
|
||||
while (squaresAfter--)
|
||||
result = 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
|
285
CryptoPP/algebra.h
Normal file
285
CryptoPP/algebra.h
Normal file
@ -0,0 +1,285 @@
|
||||
#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
|
75
CryptoPP/algparam.cpp
Normal file
75
CryptoPP/algparam.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
// 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
|
398
CryptoPP/algparam.h
Normal file
398
CryptoPP/algparam.h
Normal file
@ -0,0 +1,398 @@
|
||||
#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
|
120
CryptoPP/arc4.cpp
Normal file
120
CryptoPP/arc4.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
// arc4.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
// The ARC4 algorithm was first revealed in an anonymous email to the
|
||||
// cypherpunks mailing list. This file originally contained some
|
||||
// code copied from this email. The code has since been rewritten in order
|
||||
// to clarify the copyright status of this file. It should now be
|
||||
// completely in the public domain.
|
||||
|
||||
#include "pch.h"
|
||||
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
|
||||
#include "arc4.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
namespace Weak1 {
|
||||
|
||||
void ARC4_TestInstantiations()
|
||||
{
|
||||
ARC4 x;
|
||||
}
|
||||
|
||||
ARC4_Base::~ARC4_Base()
|
||||
{
|
||||
m_x = m_y = 0;
|
||||
}
|
||||
|
||||
void ARC4_Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs ¶ms)
|
||||
{
|
||||
AssertValidKeyLength(keyLen);
|
||||
|
||||
m_x = 1;
|
||||
m_y = 0;
|
||||
|
||||
unsigned int i;
|
||||
for (i=0; i<256; i++)
|
||||
m_state[i] = i;
|
||||
|
||||
unsigned int keyIndex = 0, stateIndex = 0;
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
unsigned int a = m_state[i];
|
||||
stateIndex += key[keyIndex] + a;
|
||||
stateIndex &= 0xff;
|
||||
m_state[i] = m_state[stateIndex];
|
||||
m_state[stateIndex] = a;
|
||||
if (++keyIndex >= keyLen)
|
||||
keyIndex = 0;
|
||||
}
|
||||
|
||||
int discardBytes = params.GetIntValueWithDefault("DiscardBytes", GetDefaultDiscardBytes());
|
||||
DiscardBytes(discardBytes);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline unsigned int MakeByte(T &x, T &y, byte *s)
|
||||
{
|
||||
unsigned int a = s[x];
|
||||
y = (y+a) & 0xff;
|
||||
unsigned int b = s[y];
|
||||
s[x] = b;
|
||||
s[y] = a;
|
||||
x = (x+1) & 0xff;
|
||||
return s[(a+b) & 0xff];
|
||||
}
|
||||
|
||||
void ARC4_Base::GenerateBlock(byte *output, size_t size)
|
||||
{
|
||||
while (size--)
|
||||
*output++ = MakeByte(m_x, m_y, m_state);
|
||||
}
|
||||
|
||||
void ARC4_Base::ProcessData(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
byte *const s = m_state;
|
||||
unsigned int x = m_x;
|
||||
unsigned int y = m_y;
|
||||
|
||||
if (inString == outString)
|
||||
{
|
||||
do
|
||||
{
|
||||
*outString++ ^= MakeByte(x, y, s);
|
||||
} while (--length);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
*outString++ = *inString++ ^ MakeByte(x, y, s);
|
||||
}
|
||||
while(--length);
|
||||
}
|
||||
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
void ARC4_Base::DiscardBytes(size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
byte *const s = m_state;
|
||||
unsigned int x = m_x;
|
||||
unsigned int y = m_y;
|
||||
|
||||
do
|
||||
{
|
||||
MakeByte(x, y, s);
|
||||
}
|
||||
while(--length);
|
||||
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
}
|
||||
NAMESPACE_END
|
71
CryptoPP/arc4.h
Normal file
71
CryptoPP/arc4.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef CRYPTOPP_ARC4_H
|
||||
#define CRYPTOPP_ARC4_H
|
||||
|
||||
#include "strciphr.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
namespace Weak1 {
|
||||
|
||||
//! _
|
||||
class CRYPTOPP_NO_VTABLE ARC4_Base : public VariableKeyLength<16, 1, 256>, public RandomNumberGenerator, public SymmetricCipher, public SymmetricCipherDocumentation
|
||||
{
|
||||
public:
|
||||
~ARC4_Base();
|
||||
|
||||
static const char *StaticAlgorithmName() {return "ARC4";}
|
||||
|
||||
void GenerateBlock(byte *output, size_t size);
|
||||
void DiscardBytes(size_t n);
|
||||
|
||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
||||
|
||||
bool IsRandomAccess() const {return false;}
|
||||
bool IsSelfInverting() const {return true;}
|
||||
bool IsForwardTransformation() const {return true;}
|
||||
|
||||
typedef SymmetricCipherFinal<ARC4_Base> Encryption;
|
||||
typedef SymmetricCipherFinal<ARC4_Base> Decryption;
|
||||
|
||||
protected:
|
||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
||||
virtual unsigned int GetDefaultDiscardBytes() const {return 0;}
|
||||
|
||||
FixedSizeSecBlock<byte, 256> m_state;
|
||||
byte m_x, m_y;
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/cs.html#RC4">Alleged RC4</a>
|
||||
DOCUMENTED_TYPEDEF(SymmetricCipherFinal<ARC4_Base>, ARC4)
|
||||
|
||||
//! _
|
||||
class CRYPTOPP_NO_VTABLE MARC4_Base : public ARC4_Base
|
||||
{
|
||||
public:
|
||||
static const char *StaticAlgorithmName() {return "MARC4";}
|
||||
|
||||
typedef SymmetricCipherFinal<MARC4_Base> Encryption;
|
||||
typedef SymmetricCipherFinal<MARC4_Base> Decryption;
|
||||
|
||||
protected:
|
||||
unsigned int GetDefaultDiscardBytes() const {return 256;}
|
||||
};
|
||||
|
||||
//! Modified ARC4: it discards the first 256 bytes of keystream which may be weaker than the rest
|
||||
DOCUMENTED_TYPEDEF(SymmetricCipherFinal<MARC4_Base>, MARC4)
|
||||
|
||||
}
|
||||
#if CRYPTOPP_ENABLE_NAMESPACE_WEAK >= 1
|
||||
namespace Weak {using namespace Weak1;} // import Weak1 into CryptoPP::Weak
|
||||
#else
|
||||
using namespace Weak1; // import Weak1 into CryptoPP with warning
|
||||
#ifdef __GNUC__
|
||||
#warning "You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning."
|
||||
#else
|
||||
#pragma message("You may be using a weak algorithm that has been retained for backwards compatibility. Please '#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1' before including this .h file and prepend the class name with 'Weak::' to remove this warning.")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
81
CryptoPP/argnames.h
Normal file
81
CryptoPP/argnames.h
Normal file
@ -0,0 +1,81 @@
|
||||
#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
|
597
CryptoPP/asn.cpp
Normal file
597
CryptoPP/asn.cpp
Normal file
@ -0,0 +1,597 @@
|
||||
// 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
|
369
CryptoPP/asn.h
Normal file
369
CryptoPP/asn.h
Normal file
@ -0,0 +1,369 @@
|
||||
#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
|
180
CryptoPP/authenc.cpp
Normal file
180
CryptoPP/authenc.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
// 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
|
49
CryptoPP/authenc.h
Normal file
49
CryptoPP/authenc.h
Normal file
@ -0,0 +1,49 @@
|
||||
#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
|
39
CryptoPP/base32.cpp
Normal file
39
CryptoPP/base32.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
// 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
|
38
CryptoPP/base32.h
Normal file
38
CryptoPP/base32.h
Normal file
@ -0,0 +1,38 @@
|
||||
#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
|
42
CryptoPP/base64.cpp
Normal file
42
CryptoPP/base64.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// 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
|
36
CryptoPP/base64.h
Normal file
36
CryptoPP/base64.h
Normal file
@ -0,0 +1,36 @@
|
||||
#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
|
238
CryptoPP/basecode.cpp
Normal file
238
CryptoPP/basecode.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
// 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
|
86
CryptoPP/basecode.h
Normal file
86
CryptoPP/basecode.h
Normal file
@ -0,0 +1,86 @@
|
||||
#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
|
277
CryptoPP/bfinit.cpp
Normal file
277
CryptoPP/bfinit.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
#include "pch.h"
|
||||
#include "blowfish.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
const word32 Blowfish::Base::p_init[Blowfish::ROUNDS+2] =
|
||||
{
|
||||
608135816U, 2242054355U, 320440878U, 57701188U,
|
||||
2752067618U, 698298832U, 137296536U, 3964562569U,
|
||||
1160258022U, 953160567U, 3193202383U, 887688300U,
|
||||
3232508343U, 3380367581U, 1065670069U, 3041331479U,
|
||||
2450970073U, 2306472731U
|
||||
} ;
|
||||
|
||||
const word32 Blowfish::Base::s_init[4*256] = {
|
||||
3509652390U, 2564797868U, 805139163U, 3491422135U,
|
||||
3101798381U, 1780907670U, 3128725573U, 4046225305U,
|
||||
614570311U, 3012652279U, 134345442U, 2240740374U,
|
||||
1667834072U, 1901547113U, 2757295779U, 4103290238U,
|
||||
227898511U, 1921955416U, 1904987480U, 2182433518U,
|
||||
2069144605U, 3260701109U, 2620446009U, 720527379U,
|
||||
3318853667U, 677414384U, 3393288472U, 3101374703U,
|
||||
2390351024U, 1614419982U, 1822297739U, 2954791486U,
|
||||
3608508353U, 3174124327U, 2024746970U, 1432378464U,
|
||||
3864339955U, 2857741204U, 1464375394U, 1676153920U,
|
||||
1439316330U, 715854006U, 3033291828U, 289532110U,
|
||||
2706671279U, 2087905683U, 3018724369U, 1668267050U,
|
||||
732546397U, 1947742710U, 3462151702U, 2609353502U,
|
||||
2950085171U, 1814351708U, 2050118529U, 680887927U,
|
||||
999245976U, 1800124847U, 3300911131U, 1713906067U,
|
||||
1641548236U, 4213287313U, 1216130144U, 1575780402U,
|
||||
4018429277U, 3917837745U, 3693486850U, 3949271944U,
|
||||
596196993U, 3549867205U, 258830323U, 2213823033U,
|
||||
772490370U, 2760122372U, 1774776394U, 2652871518U,
|
||||
566650946U, 4142492826U, 1728879713U, 2882767088U,
|
||||
1783734482U, 3629395816U, 2517608232U, 2874225571U,
|
||||
1861159788U, 326777828U, 3124490320U, 2130389656U,
|
||||
2716951837U, 967770486U, 1724537150U, 2185432712U,
|
||||
2364442137U, 1164943284U, 2105845187U, 998989502U,
|
||||
3765401048U, 2244026483U, 1075463327U, 1455516326U,
|
||||
1322494562U, 910128902U, 469688178U, 1117454909U,
|
||||
936433444U, 3490320968U, 3675253459U, 1240580251U,
|
||||
122909385U, 2157517691U, 634681816U, 4142456567U,
|
||||
3825094682U, 3061402683U, 2540495037U, 79693498U,
|
||||
3249098678U, 1084186820U, 1583128258U, 426386531U,
|
||||
1761308591U, 1047286709U, 322548459U, 995290223U,
|
||||
1845252383U, 2603652396U, 3431023940U, 2942221577U,
|
||||
3202600964U, 3727903485U, 1712269319U, 422464435U,
|
||||
3234572375U, 1170764815U, 3523960633U, 3117677531U,
|
||||
1434042557U, 442511882U, 3600875718U, 1076654713U,
|
||||
1738483198U, 4213154764U, 2393238008U, 3677496056U,
|
||||
1014306527U, 4251020053U, 793779912U, 2902807211U,
|
||||
842905082U, 4246964064U, 1395751752U, 1040244610U,
|
||||
2656851899U, 3396308128U, 445077038U, 3742853595U,
|
||||
3577915638U, 679411651U, 2892444358U, 2354009459U,
|
||||
1767581616U, 3150600392U, 3791627101U, 3102740896U,
|
||||
284835224U, 4246832056U, 1258075500U, 768725851U,
|
||||
2589189241U, 3069724005U, 3532540348U, 1274779536U,
|
||||
3789419226U, 2764799539U, 1660621633U, 3471099624U,
|
||||
4011903706U, 913787905U, 3497959166U, 737222580U,
|
||||
2514213453U, 2928710040U, 3937242737U, 1804850592U,
|
||||
3499020752U, 2949064160U, 2386320175U, 2390070455U,
|
||||
2415321851U, 4061277028U, 2290661394U, 2416832540U,
|
||||
1336762016U, 1754252060U, 3520065937U, 3014181293U,
|
||||
791618072U, 3188594551U, 3933548030U, 2332172193U,
|
||||
3852520463U, 3043980520U, 413987798U, 3465142937U,
|
||||
3030929376U, 4245938359U, 2093235073U, 3534596313U,
|
||||
375366246U, 2157278981U, 2479649556U, 555357303U,
|
||||
3870105701U, 2008414854U, 3344188149U, 4221384143U,
|
||||
3956125452U, 2067696032U, 3594591187U, 2921233993U,
|
||||
2428461U, 544322398U, 577241275U, 1471733935U,
|
||||
610547355U, 4027169054U, 1432588573U, 1507829418U,
|
||||
2025931657U, 3646575487U, 545086370U, 48609733U,
|
||||
2200306550U, 1653985193U, 298326376U, 1316178497U,
|
||||
3007786442U, 2064951626U, 458293330U, 2589141269U,
|
||||
3591329599U, 3164325604U, 727753846U, 2179363840U,
|
||||
146436021U, 1461446943U, 4069977195U, 705550613U,
|
||||
3059967265U, 3887724982U, 4281599278U, 3313849956U,
|
||||
1404054877U, 2845806497U, 146425753U, 1854211946U,
|
||||
|
||||
1266315497U, 3048417604U, 3681880366U, 3289982499U,
|
||||
2909710000U, 1235738493U, 2632868024U, 2414719590U,
|
||||
3970600049U, 1771706367U, 1449415276U, 3266420449U,
|
||||
422970021U, 1963543593U, 2690192192U, 3826793022U,
|
||||
1062508698U, 1531092325U, 1804592342U, 2583117782U,
|
||||
2714934279U, 4024971509U, 1294809318U, 4028980673U,
|
||||
1289560198U, 2221992742U, 1669523910U, 35572830U,
|
||||
157838143U, 1052438473U, 1016535060U, 1802137761U,
|
||||
1753167236U, 1386275462U, 3080475397U, 2857371447U,
|
||||
1040679964U, 2145300060U, 2390574316U, 1461121720U,
|
||||
2956646967U, 4031777805U, 4028374788U, 33600511U,
|
||||
2920084762U, 1018524850U, 629373528U, 3691585981U,
|
||||
3515945977U, 2091462646U, 2486323059U, 586499841U,
|
||||
988145025U, 935516892U, 3367335476U, 2599673255U,
|
||||
2839830854U, 265290510U, 3972581182U, 2759138881U,
|
||||
3795373465U, 1005194799U, 847297441U, 406762289U,
|
||||
1314163512U, 1332590856U, 1866599683U, 4127851711U,
|
||||
750260880U, 613907577U, 1450815602U, 3165620655U,
|
||||
3734664991U, 3650291728U, 3012275730U, 3704569646U,
|
||||
1427272223U, 778793252U, 1343938022U, 2676280711U,
|
||||
2052605720U, 1946737175U, 3164576444U, 3914038668U,
|
||||
3967478842U, 3682934266U, 1661551462U, 3294938066U,
|
||||
4011595847U, 840292616U, 3712170807U, 616741398U,
|
||||
312560963U, 711312465U, 1351876610U, 322626781U,
|
||||
1910503582U, 271666773U, 2175563734U, 1594956187U,
|
||||
70604529U, 3617834859U, 1007753275U, 1495573769U,
|
||||
4069517037U, 2549218298U, 2663038764U, 504708206U,
|
||||
2263041392U, 3941167025U, 2249088522U, 1514023603U,
|
||||
1998579484U, 1312622330U, 694541497U, 2582060303U,
|
||||
2151582166U, 1382467621U, 776784248U, 2618340202U,
|
||||
3323268794U, 2497899128U, 2784771155U, 503983604U,
|
||||
4076293799U, 907881277U, 423175695U, 432175456U,
|
||||
1378068232U, 4145222326U, 3954048622U, 3938656102U,
|
||||
3820766613U, 2793130115U, 2977904593U, 26017576U,
|
||||
3274890735U, 3194772133U, 1700274565U, 1756076034U,
|
||||
4006520079U, 3677328699U, 720338349U, 1533947780U,
|
||||
354530856U, 688349552U, 3973924725U, 1637815568U,
|
||||
332179504U, 3949051286U, 53804574U, 2852348879U,
|
||||
3044236432U, 1282449977U, 3583942155U, 3416972820U,
|
||||
4006381244U, 1617046695U, 2628476075U, 3002303598U,
|
||||
1686838959U, 431878346U, 2686675385U, 1700445008U,
|
||||
1080580658U, 1009431731U, 832498133U, 3223435511U,
|
||||
2605976345U, 2271191193U, 2516031870U, 1648197032U,
|
||||
4164389018U, 2548247927U, 300782431U, 375919233U,
|
||||
238389289U, 3353747414U, 2531188641U, 2019080857U,
|
||||
1475708069U, 455242339U, 2609103871U, 448939670U,
|
||||
3451063019U, 1395535956U, 2413381860U, 1841049896U,
|
||||
1491858159U, 885456874U, 4264095073U, 4001119347U,
|
||||
1565136089U, 3898914787U, 1108368660U, 540939232U,
|
||||
1173283510U, 2745871338U, 3681308437U, 4207628240U,
|
||||
3343053890U, 4016749493U, 1699691293U, 1103962373U,
|
||||
3625875870U, 2256883143U, 3830138730U, 1031889488U,
|
||||
3479347698U, 1535977030U, 4236805024U, 3251091107U,
|
||||
2132092099U, 1774941330U, 1199868427U, 1452454533U,
|
||||
157007616U, 2904115357U, 342012276U, 595725824U,
|
||||
1480756522U, 206960106U, 497939518U, 591360097U,
|
||||
863170706U, 2375253569U, 3596610801U, 1814182875U,
|
||||
2094937945U, 3421402208U, 1082520231U, 3463918190U,
|
||||
2785509508U, 435703966U, 3908032597U, 1641649973U,
|
||||
2842273706U, 3305899714U, 1510255612U, 2148256476U,
|
||||
2655287854U, 3276092548U, 4258621189U, 236887753U,
|
||||
3681803219U, 274041037U, 1734335097U, 3815195456U,
|
||||
3317970021U, 1899903192U, 1026095262U, 4050517792U,
|
||||
356393447U, 2410691914U, 3873677099U, 3682840055U,
|
||||
|
||||
3913112168U, 2491498743U, 4132185628U, 2489919796U,
|
||||
1091903735U, 1979897079U, 3170134830U, 3567386728U,
|
||||
3557303409U, 857797738U, 1136121015U, 1342202287U,
|
||||
507115054U, 2535736646U, 337727348U, 3213592640U,
|
||||
1301675037U, 2528481711U, 1895095763U, 1721773893U,
|
||||
3216771564U, 62756741U, 2142006736U, 835421444U,
|
||||
2531993523U, 1442658625U, 3659876326U, 2882144922U,
|
||||
676362277U, 1392781812U, 170690266U, 3921047035U,
|
||||
1759253602U, 3611846912U, 1745797284U, 664899054U,
|
||||
1329594018U, 3901205900U, 3045908486U, 2062866102U,
|
||||
2865634940U, 3543621612U, 3464012697U, 1080764994U,
|
||||
553557557U, 3656615353U, 3996768171U, 991055499U,
|
||||
499776247U, 1265440854U, 648242737U, 3940784050U,
|
||||
980351604U, 3713745714U, 1749149687U, 3396870395U,
|
||||
4211799374U, 3640570775U, 1161844396U, 3125318951U,
|
||||
1431517754U, 545492359U, 4268468663U, 3499529547U,
|
||||
1437099964U, 2702547544U, 3433638243U, 2581715763U,
|
||||
2787789398U, 1060185593U, 1593081372U, 2418618748U,
|
||||
4260947970U, 69676912U, 2159744348U, 86519011U,
|
||||
2512459080U, 3838209314U, 1220612927U, 3339683548U,
|
||||
133810670U, 1090789135U, 1078426020U, 1569222167U,
|
||||
845107691U, 3583754449U, 4072456591U, 1091646820U,
|
||||
628848692U, 1613405280U, 3757631651U, 526609435U,
|
||||
236106946U, 48312990U, 2942717905U, 3402727701U,
|
||||
1797494240U, 859738849U, 992217954U, 4005476642U,
|
||||
2243076622U, 3870952857U, 3732016268U, 765654824U,
|
||||
3490871365U, 2511836413U, 1685915746U, 3888969200U,
|
||||
1414112111U, 2273134842U, 3281911079U, 4080962846U,
|
||||
172450625U, 2569994100U, 980381355U, 4109958455U,
|
||||
2819808352U, 2716589560U, 2568741196U, 3681446669U,
|
||||
3329971472U, 1835478071U, 660984891U, 3704678404U,
|
||||
4045999559U, 3422617507U, 3040415634U, 1762651403U,
|
||||
1719377915U, 3470491036U, 2693910283U, 3642056355U,
|
||||
3138596744U, 1364962596U, 2073328063U, 1983633131U,
|
||||
926494387U, 3423689081U, 2150032023U, 4096667949U,
|
||||
1749200295U, 3328846651U, 309677260U, 2016342300U,
|
||||
1779581495U, 3079819751U, 111262694U, 1274766160U,
|
||||
443224088U, 298511866U, 1025883608U, 3806446537U,
|
||||
1145181785U, 168956806U, 3641502830U, 3584813610U,
|
||||
1689216846U, 3666258015U, 3200248200U, 1692713982U,
|
||||
2646376535U, 4042768518U, 1618508792U, 1610833997U,
|
||||
3523052358U, 4130873264U, 2001055236U, 3610705100U,
|
||||
2202168115U, 4028541809U, 2961195399U, 1006657119U,
|
||||
2006996926U, 3186142756U, 1430667929U, 3210227297U,
|
||||
1314452623U, 4074634658U, 4101304120U, 2273951170U,
|
||||
1399257539U, 3367210612U, 3027628629U, 1190975929U,
|
||||
2062231137U, 2333990788U, 2221543033U, 2438960610U,
|
||||
1181637006U, 548689776U, 2362791313U, 3372408396U,
|
||||
3104550113U, 3145860560U, 296247880U, 1970579870U,
|
||||
3078560182U, 3769228297U, 1714227617U, 3291629107U,
|
||||
3898220290U, 166772364U, 1251581989U, 493813264U,
|
||||
448347421U, 195405023U, 2709975567U, 677966185U,
|
||||
3703036547U, 1463355134U, 2715995803U, 1338867538U,
|
||||
1343315457U, 2802222074U, 2684532164U, 233230375U,
|
||||
2599980071U, 2000651841U, 3277868038U, 1638401717U,
|
||||
4028070440U, 3237316320U, 6314154U, 819756386U,
|
||||
300326615U, 590932579U, 1405279636U, 3267499572U,
|
||||
3150704214U, 2428286686U, 3959192993U, 3461946742U,
|
||||
1862657033U, 1266418056U, 963775037U, 2089974820U,
|
||||
2263052895U, 1917689273U, 448879540U, 3550394620U,
|
||||
3981727096U, 150775221U, 3627908307U, 1303187396U,
|
||||
508620638U, 2975983352U, 2726630617U, 1817252668U,
|
||||
1876281319U, 1457606340U, 908771278U, 3720792119U,
|
||||
3617206836U, 2455994898U, 1729034894U, 1080033504U,
|
||||
|
||||
976866871U, 3556439503U, 2881648439U, 1522871579U,
|
||||
1555064734U, 1336096578U, 3548522304U, 2579274686U,
|
||||
3574697629U, 3205460757U, 3593280638U, 3338716283U,
|
||||
3079412587U, 564236357U, 2993598910U, 1781952180U,
|
||||
1464380207U, 3163844217U, 3332601554U, 1699332808U,
|
||||
1393555694U, 1183702653U, 3581086237U, 1288719814U,
|
||||
691649499U, 2847557200U, 2895455976U, 3193889540U,
|
||||
2717570544U, 1781354906U, 1676643554U, 2592534050U,
|
||||
3230253752U, 1126444790U, 2770207658U, 2633158820U,
|
||||
2210423226U, 2615765581U, 2414155088U, 3127139286U,
|
||||
673620729U, 2805611233U, 1269405062U, 4015350505U,
|
||||
3341807571U, 4149409754U, 1057255273U, 2012875353U,
|
||||
2162469141U, 2276492801U, 2601117357U, 993977747U,
|
||||
3918593370U, 2654263191U, 753973209U, 36408145U,
|
||||
2530585658U, 25011837U, 3520020182U, 2088578344U,
|
||||
530523599U, 2918365339U, 1524020338U, 1518925132U,
|
||||
3760827505U, 3759777254U, 1202760957U, 3985898139U,
|
||||
3906192525U, 674977740U, 4174734889U, 2031300136U,
|
||||
2019492241U, 3983892565U, 4153806404U, 3822280332U,
|
||||
352677332U, 2297720250U, 60907813U, 90501309U,
|
||||
3286998549U, 1016092578U, 2535922412U, 2839152426U,
|
||||
457141659U, 509813237U, 4120667899U, 652014361U,
|
||||
1966332200U, 2975202805U, 55981186U, 2327461051U,
|
||||
676427537U, 3255491064U, 2882294119U, 3433927263U,
|
||||
1307055953U, 942726286U, 933058658U, 2468411793U,
|
||||
3933900994U, 4215176142U, 1361170020U, 2001714738U,
|
||||
2830558078U, 3274259782U, 1222529897U, 1679025792U,
|
||||
2729314320U, 3714953764U, 1770335741U, 151462246U,
|
||||
3013232138U, 1682292957U, 1483529935U, 471910574U,
|
||||
1539241949U, 458788160U, 3436315007U, 1807016891U,
|
||||
3718408830U, 978976581U, 1043663428U, 3165965781U,
|
||||
1927990952U, 4200891579U, 2372276910U, 3208408903U,
|
||||
3533431907U, 1412390302U, 2931980059U, 4132332400U,
|
||||
1947078029U, 3881505623U, 4168226417U, 2941484381U,
|
||||
1077988104U, 1320477388U, 886195818U, 18198404U,
|
||||
3786409000U, 2509781533U, 112762804U, 3463356488U,
|
||||
1866414978U, 891333506U, 18488651U, 661792760U,
|
||||
1628790961U, 3885187036U, 3141171499U, 876946877U,
|
||||
2693282273U, 1372485963U, 791857591U, 2686433993U,
|
||||
3759982718U, 3167212022U, 3472953795U, 2716379847U,
|
||||
445679433U, 3561995674U, 3504004811U, 3574258232U,
|
||||
54117162U, 3331405415U, 2381918588U, 3769707343U,
|
||||
4154350007U, 1140177722U, 4074052095U, 668550556U,
|
||||
3214352940U, 367459370U, 261225585U, 2610173221U,
|
||||
4209349473U, 3468074219U, 3265815641U, 314222801U,
|
||||
3066103646U, 3808782860U, 282218597U, 3406013506U,
|
||||
3773591054U, 379116347U, 1285071038U, 846784868U,
|
||||
2669647154U, 3771962079U, 3550491691U, 2305946142U,
|
||||
453669953U, 1268987020U, 3317592352U, 3279303384U,
|
||||
3744833421U, 2610507566U, 3859509063U, 266596637U,
|
||||
3847019092U, 517658769U, 3462560207U, 3443424879U,
|
||||
370717030U, 4247526661U, 2224018117U, 4143653529U,
|
||||
4112773975U, 2788324899U, 2477274417U, 1456262402U,
|
||||
2901442914U, 1517677493U, 1846949527U, 2295493580U,
|
||||
3734397586U, 2176403920U, 1280348187U, 1908823572U,
|
||||
3871786941U, 846861322U, 1172426758U, 3287448474U,
|
||||
3383383037U, 1655181056U, 3139813346U, 901632758U,
|
||||
1897031941U, 2986607138U, 3066810236U, 3447102507U,
|
||||
1393639104U, 373351379U, 950779232U, 625454576U,
|
||||
3124240540U, 4148612726U, 2007998917U, 544563296U,
|
||||
2244738638U, 2330496472U, 2058025392U, 1291430526U,
|
||||
424198748U, 50039436U, 29584100U, 3605783033U,
|
||||
2429876329U, 2791104160U, 1057563949U, 3255363231U,
|
||||
3075367218U, 3463963227U, 1469046755U, 985887462U
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
99
CryptoPP/blowfish.cpp
Normal file
99
CryptoPP/blowfish.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
// blowfish.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "blowfish.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void Blowfish::Base::UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(keylength);
|
||||
|
||||
unsigned i, j=0, k;
|
||||
word32 data, dspace[2] = {0, 0};
|
||||
|
||||
memcpy(pbox, p_init, sizeof(p_init));
|
||||
memcpy(sbox, s_init, sizeof(s_init));
|
||||
|
||||
// Xor key string into encryption key vector
|
||||
for (i=0 ; i<ROUNDS+2 ; ++i)
|
||||
{
|
||||
data = 0 ;
|
||||
for (k=0 ; k<4 ; ++k )
|
||||
data = (data << 8) | key_string[j++ % keylength];
|
||||
pbox[i] ^= data;
|
||||
}
|
||||
|
||||
crypt_block(dspace, pbox);
|
||||
|
||||
for (i=0; i<ROUNDS; i+=2)
|
||||
crypt_block(pbox+i, pbox+i+2);
|
||||
|
||||
crypt_block(pbox+ROUNDS, sbox);
|
||||
|
||||
for (i=0; i<4*256-2; i+=2)
|
||||
crypt_block(sbox+i, sbox+i+2);
|
||||
|
||||
if (!IsForwardTransformation())
|
||||
for (i=0; i<(ROUNDS+2)/2; i++)
|
||||
std::swap(pbox[i], pbox[ROUNDS+1-i]);
|
||||
}
|
||||
|
||||
// this version is only used to make pbox and sbox
|
||||
void Blowfish::Base::crypt_block(const word32 in[2], word32 out[2]) const
|
||||
{
|
||||
word32 left = in[0];
|
||||
word32 right = in[1];
|
||||
|
||||
const word32 *const s=sbox;
|
||||
const word32 *p=pbox;
|
||||
|
||||
left ^= p[0];
|
||||
|
||||
for (unsigned i=0; i<ROUNDS/2; i++)
|
||||
{
|
||||
right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
|
||||
^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
|
||||
^ p[2*i+1];
|
||||
|
||||
left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
|
||||
^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
|
||||
^ p[2*i+2];
|
||||
}
|
||||
|
||||
right ^= p[ROUNDS+1];
|
||||
|
||||
out[0] = right;
|
||||
out[1] = left;
|
||||
}
|
||||
|
||||
void Blowfish::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
||||
|
||||
word32 left, right;
|
||||
Block::Get(inBlock)(left)(right);
|
||||
|
||||
const word32 *const s=sbox;
|
||||
const word32 *p=pbox;
|
||||
|
||||
left ^= p[0];
|
||||
|
||||
for (unsigned i=0; i<ROUNDS/2; i++)
|
||||
{
|
||||
right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
|
||||
^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
|
||||
^ p[2*i+1];
|
||||
|
||||
left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
|
||||
^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
|
||||
^ p[2*i+2];
|
||||
}
|
||||
|
||||
right ^= p[ROUNDS+1];
|
||||
|
||||
Block::Put(xorBlock, outBlock)(right)(left);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
46
CryptoPP/blowfish.h
Normal file
46
CryptoPP/blowfish.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef CRYPTOPP_BLOWFISH_H
|
||||
#define CRYPTOPP_BLOWFISH_H
|
||||
|
||||
/** \file */
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! _
|
||||
struct Blowfish_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 1, 56>, public FixedRounds<16>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "Blowfish";}
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/cs.html#Blowfish">Blowfish</a>
|
||||
class Blowfish : public Blowfish_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<Blowfish_Info>
|
||||
{
|
||||
public:
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
void UncheckedSetKey(const byte *key_string, unsigned int keylength, const NameValuePairs ¶ms);
|
||||
|
||||
private:
|
||||
void crypt_block(const word32 in[2], word32 out[2]) const;
|
||||
|
||||
static const word32 p_init[ROUNDS+2];
|
||||
static const word32 s_init[4*256];
|
||||
|
||||
FixedSizeSecBlock<word32, ROUNDS+2> pbox;
|
||||
FixedSizeSecBlock<word32, 4*256> sbox;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
typedef Blowfish::Encryption BlowfishEncryption;
|
||||
typedef Blowfish::Decryption BlowfishDecryption;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
63
CryptoPP/blumshub.cpp
Normal file
63
CryptoPP/blumshub.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
// blumshub.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "blumshub.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
PublicBlumBlumShub::PublicBlumBlumShub(const Integer &n, const Integer &seed)
|
||||
: modn(n),
|
||||
maxBits(BitPrecision(n.BitCount())-1)
|
||||
{
|
||||
current = modn.Square(modn.Square(seed));
|
||||
bitsLeft = maxBits;
|
||||
}
|
||||
|
||||
unsigned int PublicBlumBlumShub::GenerateBit()
|
||||
{
|
||||
if (bitsLeft==0)
|
||||
{
|
||||
current = modn.Square(current);
|
||||
bitsLeft = maxBits;
|
||||
}
|
||||
|
||||
return current.GetBit(--bitsLeft);
|
||||
}
|
||||
|
||||
byte PublicBlumBlumShub::GenerateByte()
|
||||
{
|
||||
byte b=0;
|
||||
for (int i=0; i<8; i++)
|
||||
b = (b << 1) | PublicBlumBlumShub::GenerateBit();
|
||||
return b;
|
||||
}
|
||||
|
||||
void PublicBlumBlumShub::GenerateBlock(byte *output, size_t size)
|
||||
{
|
||||
while (size--)
|
||||
*output++ = PublicBlumBlumShub::GenerateByte();
|
||||
}
|
||||
|
||||
void PublicBlumBlumShub::ProcessData(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
while (length--)
|
||||
*outString++ = *inString++ ^ PublicBlumBlumShub::GenerateByte();
|
||||
}
|
||||
|
||||
BlumBlumShub::BlumBlumShub(const Integer &p, const Integer &q, const Integer &seed)
|
||||
: PublicBlumBlumShub(p*q, seed),
|
||||
p(p), q(q),
|
||||
x0(modn.Square(seed))
|
||||
{
|
||||
}
|
||||
|
||||
void BlumBlumShub::Seek(lword index)
|
||||
{
|
||||
Integer i(Integer::POSITIVE, index);
|
||||
i *= 8;
|
||||
Integer e = a_exp_b_mod_c (2, i / maxBits + 1, (p-1)*(q-1));
|
||||
current = modn.Exponentiate(x0, e);
|
||||
bitsLeft = maxBits - i % maxBits;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
53
CryptoPP/blumshub.h
Normal file
53
CryptoPP/blumshub.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef CRYPTOPP_BLUMSHUB_H
|
||||
#define CRYPTOPP_BLUMSHUB_H
|
||||
|
||||
#include "modarith.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class BlumGoldwasserPublicKey;
|
||||
class BlumGoldwasserPrivateKey;
|
||||
|
||||
//! BlumBlumShub without factorization of the modulus
|
||||
class PublicBlumBlumShub : public RandomNumberGenerator,
|
||||
public StreamTransformation
|
||||
{
|
||||
public:
|
||||
PublicBlumBlumShub(const Integer &n, const Integer &seed);
|
||||
|
||||
unsigned int GenerateBit();
|
||||
byte GenerateByte();
|
||||
void GenerateBlock(byte *output, size_t size);
|
||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
||||
|
||||
bool IsSelfInverting() const {return true;}
|
||||
bool IsForwardTransformation() const {return true;}
|
||||
|
||||
protected:
|
||||
ModularArithmetic modn;
|
||||
word maxBits, bitsLeft;
|
||||
Integer current;
|
||||
|
||||
friend class BlumGoldwasserPublicKey;
|
||||
friend class BlumGoldwasserPrivateKey;
|
||||
};
|
||||
|
||||
//! BlumBlumShub with factorization of the modulus
|
||||
class BlumBlumShub : public PublicBlumBlumShub
|
||||
{
|
||||
public:
|
||||
// Make sure p and q are both primes congruent to 3 mod 4 and at least 512 bits long,
|
||||
// seed is the secret key and should be about as big as p*q
|
||||
BlumBlumShub(const Integer &p, const Integer &q, const Integer &seed);
|
||||
|
||||
bool IsRandomAccess() const {return true;}
|
||||
void Seek(lword index);
|
||||
|
||||
protected:
|
||||
const Integer p, q;
|
||||
const Integer x0;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
524
CryptoPP/camellia.cpp
Normal file
524
CryptoPP/camellia.cpp
Normal file
@ -0,0 +1,524 @@
|
||||
// camellia.cpp - by Kevin Springle, 2003
|
||||
// This code is hereby placed in the public domain.
|
||||
|
||||
/*
|
||||
Optimisations and defense against timing attacks added in Jan 2007 by Wei Dai.
|
||||
|
||||
The first 2 rounds and the last round seem especially vulnerable to timing
|
||||
attacks. The protection is similar to what was implemented for Rijndael.
|
||||
See comments at top of rijndael.cpp for more details.
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "camellia.h"
|
||||
#include "misc.h"
|
||||
#include "cpu.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// round implementation that uses a small table for protection against timing attacks
|
||||
#define SLOW_ROUND(lh, ll, rh, rl, kh, kl) { \
|
||||
word32 zr = ll ^ kl; \
|
||||
word32 zl = lh ^ kh; \
|
||||
zr= rotlFixed(s1[GETBYTE(zr, 3)], 1) | \
|
||||
(rotrFixed(s1[GETBYTE(zr, 2)], 1) << 24) | \
|
||||
(s1[rotlFixed(CRYPTOPP_GET_BYTE_AS_BYTE(zr, 1),1)] << 16) | \
|
||||
(s1[GETBYTE(zr, 0)] << 8); \
|
||||
zl= (s1[GETBYTE(zl, 3)] << 24) | \
|
||||
(rotlFixed(s1[GETBYTE(zl, 2)], 1) << 16) | \
|
||||
(rotrFixed(s1[GETBYTE(zl, 1)], 1) << 8) | \
|
||||
s1[rotlFixed(CRYPTOPP_GET_BYTE_AS_BYTE(zl, 0), 1)]; \
|
||||
zl ^= zr; \
|
||||
zr = zl ^ rotlFixed(zr, 8); \
|
||||
zl = zr ^ rotrFixed(zl, 8); \
|
||||
rh ^= rotlFixed(zr, 16); \
|
||||
rh ^= zl; \
|
||||
rl ^= rotlFixed(zl, 8); \
|
||||
}
|
||||
|
||||
// normal round - same output as above but using larger tables for faster speed
|
||||
#define ROUND(lh, ll, rh, rl, kh, kl) { \
|
||||
word32 th = lh ^ kh; \
|
||||
word32 tl = ll ^ kl; \
|
||||
word32 d = SP[0][GETBYTE(tl,0)] ^ SP[1][GETBYTE(tl,3)] ^ SP[2][GETBYTE(tl,2)] ^ SP[3][GETBYTE(tl,1)]; \
|
||||
word32 u = SP[0][GETBYTE(th,3)] ^ SP[1][GETBYTE(th,2)] ^ SP[2][GETBYTE(th,1)] ^ SP[3][GETBYTE(th,0)]; \
|
||||
d ^= u; \
|
||||
rh ^= d; \
|
||||
rl ^= d; \
|
||||
rl ^= rotrFixed(u, 8);}
|
||||
|
||||
#define DOUBLE_ROUND(lh, ll, rh, rl, k0, k1, k2, k3) \
|
||||
ROUND(lh, ll, rh, rl, k0, k1) \
|
||||
ROUND(rh, rl, lh, ll, k2, k3)
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define EFI(i) (1-(i))
|
||||
#else
|
||||
#define EFI(i) (i)
|
||||
#endif
|
||||
|
||||
void Camellia::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &)
|
||||
{
|
||||
m_rounds = (keylen >= 24) ? 4 : 3;
|
||||
unsigned int kslen = (8 * m_rounds + 2);
|
||||
m_key.New(kslen*2);
|
||||
word32 *ks32 = m_key.data();
|
||||
int m=0, a=0;
|
||||
if (!IsForwardTransformation())
|
||||
m = -1, a = kslen-1;
|
||||
|
||||
word32 kl0, kl1, kl2, kl3;
|
||||
GetBlock<word32, BigEndian> getBlock(key);
|
||||
getBlock(kl0)(kl1)(kl2)(kl3);
|
||||
word32 k0=kl0, k1=kl1, k2=kl2, k3=kl3;
|
||||
|
||||
#define CALC_ADDR2(base, i, j) ((byte *)(base)+8*(i)+4*(j)+((-16*(i))&m))
|
||||
#define CALC_ADDR(base, i) CALC_ADDR2(base, i, 0)
|
||||
|
||||
#if 1
|
||||
word64 kwl, kwr;
|
||||
ks32 += 2*a;
|
||||
#define PREPARE_KS_ROUNDS \
|
||||
kwl = (word64(k0) << 32) | k1; \
|
||||
kwr = (word64(k2) << 32) | k3
|
||||
#define KS_ROUND_0(i) \
|
||||
*(word64*)CALC_ADDR(ks32, i+EFI(0)) = kwl; \
|
||||
*(word64*)CALC_ADDR(ks32, i+EFI(1)) = kwr
|
||||
#define KS_ROUND(i, r, which) \
|
||||
if (which & (1<<int(r<64))) *(word64*)CALC_ADDR(ks32, i+EFI(r<64)) = (kwr << (r%64)) | (kwl >> (64 - (r%64))); \
|
||||
if (which & (1<<int(r>64))) *(word64*)CALC_ADDR(ks32, i+EFI(r>64)) = (kwl << (r%64)) | (kwr >> (64 - (r%64)))
|
||||
#else
|
||||
// SSE2 version is 30% faster on Intel Core 2. Doesn't seem worth the hassle of maintenance, but left here
|
||||
// #if'd out in case someone needs it.
|
||||
__m128i kw, kw2;
|
||||
__m128i *ks128 = (__m128i *)ks32+a/2;
|
||||
ks32 += 2*a;
|
||||
#define PREPARE_KS_ROUNDS \
|
||||
kw = _mm_set_epi32(k0, k1, k2, k3); \
|
||||
if (m) kw2 = kw, kw = _mm_shuffle_epi32(kw, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
else kw2 = _mm_shuffle_epi32(kw, _MM_SHUFFLE(1, 0, 3, 2))
|
||||
#define KS_ROUND_0(i) \
|
||||
_mm_store_si128((__m128i *)CALC_ADDR(ks128, i), kw)
|
||||
#define KS_ROUND(i, r, which) { \
|
||||
__m128i temp; \
|
||||
if (r<64 && (which!=1 || m)) temp = _mm_or_si128(_mm_slli_epi64(kw, r%64), _mm_srli_epi64(kw2, 64-r%64)); \
|
||||
else temp = _mm_or_si128(_mm_slli_epi64(kw2, r%64), _mm_srli_epi64(kw, 64-r%64)); \
|
||||
if (which & 2) _mm_store_si128((__m128i *)CALC_ADDR(ks128, i), temp); \
|
||||
else _mm_storel_epi64((__m128i*)CALC_ADDR(ks32, i+EFI(0)), temp); \
|
||||
}
|
||||
#endif
|
||||
|
||||
if (keylen == 16)
|
||||
{
|
||||
// KL
|
||||
PREPARE_KS_ROUNDS;
|
||||
KS_ROUND_0(0);
|
||||
KS_ROUND(4, 15, 3);
|
||||
KS_ROUND(10, 45, 3);
|
||||
KS_ROUND(12, 60, 2);
|
||||
KS_ROUND(16, 77, 3);
|
||||
KS_ROUND(18, 94, 3);
|
||||
KS_ROUND(22, 111, 3);
|
||||
|
||||
// KA
|
||||
k0=kl0, k1=kl1, k2=kl2, k3=kl3;
|
||||
DOUBLE_ROUND(k0, k1, k2, k3, 0xA09E667Ful, 0x3BCC908Bul, 0xB67AE858ul, 0x4CAA73B2ul);
|
||||
k0^=kl0, k1^=kl1, k2^=kl2, k3^=kl3;
|
||||
DOUBLE_ROUND(k0, k1, k2, k3, 0xC6EF372Ful, 0xE94F82BEul, 0x54FF53A5ul, 0xF1D36F1Cul);
|
||||
|
||||
PREPARE_KS_ROUNDS;
|
||||
KS_ROUND_0(2);
|
||||
KS_ROUND(6, 15, 3);
|
||||
KS_ROUND(8, 30, 3);
|
||||
KS_ROUND(12, 45, 1);
|
||||
KS_ROUND(14, 60, 3);
|
||||
KS_ROUND(20, 94, 3);
|
||||
KS_ROUND(24, 47, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
// KL
|
||||
PREPARE_KS_ROUNDS;
|
||||
KS_ROUND_0(0);
|
||||
KS_ROUND(12, 45, 3);
|
||||
KS_ROUND(16, 60, 3);
|
||||
KS_ROUND(22, 77, 3);
|
||||
KS_ROUND(30, 111, 3);
|
||||
|
||||
// KR
|
||||
word32 kr0, kr1, kr2, kr3;
|
||||
GetBlock<word32, BigEndian>(key+16)(kr0)(kr1);
|
||||
if (keylen == 24)
|
||||
kr2 = ~kr0, kr3 = ~kr1;
|
||||
else
|
||||
GetBlock<word32, BigEndian>(key+24)(kr2)(kr3);
|
||||
k0=kr0, k1=kr1, k2=kr2, k3=kr3;
|
||||
|
||||
PREPARE_KS_ROUNDS;
|
||||
KS_ROUND(4, 15, 3);
|
||||
KS_ROUND(8, 30, 3);
|
||||
KS_ROUND(18, 60, 3);
|
||||
KS_ROUND(26, 94, 3);
|
||||
|
||||
// KA
|
||||
k0^=kl0, k1^=kl1, k2^=kl2, k3^=kl3;
|
||||
DOUBLE_ROUND(k0, k1, k2, k3, 0xA09E667Ful, 0x3BCC908Bul, 0xB67AE858ul, 0x4CAA73B2ul);
|
||||
k0^=kl0, k1^=kl1, k2^=kl2, k3^=kl3;
|
||||
DOUBLE_ROUND(k0, k1, k2, k3, 0xC6EF372Ful, 0xE94F82BEul, 0x54FF53A5ul, 0xF1D36F1Cul);
|
||||
|
||||
PREPARE_KS_ROUNDS;
|
||||
KS_ROUND(6, 15, 3);
|
||||
KS_ROUND(14, 45, 3);
|
||||
KS_ROUND(24, 77, 3);
|
||||
KS_ROUND(28, 94, 3);
|
||||
|
||||
// KB
|
||||
k0^=kr0, k1^=kr1, k2^=kr2, k3^=kr3;
|
||||
DOUBLE_ROUND(k0, k1, k2, k3, 0x10E527FAul, 0xDE682D1Dul, 0xB05688C2ul, 0xB3E6C1FDul);
|
||||
|
||||
PREPARE_KS_ROUNDS;
|
||||
KS_ROUND_0(2);
|
||||
KS_ROUND(10, 30, 3);
|
||||
KS_ROUND(20, 60, 3);
|
||||
KS_ROUND(32, 47, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void Camellia::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
#define KS(i, j) ks[i*4 + EFI(j/2)*2 + EFI(j%2)]
|
||||
|
||||
#define FL(klh, kll, krh, krl) \
|
||||
ll ^= rotlFixed(lh & klh, 1); \
|
||||
lh ^= (ll | kll); \
|
||||
rh ^= (rl | krl); \
|
||||
rl ^= rotlFixed(rh & krh, 1);
|
||||
|
||||
word32 lh, ll, rh, rl;
|
||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
||||
Block::Get(inBlock)(lh)(ll)(rh)(rl);
|
||||
const word32 *ks = m_key.data();
|
||||
lh ^= KS(0,0);
|
||||
ll ^= KS(0,1);
|
||||
rh ^= KS(0,2);
|
||||
rl ^= KS(0,3);
|
||||
|
||||
// timing attack countermeasure. see comments at top for more details
|
||||
const int cacheLineSize = GetCacheLineSize();
|
||||
unsigned int i;
|
||||
word32 u = 0;
|
||||
for (i=0; i<256; i+=cacheLineSize)
|
||||
u &= *(const word32 *)(s1+i);
|
||||
u &= *(const word32 *)(s1+252);
|
||||
lh |= u; ll |= u;
|
||||
|
||||
SLOW_ROUND(lh, ll, rh, rl, KS(1,0), KS(1,1))
|
||||
SLOW_ROUND(rh, rl, lh, ll, KS(1,2), KS(1,3))
|
||||
for (i = m_rounds-1; i > 0; --i)
|
||||
{
|
||||
DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3))
|
||||
DOUBLE_ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1), KS(3,2), KS(3,3))
|
||||
FL(KS(4,0), KS(4,1), KS(4,2), KS(4,3));
|
||||
DOUBLE_ROUND(lh, ll, rh, rl, KS(5,0), KS(5,1), KS(5,2), KS(5,3))
|
||||
ks += 16;
|
||||
}
|
||||
DOUBLE_ROUND(lh, ll, rh, rl, KS(2,0), KS(2,1), KS(2,2), KS(2,3))
|
||||
ROUND(lh, ll, rh, rl, KS(3,0), KS(3,1))
|
||||
SLOW_ROUND(rh, rl, lh, ll, KS(3,2), KS(3,3))
|
||||
lh ^= KS(4,0);
|
||||
ll ^= KS(4,1);
|
||||
rh ^= KS(4,2);
|
||||
rl ^= KS(4,3);
|
||||
Block::Put(xorBlock, outBlock)(rh)(rl)(lh)(ll);
|
||||
}
|
||||
|
||||
// The Camellia s-boxes
|
||||
|
||||
const byte Camellia::Base::s1[256] =
|
||||
{
|
||||
112,130,44,236,179,39,192,229,228,133,87,53,234,12,174,65,
|
||||
35,239,107,147,69,25,165,33,237,14,79,78,29,101,146,189,
|
||||
134,184,175,143,124,235,31,206,62,48,220,95,94,197,11,26,
|
||||
166,225,57,202,213,71,93,61,217,1,90,214,81,86,108,77,
|
||||
139,13,154,102,251,204,176,45,116,18,43,32,240,177,132,153,
|
||||
223,76,203,194,52,126,118,5,109,183,169,49,209,23,4,215,
|
||||
20,88,58,97,222,27,17,28,50,15,156,22,83,24,242,34,
|
||||
254,68,207,178,195,181,122,145,36,8,232,168,96,252,105,80,
|
||||
170,208,160,125,161,137,98,151,84,91,30,149,224,255,100,210,
|
||||
16,196,0,72,163,247,117,219,138,3,230,218,9,63,221,148,
|
||||
135,92,131,2,205,74,144,51,115,103,246,243,157,127,191,226,
|
||||
82,155,216,38,200,55,198,59,129,150,111,75,19,190,99,46,
|
||||
233,121,167,140,159,110,188,142,41,245,249,182,47,253,180,89,
|
||||
120,152,6,106,231,70,113,186,212,37,171,66,136,162,141,250,
|
||||
114,7,185,85,248,238,172,10,54,73,42,104,60,56,241,164,
|
||||
64,40,211,123,187,201,67,193,21,227,173,244,119,199,128,158
|
||||
};
|
||||
|
||||
const word32 Camellia::Base::SP[4][256] = {
|
||||
{
|
||||
0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00,
|
||||
0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500,
|
||||
0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
|
||||
0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100,
|
||||
0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300,
|
||||
0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
|
||||
0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00,
|
||||
0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00,
|
||||
0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
|
||||
0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00,
|
||||
0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00,
|
||||
0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
|
||||
0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00,
|
||||
0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00,
|
||||
0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
|
||||
0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00,
|
||||
0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600,
|
||||
0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
|
||||
0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000,
|
||||
0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900,
|
||||
0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
|
||||
0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500,
|
||||
0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100,
|
||||
0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
|
||||
0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100,
|
||||
0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00,
|
||||
0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
|
||||
0x53535300, 0x18181800, 0xf2f2f200, 0x22222200,
|
||||
0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200,
|
||||
0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
|
||||
0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800,
|
||||
0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000,
|
||||
0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
|
||||
0xa1a1a100, 0x89898900, 0x62626200, 0x97979700,
|
||||
0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500,
|
||||
0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
|
||||
0x10101000, 0xc4c4c400, 0x00000000, 0x48484800,
|
||||
0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00,
|
||||
0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
|
||||
0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400,
|
||||
0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200,
|
||||
0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
|
||||
0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300,
|
||||
0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200,
|
||||
0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
|
||||
0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00,
|
||||
0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00,
|
||||
0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
|
||||
0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00,
|
||||
0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00,
|
||||
0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
|
||||
0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900,
|
||||
0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00,
|
||||
0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
|
||||
0xd4d4d400, 0x25252500, 0xababab00, 0x42424200,
|
||||
0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00,
|
||||
0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
|
||||
0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00,
|
||||
0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800,
|
||||
0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
|
||||
0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00,
|
||||
0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100,
|
||||
0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
|
||||
0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00
|
||||
},
|
||||
{
|
||||
0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9,
|
||||
0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb,
|
||||
0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
|
||||
0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282,
|
||||
0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727,
|
||||
0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
|
||||
0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c,
|
||||
0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b,
|
||||
0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
|
||||
0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d,
|
||||
0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe,
|
||||
0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
|
||||
0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595,
|
||||
0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a,
|
||||
0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
|
||||
0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a,
|
||||
0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc,
|
||||
0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
|
||||
0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040,
|
||||
0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333,
|
||||
0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
|
||||
0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a,
|
||||
0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262,
|
||||
0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
|
||||
0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2,
|
||||
0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838,
|
||||
0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
|
||||
0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444,
|
||||
0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565,
|
||||
0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
|
||||
0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151,
|
||||
0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0,
|
||||
0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
|
||||
0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f,
|
||||
0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b,
|
||||
0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
|
||||
0x00202020, 0x00898989, 0x00000000, 0x00909090,
|
||||
0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7,
|
||||
0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
|
||||
0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929,
|
||||
0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404,
|
||||
0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
|
||||
0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7,
|
||||
0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5,
|
||||
0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
|
||||
0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676,
|
||||
0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696,
|
||||
0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
|
||||
0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919,
|
||||
0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d,
|
||||
0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
|
||||
0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2,
|
||||
0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4,
|
||||
0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
|
||||
0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484,
|
||||
0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5,
|
||||
0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
|
||||
0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414,
|
||||
0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0,
|
||||
0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
|
||||
0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6,
|
||||
0x00777777, 0x00939393, 0x00868686, 0x00838383,
|
||||
0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
|
||||
0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d
|
||||
},
|
||||
{
|
||||
0x38003838, 0x41004141, 0x16001616, 0x76007676,
|
||||
0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2,
|
||||
0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
|
||||
0x75007575, 0x06000606, 0x57005757, 0xa000a0a0,
|
||||
0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9,
|
||||
0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
|
||||
0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727,
|
||||
0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede,
|
||||
0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
|
||||
0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767,
|
||||
0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf,
|
||||
0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
|
||||
0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565,
|
||||
0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e,
|
||||
0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
|
||||
0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6,
|
||||
0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333,
|
||||
0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
|
||||
0x3a003a3a, 0x09000909, 0x95009595, 0x10001010,
|
||||
0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc,
|
||||
0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
|
||||
0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282,
|
||||
0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898,
|
||||
0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
|
||||
0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0,
|
||||
0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e,
|
||||
0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
|
||||
0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111,
|
||||
0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959,
|
||||
0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
|
||||
0x12001212, 0x04000404, 0x74007474, 0x54005454,
|
||||
0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828,
|
||||
0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
|
||||
0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb,
|
||||
0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca,
|
||||
0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
|
||||
0x08000808, 0x62006262, 0x00000000, 0x24002424,
|
||||
0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded,
|
||||
0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
|
||||
0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a,
|
||||
0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101,
|
||||
0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
|
||||
0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9,
|
||||
0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171,
|
||||
0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
|
||||
0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d,
|
||||
0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5,
|
||||
0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
|
||||
0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646,
|
||||
0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747,
|
||||
0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
|
||||
0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac,
|
||||
0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535,
|
||||
0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
|
||||
0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121,
|
||||
0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d,
|
||||
0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
|
||||
0x7c007c7c, 0x77007777, 0x56005656, 0x05000505,
|
||||
0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434,
|
||||
0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
|
||||
0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd,
|
||||
0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0,
|
||||
0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
|
||||
0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f
|
||||
},
|
||||
{
|
||||
0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0,
|
||||
0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae,
|
||||
0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
|
||||
0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092,
|
||||
0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f,
|
||||
0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
|
||||
0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d,
|
||||
0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c,
|
||||
0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
|
||||
0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084,
|
||||
0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076,
|
||||
0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
|
||||
0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011,
|
||||
0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2,
|
||||
0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
|
||||
0x24240024, 0xe8e800e8, 0x60600060, 0x69690069,
|
||||
0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062,
|
||||
0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
|
||||
0x10100010, 0x00000000, 0xa3a300a3, 0x75750075,
|
||||
0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd,
|
||||
0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
|
||||
0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf,
|
||||
0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6,
|
||||
0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
|
||||
0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc,
|
||||
0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4,
|
||||
0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
|
||||
0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d,
|
||||
0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac,
|
||||
0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
|
||||
0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043,
|
||||
0x15150015, 0xadad00ad, 0x77770077, 0x80800080,
|
||||
0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
|
||||
0x85850085, 0x35350035, 0x0c0c000c, 0x41410041,
|
||||
0xefef00ef, 0x93930093, 0x19190019, 0x21210021,
|
||||
0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
|
||||
0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce,
|
||||
0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a,
|
||||
0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
|
||||
0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d,
|
||||
0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d,
|
||||
0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
|
||||
0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005,
|
||||
0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7,
|
||||
0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
|
||||
0x0f0f000f, 0x16160016, 0x18180018, 0x22220022,
|
||||
0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091,
|
||||
0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
|
||||
0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097,
|
||||
0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2,
|
||||
0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
|
||||
0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094,
|
||||
0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033,
|
||||
0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
|
||||
0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b,
|
||||
0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e,
|
||||
0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
|
||||
0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059,
|
||||
0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba,
|
||||
0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
|
||||
0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a,
|
||||
0x49490049, 0x68680068, 0x38380038, 0xa4a400a4,
|
||||
0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
|
||||
0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e
|
||||
}};
|
||||
|
||||
NAMESPACE_END
|
47
CryptoPP/camellia.h
Normal file
47
CryptoPP/camellia.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef CRYPTOPP_CAMELLIA_H
|
||||
#define CRYPTOPP_CAMELLIA_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! _
|
||||
struct Camellia_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "Camellia";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#Camellia">Camellia</a>
|
||||
class Camellia : public Camellia_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<Camellia_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
|
||||
protected:
|
||||
static const byte s1[256];
|
||||
static const word32 SP[4][256];
|
||||
|
||||
unsigned int m_rounds;
|
||||
SecBlock<word32> m_key;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
typedef Camellia::Encryption CamelliaEncryption;
|
||||
typedef Camellia::Decryption CamelliaDecryption;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
296
CryptoPP/cast.cpp
Normal file
296
CryptoPP/cast.cpp
Normal file
@ -0,0 +1,296 @@
|
||||
// cast.cpp - written and placed in the public domain by Wei Dai and Leonard Janke
|
||||
// based on Steve Reid's public domain cast.c
|
||||
|
||||
#include "pch.h"
|
||||
#include "cast.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/* Macros to access 8-bit bytes out of a 32-bit word */
|
||||
#define U8a(x) GETBYTE(x,3)
|
||||
#define U8b(x) GETBYTE(x,2)
|
||||
#define U8c(x) GETBYTE(x,1)
|
||||
#define U8d(x) GETBYTE(x,0)
|
||||
|
||||
/* CAST uses three different round functions */
|
||||
#define f1(l, r, km, kr) \
|
||||
t = rotlVariable(km + r, kr); \
|
||||
l ^= ((S[0][U8a(t)] ^ S[1][U8b(t)]) - \
|
||||
S[2][U8c(t)]) + S[3][U8d(t)];
|
||||
#define f2(l, r, km, kr) \
|
||||
t = rotlVariable(km ^ r, kr); \
|
||||
l ^= ((S[0][U8a(t)] - S[1][U8b(t)]) + \
|
||||
S[2][U8c(t)]) ^ S[3][U8d(t)];
|
||||
#define f3(l, r, km, kr) \
|
||||
t = rotlVariable(km - r, kr); \
|
||||
l ^= ((S[0][U8a(t)] + S[1][U8b(t)]) ^ \
|
||||
S[2][U8c(t)]) - S[3][U8d(t)];
|
||||
|
||||
#define F1(l, r, i, j) f1(l, r, K[i], K[i+j])
|
||||
#define F2(l, r, i, j) f2(l, r, K[i], K[i+j])
|
||||
#define F3(l, r, i, j) f3(l, r, K[i], K[i+j])
|
||||
|
||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
||||
|
||||
void CAST128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 t, l, r;
|
||||
|
||||
/* Get inblock into l,r */
|
||||
Block::Get(inBlock)(l)(r);
|
||||
/* Do the work */
|
||||
F1(l, r, 0, 16);
|
||||
F2(r, l, 1, 16);
|
||||
F3(l, r, 2, 16);
|
||||
F1(r, l, 3, 16);
|
||||
F2(l, r, 4, 16);
|
||||
F3(r, l, 5, 16);
|
||||
F1(l, r, 6, 16);
|
||||
F2(r, l, 7, 16);
|
||||
F3(l, r, 8, 16);
|
||||
F1(r, l, 9, 16);
|
||||
F2(l, r, 10, 16);
|
||||
F3(r, l, 11, 16);
|
||||
/* Only do full 16 rounds if key length > 80 bits */
|
||||
if (!reduced) {
|
||||
F1(l, r, 12, 16);
|
||||
F2(r, l, 13, 16);
|
||||
F3(l, r, 14, 16);
|
||||
F1(r, l, 15, 16);
|
||||
}
|
||||
/* Put l,r into outblock */
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
void CAST128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 t, l, r;
|
||||
|
||||
/* Get inblock into l,r */
|
||||
Block::Get(inBlock)(r)(l);
|
||||
/* Only do full 16 rounds if key length > 80 bits */
|
||||
if (!reduced) {
|
||||
F1(r, l, 15, 16);
|
||||
F3(l, r, 14, 16);
|
||||
F2(r, l, 13, 16);
|
||||
F1(l, r, 12, 16);
|
||||
}
|
||||
F3(r, l, 11, 16);
|
||||
F2(l, r, 10, 16);
|
||||
F1(r, l, 9, 16);
|
||||
F3(l, r, 8, 16);
|
||||
F2(r, l, 7, 16);
|
||||
F1(l, r, 6, 16);
|
||||
F3(r, l, 5, 16);
|
||||
F2(l, r, 4, 16);
|
||||
F1(r, l, 3, 16);
|
||||
F3(l, r, 2, 16);
|
||||
F2(r, l, 1, 16);
|
||||
F1(l, r, 0, 16);
|
||||
/* Put l,r into outblock */
|
||||
Block::Put(xorBlock, outBlock)(l)(r);
|
||||
/* Wipe clean */
|
||||
t = l = r = 0;
|
||||
}
|
||||
|
||||
void CAST128::Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(keylength);
|
||||
|
||||
reduced = (keylength <= 10);
|
||||
|
||||
word32 X[4], Z[4];
|
||||
GetUserKey(BIG_ENDIAN_ORDER, X, 4, userKey, keylength);
|
||||
|
||||
#define x(i) GETBYTE(X[i/4], 3-i%4)
|
||||
#define z(i) GETBYTE(Z[i/4], 3-i%4)
|
||||
|
||||
unsigned int i;
|
||||
for (i=0; i<=16; i+=16)
|
||||
{
|
||||
// this part is copied directly from RFC 2144 (with some search and replace) by Wei Dai
|
||||
Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)];
|
||||
Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)];
|
||||
Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)];
|
||||
Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)];
|
||||
K[i+0] = S[4][z(0x8)] ^ S[5][z(0x9)] ^ S[6][z(0x7)] ^ S[7][z(0x6)] ^ S[4][z(0x2)];
|
||||
K[i+1] = S[4][z(0xA)] ^ S[5][z(0xB)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[5][z(0x6)];
|
||||
K[i+2] = S[4][z(0xC)] ^ S[5][z(0xD)] ^ S[6][z(0x3)] ^ S[7][z(0x2)] ^ S[6][z(0x9)];
|
||||
K[i+3] = S[4][z(0xE)] ^ S[5][z(0xF)] ^ S[6][z(0x1)] ^ S[7][z(0x0)] ^ S[7][z(0xC)];
|
||||
X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)];
|
||||
X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)];
|
||||
X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)];
|
||||
X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)];
|
||||
K[i+4] = S[4][x(0x3)] ^ S[5][x(0x2)] ^ S[6][x(0xC)] ^ S[7][x(0xD)] ^ S[4][x(0x8)];
|
||||
K[i+5] = S[4][x(0x1)] ^ S[5][x(0x0)] ^ S[6][x(0xE)] ^ S[7][x(0xF)] ^ S[5][x(0xD)];
|
||||
K[i+6] = S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x8)] ^ S[7][x(0x9)] ^ S[6][x(0x3)];
|
||||
K[i+7] = S[4][x(0x5)] ^ S[5][x(0x4)] ^ S[6][x(0xA)] ^ S[7][x(0xB)] ^ S[7][x(0x7)];
|
||||
Z[0] = X[0] ^ S[4][x(0xD)] ^ S[5][x(0xF)] ^ S[6][x(0xC)] ^ S[7][x(0xE)] ^ S[6][x(0x8)];
|
||||
Z[1] = X[2] ^ S[4][z(0x0)] ^ S[5][z(0x2)] ^ S[6][z(0x1)] ^ S[7][z(0x3)] ^ S[7][x(0xA)];
|
||||
Z[2] = X[3] ^ S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x5)] ^ S[7][z(0x4)] ^ S[4][x(0x9)];
|
||||
Z[3] = X[1] ^ S[4][z(0xA)] ^ S[5][z(0x9)] ^ S[6][z(0xB)] ^ S[7][z(0x8)] ^ S[5][x(0xB)];
|
||||
K[i+8] = S[4][z(0x3)] ^ S[5][z(0x2)] ^ S[6][z(0xC)] ^ S[7][z(0xD)] ^ S[4][z(0x9)];
|
||||
K[i+9] = S[4][z(0x1)] ^ S[5][z(0x0)] ^ S[6][z(0xE)] ^ S[7][z(0xF)] ^ S[5][z(0xC)];
|
||||
K[i+10] = S[4][z(0x7)] ^ S[5][z(0x6)] ^ S[6][z(0x8)] ^ S[7][z(0x9)] ^ S[6][z(0x2)];
|
||||
K[i+11] = S[4][z(0x5)] ^ S[5][z(0x4)] ^ S[6][z(0xA)] ^ S[7][z(0xB)] ^ S[7][z(0x6)];
|
||||
X[0] = Z[2] ^ S[4][z(0x5)] ^ S[5][z(0x7)] ^ S[6][z(0x4)] ^ S[7][z(0x6)] ^ S[6][z(0x0)];
|
||||
X[1] = Z[0] ^ S[4][x(0x0)] ^ S[5][x(0x2)] ^ S[6][x(0x1)] ^ S[7][x(0x3)] ^ S[7][z(0x2)];
|
||||
X[2] = Z[1] ^ S[4][x(0x7)] ^ S[5][x(0x6)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[4][z(0x1)];
|
||||
X[3] = Z[3] ^ S[4][x(0xA)] ^ S[5][x(0x9)] ^ S[6][x(0xB)] ^ S[7][x(0x8)] ^ S[5][z(0x3)];
|
||||
K[i+12] = S[4][x(0x8)] ^ S[5][x(0x9)] ^ S[6][x(0x7)] ^ S[7][x(0x6)] ^ S[4][x(0x3)];
|
||||
K[i+13] = S[4][x(0xA)] ^ S[5][x(0xB)] ^ S[6][x(0x5)] ^ S[7][x(0x4)] ^ S[5][x(0x7)];
|
||||
K[i+14] = S[4][x(0xC)] ^ S[5][x(0xD)] ^ S[6][x(0x3)] ^ S[7][x(0x2)] ^ S[6][x(0x8)];
|
||||
K[i+15] = S[4][x(0xE)] ^ S[5][x(0xF)] ^ S[6][x(0x1)] ^ S[7][x(0x0)] ^ S[7][x(0xD)];
|
||||
}
|
||||
|
||||
for (i=16; i<32; i++)
|
||||
K[i] &= 0x1f;
|
||||
}
|
||||
|
||||
// The following CAST-256 implementation was contributed by Leonard Janke
|
||||
|
||||
const word32 CAST256::Base::t_m[8][24]={
|
||||
{ 0x5a827999, 0xd151d6a1, 0x482133a9, 0xbef090b1, 0x35bfedb9, 0xac8f4ac1,
|
||||
0x235ea7c9, 0x9a2e04d1, 0x10fd61d9, 0x87ccbee1, 0xfe9c1be9, 0x756b78f1,
|
||||
0xec3ad5f9, 0x630a3301, 0xd9d99009, 0x50a8ed11, 0xc7784a19, 0x3e47a721,
|
||||
0xb5170429, 0x2be66131, 0xa2b5be39, 0x19851b41, 0x90547849, 0x0723d551},
|
||||
{ 0xc95c653a, 0x402bc242, 0xb6fb1f4a, 0x2dca7c52, 0xa499d95a, 0x1b693662,
|
||||
0x9238936a, 0x0907f072, 0x7fd74d7a, 0xf6a6aa82, 0x6d76078a, 0xe4456492,
|
||||
0x5b14c19a, 0xd1e41ea2, 0x48b37baa, 0xbf82d8b2, 0x365235ba, 0xad2192c2,
|
||||
0x23f0efca, 0x9ac04cd2, 0x118fa9da, 0x885f06e2, 0xff2e63ea, 0x75fdc0f2},
|
||||
{ 0x383650db, 0xaf05ade3, 0x25d50aeb, 0x9ca467f3, 0x1373c4fb, 0x8a432203,
|
||||
0x01127f0b, 0x77e1dc13, 0xeeb1391b, 0x65809623, 0xdc4ff32b, 0x531f5033,
|
||||
0xc9eead3b, 0x40be0a43, 0xb78d674b, 0x2e5cc453, 0xa52c215b, 0x1bfb7e63,
|
||||
0x92cadb6b, 0x099a3873, 0x8069957b, 0xf738f283, 0x6e084f8b, 0xe4d7ac93},
|
||||
{ 0xa7103c7c, 0x1ddf9984, 0x94aef68c, 0x0b7e5394, 0x824db09c, 0xf91d0da4,
|
||||
0x6fec6aac, 0xe6bbc7b4, 0x5d8b24bc, 0xd45a81c4, 0x4b29decc, 0xc1f93bd4,
|
||||
0x38c898dc, 0xaf97f5e4, 0x266752ec, 0x9d36aff4, 0x14060cfc, 0x8ad56a04,
|
||||
0x01a4c70c, 0x78742414, 0xef43811c, 0x6612de24, 0xdce23b2c, 0x53b19834},
|
||||
{ 0x15ea281d, 0x8cb98525, 0x0388e22d, 0x7a583f35, 0xf1279c3d, 0x67f6f945,
|
||||
0xdec6564d, 0x5595b355, 0xcc65105d, 0x43346d65, 0xba03ca6d, 0x30d32775,
|
||||
0xa7a2847d, 0x1e71e185, 0x95413e8d, 0x0c109b95, 0x82dff89d, 0xf9af55a5,
|
||||
0x707eb2ad, 0xe74e0fb5, 0x5e1d6cbd, 0xd4ecc9c5, 0x4bbc26cd, 0xc28b83d5},
|
||||
{ 0x84c413be, 0xfb9370c6, 0x7262cdce, 0xe9322ad6, 0x600187de, 0xd6d0e4e6,
|
||||
0x4da041ee, 0xc46f9ef6, 0x3b3efbfe, 0xb20e5906, 0x28ddb60e, 0x9fad1316,
|
||||
0x167c701e, 0x8d4bcd26, 0x041b2a2e, 0x7aea8736, 0xf1b9e43e, 0x68894146,
|
||||
0xdf589e4e, 0x5627fb56, 0xccf7585e, 0x43c6b566, 0xba96126e, 0x31656f76},
|
||||
{ 0xf39dff5f, 0x6a6d5c67, 0xe13cb96f, 0x580c1677, 0xcedb737f, 0x45aad087,
|
||||
0xbc7a2d8f, 0x33498a97, 0xaa18e79f, 0x20e844a7, 0x97b7a1af, 0x0e86feb7,
|
||||
0x85565bbf, 0xfc25b8c7, 0x72f515cf, 0xe9c472d7, 0x6093cfdf, 0xd7632ce7,
|
||||
0x4e3289ef, 0xc501e6f7, 0x3bd143ff, 0xb2a0a107, 0x296ffe0f, 0xa03f5b17},
|
||||
{ 0x6277eb00, 0xd9474808, 0x5016a510, 0xc6e60218, 0x3db55f20, 0xb484bc28,
|
||||
0x2b541930, 0xa2237638, 0x18f2d340, 0x8fc23048, 0x06918d50, 0x7d60ea58,
|
||||
0xf4304760, 0x6affa468, 0xe1cf0170, 0x589e5e78, 0xcf6dbb80, 0x463d1888,
|
||||
0xbd0c7590, 0x33dbd298, 0xaaab2fa0, 0x217a8ca8, 0x9849e9b0, 0x0f1946b8}
|
||||
};
|
||||
|
||||
const unsigned int CAST256::Base::t_r[8][24]={
|
||||
{19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11, 19, 27, 3, 11},
|
||||
{4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28, 4, 12, 20, 28},
|
||||
{21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13, 21, 29, 5, 13},
|
||||
{6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30, 6, 14, 22, 30},
|
||||
{23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15, 23, 31, 7, 15},
|
||||
{8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0, 8, 16, 24, 0},
|
||||
{25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17, 25, 1, 9, 17},
|
||||
{10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2, 10, 18, 26, 2}
|
||||
};
|
||||
|
||||
#define Q(i) \
|
||||
F1(block[2],block[3],8*i+4,-4); \
|
||||
F2(block[1],block[2],8*i+5,-4); \
|
||||
F3(block[0],block[1],8*i+6,-4); \
|
||||
F1(block[3],block[0],8*i+7,-4);
|
||||
|
||||
#define QBar(i) \
|
||||
F1(block[3],block[0],8*i+7,-4); \
|
||||
F3(block[0],block[1],8*i+6,-4); \
|
||||
F2(block[1],block[2],8*i+5,-4); \
|
||||
F1(block[2],block[3],8*i+4,-4);
|
||||
|
||||
/* CAST256's encrypt/decrypt functions are identical except for the order that
|
||||
the keys are used */
|
||||
|
||||
void CAST256::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 t, block[4];
|
||||
Block::Get(inBlock)(block[0])(block[1])(block[2])(block[3]);
|
||||
|
||||
// Perform 6 forward quad rounds
|
||||
Q(0);
|
||||
Q(1);
|
||||
Q(2);
|
||||
Q(3);
|
||||
Q(4);
|
||||
Q(5);
|
||||
|
||||
// Perform 6 reverse quad rounds
|
||||
QBar(6);
|
||||
QBar(7);
|
||||
QBar(8);
|
||||
QBar(9);
|
||||
QBar(10);
|
||||
QBar(11);
|
||||
|
||||
Block::Put(xorBlock, outBlock)(block[0])(block[1])(block[2])(block[3]);
|
||||
}
|
||||
|
||||
/* Set up a CAST-256 key */
|
||||
|
||||
void CAST256::Base::Omega(int i, word32 kappa[8])
|
||||
{
|
||||
word32 t;
|
||||
|
||||
f1(kappa[6],kappa[7],t_m[0][i],t_r[0][i]);
|
||||
f2(kappa[5],kappa[6],t_m[1][i],t_r[1][i]);
|
||||
f3(kappa[4],kappa[5],t_m[2][i],t_r[2][i]);
|
||||
f1(kappa[3],kappa[4],t_m[3][i],t_r[3][i]);
|
||||
f2(kappa[2],kappa[3],t_m[4][i],t_r[4][i]);
|
||||
f3(kappa[1],kappa[2],t_m[5][i],t_r[5][i]);
|
||||
f1(kappa[0],kappa[1],t_m[6][i],t_r[6][i]);
|
||||
f2(kappa[7],kappa[0],t_m[7][i],t_r[7][i]);
|
||||
}
|
||||
|
||||
void CAST256::Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(keylength);
|
||||
|
||||
word32 kappa[8];
|
||||
GetUserKey(BIG_ENDIAN_ORDER, kappa, 8, userKey, keylength);
|
||||
|
||||
for(int i=0; i<12; ++i)
|
||||
{
|
||||
Omega(2*i,kappa);
|
||||
Omega(2*i+1,kappa);
|
||||
|
||||
K[8*i]=kappa[0] & 31;
|
||||
K[8*i+1]=kappa[2] & 31;
|
||||
K[8*i+2]=kappa[4] & 31;
|
||||
K[8*i+3]=kappa[6] & 31;
|
||||
K[8*i+4]=kappa[7];
|
||||
K[8*i+5]=kappa[5];
|
||||
K[8*i+6]=kappa[3];
|
||||
K[8*i+7]=kappa[1];
|
||||
}
|
||||
|
||||
if (!IsForwardTransformation())
|
||||
{
|
||||
for(int j=0; j<6; ++j)
|
||||
{
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
int i1=8*j+i;
|
||||
int i2=8*(11-j)+i;
|
||||
|
||||
assert(i1<i2);
|
||||
|
||||
std::swap(K[i1],K[i2]);
|
||||
std::swap(K[i1+4],K[i2+4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(kappa, 0, sizeof(kappa));
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
91
CryptoPP/cast.h
Normal file
91
CryptoPP/cast.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef CRYPTOPP_CAST_H
|
||||
#define CRYPTOPP_CAST_H
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class CAST
|
||||
{
|
||||
protected:
|
||||
static const word32 S[8][256];
|
||||
};
|
||||
|
||||
//! algorithm info
|
||||
struct CAST128_Info : public FixedBlockSize<8>, public VariableKeyLength<16, 5, 16>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "CAST-128";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#CAST-128">CAST-128</a>
|
||||
class CAST128 : public CAST128_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_NO_VTABLE Base : public CAST, public BlockCipherImpl<CAST128_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
||||
|
||||
protected:
|
||||
bool reduced;
|
||||
FixedSizeSecBlock<word32, 32> K;
|
||||
};
|
||||
|
||||
class CRYPTOPP_NO_VTABLE Enc : public Base
|
||||
{
|
||||
public:
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
};
|
||||
|
||||
class CRYPTOPP_NO_VTABLE Dec : public Base
|
||||
{
|
||||
public:
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
||||
};
|
||||
|
||||
//! algorithm info
|
||||
struct CAST256_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "CAST-256";}
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/cs.html#CAST-256">CAST-256</a>
|
||||
class CAST256 : public CAST256_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_NO_VTABLE Base : public CAST, public BlockCipherImpl<CAST256_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:
|
||||
static const word32 t_m[8][24];
|
||||
static const unsigned int t_r[8][24];
|
||||
|
||||
static void Omega(int i, word32 kappa[8]);
|
||||
|
||||
FixedSizeSecBlock<word32, 8*12> K;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
typedef CAST128::Encryption CAST128Encryption;
|
||||
typedef CAST128::Decryption CAST128Decryption;
|
||||
|
||||
typedef CAST256::Encryption CAST256Encryption;
|
||||
typedef CAST256::Decryption CAST256Decryption;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
545
CryptoPP/casts.cpp
Normal file
545
CryptoPP/casts.cpp
Normal file
@ -0,0 +1,545 @@
|
||||
#include "pch.h"
|
||||
#include "cast.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// CAST S-boxes
|
||||
|
||||
const word32 CAST::S[8][256] = {
|
||||
{
|
||||
0x30FB40D4UL, 0x9FA0FF0BUL, 0x6BECCD2FUL, 0x3F258C7AUL,
|
||||
0x1E213F2FUL, 0x9C004DD3UL, 0x6003E540UL, 0xCF9FC949UL,
|
||||
0xBFD4AF27UL, 0x88BBBDB5UL, 0xE2034090UL, 0x98D09675UL,
|
||||
0x6E63A0E0UL, 0x15C361D2UL, 0xC2E7661DUL, 0x22D4FF8EUL,
|
||||
0x28683B6FUL, 0xC07FD059UL, 0xFF2379C8UL, 0x775F50E2UL,
|
||||
0x43C340D3UL, 0xDF2F8656UL, 0x887CA41AUL, 0xA2D2BD2DUL,
|
||||
0xA1C9E0D6UL, 0x346C4819UL, 0x61B76D87UL, 0x22540F2FUL,
|
||||
0x2ABE32E1UL, 0xAA54166BUL, 0x22568E3AUL, 0xA2D341D0UL,
|
||||
0x66DB40C8UL, 0xA784392FUL, 0x004DFF2FUL, 0x2DB9D2DEUL,
|
||||
0x97943FACUL, 0x4A97C1D8UL, 0x527644B7UL, 0xB5F437A7UL,
|
||||
0xB82CBAEFUL, 0xD751D159UL, 0x6FF7F0EDUL, 0x5A097A1FUL,
|
||||
0x827B68D0UL, 0x90ECF52EUL, 0x22B0C054UL, 0xBC8E5935UL,
|
||||
0x4B6D2F7FUL, 0x50BB64A2UL, 0xD2664910UL, 0xBEE5812DUL,
|
||||
0xB7332290UL, 0xE93B159FUL, 0xB48EE411UL, 0x4BFF345DUL,
|
||||
0xFD45C240UL, 0xAD31973FUL, 0xC4F6D02EUL, 0x55FC8165UL,
|
||||
0xD5B1CAADUL, 0xA1AC2DAEUL, 0xA2D4B76DUL, 0xC19B0C50UL,
|
||||
0x882240F2UL, 0x0C6E4F38UL, 0xA4E4BFD7UL, 0x4F5BA272UL,
|
||||
0x564C1D2FUL, 0xC59C5319UL, 0xB949E354UL, 0xB04669FEUL,
|
||||
0xB1B6AB8AUL, 0xC71358DDUL, 0x6385C545UL, 0x110F935DUL,
|
||||
0x57538AD5UL, 0x6A390493UL, 0xE63D37E0UL, 0x2A54F6B3UL,
|
||||
0x3A787D5FUL, 0x6276A0B5UL, 0x19A6FCDFUL, 0x7A42206AUL,
|
||||
0x29F9D4D5UL, 0xF61B1891UL, 0xBB72275EUL, 0xAA508167UL,
|
||||
0x38901091UL, 0xC6B505EBUL, 0x84C7CB8CUL, 0x2AD75A0FUL,
|
||||
0x874A1427UL, 0xA2D1936BUL, 0x2AD286AFUL, 0xAA56D291UL,
|
||||
0xD7894360UL, 0x425C750DUL, 0x93B39E26UL, 0x187184C9UL,
|
||||
0x6C00B32DUL, 0x73E2BB14UL, 0xA0BEBC3CUL, 0x54623779UL,
|
||||
0x64459EABUL, 0x3F328B82UL, 0x7718CF82UL, 0x59A2CEA6UL,
|
||||
0x04EE002EUL, 0x89FE78E6UL, 0x3FAB0950UL, 0x325FF6C2UL,
|
||||
0x81383F05UL, 0x6963C5C8UL, 0x76CB5AD6UL, 0xD49974C9UL,
|
||||
0xCA180DCFUL, 0x380782D5UL, 0xC7FA5CF6UL, 0x8AC31511UL,
|
||||
0x35E79E13UL, 0x47DA91D0UL, 0xF40F9086UL, 0xA7E2419EUL,
|
||||
0x31366241UL, 0x051EF495UL, 0xAA573B04UL, 0x4A805D8DUL,
|
||||
0x548300D0UL, 0x00322A3CUL, 0xBF64CDDFUL, 0xBA57A68EUL,
|
||||
0x75C6372BUL, 0x50AFD341UL, 0xA7C13275UL, 0x915A0BF5UL,
|
||||
0x6B54BFABUL, 0x2B0B1426UL, 0xAB4CC9D7UL, 0x449CCD82UL,
|
||||
0xF7FBF265UL, 0xAB85C5F3UL, 0x1B55DB94UL, 0xAAD4E324UL,
|
||||
0xCFA4BD3FUL, 0x2DEAA3E2UL, 0x9E204D02UL, 0xC8BD25ACUL,
|
||||
0xEADF55B3UL, 0xD5BD9E98UL, 0xE31231B2UL, 0x2AD5AD6CUL,
|
||||
0x954329DEUL, 0xADBE4528UL, 0xD8710F69UL, 0xAA51C90FUL,
|
||||
0xAA786BF6UL, 0x22513F1EUL, 0xAA51A79BUL, 0x2AD344CCUL,
|
||||
0x7B5A41F0UL, 0xD37CFBADUL, 0x1B069505UL, 0x41ECE491UL,
|
||||
0xB4C332E6UL, 0x032268D4UL, 0xC9600ACCUL, 0xCE387E6DUL,
|
||||
0xBF6BB16CUL, 0x6A70FB78UL, 0x0D03D9C9UL, 0xD4DF39DEUL,
|
||||
0xE01063DAUL, 0x4736F464UL, 0x5AD328D8UL, 0xB347CC96UL,
|
||||
0x75BB0FC3UL, 0x98511BFBUL, 0x4FFBCC35UL, 0xB58BCF6AUL,
|
||||
0xE11F0ABCUL, 0xBFC5FE4AUL, 0xA70AEC10UL, 0xAC39570AUL,
|
||||
0x3F04442FUL, 0x6188B153UL, 0xE0397A2EUL, 0x5727CB79UL,
|
||||
0x9CEB418FUL, 0x1CACD68DUL, 0x2AD37C96UL, 0x0175CB9DUL,
|
||||
0xC69DFF09UL, 0xC75B65F0UL, 0xD9DB40D8UL, 0xEC0E7779UL,
|
||||
0x4744EAD4UL, 0xB11C3274UL, 0xDD24CB9EUL, 0x7E1C54BDUL,
|
||||
0xF01144F9UL, 0xD2240EB1UL, 0x9675B3FDUL, 0xA3AC3755UL,
|
||||
0xD47C27AFUL, 0x51C85F4DUL, 0x56907596UL, 0xA5BB15E6UL,
|
||||
0x580304F0UL, 0xCA042CF1UL, 0x011A37EAUL, 0x8DBFAADBUL,
|
||||
0x35BA3E4AUL, 0x3526FFA0UL, 0xC37B4D09UL, 0xBC306ED9UL,
|
||||
0x98A52666UL, 0x5648F725UL, 0xFF5E569DUL, 0x0CED63D0UL,
|
||||
0x7C63B2CFUL, 0x700B45E1UL, 0xD5EA50F1UL, 0x85A92872UL,
|
||||
0xAF1FBDA7UL, 0xD4234870UL, 0xA7870BF3UL, 0x2D3B4D79UL,
|
||||
0x42E04198UL, 0x0CD0EDE7UL, 0x26470DB8UL, 0xF881814CUL,
|
||||
0x474D6AD7UL, 0x7C0C5E5CUL, 0xD1231959UL, 0x381B7298UL,
|
||||
0xF5D2F4DBUL, 0xAB838653UL, 0x6E2F1E23UL, 0x83719C9EUL,
|
||||
0xBD91E046UL, 0x9A56456EUL, 0xDC39200CUL, 0x20C8C571UL,
|
||||
0x962BDA1CUL, 0xE1E696FFUL, 0xB141AB08UL, 0x7CCA89B9UL,
|
||||
0x1A69E783UL, 0x02CC4843UL, 0xA2F7C579UL, 0x429EF47DUL,
|
||||
0x427B169CUL, 0x5AC9F049UL, 0xDD8F0F00UL, 0x5C8165BFUL
|
||||
},
|
||||
|
||||
{
|
||||
0x1F201094UL, 0xEF0BA75BUL, 0x69E3CF7EUL, 0x393F4380UL,
|
||||
0xFE61CF7AUL, 0xEEC5207AUL, 0x55889C94UL, 0x72FC0651UL,
|
||||
0xADA7EF79UL, 0x4E1D7235UL, 0xD55A63CEUL, 0xDE0436BAUL,
|
||||
0x99C430EFUL, 0x5F0C0794UL, 0x18DCDB7DUL, 0xA1D6EFF3UL,
|
||||
0xA0B52F7BUL, 0x59E83605UL, 0xEE15B094UL, 0xE9FFD909UL,
|
||||
0xDC440086UL, 0xEF944459UL, 0xBA83CCB3UL, 0xE0C3CDFBUL,
|
||||
0xD1DA4181UL, 0x3B092AB1UL, 0xF997F1C1UL, 0xA5E6CF7BUL,
|
||||
0x01420DDBUL, 0xE4E7EF5BUL, 0x25A1FF41UL, 0xE180F806UL,
|
||||
0x1FC41080UL, 0x179BEE7AUL, 0xD37AC6A9UL, 0xFE5830A4UL,
|
||||
0x98DE8B7FUL, 0x77E83F4EUL, 0x79929269UL, 0x24FA9F7BUL,
|
||||
0xE113C85BUL, 0xACC40083UL, 0xD7503525UL, 0xF7EA615FUL,
|
||||
0x62143154UL, 0x0D554B63UL, 0x5D681121UL, 0xC866C359UL,
|
||||
0x3D63CF73UL, 0xCEE234C0UL, 0xD4D87E87UL, 0x5C672B21UL,
|
||||
0x071F6181UL, 0x39F7627FUL, 0x361E3084UL, 0xE4EB573BUL,
|
||||
0x602F64A4UL, 0xD63ACD9CUL, 0x1BBC4635UL, 0x9E81032DUL,
|
||||
0x2701F50CUL, 0x99847AB4UL, 0xA0E3DF79UL, 0xBA6CF38CUL,
|
||||
0x10843094UL, 0x2537A95EUL, 0xF46F6FFEUL, 0xA1FF3B1FUL,
|
||||
0x208CFB6AUL, 0x8F458C74UL, 0xD9E0A227UL, 0x4EC73A34UL,
|
||||
0xFC884F69UL, 0x3E4DE8DFUL, 0xEF0E0088UL, 0x3559648DUL,
|
||||
0x8A45388CUL, 0x1D804366UL, 0x721D9BFDUL, 0xA58684BBUL,
|
||||
0xE8256333UL, 0x844E8212UL, 0x128D8098UL, 0xFED33FB4UL,
|
||||
0xCE280AE1UL, 0x27E19BA5UL, 0xD5A6C252UL, 0xE49754BDUL,
|
||||
0xC5D655DDUL, 0xEB667064UL, 0x77840B4DUL, 0xA1B6A801UL,
|
||||
0x84DB26A9UL, 0xE0B56714UL, 0x21F043B7UL, 0xE5D05860UL,
|
||||
0x54F03084UL, 0x066FF472UL, 0xA31AA153UL, 0xDADC4755UL,
|
||||
0xB5625DBFUL, 0x68561BE6UL, 0x83CA6B94UL, 0x2D6ED23BUL,
|
||||
0xECCF01DBUL, 0xA6D3D0BAUL, 0xB6803D5CUL, 0xAF77A709UL,
|
||||
0x33B4A34CUL, 0x397BC8D6UL, 0x5EE22B95UL, 0x5F0E5304UL,
|
||||
0x81ED6F61UL, 0x20E74364UL, 0xB45E1378UL, 0xDE18639BUL,
|
||||
0x881CA122UL, 0xB96726D1UL, 0x8049A7E8UL, 0x22B7DA7BUL,
|
||||
0x5E552D25UL, 0x5272D237UL, 0x79D2951CUL, 0xC60D894CUL,
|
||||
0x488CB402UL, 0x1BA4FE5BUL, 0xA4B09F6BUL, 0x1CA815CFUL,
|
||||
0xA20C3005UL, 0x8871DF63UL, 0xB9DE2FCBUL, 0x0CC6C9E9UL,
|
||||
0x0BEEFF53UL, 0xE3214517UL, 0xB4542835UL, 0x9F63293CUL,
|
||||
0xEE41E729UL, 0x6E1D2D7CUL, 0x50045286UL, 0x1E6685F3UL,
|
||||
0xF33401C6UL, 0x30A22C95UL, 0x31A70850UL, 0x60930F13UL,
|
||||
0x73F98417UL, 0xA1269859UL, 0xEC645C44UL, 0x52C877A9UL,
|
||||
0xCDFF33A6UL, 0xA02B1741UL, 0x7CBAD9A2UL, 0x2180036FUL,
|
||||
0x50D99C08UL, 0xCB3F4861UL, 0xC26BD765UL, 0x64A3F6ABUL,
|
||||
0x80342676UL, 0x25A75E7BUL, 0xE4E6D1FCUL, 0x20C710E6UL,
|
||||
0xCDF0B680UL, 0x17844D3BUL, 0x31EEF84DUL, 0x7E0824E4UL,
|
||||
0x2CCB49EBUL, 0x846A3BAEUL, 0x8FF77888UL, 0xEE5D60F6UL,
|
||||
0x7AF75673UL, 0x2FDD5CDBUL, 0xA11631C1UL, 0x30F66F43UL,
|
||||
0xB3FAEC54UL, 0x157FD7FAUL, 0xEF8579CCUL, 0xD152DE58UL,
|
||||
0xDB2FFD5EUL, 0x8F32CE19UL, 0x306AF97AUL, 0x02F03EF8UL,
|
||||
0x99319AD5UL, 0xC242FA0FUL, 0xA7E3EBB0UL, 0xC68E4906UL,
|
||||
0xB8DA230CUL, 0x80823028UL, 0xDCDEF3C8UL, 0xD35FB171UL,
|
||||
0x088A1BC8UL, 0xBEC0C560UL, 0x61A3C9E8UL, 0xBCA8F54DUL,
|
||||
0xC72FEFFAUL, 0x22822E99UL, 0x82C570B4UL, 0xD8D94E89UL,
|
||||
0x8B1C34BCUL, 0x301E16E6UL, 0x273BE979UL, 0xB0FFEAA6UL,
|
||||
0x61D9B8C6UL, 0x00B24869UL, 0xB7FFCE3FUL, 0x08DC283BUL,
|
||||
0x43DAF65AUL, 0xF7E19798UL, 0x7619B72FUL, 0x8F1C9BA4UL,
|
||||
0xDC8637A0UL, 0x16A7D3B1UL, 0x9FC393B7UL, 0xA7136EEBUL,
|
||||
0xC6BCC63EUL, 0x1A513742UL, 0xEF6828BCUL, 0x520365D6UL,
|
||||
0x2D6A77ABUL, 0x3527ED4BUL, 0x821FD216UL, 0x095C6E2EUL,
|
||||
0xDB92F2FBUL, 0x5EEA29CBUL, 0x145892F5UL, 0x91584F7FUL,
|
||||
0x5483697BUL, 0x2667A8CCUL, 0x85196048UL, 0x8C4BACEAUL,
|
||||
0x833860D4UL, 0x0D23E0F9UL, 0x6C387E8AUL, 0x0AE6D249UL,
|
||||
0xB284600CUL, 0xD835731DUL, 0xDCB1C647UL, 0xAC4C56EAUL,
|
||||
0x3EBD81B3UL, 0x230EABB0UL, 0x6438BC87UL, 0xF0B5B1FAUL,
|
||||
0x8F5EA2B3UL, 0xFC184642UL, 0x0A036B7AUL, 0x4FB089BDUL,
|
||||
0x649DA589UL, 0xA345415EUL, 0x5C038323UL, 0x3E5D3BB9UL,
|
||||
0x43D79572UL, 0x7E6DD07CUL, 0x06DFDF1EUL, 0x6C6CC4EFUL,
|
||||
0x7160A539UL, 0x73BFBE70UL, 0x83877605UL, 0x4523ECF1UL
|
||||
},
|
||||
|
||||
{
|
||||
0x8DEFC240UL, 0x25FA5D9FUL, 0xEB903DBFUL, 0xE810C907UL,
|
||||
0x47607FFFUL, 0x369FE44BUL, 0x8C1FC644UL, 0xAECECA90UL,
|
||||
0xBEB1F9BFUL, 0xEEFBCAEAUL, 0xE8CF1950UL, 0x51DF07AEUL,
|
||||
0x920E8806UL, 0xF0AD0548UL, 0xE13C8D83UL, 0x927010D5UL,
|
||||
0x11107D9FUL, 0x07647DB9UL, 0xB2E3E4D4UL, 0x3D4F285EUL,
|
||||
0xB9AFA820UL, 0xFADE82E0UL, 0xA067268BUL, 0x8272792EUL,
|
||||
0x553FB2C0UL, 0x489AE22BUL, 0xD4EF9794UL, 0x125E3FBCUL,
|
||||
0x21FFFCEEUL, 0x825B1BFDUL, 0x9255C5EDUL, 0x1257A240UL,
|
||||
0x4E1A8302UL, 0xBAE07FFFUL, 0x528246E7UL, 0x8E57140EUL,
|
||||
0x3373F7BFUL, 0x8C9F8188UL, 0xA6FC4EE8UL, 0xC982B5A5UL,
|
||||
0xA8C01DB7UL, 0x579FC264UL, 0x67094F31UL, 0xF2BD3F5FUL,
|
||||
0x40FFF7C1UL, 0x1FB78DFCUL, 0x8E6BD2C1UL, 0x437BE59BUL,
|
||||
0x99B03DBFUL, 0xB5DBC64BUL, 0x638DC0E6UL, 0x55819D99UL,
|
||||
0xA197C81CUL, 0x4A012D6EUL, 0xC5884A28UL, 0xCCC36F71UL,
|
||||
0xB843C213UL, 0x6C0743F1UL, 0x8309893CUL, 0x0FEDDD5FUL,
|
||||
0x2F7FE850UL, 0xD7C07F7EUL, 0x02507FBFUL, 0x5AFB9A04UL,
|
||||
0xA747D2D0UL, 0x1651192EUL, 0xAF70BF3EUL, 0x58C31380UL,
|
||||
0x5F98302EUL, 0x727CC3C4UL, 0x0A0FB402UL, 0x0F7FEF82UL,
|
||||
0x8C96FDADUL, 0x5D2C2AAEUL, 0x8EE99A49UL, 0x50DA88B8UL,
|
||||
0x8427F4A0UL, 0x1EAC5790UL, 0x796FB449UL, 0x8252DC15UL,
|
||||
0xEFBD7D9BUL, 0xA672597DUL, 0xADA840D8UL, 0x45F54504UL,
|
||||
0xFA5D7403UL, 0xE83EC305UL, 0x4F91751AUL, 0x925669C2UL,
|
||||
0x23EFE941UL, 0xA903F12EUL, 0x60270DF2UL, 0x0276E4B6UL,
|
||||
0x94FD6574UL, 0x927985B2UL, 0x8276DBCBUL, 0x02778176UL,
|
||||
0xF8AF918DUL, 0x4E48F79EUL, 0x8F616DDFUL, 0xE29D840EUL,
|
||||
0x842F7D83UL, 0x340CE5C8UL, 0x96BBB682UL, 0x93B4B148UL,
|
||||
0xEF303CABUL, 0x984FAF28UL, 0x779FAF9BUL, 0x92DC560DUL,
|
||||
0x224D1E20UL, 0x8437AA88UL, 0x7D29DC96UL, 0x2756D3DCUL,
|
||||
0x8B907CEEUL, 0xB51FD240UL, 0xE7C07CE3UL, 0xE566B4A1UL,
|
||||
0xC3E9615EUL, 0x3CF8209DUL, 0x6094D1E3UL, 0xCD9CA341UL,
|
||||
0x5C76460EUL, 0x00EA983BUL, 0xD4D67881UL, 0xFD47572CUL,
|
||||
0xF76CEDD9UL, 0xBDA8229CUL, 0x127DADAAUL, 0x438A074EUL,
|
||||
0x1F97C090UL, 0x081BDB8AUL, 0x93A07EBEUL, 0xB938CA15UL,
|
||||
0x97B03CFFUL, 0x3DC2C0F8UL, 0x8D1AB2ECUL, 0x64380E51UL,
|
||||
0x68CC7BFBUL, 0xD90F2788UL, 0x12490181UL, 0x5DE5FFD4UL,
|
||||
0xDD7EF86AUL, 0x76A2E214UL, 0xB9A40368UL, 0x925D958FUL,
|
||||
0x4B39FFFAUL, 0xBA39AEE9UL, 0xA4FFD30BUL, 0xFAF7933BUL,
|
||||
0x6D498623UL, 0x193CBCFAUL, 0x27627545UL, 0x825CF47AUL,
|
||||
0x61BD8BA0UL, 0xD11E42D1UL, 0xCEAD04F4UL, 0x127EA392UL,
|
||||
0x10428DB7UL, 0x8272A972UL, 0x9270C4A8UL, 0x127DE50BUL,
|
||||
0x285BA1C8UL, 0x3C62F44FUL, 0x35C0EAA5UL, 0xE805D231UL,
|
||||
0x428929FBUL, 0xB4FCDF82UL, 0x4FB66A53UL, 0x0E7DC15BUL,
|
||||
0x1F081FABUL, 0x108618AEUL, 0xFCFD086DUL, 0xF9FF2889UL,
|
||||
0x694BCC11UL, 0x236A5CAEUL, 0x12DECA4DUL, 0x2C3F8CC5UL,
|
||||
0xD2D02DFEUL, 0xF8EF5896UL, 0xE4CF52DAUL, 0x95155B67UL,
|
||||
0x494A488CUL, 0xB9B6A80CUL, 0x5C8F82BCUL, 0x89D36B45UL,
|
||||
0x3A609437UL, 0xEC00C9A9UL, 0x44715253UL, 0x0A874B49UL,
|
||||
0xD773BC40UL, 0x7C34671CUL, 0x02717EF6UL, 0x4FEB5536UL,
|
||||
0xA2D02FFFUL, 0xD2BF60C4UL, 0xD43F03C0UL, 0x50B4EF6DUL,
|
||||
0x07478CD1UL, 0x006E1888UL, 0xA2E53F55UL, 0xB9E6D4BCUL,
|
||||
0xA2048016UL, 0x97573833UL, 0xD7207D67UL, 0xDE0F8F3DUL,
|
||||
0x72F87B33UL, 0xABCC4F33UL, 0x7688C55DUL, 0x7B00A6B0UL,
|
||||
0x947B0001UL, 0x570075D2UL, 0xF9BB88F8UL, 0x8942019EUL,
|
||||
0x4264A5FFUL, 0x856302E0UL, 0x72DBD92BUL, 0xEE971B69UL,
|
||||
0x6EA22FDEUL, 0x5F08AE2BUL, 0xAF7A616DUL, 0xE5C98767UL,
|
||||
0xCF1FEBD2UL, 0x61EFC8C2UL, 0xF1AC2571UL, 0xCC8239C2UL,
|
||||
0x67214CB8UL, 0xB1E583D1UL, 0xB7DC3E62UL, 0x7F10BDCEUL,
|
||||
0xF90A5C38UL, 0x0FF0443DUL, 0x606E6DC6UL, 0x60543A49UL,
|
||||
0x5727C148UL, 0x2BE98A1DUL, 0x8AB41738UL, 0x20E1BE24UL,
|
||||
0xAF96DA0FUL, 0x68458425UL, 0x99833BE5UL, 0x600D457DUL,
|
||||
0x282F9350UL, 0x8334B362UL, 0xD91D1120UL, 0x2B6D8DA0UL,
|
||||
0x642B1E31UL, 0x9C305A00UL, 0x52BCE688UL, 0x1B03588AUL,
|
||||
0xF7BAEFD5UL, 0x4142ED9CUL, 0xA4315C11UL, 0x83323EC5UL,
|
||||
0xDFEF4636UL, 0xA133C501UL, 0xE9D3531CUL, 0xEE353783UL
|
||||
},
|
||||
|
||||
{
|
||||
0x9DB30420UL, 0x1FB6E9DEUL, 0xA7BE7BEFUL, 0xD273A298UL,
|
||||
0x4A4F7BDBUL, 0x64AD8C57UL, 0x85510443UL, 0xFA020ED1UL,
|
||||
0x7E287AFFUL, 0xE60FB663UL, 0x095F35A1UL, 0x79EBF120UL,
|
||||
0xFD059D43UL, 0x6497B7B1UL, 0xF3641F63UL, 0x241E4ADFUL,
|
||||
0x28147F5FUL, 0x4FA2B8CDUL, 0xC9430040UL, 0x0CC32220UL,
|
||||
0xFDD30B30UL, 0xC0A5374FUL, 0x1D2D00D9UL, 0x24147B15UL,
|
||||
0xEE4D111AUL, 0x0FCA5167UL, 0x71FF904CUL, 0x2D195FFEUL,
|
||||
0x1A05645FUL, 0x0C13FEFEUL, 0x081B08CAUL, 0x05170121UL,
|
||||
0x80530100UL, 0xE83E5EFEUL, 0xAC9AF4F8UL, 0x7FE72701UL,
|
||||
0xD2B8EE5FUL, 0x06DF4261UL, 0xBB9E9B8AUL, 0x7293EA25UL,
|
||||
0xCE84FFDFUL, 0xF5718801UL, 0x3DD64B04UL, 0xA26F263BUL,
|
||||
0x7ED48400UL, 0x547EEBE6UL, 0x446D4CA0UL, 0x6CF3D6F5UL,
|
||||
0x2649ABDFUL, 0xAEA0C7F5UL, 0x36338CC1UL, 0x503F7E93UL,
|
||||
0xD3772061UL, 0x11B638E1UL, 0x72500E03UL, 0xF80EB2BBUL,
|
||||
0xABE0502EUL, 0xEC8D77DEUL, 0x57971E81UL, 0xE14F6746UL,
|
||||
0xC9335400UL, 0x6920318FUL, 0x081DBB99UL, 0xFFC304A5UL,
|
||||
0x4D351805UL, 0x7F3D5CE3UL, 0xA6C866C6UL, 0x5D5BCCA9UL,
|
||||
0xDAEC6FEAUL, 0x9F926F91UL, 0x9F46222FUL, 0x3991467DUL,
|
||||
0xA5BF6D8EUL, 0x1143C44FUL, 0x43958302UL, 0xD0214EEBUL,
|
||||
0x022083B8UL, 0x3FB6180CUL, 0x18F8931EUL, 0x281658E6UL,
|
||||
0x26486E3EUL, 0x8BD78A70UL, 0x7477E4C1UL, 0xB506E07CUL,
|
||||
0xF32D0A25UL, 0x79098B02UL, 0xE4EABB81UL, 0x28123B23UL,
|
||||
0x69DEAD38UL, 0x1574CA16UL, 0xDF871B62UL, 0x211C40B7UL,
|
||||
0xA51A9EF9UL, 0x0014377BUL, 0x041E8AC8UL, 0x09114003UL,
|
||||
0xBD59E4D2UL, 0xE3D156D5UL, 0x4FE876D5UL, 0x2F91A340UL,
|
||||
0x557BE8DEUL, 0x00EAE4A7UL, 0x0CE5C2ECUL, 0x4DB4BBA6UL,
|
||||
0xE756BDFFUL, 0xDD3369ACUL, 0xEC17B035UL, 0x06572327UL,
|
||||
0x99AFC8B0UL, 0x56C8C391UL, 0x6B65811CUL, 0x5E146119UL,
|
||||
0x6E85CB75UL, 0xBE07C002UL, 0xC2325577UL, 0x893FF4ECUL,
|
||||
0x5BBFC92DUL, 0xD0EC3B25UL, 0xB7801AB7UL, 0x8D6D3B24UL,
|
||||
0x20C763EFUL, 0xC366A5FCUL, 0x9C382880UL, 0x0ACE3205UL,
|
||||
0xAAC9548AUL, 0xECA1D7C7UL, 0x041AFA32UL, 0x1D16625AUL,
|
||||
0x6701902CUL, 0x9B757A54UL, 0x31D477F7UL, 0x9126B031UL,
|
||||
0x36CC6FDBUL, 0xC70B8B46UL, 0xD9E66A48UL, 0x56E55A79UL,
|
||||
0x026A4CEBUL, 0x52437EFFUL, 0x2F8F76B4UL, 0x0DF980A5UL,
|
||||
0x8674CDE3UL, 0xEDDA04EBUL, 0x17A9BE04UL, 0x2C18F4DFUL,
|
||||
0xB7747F9DUL, 0xAB2AF7B4UL, 0xEFC34D20UL, 0x2E096B7CUL,
|
||||
0x1741A254UL, 0xE5B6A035UL, 0x213D42F6UL, 0x2C1C7C26UL,
|
||||
0x61C2F50FUL, 0x6552DAF9UL, 0xD2C231F8UL, 0x25130F69UL,
|
||||
0xD8167FA2UL, 0x0418F2C8UL, 0x001A96A6UL, 0x0D1526ABUL,
|
||||
0x63315C21UL, 0x5E0A72ECUL, 0x49BAFEFDUL, 0x187908D9UL,
|
||||
0x8D0DBD86UL, 0x311170A7UL, 0x3E9B640CUL, 0xCC3E10D7UL,
|
||||
0xD5CAD3B6UL, 0x0CAEC388UL, 0xF73001E1UL, 0x6C728AFFUL,
|
||||
0x71EAE2A1UL, 0x1F9AF36EUL, 0xCFCBD12FUL, 0xC1DE8417UL,
|
||||
0xAC07BE6BUL, 0xCB44A1D8UL, 0x8B9B0F56UL, 0x013988C3UL,
|
||||
0xB1C52FCAUL, 0xB4BE31CDUL, 0xD8782806UL, 0x12A3A4E2UL,
|
||||
0x6F7DE532UL, 0x58FD7EB6UL, 0xD01EE900UL, 0x24ADFFC2UL,
|
||||
0xF4990FC5UL, 0x9711AAC5UL, 0x001D7B95UL, 0x82E5E7D2UL,
|
||||
0x109873F6UL, 0x00613096UL, 0xC32D9521UL, 0xADA121FFUL,
|
||||
0x29908415UL, 0x7FBB977FUL, 0xAF9EB3DBUL, 0x29C9ED2AUL,
|
||||
0x5CE2A465UL, 0xA730F32CUL, 0xD0AA3FE8UL, 0x8A5CC091UL,
|
||||
0xD49E2CE7UL, 0x0CE454A9UL, 0xD60ACD86UL, 0x015F1919UL,
|
||||
0x77079103UL, 0xDEA03AF6UL, 0x78A8565EUL, 0xDEE356DFUL,
|
||||
0x21F05CBEUL, 0x8B75E387UL, 0xB3C50651UL, 0xB8A5C3EFUL,
|
||||
0xD8EEB6D2UL, 0xE523BE77UL, 0xC2154529UL, 0x2F69EFDFUL,
|
||||
0xAFE67AFBUL, 0xF470C4B2UL, 0xF3E0EB5BUL, 0xD6CC9876UL,
|
||||
0x39E4460CUL, 0x1FDA8538UL, 0x1987832FUL, 0xCA007367UL,
|
||||
0xA99144F8UL, 0x296B299EUL, 0x492FC295UL, 0x9266BEABUL,
|
||||
0xB5676E69UL, 0x9BD3DDDAUL, 0xDF7E052FUL, 0xDB25701CUL,
|
||||
0x1B5E51EEUL, 0xF65324E6UL, 0x6AFCE36CUL, 0x0316CC04UL,
|
||||
0x8644213EUL, 0xB7DC59D0UL, 0x7965291FUL, 0xCCD6FD43UL,
|
||||
0x41823979UL, 0x932BCDF6UL, 0xB657C34DUL, 0x4EDFD282UL,
|
||||
0x7AE5290CUL, 0x3CB9536BUL, 0x851E20FEUL, 0x9833557EUL,
|
||||
0x13ECF0B0UL, 0xD3FFB372UL, 0x3F85C5C1UL, 0x0AEF7ED2UL
|
||||
},
|
||||
|
||||
{
|
||||
0x7EC90C04UL, 0x2C6E74B9UL, 0x9B0E66DFUL, 0xA6337911UL,
|
||||
0xB86A7FFFUL, 0x1DD358F5UL, 0x44DD9D44UL, 0x1731167FUL,
|
||||
0x08FBF1FAUL, 0xE7F511CCUL, 0xD2051B00UL, 0x735ABA00UL,
|
||||
0x2AB722D8UL, 0x386381CBUL, 0xACF6243AUL, 0x69BEFD7AUL,
|
||||
0xE6A2E77FUL, 0xF0C720CDUL, 0xC4494816UL, 0xCCF5C180UL,
|
||||
0x38851640UL, 0x15B0A848UL, 0xE68B18CBUL, 0x4CAADEFFUL,
|
||||
0x5F480A01UL, 0x0412B2AAUL, 0x259814FCUL, 0x41D0EFE2UL,
|
||||
0x4E40B48DUL, 0x248EB6FBUL, 0x8DBA1CFEUL, 0x41A99B02UL,
|
||||
0x1A550A04UL, 0xBA8F65CBUL, 0x7251F4E7UL, 0x95A51725UL,
|
||||
0xC106ECD7UL, 0x97A5980AUL, 0xC539B9AAUL, 0x4D79FE6AUL,
|
||||
0xF2F3F763UL, 0x68AF8040UL, 0xED0C9E56UL, 0x11B4958BUL,
|
||||
0xE1EB5A88UL, 0x8709E6B0UL, 0xD7E07156UL, 0x4E29FEA7UL,
|
||||
0x6366E52DUL, 0x02D1C000UL, 0xC4AC8E05UL, 0x9377F571UL,
|
||||
0x0C05372AUL, 0x578535F2UL, 0x2261BE02UL, 0xD642A0C9UL,
|
||||
0xDF13A280UL, 0x74B55BD2UL, 0x682199C0UL, 0xD421E5ECUL,
|
||||
0x53FB3CE8UL, 0xC8ADEDB3UL, 0x28A87FC9UL, 0x3D959981UL,
|
||||
0x5C1FF900UL, 0xFE38D399UL, 0x0C4EFF0BUL, 0x062407EAUL,
|
||||
0xAA2F4FB1UL, 0x4FB96976UL, 0x90C79505UL, 0xB0A8A774UL,
|
||||
0xEF55A1FFUL, 0xE59CA2C2UL, 0xA6B62D27UL, 0xE66A4263UL,
|
||||
0xDF65001FUL, 0x0EC50966UL, 0xDFDD55BCUL, 0x29DE0655UL,
|
||||
0x911E739AUL, 0x17AF8975UL, 0x32C7911CUL, 0x89F89468UL,
|
||||
0x0D01E980UL, 0x524755F4UL, 0x03B63CC9UL, 0x0CC844B2UL,
|
||||
0xBCF3F0AAUL, 0x87AC36E9UL, 0xE53A7426UL, 0x01B3D82BUL,
|
||||
0x1A9E7449UL, 0x64EE2D7EUL, 0xCDDBB1DAUL, 0x01C94910UL,
|
||||
0xB868BF80UL, 0x0D26F3FDUL, 0x9342EDE7UL, 0x04A5C284UL,
|
||||
0x636737B6UL, 0x50F5B616UL, 0xF24766E3UL, 0x8ECA36C1UL,
|
||||
0x136E05DBUL, 0xFEF18391UL, 0xFB887A37UL, 0xD6E7F7D4UL,
|
||||
0xC7FB7DC9UL, 0x3063FCDFUL, 0xB6F589DEUL, 0xEC2941DAUL,
|
||||
0x26E46695UL, 0xB7566419UL, 0xF654EFC5UL, 0xD08D58B7UL,
|
||||
0x48925401UL, 0xC1BACB7FUL, 0xE5FF550FUL, 0xB6083049UL,
|
||||
0x5BB5D0E8UL, 0x87D72E5AUL, 0xAB6A6EE1UL, 0x223A66CEUL,
|
||||
0xC62BF3CDUL, 0x9E0885F9UL, 0x68CB3E47UL, 0x086C010FUL,
|
||||
0xA21DE820UL, 0xD18B69DEUL, 0xF3F65777UL, 0xFA02C3F6UL,
|
||||
0x407EDAC3UL, 0xCBB3D550UL, 0x1793084DUL, 0xB0D70EBAUL,
|
||||
0x0AB378D5UL, 0xD951FB0CUL, 0xDED7DA56UL, 0x4124BBE4UL,
|
||||
0x94CA0B56UL, 0x0F5755D1UL, 0xE0E1E56EUL, 0x6184B5BEUL,
|
||||
0x580A249FUL, 0x94F74BC0UL, 0xE327888EUL, 0x9F7B5561UL,
|
||||
0xC3DC0280UL, 0x05687715UL, 0x646C6BD7UL, 0x44904DB3UL,
|
||||
0x66B4F0A3UL, 0xC0F1648AUL, 0x697ED5AFUL, 0x49E92FF6UL,
|
||||
0x309E374FUL, 0x2CB6356AUL, 0x85808573UL, 0x4991F840UL,
|
||||
0x76F0AE02UL, 0x083BE84DUL, 0x28421C9AUL, 0x44489406UL,
|
||||
0x736E4CB8UL, 0xC1092910UL, 0x8BC95FC6UL, 0x7D869CF4UL,
|
||||
0x134F616FUL, 0x2E77118DUL, 0xB31B2BE1UL, 0xAA90B472UL,
|
||||
0x3CA5D717UL, 0x7D161BBAUL, 0x9CAD9010UL, 0xAF462BA2UL,
|
||||
0x9FE459D2UL, 0x45D34559UL, 0xD9F2DA13UL, 0xDBC65487UL,
|
||||
0xF3E4F94EUL, 0x176D486FUL, 0x097C13EAUL, 0x631DA5C7UL,
|
||||
0x445F7382UL, 0x175683F4UL, 0xCDC66A97UL, 0x70BE0288UL,
|
||||
0xB3CDCF72UL, 0x6E5DD2F3UL, 0x20936079UL, 0x459B80A5UL,
|
||||
0xBE60E2DBUL, 0xA9C23101UL, 0xEBA5315CUL, 0x224E42F2UL,
|
||||
0x1C5C1572UL, 0xF6721B2CUL, 0x1AD2FFF3UL, 0x8C25404EUL,
|
||||
0x324ED72FUL, 0x4067B7FDUL, 0x0523138EUL, 0x5CA3BC78UL,
|
||||
0xDC0FD66EUL, 0x75922283UL, 0x784D6B17UL, 0x58EBB16EUL,
|
||||
0x44094F85UL, 0x3F481D87UL, 0xFCFEAE7BUL, 0x77B5FF76UL,
|
||||
0x8C2302BFUL, 0xAAF47556UL, 0x5F46B02AUL, 0x2B092801UL,
|
||||
0x3D38F5F7UL, 0x0CA81F36UL, 0x52AF4A8AUL, 0x66D5E7C0UL,
|
||||
0xDF3B0874UL, 0x95055110UL, 0x1B5AD7A8UL, 0xF61ED5ADUL,
|
||||
0x6CF6E479UL, 0x20758184UL, 0xD0CEFA65UL, 0x88F7BE58UL,
|
||||
0x4A046826UL, 0x0FF6F8F3UL, 0xA09C7F70UL, 0x5346ABA0UL,
|
||||
0x5CE96C28UL, 0xE176EDA3UL, 0x6BAC307FUL, 0x376829D2UL,
|
||||
0x85360FA9UL, 0x17E3FE2AUL, 0x24B79767UL, 0xF5A96B20UL,
|
||||
0xD6CD2595UL, 0x68FF1EBFUL, 0x7555442CUL, 0xF19F06BEUL,
|
||||
0xF9E0659AUL, 0xEEB9491DUL, 0x34010718UL, 0xBB30CAB8UL,
|
||||
0xE822FE15UL, 0x88570983UL, 0x750E6249UL, 0xDA627E55UL,
|
||||
0x5E76FFA8UL, 0xB1534546UL, 0x6D47DE08UL, 0xEFE9E7D4UL
|
||||
},
|
||||
|
||||
{
|
||||
0xF6FA8F9DUL, 0x2CAC6CE1UL, 0x4CA34867UL, 0xE2337F7CUL,
|
||||
0x95DB08E7UL, 0x016843B4UL, 0xECED5CBCUL, 0x325553ACUL,
|
||||
0xBF9F0960UL, 0xDFA1E2EDUL, 0x83F0579DUL, 0x63ED86B9UL,
|
||||
0x1AB6A6B8UL, 0xDE5EBE39UL, 0xF38FF732UL, 0x8989B138UL,
|
||||
0x33F14961UL, 0xC01937BDUL, 0xF506C6DAUL, 0xE4625E7EUL,
|
||||
0xA308EA99UL, 0x4E23E33CUL, 0x79CBD7CCUL, 0x48A14367UL,
|
||||
0xA3149619UL, 0xFEC94BD5UL, 0xA114174AUL, 0xEAA01866UL,
|
||||
0xA084DB2DUL, 0x09A8486FUL, 0xA888614AUL, 0x2900AF98UL,
|
||||
0x01665991UL, 0xE1992863UL, 0xC8F30C60UL, 0x2E78EF3CUL,
|
||||
0xD0D51932UL, 0xCF0FEC14UL, 0xF7CA07D2UL, 0xD0A82072UL,
|
||||
0xFD41197EUL, 0x9305A6B0UL, 0xE86BE3DAUL, 0x74BED3CDUL,
|
||||
0x372DA53CUL, 0x4C7F4448UL, 0xDAB5D440UL, 0x6DBA0EC3UL,
|
||||
0x083919A7UL, 0x9FBAEED9UL, 0x49DBCFB0UL, 0x4E670C53UL,
|
||||
0x5C3D9C01UL, 0x64BDB941UL, 0x2C0E636AUL, 0xBA7DD9CDUL,
|
||||
0xEA6F7388UL, 0xE70BC762UL, 0x35F29ADBUL, 0x5C4CDD8DUL,
|
||||
0xF0D48D8CUL, 0xB88153E2UL, 0x08A19866UL, 0x1AE2EAC8UL,
|
||||
0x284CAF89UL, 0xAA928223UL, 0x9334BE53UL, 0x3B3A21BFUL,
|
||||
0x16434BE3UL, 0x9AEA3906UL, 0xEFE8C36EUL, 0xF890CDD9UL,
|
||||
0x80226DAEUL, 0xC340A4A3UL, 0xDF7E9C09UL, 0xA694A807UL,
|
||||
0x5B7C5ECCUL, 0x221DB3A6UL, 0x9A69A02FUL, 0x68818A54UL,
|
||||
0xCEB2296FUL, 0x53C0843AUL, 0xFE893655UL, 0x25BFE68AUL,
|
||||
0xB4628ABCUL, 0xCF222EBFUL, 0x25AC6F48UL, 0xA9A99387UL,
|
||||
0x53BDDB65UL, 0xE76FFBE7UL, 0xE967FD78UL, 0x0BA93563UL,
|
||||
0x8E342BC1UL, 0xE8A11BE9UL, 0x4980740DUL, 0xC8087DFCUL,
|
||||
0x8DE4BF99UL, 0xA11101A0UL, 0x7FD37975UL, 0xDA5A26C0UL,
|
||||
0xE81F994FUL, 0x9528CD89UL, 0xFD339FEDUL, 0xB87834BFUL,
|
||||
0x5F04456DUL, 0x22258698UL, 0xC9C4C83BUL, 0x2DC156BEUL,
|
||||
0x4F628DAAUL, 0x57F55EC5UL, 0xE2220ABEUL, 0xD2916EBFUL,
|
||||
0x4EC75B95UL, 0x24F2C3C0UL, 0x42D15D99UL, 0xCD0D7FA0UL,
|
||||
0x7B6E27FFUL, 0xA8DC8AF0UL, 0x7345C106UL, 0xF41E232FUL,
|
||||
0x35162386UL, 0xE6EA8926UL, 0x3333B094UL, 0x157EC6F2UL,
|
||||
0x372B74AFUL, 0x692573E4UL, 0xE9A9D848UL, 0xF3160289UL,
|
||||
0x3A62EF1DUL, 0xA787E238UL, 0xF3A5F676UL, 0x74364853UL,
|
||||
0x20951063UL, 0x4576698DUL, 0xB6FAD407UL, 0x592AF950UL,
|
||||
0x36F73523UL, 0x4CFB6E87UL, 0x7DA4CEC0UL, 0x6C152DAAUL,
|
||||
0xCB0396A8UL, 0xC50DFE5DUL, 0xFCD707ABUL, 0x0921C42FUL,
|
||||
0x89DFF0BBUL, 0x5FE2BE78UL, 0x448F4F33UL, 0x754613C9UL,
|
||||
0x2B05D08DUL, 0x48B9D585UL, 0xDC049441UL, 0xC8098F9BUL,
|
||||
0x7DEDE786UL, 0xC39A3373UL, 0x42410005UL, 0x6A091751UL,
|
||||
0x0EF3C8A6UL, 0x890072D6UL, 0x28207682UL, 0xA9A9F7BEUL,
|
||||
0xBF32679DUL, 0xD45B5B75UL, 0xB353FD00UL, 0xCBB0E358UL,
|
||||
0x830F220AUL, 0x1F8FB214UL, 0xD372CF08UL, 0xCC3C4A13UL,
|
||||
0x8CF63166UL, 0x061C87BEUL, 0x88C98F88UL, 0x6062E397UL,
|
||||
0x47CF8E7AUL, 0xB6C85283UL, 0x3CC2ACFBUL, 0x3FC06976UL,
|
||||
0x4E8F0252UL, 0x64D8314DUL, 0xDA3870E3UL, 0x1E665459UL,
|
||||
0xC10908F0UL, 0x513021A5UL, 0x6C5B68B7UL, 0x822F8AA0UL,
|
||||
0x3007CD3EUL, 0x74719EEFUL, 0xDC872681UL, 0x073340D4UL,
|
||||
0x7E432FD9UL, 0x0C5EC241UL, 0x8809286CUL, 0xF592D891UL,
|
||||
0x08A930F6UL, 0x957EF305UL, 0xB7FBFFBDUL, 0xC266E96FUL,
|
||||
0x6FE4AC98UL, 0xB173ECC0UL, 0xBC60B42AUL, 0x953498DAUL,
|
||||
0xFBA1AE12UL, 0x2D4BD736UL, 0x0F25FAABUL, 0xA4F3FCEBUL,
|
||||
0xE2969123UL, 0x257F0C3DUL, 0x9348AF49UL, 0x361400BCUL,
|
||||
0xE8816F4AUL, 0x3814F200UL, 0xA3F94043UL, 0x9C7A54C2UL,
|
||||
0xBC704F57UL, 0xDA41E7F9UL, 0xC25AD33AUL, 0x54F4A084UL,
|
||||
0xB17F5505UL, 0x59357CBEUL, 0xEDBD15C8UL, 0x7F97C5ABUL,
|
||||
0xBA5AC7B5UL, 0xB6F6DEAFUL, 0x3A479C3AUL, 0x5302DA25UL,
|
||||
0x653D7E6AUL, 0x54268D49UL, 0x51A477EAUL, 0x5017D55BUL,
|
||||
0xD7D25D88UL, 0x44136C76UL, 0x0404A8C8UL, 0xB8E5A121UL,
|
||||
0xB81A928AUL, 0x60ED5869UL, 0x97C55B96UL, 0xEAEC991BUL,
|
||||
0x29935913UL, 0x01FDB7F1UL, 0x088E8DFAUL, 0x9AB6F6F5UL,
|
||||
0x3B4CBF9FUL, 0x4A5DE3ABUL, 0xE6051D35UL, 0xA0E1D855UL,
|
||||
0xD36B4CF1UL, 0xF544EDEBUL, 0xB0E93524UL, 0xBEBB8FBDUL,
|
||||
0xA2D762CFUL, 0x49C92F54UL, 0x38B5F331UL, 0x7128A454UL,
|
||||
0x48392905UL, 0xA65B1DB8UL, 0x851C97BDUL, 0xD675CF2FUL
|
||||
},
|
||||
|
||||
{
|
||||
0x85E04019UL, 0x332BF567UL, 0x662DBFFFUL, 0xCFC65693UL,
|
||||
0x2A8D7F6FUL, 0xAB9BC912UL, 0xDE6008A1UL, 0x2028DA1FUL,
|
||||
0x0227BCE7UL, 0x4D642916UL, 0x18FAC300UL, 0x50F18B82UL,
|
||||
0x2CB2CB11UL, 0xB232E75CUL, 0x4B3695F2UL, 0xB28707DEUL,
|
||||
0xA05FBCF6UL, 0xCD4181E9UL, 0xE150210CUL, 0xE24EF1BDUL,
|
||||
0xB168C381UL, 0xFDE4E789UL, 0x5C79B0D8UL, 0x1E8BFD43UL,
|
||||
0x4D495001UL, 0x38BE4341UL, 0x913CEE1DUL, 0x92A79C3FUL,
|
||||
0x089766BEUL, 0xBAEEADF4UL, 0x1286BECFUL, 0xB6EACB19UL,
|
||||
0x2660C200UL, 0x7565BDE4UL, 0x64241F7AUL, 0x8248DCA9UL,
|
||||
0xC3B3AD66UL, 0x28136086UL, 0x0BD8DFA8UL, 0x356D1CF2UL,
|
||||
0x107789BEUL, 0xB3B2E9CEUL, 0x0502AA8FUL, 0x0BC0351EUL,
|
||||
0x166BF52AUL, 0xEB12FF82UL, 0xE3486911UL, 0xD34D7516UL,
|
||||
0x4E7B3AFFUL, 0x5F43671BUL, 0x9CF6E037UL, 0x4981AC83UL,
|
||||
0x334266CEUL, 0x8C9341B7UL, 0xD0D854C0UL, 0xCB3A6C88UL,
|
||||
0x47BC2829UL, 0x4725BA37UL, 0xA66AD22BUL, 0x7AD61F1EUL,
|
||||
0x0C5CBAFAUL, 0x4437F107UL, 0xB6E79962UL, 0x42D2D816UL,
|
||||
0x0A961288UL, 0xE1A5C06EUL, 0x13749E67UL, 0x72FC081AUL,
|
||||
0xB1D139F7UL, 0xF9583745UL, 0xCF19DF58UL, 0xBEC3F756UL,
|
||||
0xC06EBA30UL, 0x07211B24UL, 0x45C28829UL, 0xC95E317FUL,
|
||||
0xBC8EC511UL, 0x38BC46E9UL, 0xC6E6FA14UL, 0xBAE8584AUL,
|
||||
0xAD4EBC46UL, 0x468F508BUL, 0x7829435FUL, 0xF124183BUL,
|
||||
0x821DBA9FUL, 0xAFF60FF4UL, 0xEA2C4E6DUL, 0x16E39264UL,
|
||||
0x92544A8BUL, 0x009B4FC3UL, 0xABA68CEDUL, 0x9AC96F78UL,
|
||||
0x06A5B79AUL, 0xB2856E6EUL, 0x1AEC3CA9UL, 0xBE838688UL,
|
||||
0x0E0804E9UL, 0x55F1BE56UL, 0xE7E5363BUL, 0xB3A1F25DUL,
|
||||
0xF7DEBB85UL, 0x61FE033CUL, 0x16746233UL, 0x3C034C28UL,
|
||||
0xDA6D0C74UL, 0x79AAC56CUL, 0x3CE4E1ADUL, 0x51F0C802UL,
|
||||
0x98F8F35AUL, 0x1626A49FUL, 0xEED82B29UL, 0x1D382FE3UL,
|
||||
0x0C4FB99AUL, 0xBB325778UL, 0x3EC6D97BUL, 0x6E77A6A9UL,
|
||||
0xCB658B5CUL, 0xD45230C7UL, 0x2BD1408BUL, 0x60C03EB7UL,
|
||||
0xB9068D78UL, 0xA33754F4UL, 0xF430C87DUL, 0xC8A71302UL,
|
||||
0xB96D8C32UL, 0xEBD4E7BEUL, 0xBE8B9D2DUL, 0x7979FB06UL,
|
||||
0xE7225308UL, 0x8B75CF77UL, 0x11EF8DA4UL, 0xE083C858UL,
|
||||
0x8D6B786FUL, 0x5A6317A6UL, 0xFA5CF7A0UL, 0x5DDA0033UL,
|
||||
0xF28EBFB0UL, 0xF5B9C310UL, 0xA0EAC280UL, 0x08B9767AUL,
|
||||
0xA3D9D2B0UL, 0x79D34217UL, 0x021A718DUL, 0x9AC6336AUL,
|
||||
0x2711FD60UL, 0x438050E3UL, 0x069908A8UL, 0x3D7FEDC4UL,
|
||||
0x826D2BEFUL, 0x4EEB8476UL, 0x488DCF25UL, 0x36C9D566UL,
|
||||
0x28E74E41UL, 0xC2610ACAUL, 0x3D49A9CFUL, 0xBAE3B9DFUL,
|
||||
0xB65F8DE6UL, 0x92AEAF64UL, 0x3AC7D5E6UL, 0x9EA80509UL,
|
||||
0xF22B017DUL, 0xA4173F70UL, 0xDD1E16C3UL, 0x15E0D7F9UL,
|
||||
0x50B1B887UL, 0x2B9F4FD5UL, 0x625ABA82UL, 0x6A017962UL,
|
||||
0x2EC01B9CUL, 0x15488AA9UL, 0xD716E740UL, 0x40055A2CUL,
|
||||
0x93D29A22UL, 0xE32DBF9AUL, 0x058745B9UL, 0x3453DC1EUL,
|
||||
0xD699296EUL, 0x496CFF6FUL, 0x1C9F4986UL, 0xDFE2ED07UL,
|
||||
0xB87242D1UL, 0x19DE7EAEUL, 0x053E561AUL, 0x15AD6F8CUL,
|
||||
0x66626C1CUL, 0x7154C24CUL, 0xEA082B2AUL, 0x93EB2939UL,
|
||||
0x17DCB0F0UL, 0x58D4F2AEUL, 0x9EA294FBUL, 0x52CF564CUL,
|
||||
0x9883FE66UL, 0x2EC40581UL, 0x763953C3UL, 0x01D6692EUL,
|
||||
0xD3A0C108UL, 0xA1E7160EUL, 0xE4F2DFA6UL, 0x693ED285UL,
|
||||
0x74904698UL, 0x4C2B0EDDUL, 0x4F757656UL, 0x5D393378UL,
|
||||
0xA132234FUL, 0x3D321C5DUL, 0xC3F5E194UL, 0x4B269301UL,
|
||||
0xC79F022FUL, 0x3C997E7EUL, 0x5E4F9504UL, 0x3FFAFBBDUL,
|
||||
0x76F7AD0EUL, 0x296693F4UL, 0x3D1FCE6FUL, 0xC61E45BEUL,
|
||||
0xD3B5AB34UL, 0xF72BF9B7UL, 0x1B0434C0UL, 0x4E72B567UL,
|
||||
0x5592A33DUL, 0xB5229301UL, 0xCFD2A87FUL, 0x60AEB767UL,
|
||||
0x1814386BUL, 0x30BCC33DUL, 0x38A0C07DUL, 0xFD1606F2UL,
|
||||
0xC363519BUL, 0x589DD390UL, 0x5479F8E6UL, 0x1CB8D647UL,
|
||||
0x97FD61A9UL, 0xEA7759F4UL, 0x2D57539DUL, 0x569A58CFUL,
|
||||
0xE84E63ADUL, 0x462E1B78UL, 0x6580F87EUL, 0xF3817914UL,
|
||||
0x91DA55F4UL, 0x40A230F3UL, 0xD1988F35UL, 0xB6E318D2UL,
|
||||
0x3FFA50BCUL, 0x3D40F021UL, 0xC3C0BDAEUL, 0x4958C24CUL,
|
||||
0x518F36B2UL, 0x84B1D370UL, 0x0FEDCE83UL, 0x878DDADAUL,
|
||||
0xF2A279C7UL, 0x94E01BE8UL, 0x90716F4BUL, 0x954B8AA3UL
|
||||
},
|
||||
|
||||
{
|
||||
0xE216300DUL, 0xBBDDFFFCUL, 0xA7EBDABDUL, 0x35648095UL,
|
||||
0x7789F8B7UL, 0xE6C1121BUL, 0x0E241600UL, 0x052CE8B5UL,
|
||||
0x11A9CFB0UL, 0xE5952F11UL, 0xECE7990AUL, 0x9386D174UL,
|
||||
0x2A42931CUL, 0x76E38111UL, 0xB12DEF3AUL, 0x37DDDDFCUL,
|
||||
0xDE9ADEB1UL, 0x0A0CC32CUL, 0xBE197029UL, 0x84A00940UL,
|
||||
0xBB243A0FUL, 0xB4D137CFUL, 0xB44E79F0UL, 0x049EEDFDUL,
|
||||
0x0B15A15DUL, 0x480D3168UL, 0x8BBBDE5AUL, 0x669DED42UL,
|
||||
0xC7ECE831UL, 0x3F8F95E7UL, 0x72DF191BUL, 0x7580330DUL,
|
||||
0x94074251UL, 0x5C7DCDFAUL, 0xABBE6D63UL, 0xAA402164UL,
|
||||
0xB301D40AUL, 0x02E7D1CAUL, 0x53571DAEUL, 0x7A3182A2UL,
|
||||
0x12A8DDECUL, 0xFDAA335DUL, 0x176F43E8UL, 0x71FB46D4UL,
|
||||
0x38129022UL, 0xCE949AD4UL, 0xB84769ADUL, 0x965BD862UL,
|
||||
0x82F3D055UL, 0x66FB9767UL, 0x15B80B4EUL, 0x1D5B47A0UL,
|
||||
0x4CFDE06FUL, 0xC28EC4B8UL, 0x57E8726EUL, 0x647A78FCUL,
|
||||
0x99865D44UL, 0x608BD593UL, 0x6C200E03UL, 0x39DC5FF6UL,
|
||||
0x5D0B00A3UL, 0xAE63AFF2UL, 0x7E8BD632UL, 0x70108C0CUL,
|
||||
0xBBD35049UL, 0x2998DF04UL, 0x980CF42AUL, 0x9B6DF491UL,
|
||||
0x9E7EDD53UL, 0x06918548UL, 0x58CB7E07UL, 0x3B74EF2EUL,
|
||||
0x522FFFB1UL, 0xD24708CCUL, 0x1C7E27CDUL, 0xA4EB215BUL,
|
||||
0x3CF1D2E2UL, 0x19B47A38UL, 0x424F7618UL, 0x35856039UL,
|
||||
0x9D17DEE7UL, 0x27EB35E6UL, 0xC9AFF67BUL, 0x36BAF5B8UL,
|
||||
0x09C467CDUL, 0xC18910B1UL, 0xE11DBF7BUL, 0x06CD1AF8UL,
|
||||
0x7170C608UL, 0x2D5E3354UL, 0xD4DE495AUL, 0x64C6D006UL,
|
||||
0xBCC0C62CUL, 0x3DD00DB3UL, 0x708F8F34UL, 0x77D51B42UL,
|
||||
0x264F620FUL, 0x24B8D2BFUL, 0x15C1B79EUL, 0x46A52564UL,
|
||||
0xF8D7E54EUL, 0x3E378160UL, 0x7895CDA5UL, 0x859C15A5UL,
|
||||
0xE6459788UL, 0xC37BC75FUL, 0xDB07BA0CUL, 0x0676A3ABUL,
|
||||
0x7F229B1EUL, 0x31842E7BUL, 0x24259FD7UL, 0xF8BEF472UL,
|
||||
0x835FFCB8UL, 0x6DF4C1F2UL, 0x96F5B195UL, 0xFD0AF0FCUL,
|
||||
0xB0FE134CUL, 0xE2506D3DUL, 0x4F9B12EAUL, 0xF215F225UL,
|
||||
0xA223736FUL, 0x9FB4C428UL, 0x25D04979UL, 0x34C713F8UL,
|
||||
0xC4618187UL, 0xEA7A6E98UL, 0x7CD16EFCUL, 0x1436876CUL,
|
||||
0xF1544107UL, 0xBEDEEE14UL, 0x56E9AF27UL, 0xA04AA441UL,
|
||||
0x3CF7C899UL, 0x92ECBAE6UL, 0xDD67016DUL, 0x151682EBUL,
|
||||
0xA842EEDFUL, 0xFDBA60B4UL, 0xF1907B75UL, 0x20E3030FUL,
|
||||
0x24D8C29EUL, 0xE139673BUL, 0xEFA63FB8UL, 0x71873054UL,
|
||||
0xB6F2CF3BUL, 0x9F326442UL, 0xCB15A4CCUL, 0xB01A4504UL,
|
||||
0xF1E47D8DUL, 0x844A1BE5UL, 0xBAE7DFDCUL, 0x42CBDA70UL,
|
||||
0xCD7DAE0AUL, 0x57E85B7AUL, 0xD53F5AF6UL, 0x20CF4D8CUL,
|
||||
0xCEA4D428UL, 0x79D130A4UL, 0x3486EBFBUL, 0x33D3CDDCUL,
|
||||
0x77853B53UL, 0x37EFFCB5UL, 0xC5068778UL, 0xE580B3E6UL,
|
||||
0x4E68B8F4UL, 0xC5C8B37EUL, 0x0D809EA2UL, 0x398FEB7CUL,
|
||||
0x132A4F94UL, 0x43B7950EUL, 0x2FEE7D1CUL, 0x223613BDUL,
|
||||
0xDD06CAA2UL, 0x37DF932BUL, 0xC4248289UL, 0xACF3EBC3UL,
|
||||
0x5715F6B7UL, 0xEF3478DDUL, 0xF267616FUL, 0xC148CBE4UL,
|
||||
0x9052815EUL, 0x5E410FABUL, 0xB48A2465UL, 0x2EDA7FA4UL,
|
||||
0xE87B40E4UL, 0xE98EA084UL, 0x5889E9E1UL, 0xEFD390FCUL,
|
||||
0xDD07D35BUL, 0xDB485694UL, 0x38D7E5B2UL, 0x57720101UL,
|
||||
0x730EDEBCUL, 0x5B643113UL, 0x94917E4FUL, 0x503C2FBAUL,
|
||||
0x646F1282UL, 0x7523D24AUL, 0xE0779695UL, 0xF9C17A8FUL,
|
||||
0x7A5B2121UL, 0xD187B896UL, 0x29263A4DUL, 0xBA510CDFUL,
|
||||
0x81F47C9FUL, 0xAD1163EDUL, 0xEA7B5965UL, 0x1A00726EUL,
|
||||
0x11403092UL, 0x00DA6D77UL, 0x4A0CDD61UL, 0xAD1F4603UL,
|
||||
0x605BDFB0UL, 0x9EEDC364UL, 0x22EBE6A8UL, 0xCEE7D28AUL,
|
||||
0xA0E736A0UL, 0x5564A6B9UL, 0x10853209UL, 0xC7EB8F37UL,
|
||||
0x2DE705CAUL, 0x8951570FUL, 0xDF09822BUL, 0xBD691A6CUL,
|
||||
0xAA12E4F2UL, 0x87451C0FUL, 0xE0F6A27AUL, 0x3ADA4819UL,
|
||||
0x4CF1764FUL, 0x0D771C2BUL, 0x67CDB156UL, 0x350D8384UL,
|
||||
0x5938FA0FUL, 0x42399EF3UL, 0x36997B07UL, 0x0E84093DUL,
|
||||
0x4AA93E61UL, 0x8360D87BUL, 0x1FA98B0CUL, 0x1149382CUL,
|
||||
0xE97625A5UL, 0x0614D1B7UL, 0x0E25244BUL, 0x0C768347UL,
|
||||
0x589E8D82UL, 0x0D2059D1UL, 0xA466BB1EUL, 0xF8DA0A82UL,
|
||||
0x04F19130UL, 0xBA6E4EC0UL, 0x99265164UL, 0x1EE7230DUL,
|
||||
0x50B2AD80UL, 0xEAEE6801UL, 0x8DB2A283UL, 0xEA8BF59EUL
|
||||
}};
|
||||
|
||||
NAMESPACE_END
|
62
CryptoPP/cbcmac.cpp
Normal file
62
CryptoPP/cbcmac.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#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
|
50
CryptoPP/cbcmac.h
Normal file
50
CryptoPP/cbcmac.h
Normal file
@ -0,0 +1,50 @@
|
||||
#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
|
140
CryptoPP/ccm.cpp
Normal file
140
CryptoPP/ccm.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
// 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
|
101
CryptoPP/ccm.h
Normal file
101
CryptoPP/ccm.h
Normal file
@ -0,0 +1,101 @@
|
||||
#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
|
309
CryptoPP/channels.cpp
Normal file
309
CryptoPP/channels.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
// 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
|
123
CryptoPP/channels.h
Normal file
123
CryptoPP/channels.h
Normal file
@ -0,0 +1,123 @@
|
||||
#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
|
122
CryptoPP/cmac.cpp
Normal file
122
CryptoPP/cmac.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
// 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
|
52
CryptoPP/cmac.h
Normal file
52
CryptoPP/cmac.h
Normal file
@ -0,0 +1,52 @@
|
||||
#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
|
462
CryptoPP/config.h
Normal file
462
CryptoPP/config.h
Normal file
@ -0,0 +1,462 @@
|
||||
#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)
|
||||
#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 561
|
||||
|
||||
// ***************** 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
|
199
CryptoPP/cpu.cpp
Normal file
199
CryptoPP/cpu.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
// 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
|
345
CryptoPP/cpu.h
Normal file
345
CryptoPP/cpu.h
Normal file
@ -0,0 +1,345 @@
|
||||
#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
|
160
CryptoPP/crc.cpp
Normal file
160
CryptoPP/crc.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
// 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
|
42
CryptoPP/crc.h
Normal file
42
CryptoPP/crc.h
Normal file
@ -0,0 +1,42 @@
|
||||
#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
|
828
CryptoPP/cryptlib.cpp
Normal file
828
CryptoPP/cryptlib.cpp
Normal file
@ -0,0 +1,828 @@
|
||||
// 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
|
1655
CryptoPP/cryptlib.h
Normal file
1655
CryptoPP/cryptlib.h
Normal file
File diff suppressed because it is too large
Load Diff
258
CryptoPP/default.cpp
Normal file
258
CryptoPP/default.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
// 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
|
104
CryptoPP/default.h
Normal file
104
CryptoPP/default.h
Normal file
@ -0,0 +1,104 @@
|
||||
#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
|
449
CryptoPP/des.cpp
Normal file
449
CryptoPP/des.cpp
Normal file
@ -0,0 +1,449 @@
|
||||
// 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
|
144
CryptoPP/des.h
Normal file
144
CryptoPP/des.h
Normal file
@ -0,0 +1,144 @@
|
||||
#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
|
95
CryptoPP/dessp.cpp
Normal file
95
CryptoPP/dessp.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
// 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
|
19
CryptoPP/dh.cpp
Normal file
19
CryptoPP/dh.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
// 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
|
99
CryptoPP/dh.h
Normal file
99
CryptoPP/dh.h
Normal file
@ -0,0 +1,99 @@
|
||||
#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
|
22
CryptoPP/dh2.cpp
Normal file
22
CryptoPP/dh2.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
// 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
|
58
CryptoPP/dh2.h
Normal file
58
CryptoPP/dh2.h
Normal file
@ -0,0 +1,58 @@
|
||||
#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
|
146
CryptoPP/dll.cpp
Normal file
146
CryptoPP/dll.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
// 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
|
71
CryptoPP/dll.h
Normal file
71
CryptoPP/dll.h
Normal file
@ -0,0 +1,71 @@
|
||||
#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 "skipjack.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
|
93
CryptoPP/dmac.h
Normal file
93
CryptoPP/dmac.h
Normal file
@ -0,0 +1,93 @@
|
||||
#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
|
119
CryptoPP/dsa.cpp
Normal file
119
CryptoPP/dsa.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
// 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();
|
||||
}
|
||||
|
||||
bool DSA::GeneratePrimes(const byte *seedIn, unsigned int g, int &counter,
|
||||
Integer &p, unsigned int L, Integer &q, bool useInputCounterValue)
|
||||
{
|
||||
assert(g%8 == 0);
|
||||
|
||||
SHA sha;
|
||||
SecByteBlock seed(seedIn, g/8);
|
||||
SecByteBlock U(SHA::DIGESTSIZE);
|
||||
SecByteBlock temp(SHA::DIGESTSIZE);
|
||||
SecByteBlock W(((L-1)/160+1) * SHA::DIGESTSIZE);
|
||||
const int n = (L-1) / 160;
|
||||
const int b = (L-1) % 160;
|
||||
Integer X;
|
||||
|
||||
sha.CalculateDigest(U, seed, g/8);
|
||||
|
||||
for (int i=g/8-1, carry=true; i>=0 && carry; i--)
|
||||
carry=!++seed[i];
|
||||
|
||||
sha.CalculateDigest(temp, seed, g/8);
|
||||
xorbuf(U, temp, SHA::DIGESTSIZE);
|
||||
|
||||
U[0] |= 0x80;
|
||||
U[SHA::DIGESTSIZE-1] |= 1;
|
||||
q.Decode(U, SHA::DIGESTSIZE);
|
||||
|
||||
if (!IsPrime(q))
|
||||
return false;
|
||||
|
||||
int counterEnd = useInputCounterValue ? counter+1 : 4096;
|
||||
|
||||
for (int c = 0; c < counterEnd; c++)
|
||||
{
|
||||
for (int k=0; k<=n; k++)
|
||||
{
|
||||
for (int i=g/8-1, carry=true; i>=0 && carry; i--)
|
||||
carry=!++seed[i];
|
||||
if (!useInputCounterValue || c == counter)
|
||||
sha.CalculateDigest(W+(n-k)*SHA::DIGESTSIZE, seed, g/8);
|
||||
}
|
||||
if (!useInputCounterValue || c == counter)
|
||||
{
|
||||
W[SHA::DIGESTSIZE - 1 - b/8] |= 0x80;
|
||||
X.Decode(W + SHA::DIGESTSIZE - 1 - b/8, L/8);
|
||||
p = X-((X % (2*q))-1);
|
||||
|
||||
if (p.GetBit(L-1) && IsPrime(p))
|
||||
{
|
||||
counter = c;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
35
CryptoPP/dsa.h
Normal file
35
CryptoPP/dsa.h
Normal file
@ -0,0 +1,35 @@
|
||||
#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
|
59
CryptoPP/eax.cpp
Normal file
59
CryptoPP/eax.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// 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
|
91
CryptoPP/eax.h
Normal file
91
CryptoPP/eax.h
Normal file
@ -0,0 +1,91 @@
|
||||
#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
|
292
CryptoPP/ec2n.cpp
Normal file
292
CryptoPP/ec2n.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
// 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
|
113
CryptoPP/ec2n.h
Normal file
113
CryptoPP/ec2n.h
Normal file
@ -0,0 +1,113 @@
|
||||
#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
|
694
CryptoPP/eccrypto.cpp
Normal file
694
CryptoPP/eccrypto.cpp
Normal file
@ -0,0 +1,694 @@
|
||||
// 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());
|
||||
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) : 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();
|
||||
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
|
280
CryptoPP/eccrypto.h
Normal file
280
CryptoPP/eccrypto.h
Normal file
@ -0,0 +1,280 @@
|
||||
#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);
|
||||
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; SetPublicElement(Q);}
|
||||
void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q)
|
||||
{this->AccessGroupParameters().Initialize(ec, G, n); 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)
|
||||
{GenerateRandom(rng, params);}
|
||||
void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
|
||||
{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
|
473
CryptoPP/ecp.cpp
Normal file
473
CryptoPP/ecp.cpp
Normal file
@ -0,0 +1,473 @@
|
||||
// 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
|
126
CryptoPP/ecp.h
Normal file
126
CryptoPP/ecp.h
Normal file
@ -0,0 +1,126 @@
|
||||
#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
|
17
CryptoPP/elgamal.cpp
Normal file
17
CryptoPP/elgamal.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// 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
|
121
CryptoPP/elgamal.h
Normal file
121
CryptoPP/elgamal.h
Normal file
@ -0,0 +1,121 @@
|
||||
#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
|
34
CryptoPP/emsa2.cpp
Normal file
34
CryptoPP/emsa2.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// 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
|
86
CryptoPP/emsa2.h
Normal file
86
CryptoPP/emsa2.h
Normal file
@ -0,0 +1,86 @@
|
||||
#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
|
112
CryptoPP/eprecomp.cpp
Normal file
112
CryptoPP/eprecomp.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
// 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
|
75
CryptoPP/eprecomp.h
Normal file
75
CryptoPP/eprecomp.h
Normal file
@ -0,0 +1,75 @@
|
||||
#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
|
210
CryptoPP/esign.cpp
Normal file
210
CryptoPP/esign.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
// 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
|
128
CryptoPP/esign.h
Normal file
128
CryptoPP/esign.h
Normal file
@ -0,0 +1,128 @@
|
||||
#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
|
135
CryptoPP/factory.h
Normal file
135
CryptoPP/factory.h
Normal file
@ -0,0 +1,135 @@
|
||||
#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 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
|
259
CryptoPP/files.cpp
Normal file
259
CryptoPP/files.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
// 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
|
112
CryptoPP/files.h
Normal file
112
CryptoPP/files.h
Normal file
@ -0,0 +1,112 @@
|
||||
#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
|
1120
CryptoPP/filters.cpp
Normal file
1120
CryptoPP/filters.cpp
Normal file
File diff suppressed because it is too large
Load Diff
810
CryptoPP/filters.h
Normal file
810
CryptoPP/filters.h
Normal file
@ -0,0 +1,810 @@
|
||||
#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
|
84
CryptoPP/fips140.cpp
Normal file
84
CryptoPP/fips140.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// 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
|
59
CryptoPP/fips140.h
Normal file
59
CryptoPP/fips140.h
Normal file
@ -0,0 +1,59 @@
|
||||
#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
|
601
CryptoPP/fipstest.cpp
Normal file
601
CryptoPP/fipstest.cpp
Normal file
@ -0,0 +1,601 @@
|
||||
// fipstest.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#define CRYPTOPP_DEFAULT_NO_DLL
|
||||
#include "dll.h"
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
#ifdef _M_IX86
|
||||
#define _CRT_DEBUGGER_HOOK _crt_debugger_hook
|
||||
#else
|
||||
#define _CRT_DEBUGGER_HOOK __crt_debugger_hook
|
||||
#endif
|
||||
extern "C" {_CRTIMP void __cdecl _CRT_DEBUGGER_HOOK(int);}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
extern PowerUpSelfTestStatus g_powerUpSelfTestStatus;
|
||||
SecByteBlock g_actualMac;
|
||||
unsigned long g_macFileLocation = 0;
|
||||
|
||||
// use a random dummy string here, to be searched/replaced later with the real MAC
|
||||
static const byte s_moduleMac[CryptoPP::HMAC<CryptoPP::SHA1>::DIGESTSIZE] = CRYPTOPP_DUMMY_DLL_MAC;
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(s_moduleMac) == CryptoPP::SHA1::DIGESTSIZE);
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
static HMODULE s_hModule = NULL;
|
||||
#endif
|
||||
|
||||
const byte * CRYPTOPP_API GetActualMacAndLocation(unsigned int &macSize, unsigned int &fileLocation)
|
||||
{
|
||||
macSize = (unsigned int)g_actualMac.size();
|
||||
fileLocation = g_macFileLocation;
|
||||
return g_actualMac;
|
||||
}
|
||||
|
||||
void KnownAnswerTest(RandomNumberGenerator &rng, const char *output)
|
||||
{
|
||||
EqualityComparisonFilter comparison;
|
||||
|
||||
RandomNumberStore(rng, strlen(output)/2).TransferAllTo(comparison, "0");
|
||||
StringSource(output, true, new HexDecoder(new ChannelSwitch(comparison, "1")));
|
||||
|
||||
comparison.ChannelMessageSeriesEnd("0");
|
||||
comparison.ChannelMessageSeriesEnd("1");
|
||||
}
|
||||
|
||||
template <class CIPHER>
|
||||
void X917RNG_KnownAnswerTest(
|
||||
const char *key,
|
||||
const char *seed,
|
||||
const char *deterministicTimeVector,
|
||||
const char *output,
|
||||
CIPHER *dummy = NULL)
|
||||
{
|
||||
#ifdef OS_RNG_AVAILABLE
|
||||
std::string decodedKey, decodedSeed, decodedDeterministicTimeVector;
|
||||
StringSource(key, true, new HexDecoder(new StringSink(decodedKey)));
|
||||
StringSource(seed, true, new HexDecoder(new StringSink(decodedSeed)));
|
||||
StringSource(deterministicTimeVector, true, new HexDecoder(new StringSink(decodedDeterministicTimeVector)));
|
||||
|
||||
AutoSeededX917RNG<CIPHER> rng(false, false);
|
||||
rng.Reseed((const byte *)decodedKey.data(), decodedKey.size(), (const byte *)decodedSeed.data(), (const byte *)decodedDeterministicTimeVector.data());
|
||||
KnownAnswerTest(rng, output);
|
||||
#else
|
||||
throw 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void KnownAnswerTest(StreamTransformation &encryption, StreamTransformation &decryption, const char *plaintext, const char *ciphertext)
|
||||
{
|
||||
EqualityComparisonFilter comparison;
|
||||
|
||||
StringSource(plaintext, true, new HexDecoder(new StreamTransformationFilter(encryption, new ChannelSwitch(comparison, "0"), StreamTransformationFilter::NO_PADDING)));
|
||||
StringSource(ciphertext, true, new HexDecoder(new ChannelSwitch(comparison, "1")));
|
||||
|
||||
StringSource(ciphertext, true, new HexDecoder(new StreamTransformationFilter(decryption, new ChannelSwitch(comparison, "0"), StreamTransformationFilter::NO_PADDING)));
|
||||
StringSource(plaintext, true, new HexDecoder(new ChannelSwitch(comparison, "1")));
|
||||
|
||||
comparison.ChannelMessageSeriesEnd("0");
|
||||
comparison.ChannelMessageSeriesEnd("1");
|
||||
}
|
||||
|
||||
template <class CIPHER>
|
||||
void SymmetricEncryptionKnownAnswerTest(
|
||||
const char *key,
|
||||
const char *hexIV,
|
||||
const char *plaintext,
|
||||
const char *ecb,
|
||||
const char *cbc,
|
||||
const char *cfb,
|
||||
const char *ofb,
|
||||
const char *ctr,
|
||||
CIPHER *dummy = NULL)
|
||||
{
|
||||
std::string decodedKey;
|
||||
StringSource(key, true, new HexDecoder(new StringSink(decodedKey)));
|
||||
|
||||
typename CIPHER::Encryption encryption((const byte *)decodedKey.data(), decodedKey.size());
|
||||
typename CIPHER::Decryption decryption((const byte *)decodedKey.data(), decodedKey.size());
|
||||
|
||||
SecByteBlock iv(encryption.BlockSize());
|
||||
StringSource(hexIV, true, new HexDecoder(new ArraySink(iv, iv.size())));
|
||||
|
||||
if (ecb)
|
||||
KnownAnswerTest(ECB_Mode_ExternalCipher::Encryption(encryption).Ref(), ECB_Mode_ExternalCipher::Decryption(decryption).Ref(), plaintext, ecb);
|
||||
if (cbc)
|
||||
KnownAnswerTest(CBC_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), CBC_Mode_ExternalCipher::Decryption(decryption, iv).Ref(), plaintext, cbc);
|
||||
if (cfb)
|
||||
KnownAnswerTest(CFB_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), CFB_Mode_ExternalCipher::Decryption(encryption, iv).Ref(), plaintext, cfb);
|
||||
if (ofb)
|
||||
KnownAnswerTest(OFB_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), OFB_Mode_ExternalCipher::Decryption(encryption, iv).Ref(), plaintext, ofb);
|
||||
if (ctr)
|
||||
KnownAnswerTest(CTR_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), CTR_Mode_ExternalCipher::Decryption(encryption, iv).Ref(), plaintext, ctr);
|
||||
}
|
||||
|
||||
void KnownAnswerTest(HashTransformation &hash, const char *message, const char *digest)
|
||||
{
|
||||
EqualityComparisonFilter comparison;
|
||||
StringSource(digest, true, new HexDecoder(new ChannelSwitch(comparison, "1")));
|
||||
StringSource(message, true, new HashFilter(hash, new ChannelSwitch(comparison, "0")));
|
||||
|
||||
comparison.ChannelMessageSeriesEnd("0");
|
||||
comparison.ChannelMessageSeriesEnd("1");
|
||||
}
|
||||
|
||||
template <class HASH>
|
||||
void SecureHashKnownAnswerTest(const char *message, const char *digest, HASH *dummy = NULL)
|
||||
{
|
||||
HASH hash;
|
||||
KnownAnswerTest(hash, message, digest);
|
||||
}
|
||||
|
||||
template <class MAC>
|
||||
void MAC_KnownAnswerTest(const char *key, const char *message, const char *digest, MAC *dummy = NULL)
|
||||
{
|
||||
std::string decodedKey;
|
||||
StringSource(key, true, new HexDecoder(new StringSink(decodedKey)));
|
||||
|
||||
MAC mac((const byte *)decodedKey.data(), decodedKey.size());
|
||||
KnownAnswerTest(mac, message, digest);
|
||||
}
|
||||
|
||||
template <class SCHEME>
|
||||
void SignatureKnownAnswerTest(const char *key, const char *message, const char *signature, SCHEME *dummy = NULL)
|
||||
{
|
||||
typename SCHEME::Signer signer(StringSource(key, true, new HexDecoder).Ref());
|
||||
typename SCHEME::Verifier verifier(signer);
|
||||
|
||||
RandomPool rng;
|
||||
EqualityComparisonFilter comparison;
|
||||
|
||||
StringSource(message, true, new SignerFilter(rng, signer, new ChannelSwitch(comparison, "0")));
|
||||
StringSource(signature, true, new HexDecoder(new ChannelSwitch(comparison, "1")));
|
||||
|
||||
comparison.ChannelMessageSeriesEnd("0");
|
||||
comparison.ChannelMessageSeriesEnd("1");
|
||||
|
||||
VerifierFilter verifierFilter(verifier, NULL, VerifierFilter::SIGNATURE_AT_BEGIN | VerifierFilter::THROW_EXCEPTION);
|
||||
StringSource(signature, true, new HexDecoder(new Redirector(verifierFilter, Redirector::DATA_ONLY)));
|
||||
StringSource(message, true, new Redirector(verifierFilter));
|
||||
}
|
||||
|
||||
void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor)
|
||||
{
|
||||
try
|
||||
{
|
||||
RandomPool rng;
|
||||
const char *testMessage ="test message";
|
||||
std::string ciphertext, decrypted;
|
||||
|
||||
StringSource(
|
||||
testMessage,
|
||||
true,
|
||||
new PK_EncryptorFilter(
|
||||
rng,
|
||||
encryptor,
|
||||
new StringSink(ciphertext)));
|
||||
|
||||
if (ciphertext == testMessage)
|
||||
throw 0;
|
||||
|
||||
StringSource(
|
||||
ciphertext,
|
||||
true,
|
||||
new PK_DecryptorFilter(
|
||||
rng,
|
||||
decryptor,
|
||||
new StringSink(decrypted)));
|
||||
|
||||
if (decrypted != testMessage)
|
||||
throw 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw SelfTestFailure(encryptor.AlgorithmName() + ": pairwise consistency test failed");
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier)
|
||||
{
|
||||
try
|
||||
{
|
||||
RandomPool rng;
|
||||
|
||||
StringSource(
|
||||
"test message",
|
||||
true,
|
||||
new SignerFilter(
|
||||
rng,
|
||||
signer,
|
||||
new VerifierFilter(verifier, NULL, VerifierFilter::THROW_EXCEPTION),
|
||||
true));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw SelfTestFailure(signer.AlgorithmName() + ": pairwise consistency test failed");
|
||||
}
|
||||
}
|
||||
|
||||
template <class SCHEME>
|
||||
void SignaturePairwiseConsistencyTest(const char *key, SCHEME *dummy = NULL)
|
||||
{
|
||||
typename SCHEME::Signer signer(StringSource(key, true, new HexDecoder).Ref());
|
||||
typename SCHEME::Verifier verifier(signer);
|
||||
|
||||
SignaturePairwiseConsistencyTest(signer, verifier);
|
||||
}
|
||||
|
||||
MessageAuthenticationCode * NewIntegrityCheckingMAC()
|
||||
{
|
||||
byte key[] = {0x47, 0x1E, 0x33, 0x96, 0x65, 0xB1, 0x6A, 0xED, 0x0B, 0xF8, 0x6B, 0xFD, 0x01, 0x65, 0x05, 0xCC};
|
||||
return new HMAC<SHA1>(key, sizeof(key));
|
||||
}
|
||||
|
||||
bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac, unsigned long *pMacFileLocation)
|
||||
{
|
||||
std::auto_ptr<MessageAuthenticationCode> mac(NewIntegrityCheckingMAC());
|
||||
unsigned int macSize = mac->DigestSize();
|
||||
|
||||
SecByteBlock tempMac;
|
||||
SecByteBlock &actualMac = pActualMac ? *pActualMac : tempMac;
|
||||
actualMac.resize(macSize);
|
||||
|
||||
unsigned long tempLocation;
|
||||
unsigned long &macFileLocation = pMacFileLocation ? *pMacFileLocation : tempLocation;
|
||||
macFileLocation = 0;
|
||||
|
||||
MeterFilter verifier(new HashFilter(*mac, new ArraySink(actualMac, actualMac.size())));
|
||||
// MeterFilter verifier(new FileSink("c:\\dt.tmp"));
|
||||
std::ifstream moduleStream;
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
HMODULE h;
|
||||
{
|
||||
char moduleFilenameBuf[MAX_PATH] = "";
|
||||
if (moduleFilename == NULL)
|
||||
{
|
||||
#if (_MSC_VER >= 1400 && !defined(_STLPORT_VERSION)) // ifstream doesn't support wide filename on other compilers
|
||||
wchar_t wideModuleFilename[MAX_PATH];
|
||||
if (GetModuleFileNameW(s_hModule, wideModuleFilename, MAX_PATH) > 0)
|
||||
{
|
||||
moduleStream.open(wideModuleFilename, std::ios::in | std::ios::binary);
|
||||
h = GetModuleHandleW(wideModuleFilename);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GetModuleFileNameA(s_hModule, moduleFilenameBuf, MAX_PATH);
|
||||
moduleFilename = moduleFilenameBuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (moduleFilename != NULL)
|
||||
{
|
||||
moduleStream.open(moduleFilename, std::ios::in | std::ios::binary);
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
h = GetModuleHandleA(moduleFilename);
|
||||
moduleFilename = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!moduleStream)
|
||||
{
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
OutputDebugString("Crypto++ DLL integrity check failed. Cannot open file for reading.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
FileStore file(moduleStream);
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
// try to hash from memory first
|
||||
const byte *memBase = (const byte *)h;
|
||||
const IMAGE_DOS_HEADER *ph = (IMAGE_DOS_HEADER *)memBase;
|
||||
const IMAGE_NT_HEADERS *phnt = (IMAGE_NT_HEADERS *)(memBase + ph->e_lfanew);
|
||||
const IMAGE_SECTION_HEADER *phs = IMAGE_FIRST_SECTION(phnt);
|
||||
DWORD nSections = phnt->FileHeader.NumberOfSections;
|
||||
size_t currentFilePos = 0;
|
||||
|
||||
size_t checksumPos = (byte *)&phnt->OptionalHeader.CheckSum - memBase;
|
||||
size_t checksumSize = sizeof(phnt->OptionalHeader.CheckSum);
|
||||
size_t certificateTableDirectoryPos = (byte *)&phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] - memBase;
|
||||
size_t certificateTableDirectorySize = sizeof(phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]);
|
||||
size_t certificateTablePos = phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
|
||||
size_t certificateTableSize = phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
|
||||
|
||||
verifier.AddRangeToSkip(0, checksumPos, checksumSize);
|
||||
verifier.AddRangeToSkip(0, certificateTableDirectoryPos, certificateTableDirectorySize);
|
||||
verifier.AddRangeToSkip(0, certificateTablePos, certificateTableSize);
|
||||
|
||||
while (nSections--)
|
||||
{
|
||||
switch (phs->Characteristics)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ:
|
||||
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ:
|
||||
unsigned int sectionSize = STDMIN(phs->SizeOfRawData, phs->Misc.VirtualSize);
|
||||
const byte *sectionMemStart = memBase + phs->VirtualAddress;
|
||||
unsigned int sectionFileStart = phs->PointerToRawData;
|
||||
size_t subSectionStart = 0, nextSubSectionStart;
|
||||
|
||||
do
|
||||
{
|
||||
const byte *subSectionMemStart = sectionMemStart + subSectionStart;
|
||||
size_t subSectionFileStart = sectionFileStart + subSectionStart;
|
||||
size_t subSectionSize = sectionSize - subSectionStart;
|
||||
nextSubSectionStart = 0;
|
||||
|
||||
unsigned int entriesToReadFromDisk[] = {IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IAT};
|
||||
for (unsigned int i=0; i<sizeof(entriesToReadFromDisk)/sizeof(entriesToReadFromDisk[0]); i++)
|
||||
{
|
||||
const IMAGE_DATA_DIRECTORY &entry = phnt->OptionalHeader.DataDirectory[entriesToReadFromDisk[i]];
|
||||
const byte *entryMemStart = memBase + entry.VirtualAddress;
|
||||
if (subSectionMemStart <= entryMemStart && entryMemStart < subSectionMemStart + subSectionSize)
|
||||
{
|
||||
subSectionSize = entryMemStart - subSectionMemStart;
|
||||
nextSubSectionStart = entryMemStart - sectionMemStart + entry.Size;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
// first byte of _CRT_DEBUGGER_HOOK gets modified in memory by the debugger invisibly, so read it from file
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
if (subSectionMemStart <= (byte *)&_CRT_DEBUGGER_HOOK && (byte *)&_CRT_DEBUGGER_HOOK < subSectionMemStart + subSectionSize)
|
||||
{
|
||||
subSectionSize = (byte *)&_CRT_DEBUGGER_HOOK - subSectionMemStart;
|
||||
nextSubSectionStart = (byte *)&_CRT_DEBUGGER_HOOK - sectionMemStart + 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (subSectionMemStart <= expectedModuleMac && expectedModuleMac < subSectionMemStart + subSectionSize)
|
||||
{
|
||||
// found stored MAC
|
||||
macFileLocation = (unsigned long)(subSectionFileStart + (expectedModuleMac - subSectionMemStart));
|
||||
verifier.AddRangeToSkip(0, macFileLocation, macSize);
|
||||
}
|
||||
|
||||
file.TransferTo(verifier, subSectionFileStart - currentFilePos);
|
||||
verifier.Put(subSectionMemStart, subSectionSize);
|
||||
file.Skip(subSectionSize);
|
||||
currentFilePos = subSectionFileStart + subSectionSize;
|
||||
subSectionStart = nextSubSectionStart;
|
||||
} while (nextSubSectionStart != 0);
|
||||
}
|
||||
phs++;
|
||||
}
|
||||
#endif
|
||||
file.TransferAllTo(verifier);
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
// if that fails (could be caused by debug breakpoints or DLL base relocation modifying image in memory),
|
||||
// hash from disk instead
|
||||
if (!VerifyBufsEqual(expectedModuleMac, actualMac, macSize))
|
||||
{
|
||||
OutputDebugString("In memory integrity check failed. This may be caused by debug breakpoints or DLL relocation.\n");
|
||||
moduleStream.clear();
|
||||
moduleStream.seekg(0);
|
||||
verifier.Initialize(MakeParameters(Name::OutputBuffer(), ByteArrayParameter(actualMac, (unsigned int)actualMac.size())));
|
||||
// verifier.Initialize(MakeParameters(Name::OutputFileName(), (const char *)"c:\\dt2.tmp"));
|
||||
verifier.AddRangeToSkip(0, checksumPos, checksumSize);
|
||||
verifier.AddRangeToSkip(0, certificateTableDirectoryPos, certificateTableDirectorySize);
|
||||
verifier.AddRangeToSkip(0, certificateTablePos, certificateTableSize);
|
||||
verifier.AddRangeToSkip(0, macFileLocation, macSize);
|
||||
FileStore(moduleStream).TransferAllTo(verifier);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (VerifyBufsEqual(expectedModuleMac, actualMac, macSize))
|
||||
return true;
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
std::string hexMac;
|
||||
HexEncoder(new StringSink(hexMac)).PutMessageEnd(actualMac, actualMac.size());
|
||||
OutputDebugString((("Crypto++ DLL integrity check failed. Actual MAC is: " + hexMac) + "\n").c_str());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac)
|
||||
{
|
||||
g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE;
|
||||
SetPowerUpSelfTestInProgressOnThisThread(true);
|
||||
|
||||
try
|
||||
{
|
||||
if (FIPS_140_2_ComplianceEnabled() || expectedModuleMac != NULL)
|
||||
{
|
||||
if (!IntegrityCheckModule(moduleFilename, expectedModuleMac, &g_actualMac, &g_macFileLocation))
|
||||
throw 0; // throw here so we break in the debugger, this will be caught right away
|
||||
}
|
||||
|
||||
// algorithm tests
|
||||
|
||||
X917RNG_KnownAnswerTest<AES>(
|
||||
"2b7e151628aed2a6abf7158809cf4f3c", // key
|
||||
"000102030405060708090a0b0c0d0e0f", // seed
|
||||
"00000000000000000000000000000001", // time vector
|
||||
"D176EDD27493B0395F4D10546232B0693DC7061C03C3A554F09CECF6F6B46D945A"); // output
|
||||
|
||||
SymmetricEncryptionKnownAnswerTest<DES_EDE3>(
|
||||
"385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E",
|
||||
"C141B5FCCD28DC8A",
|
||||
"6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68",
|
||||
"64EAAD4ACBB9CEAD6C7615E7C7E4792FE587D91F20C7D2F4",
|
||||
"6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9",
|
||||
"E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B",
|
||||
"E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62",
|
||||
"E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371");
|
||||
|
||||
SymmetricEncryptionKnownAnswerTest<SKIPJACK>(
|
||||
"1555E5531C3A169B2D65",
|
||||
"6EC9795701F49864",
|
||||
"00AFA48E9621E52E8CBDA312660184EDDB1F33D9DACDA8DA",
|
||||
"DBEC73562EFCAEB56204EB8AE9557EBF77473FBB52D17CD1",
|
||||
"0C7B0B74E21F99B8F2C8DF37879F6C044967F42A796DCA8B",
|
||||
"79FDDA9724E36CC2E023E9A5C717A8A8A7FDA465CADCBF63",
|
||||
"79FDDA9724E36CC26CACBD83C1ABC06EAF5B249BE5B1E040",
|
||||
"79FDDA9724E36CC211B0AEC607B95A96BCDA318440B82F49");
|
||||
|
||||
SymmetricEncryptionKnownAnswerTest<AES>(
|
||||
"2b7e151628aed2a6abf7158809cf4f3c",
|
||||
"000102030405060708090a0b0c0d0e0f",
|
||||
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", // plaintext
|
||||
"3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4", // ecb
|
||||
"7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7", // cbc
|
||||
"3b3fd92eb72dad20333449f8e83cfb4ac8a64537a0b3a93fcde3cdad9f1ce58b26751f67a3cbb140b1808cf187a4f4dfc04b05357c5d1c0eeac4c66f9ff7f2e6", // cfb
|
||||
"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e", // ofb
|
||||
NULL);
|
||||
|
||||
SymmetricEncryptionKnownAnswerTest<AES>(
|
||||
"2b7e151628aed2a6abf7158809cf4f3c",
|
||||
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
|
||||
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"); // ctr
|
||||
|
||||
|
||||
SecureHashKnownAnswerTest<SHA1>(
|
||||
"abc",
|
||||
"A9993E364706816ABA3E25717850C26C9CD0D89D");
|
||||
|
||||
SecureHashKnownAnswerTest<SHA224>(
|
||||
"abc",
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7");
|
||||
|
||||
SecureHashKnownAnswerTest<SHA256>(
|
||||
"abc",
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
|
||||
|
||||
SecureHashKnownAnswerTest<SHA384>(
|
||||
"abc",
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7");
|
||||
|
||||
SecureHashKnownAnswerTest<SHA512>(
|
||||
"abc",
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
|
||||
|
||||
MAC_KnownAnswerTest<HMAC<SHA1> >(
|
||||
"303132333435363738393a3b3c3d3e3f40414243",
|
||||
"Sample #2",
|
||||
"0922d3405faa3d194f82a45830737d5cc6c75d24");
|
||||
|
||||
const char *keyRSA1 =
|
||||
"30820150020100300d06092a864886f70d01010105000482013a3082013602010002400a66791dc6988168de7ab77419bb7fb0"
|
||||
"c001c62710270075142942e19a8d8c51d053b3e3782a1de5dc5af4ebe99468170114a1dfe67cdc9a9af55d655620bbab0203010001"
|
||||
"02400123c5b61ba36edb1d3679904199a89ea80c09b9122e1400c09adcf7784676d01d23356a7d44d6bd8bd50e94bfc723fa"
|
||||
"87d8862b75177691c11d757692df8881022033d48445c859e52340de704bcdda065fbb4058d740bd1d67d29e9c146c11cf61"
|
||||
"0220335e8408866b0fd38dc7002d3f972c67389a65d5d8306566d5c4f2a5aa52628b0220045ec90071525325d3d46db79695e9af"
|
||||
"acc4523964360e02b119baa366316241022015eb327360c7b60d12e5e2d16bdcd97981d17fba6b70db13b20b436e24eada590220"
|
||||
"2ca6366d72781dfa24d34a9a24cbc2ae927a9958af426563ff63fb11658a461d";
|
||||
|
||||
const char *keyRSA2 =
|
||||
"30820273020100300D06092A864886F70D01010105000482025D3082025902010002818100D40AF9"
|
||||
"A2B713034249E5780056D70FC7DE75D76E44565AA6A6B8ED9646F3C19F9E254D72D7DE6E49DB2264"
|
||||
"0C1D05AB9E2A5F901D8F3FE1F7AE02CEE2ECCE54A40ABAE55A004692752E70725AEEE7CDEA67628A"
|
||||
"82A9239B4AB660C2BC56D9F01E90CBAAB9BF0FC8E17173CEFC5709A29391A7DDF3E0B758691AAF30"
|
||||
"725B292F4F020111027F18C0BA087D082C45D75D3594E0767E4820818EB35612B80CEAB8C880ACA5"
|
||||
"44B6876DFFEF85A576C0D45B551AFAA1FD63209CD745DF75C5A0F0B580296EA466CD0338207E4752"
|
||||
"FF4E7DB724D8AE18CE5CF4153BB94C27869FBB50E64F02546E4B02997A0B8623E64017CC770759C6"
|
||||
"695DB649EEFD829D688D441BCC4E7348F1024100EF86DD7AF3F32CDE8A9F6564E43A559A0C9F8BAD"
|
||||
"36CC25330548B347AC158A345631FA90F7B873C36EFFAE2F7823227A3F580B5DD18304D5932751E7"
|
||||
"43E9234F024100E2A039854B55688740E32A51DF4AF88613D91A371CF8DDD95D780A89D7CF2119A9"
|
||||
"54F1AC0F3DCDB2F6959926E6D9D37D8BC07A4C634DE6F16315BD5F0DAC340102407ECEEDB9903572"
|
||||
"1B76909F174BA6698DCA72953D957B22C0A871C8531EDE3A1BB52984A719BC010D1CA57A555DB83F"
|
||||
"6DE54CBAB932AEC652F38D497A6F3F30CF024100854F30E4FF232E6DADB2CD99926855F484255AB7"
|
||||
"01FBCDCB27EC426F33A7046972AA700ADBCA008763DF87440F52F4E070531AC385B55AAC1C2AE7DD"
|
||||
"8F9278F1024100C313F4AF9E4A9DE1253C21080CE524251560C111550772FD08690F13FBE658342E"
|
||||
"BD2D41C9DCB12374E871B1839E26CAE252E1AE3DAAD5F1EE1F42B4D0EE7581";
|
||||
|
||||
SignatureKnownAnswerTest<RSASS<PKCS1v15, SHA1> >(
|
||||
keyRSA1,
|
||||
"Everyone gets Friday off.",
|
||||
"0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81");
|
||||
|
||||
SignatureKnownAnswerTest<RSASS_ISO<SHA1> >(
|
||||
keyRSA2,
|
||||
"test",
|
||||
"32F6BA41C8930DE71EE67F2627172CC539EDE04267FDE03AC295E3C50311F26C3B275D3AF513AC96"
|
||||
"8EE493BAB7DA3A754661D1A7C4A0D1A2B7EE8B313AACD8CB8BFBC5C15EFB0EF15C86A9334A1E87AD"
|
||||
"291EB961B5CA0E84930429B28780816AA94F96FC2367B71E2D2E4866FA966795B147F00600E5207E"
|
||||
"2F189C883B37477C");
|
||||
|
||||
SignaturePairwiseConsistencyTest<DSA>(
|
||||
"3082014A0201003082012B06072A8648CE3804013082011E02818100F468699A6F6EBCC0120D3B34C8E007F125EC7D81F763B8D0F33869AE3BD6B9F2ECCC7DF34DF84C0307449E9B85D30D57194BCCEB310F48141914DD13A077AAF9B624A6CBE666BBA1D7EBEA95B5BA6F54417FD5D4E4220C601E071D316A24EA814E8B0122DBF47EE8AEEFD319EBB01DD95683F10DBB4FEB023F8262A07EAEB7FD02150082AD4E034DA6EEACDFDAE68C36F2BAD614F9E53B02818071AAF73361A26081529F7D84078ADAFCA48E031DB54AD57FB1A833ADBD8672328AABAA0C756247998D7A5B10DACA359D231332CE8120B483A784FE07D46EEBFF0D7D374A10691F78653E6DC29E27CCB1B174923960DFE5B959B919B2C3816C19251832AFD8E35D810E598F82877ABF7D40A041565168BD7F0E21E3FE2A8D8C1C0416021426EBA66E846E755169F84A1DA981D86502405DDF");
|
||||
|
||||
SignaturePairwiseConsistencyTest<ECDSA<EC2N, SHA1> >(
|
||||
"302D020100301006072A8648CE3D020106052B8104000404163014020101040F0070337065E1E196980A9D00E37211");
|
||||
|
||||
SignaturePairwiseConsistencyTest<ECDSA<ECP, SHA1> >(
|
||||
"3039020100301306072A8648CE3D020106082A8648CE3D030101041F301D02010104182BB8A13C8B867010BD9471D9E81FDB01ABD0538C64D6249A");
|
||||
|
||||
SignaturePairwiseConsistencyTest<RSASS<PSS, SHA1> >(keyRSA1);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_PASSED;
|
||||
|
||||
done:
|
||||
SetPowerUpSelfTestInProgressOnThisThread(false);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
void DoDllPowerUpSelfTest()
|
||||
{
|
||||
CryptoPP::DoPowerUpSelfTest(NULL, s_moduleMac);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void DoDllPowerUpSelfTest()
|
||||
{
|
||||
throw NotImplemented("DoDllPowerUpSelfTest() only available on Windows");
|
||||
}
|
||||
|
||||
#endif // #ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
// DllMain needs to be in the global namespace
|
||||
BOOL APIENTRY DllMain(HANDLE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved)
|
||||
{
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
CryptoPP::s_hModule = (HMODULE)hModule;
|
||||
CryptoPP::DoDllPowerUpSelfTest();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // #ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
#endif // #ifndef CRYPTOPP_IMPORTS
|
67
CryptoPP/fltrimpl.h
Normal file
67
CryptoPP/fltrimpl.h
Normal file
@ -0,0 +1,67 @@
|
||||
#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
|
828
CryptoPP/gcm.cpp
Normal file
828
CryptoPP/gcm.cpp
Normal file
@ -0,0 +1,828 @@
|
||||
// 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
|
106
CryptoPP/gcm.h
Normal file
106
CryptoPP/gcm.h
Normal file
@ -0,0 +1,106 @@
|
||||
#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
|
34
CryptoPP/gf256.cpp
Normal file
34
CryptoPP/gf256.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// 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
|
66
CryptoPP/gf256.h
Normal file
66
CryptoPP/gf256.h
Normal file
@ -0,0 +1,66 @@
|
||||
#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
|
99
CryptoPP/gf2_32.cpp
Normal file
99
CryptoPP/gf2_32.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
// 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
|
66
CryptoPP/gf2_32.h
Normal file
66
CryptoPP/gf2_32.h
Normal file
@ -0,0 +1,66 @@
|
||||
#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
|
882
CryptoPP/gf2n.cpp
Normal file
882
CryptoPP/gf2n.cpp
Normal file
@ -0,0 +1,882 @@
|
||||
// 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
|
369
CryptoPP/gf2n.h
Normal file
369
CryptoPP/gf2n.h
Normal file
@ -0,0 +1,369 @@
|
||||
#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
|
275
CryptoPP/gfpcrypt.cpp
Normal file
275
CryptoPP/gfpcrypt.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
int modulusSize = 1024;
|
||||
alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
|
||||
|
||||
if (!DSA::IsValidPrimeLength(modulusSize))
|
||||
throw InvalidArgument("DSA: not a valid prime length");
|
||||
|
||||
SecByteBlock seed(SHA::DIGESTSIZE);
|
||||
Integer h;
|
||||
int c;
|
||||
|
||||
do
|
||||
{
|
||||
rng.GenerateBlock(seed, SHA::DIGESTSIZE);
|
||||
} while (!DSA::GeneratePrimes(seed, SHA::DIGESTSIZE*8, c, p, modulusSize, q));
|
||||
|
||||
do
|
||||
{
|
||||
h.Randomize(rng, 2, p-2);
|
||||
g = a_exp_b_mod_c(h, (p-1)/q, p);
|
||||
} while (g <= 1);
|
||||
}
|
||||
|
||||
Initialize(p, q, g);
|
||||
}
|
||||
|
||||
bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const
|
||||
{
|
||||
bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level);
|
||||
pass = pass && DSA::IsValidPrimeLength(GetModulus().BitCount());
|
||||
pass = pass && GetSubgroupOrder().BitCount() == 160;
|
||||
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
|
536
CryptoPP/gfpcrypt.h
Normal file
536
CryptoPP/gfpcrypt.h
Normal file
@ -0,0 +1,536 @@
|
||||
#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);
|
||||
};
|
||||
|
||||
struct DSA;
|
||||
|
||||
//! DSA keys
|
||||
struct DL_Keys_DSA
|
||||
{
|
||||
typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
|
||||
typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA> PrivateKey;
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#DSA">DSA</a>
|
||||
struct CRYPTOPP_DLL DSA : public DL_SS<
|
||||
DL_Keys_DSA,
|
||||
DL_Algorithm_GDSA<Integer>,
|
||||
DL_SignatureMessageEncodingMethod_DSA,
|
||||
SHA,
|
||||
DSA>
|
||||
{
|
||||
static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA";}
|
||||
|
||||
//! Generate DSA primes according to NIST standard
|
||||
/*! Both seedLength and primeLength are in bits, but seedLength should
|
||||
be a multiple of 8.
|
||||
If useInputCounterValue == true, the counter parameter is taken as input, otherwise it's used for output
|
||||
*/
|
||||
static bool CRYPTOPP_API GeneratePrimes(const byte *seed, unsigned int seedLength, int &counter,
|
||||
Integer &p, unsigned int primeLength, Integer &q, bool useInputCounterValue = false);
|
||||
|
||||
static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
|
||||
{return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
|
||||
|
||||
//! FIPS 186-2 Change Notice 1 changed the minimum modulus length to 1024
|
||||
enum {
|
||||
#if (DSA_1024_BIT_MODULUS_ONLY)
|
||||
MIN_PRIME_LENGTH = 1024,
|
||||
#else
|
||||
MIN_PRIME_LENGTH = 512,
|
||||
#endif
|
||||
MAX_PRIME_LENGTH = 1024, PRIME_LENGTH_MULTIPLE = 64};
|
||||
};
|
||||
|
||||
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>, DSA>;
|
||||
|
||||
//! 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
|
123
CryptoPP/gost.cpp
Normal file
123
CryptoPP/gost.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include "pch.h"
|
||||
#include "gost.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
|
||||
const byte GOST::Base::sBox[8][16]={
|
||||
{4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},
|
||||
{14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9},
|
||||
{5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11},
|
||||
{7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3},
|
||||
{6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2},
|
||||
{4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14},
|
||||
{13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12},
|
||||
{1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}};
|
||||
|
||||
/* // these are the S-boxes given in the GOST source code listing in Applied
|
||||
// Cryptography 2nd Ed., p. 644. they appear to be from the DES S-boxes
|
||||
{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
|
||||
{ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
|
||||
{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
|
||||
{ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
|
||||
{ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
|
||||
{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
|
||||
{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
|
||||
{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }};
|
||||
*/
|
||||
|
||||
volatile bool GOST::Base::sTableCalculated = false;
|
||||
word32 GOST::Base::sTable[4][256];
|
||||
|
||||
void GOST::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
PrecalculateSTable();
|
||||
|
||||
GetUserKey(LITTLE_ENDIAN_ORDER, key.begin(), 8, userKey, KEYLENGTH);
|
||||
}
|
||||
|
||||
void GOST::Base::PrecalculateSTable()
|
||||
{
|
||||
if (!sTableCalculated)
|
||||
{
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
for (unsigned j = 0; j < 256; j++)
|
||||
{
|
||||
word32 temp = sBox[2*i][j%16] | (sBox[2*i+1][j/16] << 4);
|
||||
sTable[i][j] = rotlMod(temp, 11+8*i);
|
||||
}
|
||||
|
||||
sTableCalculated=true;
|
||||
}
|
||||
}
|
||||
|
||||
#define f(x) ( t=x, \
|
||||
sTable[3][GETBYTE(t, 3)] ^ sTable[2][GETBYTE(t, 2)] \
|
||||
^ sTable[1][GETBYTE(t, 1)] ^ sTable[0][GETBYTE(t, 0)] )
|
||||
|
||||
typedef BlockGetAndPut<word32, LittleEndian> Block;
|
||||
|
||||
void GOST::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 n1, n2, t;
|
||||
|
||||
Block::Get(inBlock)(n1)(n2);
|
||||
|
||||
for (unsigned int i=0; i<3; i++)
|
||||
{
|
||||
n2 ^= f(n1+key[0]);
|
||||
n1 ^= f(n2+key[1]);
|
||||
n2 ^= f(n1+key[2]);
|
||||
n1 ^= f(n2+key[3]);
|
||||
n2 ^= f(n1+key[4]);
|
||||
n1 ^= f(n2+key[5]);
|
||||
n2 ^= f(n1+key[6]);
|
||||
n1 ^= f(n2+key[7]);
|
||||
}
|
||||
|
||||
n2 ^= f(n1+key[7]);
|
||||
n1 ^= f(n2+key[6]);
|
||||
n2 ^= f(n1+key[5]);
|
||||
n1 ^= f(n2+key[4]);
|
||||
n2 ^= f(n1+key[3]);
|
||||
n1 ^= f(n2+key[2]);
|
||||
n2 ^= f(n1+key[1]);
|
||||
n1 ^= f(n2+key[0]);
|
||||
|
||||
Block::Put(xorBlock, outBlock)(n2)(n1);
|
||||
}
|
||||
|
||||
void GOST::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 n1, n2, t;
|
||||
|
||||
Block::Get(inBlock)(n1)(n2);
|
||||
|
||||
n2 ^= f(n1+key[0]);
|
||||
n1 ^= f(n2+key[1]);
|
||||
n2 ^= f(n1+key[2]);
|
||||
n1 ^= f(n2+key[3]);
|
||||
n2 ^= f(n1+key[4]);
|
||||
n1 ^= f(n2+key[5]);
|
||||
n2 ^= f(n1+key[6]);
|
||||
n1 ^= f(n2+key[7]);
|
||||
|
||||
for (unsigned int i=0; i<3; i++)
|
||||
{
|
||||
n2 ^= f(n1+key[7]);
|
||||
n1 ^= f(n2+key[6]);
|
||||
n2 ^= f(n1+key[5]);
|
||||
n1 ^= f(n2+key[4]);
|
||||
n2 ^= f(n1+key[3]);
|
||||
n1 ^= f(n2+key[2]);
|
||||
n2 ^= f(n1+key[1]);
|
||||
n1 ^= f(n2+key[0]);
|
||||
}
|
||||
|
||||
Block::Put(xorBlock, outBlock)(n2)(n1);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user