Removed CryptoPP files.
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (cryptopp)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCRYPTOPP_DISABLE_ASM")
|
||||
endif()
|
||||
include_directories ("${PROJECT_SOURCE_DIR}/../../src/")
|
||||
|
||||
file(GLOB cryptopp_SRC
|
||||
"*.cpp"
|
||||
)
|
||||
|
||||
add_library(cryptopp ${cryptopp_SRC})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
||||
Compilation Copyright (c) 1995-2013 by Wei Dai. All rights reserved.
|
||||
This copyright applies only to this software distribution package
|
||||
as a compilation, and does not imply a copyright on any particular
|
||||
file in the package.
|
||||
|
||||
All individual files in this compilation are placed in the public domain by
|
||||
Wei Dai and other contributors.
|
||||
|
||||
I would like to thank the following authors for placing their works into
|
||||
the public domain:
|
||||
|
||||
Joan Daemen - 3way.cpp
|
||||
Leonard Janke - cast.cpp, seal.cpp
|
||||
Steve Reid - cast.cpp
|
||||
Phil Karn - des.cpp
|
||||
Andrew M. Kuchling - md2.cpp, md4.cpp
|
||||
Colin Plumb - md5.cpp
|
||||
Seal Woods - rc6.cpp
|
||||
Chris Morgan - rijndael.cpp
|
||||
Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp
|
||||
Richard De Moliner - safer.cpp
|
||||
Matthew Skala - twofish.cpp
|
||||
Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp
|
||||
Ronny Van Keer - sha3.cpp
|
||||
|
||||
The Crypto++ Library (as a compilation) is currently licensed under the Boost
|
||||
Software License 1.0 (http://www.boost.org/users/license.html).
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,452 +0,0 @@
|
||||
Crypto++: a C++ Class Library of Cryptographic Schemes
|
||||
Version 5.6.2 - 2/20/2013
|
||||
|
||||
Crypto++ Library is a free C++ class library of cryptographic schemes.
|
||||
Currently the library contains the following algorithms:
|
||||
|
||||
algorithm type name
|
||||
|
||||
authenticated encryption schemes GCM, CCM, EAX
|
||||
|
||||
high speed stream ciphers Panama, Sosemanuk, Salsa20, XSalsa20
|
||||
|
||||
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
|
||||
CAST-256
|
||||
|
||||
IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
|
||||
other block ciphers Camellia, SEED, RC5, Blowfish, TEA, XTEA,
|
||||
Skipjack, SHACAL-2
|
||||
|
||||
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
|
||||
CFB, OFB, counter mode (CTR)
|
||||
|
||||
message authentication codes VMAC, HMAC, GMAC, CMAC, CBC-MAC, DMAC,
|
||||
Two-Track-MAC
|
||||
|
||||
SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and
|
||||
hash functions SHA-512), SHA-3, Tiger, WHIRLPOOL, RIPEMD-128,
|
||||
RIPEMD-256, RIPEMD-160, RIPEMD-320
|
||||
|
||||
RSA, DSA, ElGamal, Nyberg-Rueppel (NR),
|
||||
public-key cryptography Rabin-Williams (RW), LUC, LUCELG,
|
||||
DLIES (variants of DHAES), ESIGN
|
||||
|
||||
padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363
|
||||
systems EMSA2 and EMSA5
|
||||
|
||||
Diffie-Hellman (DH), Unified Diffie-Hellman
|
||||
key agreement schemes (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF,
|
||||
XTR-DH
|
||||
|
||||
elliptic curve cryptography ECDSA, ECNR, ECIES, ECDH, ECMQV
|
||||
|
||||
insecure or obsolescent MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL
|
||||
algorithms retained for backwards 3.0, WAKE-OFB, DESX (DES-XEX3), RC2,
|
||||
compatibility and historical SAFER, 3-WAY, GOST, SHARK, CAST-128, Square
|
||||
value
|
||||
|
||||
Other features include:
|
||||
|
||||
* pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool
|
||||
* password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5,
|
||||
PBKDF from PKCS #12 appendix B
|
||||
* Shamir's secret sharing scheme and Rabin's information dispersal algorithm
|
||||
(IDA)
|
||||
* fast multi-precision integer (bignum) and polynomial operations
|
||||
* finite field arithmetics, including GF(p) and GF(2^n)
|
||||
* prime number generation and verification
|
||||
* useful non-cryptographic algorithms
|
||||
+ DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and
|
||||
zlib (RFC 1950) format support
|
||||
+ hex, base-32, and base-64 coding/decoding
|
||||
+ 32-bit CRC and Adler32 checksum
|
||||
* class wrappers for these operating system features (optional):
|
||||
+ high resolution timers on Windows, Unix, and Mac OS
|
||||
+ Berkeley and Windows style sockets
|
||||
+ Windows named pipes
|
||||
+ /dev/random, /dev/urandom, /dev/srandom
|
||||
+ Microsoft's CryptGenRandom on Windows
|
||||
* A high level interface for most of the above, using a filter/pipeline
|
||||
metaphor
|
||||
* benchmarks and validation testing
|
||||
* x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used
|
||||
algorithms, with run-time CPU feature detection and code selection
|
||||
* some versions are available in FIPS 140-2 validated form
|
||||
|
||||
You are welcome to use it for any purpose without paying me, but see
|
||||
License.txt for the fine print.
|
||||
|
||||
The following compilers are supported for this release. Please visit
|
||||
http://www.cryptopp.com the most up to date build instructions and porting notes.
|
||||
|
||||
* MSVC 6.0 - 2010
|
||||
* GCC 3.3 - 4.5
|
||||
* C++Builder 2010
|
||||
* Intel C++ Compiler 9 - 11.1
|
||||
* Sun Studio 12u1, Express 11/08, Express 06/10
|
||||
|
||||
*** Important Usage Notes ***
|
||||
|
||||
1. If a constructor for A takes a pointer to an object B (except primitive
|
||||
types such as int and char), then A owns B and will delete B at A's
|
||||
destruction. If a constructor for A takes a reference to an object B,
|
||||
then the caller retains ownership of B and should not destroy it until
|
||||
A no longer needs it.
|
||||
|
||||
2. Crypto++ is thread safe at the class level. This means you can use
|
||||
Crypto++ safely in a multithreaded application, but you must provide
|
||||
synchronization when multiple threads access a common Crypto++ object.
|
||||
|
||||
*** MSVC-Specific Information ***
|
||||
|
||||
On Windows, Crypto++ can be compiled into 3 forms: a static library
|
||||
including all algorithms, a DLL with only FIPS Approved algorithms, and
|
||||
a static library with only algorithms not in the DLL.
|
||||
(FIPS Approved means Approved according to the FIPS 140-2 standard.)
|
||||
The DLL may be used by itself, or it may be used together with the second
|
||||
form of the static library. MSVC project files are included to build
|
||||
all three forms, and sample applications using each of the three forms
|
||||
are also included.
|
||||
|
||||
To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET
|
||||
2003) or "cryptest.sln" (for MSVC 2005 - 2010) workspace file and build one or
|
||||
more of the following projects:
|
||||
|
||||
cryptopp - This builds the DLL. Please note that if you wish to use Crypto++
|
||||
as a FIPS validated module, you must use a pre-built DLL that has undergone
|
||||
the FIPS validation process instead of building your own.
|
||||
dlltest - This builds a sample application that only uses the DLL.
|
||||
cryptest Non-DLL-Import Configuration - This builds the full static library
|
||||
along with a full test driver.
|
||||
cryptest DLL-Import Configuration - This builds a static library containing
|
||||
only algorithms not in the DLL, along with a full test driver that uses
|
||||
both the DLL and the static library.
|
||||
|
||||
To use the Crypto++ DLL in your application, #include "dll.h" before including
|
||||
any other Crypto++ header files, and place the DLL in the same directory as
|
||||
your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp")
|
||||
so you don't have to explicitly list the import library in your project
|
||||
settings. To use a static library form of Crypto++, make the "cryptlib"
|
||||
project a dependency of your application project, or specify it as
|
||||
an additional library to link with in your project settings.
|
||||
In either case you should check the compiler options to
|
||||
make sure that the library and your application are using the same C++
|
||||
run-time libraries and calling conventions.
|
||||
|
||||
*** DLL Memory Management ***
|
||||
|
||||
Because it's possible for the Crypto++ DLL to delete objects allocated
|
||||
by the calling application, they must use the same C++ memory heap. Three
|
||||
methods are provided to achieve this.
|
||||
1. The calling application can tell Crypto++ what heap to use. This method
|
||||
is required when the calling application uses a non-standard heap.
|
||||
2. Crypto++ can tell the calling application what heap to use. This method
|
||||
is required when the calling application uses a statically linked C++ Run
|
||||
Time Library. (Method 1 does not work in this case because the Crypto++ DLL
|
||||
is initialized before the calling application's heap is initialized.)
|
||||
3. Crypto++ can automatically use the heap provided by the calling application's
|
||||
dynamically linked C++ Run Time Library. The calling application must
|
||||
make sure that the dynamically linked C++ Run Time Library is initialized
|
||||
before Crypto++ is loaded. (At this time it is not clear if it is possible
|
||||
to control the order in which DLLs are initialized on Windows 9x machines,
|
||||
so it might be best to avoid using this method.)
|
||||
|
||||
When Crypto++ attaches to a new process, it searches all modules loaded
|
||||
into the process space for exported functions "GetNewAndDeleteForCryptoPP"
|
||||
and "SetNewAndDeleteFromCryptoPP". If one of these functions is found,
|
||||
Crypto++ uses methods 1 or 2, respectively, by calling the function.
|
||||
Otherwise, method 3 is used.
|
||||
|
||||
*** GCC-Specific Information ***
|
||||
|
||||
A makefile is included for you to compile Crypto++ with GCC. Make sure
|
||||
you are using GNU Make and GNU ld. The make process will produce two files,
|
||||
libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation
|
||||
suite.
|
||||
|
||||
*** Documentation and Support ***
|
||||
|
||||
Crypto++ is documented through inline comments in header files, which are
|
||||
processed through Doxygen to produce an HTML reference manual. You can find
|
||||
a link to the manual from http://www.cryptopp.com. Also at that site is
|
||||
the Crypto++ FAQ, which you should browse through before attempting to
|
||||
use this library, because it will likely answer many of questions that
|
||||
may come up.
|
||||
|
||||
If you run into any problems, please try the Crypto++ mailing list.
|
||||
The subscription information and the list archive are available on
|
||||
http://www.cryptopp.com. You can also email me directly by visiting
|
||||
http://www.weidai.com, but you will probably get a faster response through
|
||||
the mailing list.
|
||||
|
||||
*** History ***
|
||||
|
||||
1.0 - First public release. Withdrawn at the request of RSA DSI.
|
||||
- included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA,
|
||||
MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression
|
||||
- had a serious bug in the RSA key generation code.
|
||||
|
||||
1.1 - Removed RSA, RC4, RC5
|
||||
- Disabled calls to RSAREF's non-public functions
|
||||
- Minor bugs fixed
|
||||
|
||||
2.0 - a completely new, faster multiprecision integer class
|
||||
- added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser,
|
||||
elliptic curve algorithms
|
||||
- added the Lucas strong probable primality test
|
||||
- ElGamal encryption and signature schemes modified to avoid weaknesses
|
||||
- Diamond changed to Diamond2 because of key schedule weakness
|
||||
- fixed bug in WAKE key setup
|
||||
- SHS class renamed to SHA
|
||||
- lots of miscellaneous optimizations
|
||||
|
||||
2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC,
|
||||
OAEP, PSSR, SHARK
|
||||
- added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms
|
||||
- added back RC5 and a new RSA
|
||||
- optimizations in elliptic curves over GF(p)
|
||||
- changed Rabin to use OAEP and PSSR
|
||||
- changed many classes to allow copy constructors to work correctly
|
||||
- improved exception generation and handling
|
||||
|
||||
2.2 - added SEAL, CAST-128, Square
|
||||
- fixed bug in HAVAL (padding problem)
|
||||
- fixed bug in triple-DES (decryption order was reversed)
|
||||
- fixed bug in RC5 (couldn't handle key length not a multiple of 4)
|
||||
- changed HMAC to conform to RFC-2104 (which is not compatible
|
||||
with the original HMAC)
|
||||
- changed secret sharing and information dispersal to use GF(2^32)
|
||||
instead of GF(65521)
|
||||
- removed zero knowledge prover/verifier for graph isomorphism
|
||||
- removed several utility classes in favor of the C++ standard library
|
||||
|
||||
2.3 - ported to EGCS
|
||||
- fixed incomplete workaround of min/max conflict in MSVC
|
||||
|
||||
3.0 - placed all names into the "CryptoPP" namespace
|
||||
- added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS
|
||||
- added abstract base classes PK_SimpleKeyAgreementDomain and
|
||||
PK_AuthenticatedKeyAgreementDomain
|
||||
- changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain
|
||||
interface and to perform domain parameter and key validation
|
||||
- changed interfaces of PK_Signer and PK_Verifier to sign and verify
|
||||
messages instead of message digests
|
||||
- changed OAEP to conform to PKCS#1 v2.0
|
||||
- changed benchmark code to produce HTML tables as output
|
||||
- changed PSSR to track IEEE P1363a
|
||||
- renamed ElGamalSignature to NR and changed it to track IEEE P1363
|
||||
- renamed ECKEP to ECMQVC and changed it to track IEEE P1363
|
||||
- renamed several other classes for clarity
|
||||
- removed support for calling RSAREF
|
||||
- removed option to compile old SHA (SHA-0)
|
||||
- removed option not to throw exceptions
|
||||
|
||||
3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC
|
||||
- added interface for querying supported key lengths of symmetric ciphers
|
||||
and MACs
|
||||
- added sample code for RSA signature and verification
|
||||
- changed CBC-CTS to be compatible with RFC 2040
|
||||
- updated SEAL to version 3.0 of the cipher specification
|
||||
- optimized multiprecision squaring and elliptic curves over GF(p)
|
||||
- fixed bug in MARS key setup
|
||||
- fixed bug with attaching objects to Deflator
|
||||
|
||||
3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC
|
||||
- renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3
|
||||
- optimized ARC4
|
||||
- generalized DSA to allow keys longer than 1024 bits
|
||||
- fixed bugs in GF2N and ModularArithmetic that can cause calculation errors
|
||||
- fixed crashing bug in Inflator when given invalid inputs
|
||||
- fixed endian bug in Serpent
|
||||
- fixed padding bug in Tiger
|
||||
|
||||
4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512),
|
||||
and XTR-DH
|
||||
- added a faster variant of Rabin's Information Dispersal Algorithm (IDA)
|
||||
- added class wrappers for these operating system features:
|
||||
- high resolution timers on Windows, Unix, and MacOS
|
||||
- Berkeley and Windows style sockets
|
||||
- Windows named pipes
|
||||
- /dev/random and /dev/urandom on Linux and FreeBSD
|
||||
- Microsoft's CryptGenRandom on Windows
|
||||
- added support for SEC 1 elliptic curve key format and compressed points
|
||||
- added support for X.509 public key format (subjectPublicKeyInfo) for
|
||||
RSA, DSA, and elliptic curve schemes
|
||||
- added support for DER and OpenPGP signature format for DSA
|
||||
- added support for ZLIB compressed data format (RFC 1950)
|
||||
- changed elliptic curve encryption to use ECIES (as defined in SEC 1)
|
||||
- changed MARS key schedule to reflect the latest specification
|
||||
- changed BufferedTransformation interface to support multiple channels
|
||||
and messages
|
||||
- changed CAST and SHA-1 implementations to use public domain source code
|
||||
- fixed bug in StringSource
|
||||
- optmized multi-precision integer code for better performance
|
||||
|
||||
4.1 - added more support for the recommended elliptic curve parameters in SEC 2
|
||||
- added Panama MAC, MARC4
|
||||
- added IV stealing feature to CTS mode
|
||||
- added support for PKCS #8 private key format for RSA, DSA, and elliptic
|
||||
curve schemes
|
||||
- changed Deflate, MD5, Rijndael, and Twofish to use public domain code
|
||||
- fixed a bug with flushing compressed streams
|
||||
- fixed a bug with decompressing stored blocks
|
||||
- fixed a bug with EC point decompression using non-trinomial basis
|
||||
- fixed a bug in NetworkSource::GeneralPump()
|
||||
- fixed a performance issue with EC over GF(p) decryption
|
||||
- fixed syntax to allow GCC to compile without -fpermissive
|
||||
- relaxed some restrictions in the license
|
||||
|
||||
4.2 - added support for longer HMAC keys
|
||||
- added MD4 (which is not secure so use for compatibility purposes only)
|
||||
- added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2,
|
||||
and MSVC 7.0
|
||||
- changed MD2 to use public domain code
|
||||
- fixed a bug with decompressing multiple messages with the same object
|
||||
- fixed a bug in CBC-MAC with MACing multiple messages with the same object
|
||||
- fixed a bug in RC5 and RC6 with zero-length keys
|
||||
- fixed a bug in Adler32 where incorrect checksum may be generated
|
||||
|
||||
5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5
|
||||
- added key validation for encryption and signature public/private keys
|
||||
- renamed StreamCipher interface to SymmetricCipher, which is now implemented
|
||||
by both stream ciphers and block cipher modes including ECB and CBC
|
||||
- added keying interfaces to support resetting of keys and IVs without
|
||||
having to destroy and recreate objects
|
||||
- changed filter interface to support non-blocking input/output
|
||||
- changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows
|
||||
- grouped related classes inside structs to help templates, for example
|
||||
AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption
|
||||
- where possible, typedefs have been added to improve backwards
|
||||
compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined
|
||||
- changed Serpent, HAVAL and IDEA to use public domain code
|
||||
- implemented SSE2 optimizations for Integer operations
|
||||
- fixed a bug in HMAC::TruncatedFinal()
|
||||
- fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02
|
||||
|
||||
5.01 - added known answer test for X9.17 RNG in FIPS 140 power-up self test
|
||||
- submitted to NIST/CSE, but not publicly released
|
||||
|
||||
5.02 - changed EDC test to MAC integrity check using HMAC/SHA1
|
||||
- improved performance of integrity check
|
||||
- added blinding to defend against RSA timing attack
|
||||
|
||||
5.03 - created DLL version of Crypto++ for FIPS 140-2 validation
|
||||
- fixed vulnerabilities in GetNextIV for CTR and OFB modes
|
||||
|
||||
5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL
|
||||
|
||||
5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard
|
||||
- added blinding for RSA and Rabin to defend against timing attacks
|
||||
on decryption operations
|
||||
- changed signing and decryption APIs to support the above
|
||||
- changed WaitObjectContainer to allow waiting for more than 64
|
||||
objects at a time on Win32 platforms
|
||||
- fixed a bug in CBC and ECB modes with processing non-aligned data
|
||||
- fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2
|
||||
signature scheme (these fixes are not backwards compatible)
|
||||
- fixed a number of compiler warnings, minor bugs, and portability problems
|
||||
- removed Sapphire
|
||||
|
||||
5.2 - merged in changes for 5.01 - 5.0.4
|
||||
- added support for using encoding parameters and key derivation parameters
|
||||
with public key encryption (implemented by OAEP and DL/ECIES)
|
||||
- added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320,
|
||||
RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode
|
||||
- added ThreadUserTimer for timing thread CPU usage
|
||||
- added option for password-based key derivation functions
|
||||
to iterate until a mimimum elapsed thread CPU time is reached
|
||||
- added option (on by default) for DEFLATE compression to detect
|
||||
uncompressible files and process them more quickly
|
||||
- improved compatibility and performance on 64-bit platforms,
|
||||
including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64
|
||||
- fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding.
|
||||
- fixed encoding/decoding of PKCS #8 privateKeyInfo to properly
|
||||
handle optional attributes
|
||||
|
||||
5.2.1 - fixed bug in the "dlltest" DLL testing program
|
||||
- fixed compiling with STLport using VC .NET
|
||||
- fixed compiling with -fPIC using GCC
|
||||
- fixed compiling with -msse2 on systems without memalign()
|
||||
- fixed inability to instantiate PanamaMAC
|
||||
- fixed problems with inline documentation
|
||||
|
||||
5.2.2 - added SHA-224
|
||||
- put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL
|
||||
|
||||
5.2.3 - fixed issues with FIPS algorithm test vectors
|
||||
- put RSASSA-ISO into DLL
|
||||
|
||||
5.3 - ported to MSVC 2005 with support for x86-64
|
||||
- added defense against AES timing attacks, and more AES test vectors
|
||||
- changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR"
|
||||
|
||||
5.4 - added Salsa20
|
||||
- updated Whirlpool to version 3.0
|
||||
- ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006
|
||||
|
||||
5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly)
|
||||
- improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20,
|
||||
Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2)
|
||||
- optimized Camellia and added defense against timing attacks
|
||||
- updated benchmarks code to show cycles per byte and to time key/IV setup
|
||||
- started using OpenMP for increased multi-core speed
|
||||
- enabled GCC optimization flags by default in GNUmakefile
|
||||
- added blinding and computational error checking for RW signing
|
||||
- changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce
|
||||
the risk of reusing random numbers and IVs after virtual machine state
|
||||
rollback
|
||||
- changed default FIPS mode RNG from AutoSeededX917RNG<DES_EDE3> to
|
||||
AutoSeededX917RNG<AES>
|
||||
- fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV
|
||||
- moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak"
|
||||
- removed HAVAL, MD5-MAC, XMAC
|
||||
|
||||
5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines
|
||||
|
||||
5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama
|
||||
to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64)
|
||||
- fixed Salsa20 initialization crash on non-SSE2 machines
|
||||
- fixed Whirlpool crash on Pentium 2 machines
|
||||
- fixed possible branch prediction analysis (BPA) vulnerability in
|
||||
MontgomeryReduce(), which may affect security of RSA, RW, LUC
|
||||
- fixed link error with MSVC 2003 when using "debug DLL" form of runtime library
|
||||
- fixed crash in SSE2_Add on P4 machines when compiled with
|
||||
MSVC 6.0 SP5 with Processor Pack
|
||||
- ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0,
|
||||
and Borland C++Builder 2007
|
||||
|
||||
5.6.0 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
|
||||
- added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED
|
||||
- added support for variable length IVs
|
||||
- added OIDs for Brainpool elliptic curve parameters
|
||||
- improved AES and SHA-256 speed on x86 and x64
|
||||
- changed BlockTransformation interface to no longer assume data alignment
|
||||
- fixed incorrect VMAC computation on message lengths
|
||||
that are >64 mod 128 (x86 assembly version is not affected)
|
||||
- fixed compiler error in vmac.cpp on x86 with GCC -fPIC
|
||||
- fixed run-time validation error on x86-64 with GCC 4.3.2 -O2
|
||||
- fixed HashFilter bug when putMessage=true
|
||||
- fixed AES-CTR data alignment bug that causes incorrect encryption on ARM
|
||||
- removed WORD64_AVAILABLE; compiler support for 64-bit int is now required
|
||||
- ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11
|
||||
|
||||
5.6.1 - added support for AES-NI and CLMUL instruction sets in AES and GMAC/GCM
|
||||
- removed WAKE-CFB
|
||||
- fixed several bugs in the SHA-256 x86/x64 assembly code:
|
||||
* incorrect hash on non-SSE2 x86 machines on non-aligned input
|
||||
* incorrect hash on x86 machines when input crosses 0x80000000
|
||||
* incorrect hash on x64 when compiled with GCC with optimizations enabled
|
||||
- fixed bugs in AES x86 and x64 assembly causing crashes in some MSVC build configurations
|
||||
- switched to a public domain implementation of MARS
|
||||
- ported to MSVC 2010, GCC 4.5.1, Sun Studio 12u1, C++Builder 2010, Intel C++ Compiler 11.1
|
||||
- renamed the MSVC DLL project to "cryptopp" for compatibility with MSVC 2010
|
||||
|
||||
5.6.2 - changed license to Boost Software License 1.0
|
||||
- added SHA-3 (Keccak)
|
||||
- updated DSA to FIPS 186-3 (see DSA2 class)
|
||||
- fixed Blowfish minimum keylength to be 4 bytes (32 bits)
|
||||
- fixed Salsa validation failure when compiling with GCC 4.6
|
||||
- fixed infinite recursion when on x64, assembly disabled, and no AESNI
|
||||
- ported to MSVC 2012, GCC 4.7, Clang 3.2, Solaris Studio 12.3, Intel C++ Compiler 13.0
|
||||
|
||||
Written by Wei Dai
|
||||
@@ -1,77 +0,0 @@
|
||||
// adler32.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "adler32.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void Adler32::Update(const byte *input, size_t length)
|
||||
{
|
||||
const unsigned long BASE = 65521;
|
||||
|
||||
unsigned long s1 = m_s1;
|
||||
unsigned long s2 = m_s2;
|
||||
|
||||
if (length % 8 != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
s1 += *input++;
|
||||
s2 += s1;
|
||||
length--;
|
||||
} while (length % 8 != 0);
|
||||
|
||||
if (s1 >= BASE)
|
||||
s1 -= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
s1 += input[0]; s2 += s1;
|
||||
s1 += input[1]; s2 += s1;
|
||||
s1 += input[2]; s2 += s1;
|
||||
s1 += input[3]; s2 += s1;
|
||||
s1 += input[4]; s2 += s1;
|
||||
s1 += input[5]; s2 += s1;
|
||||
s1 += input[6]; s2 += s1;
|
||||
s1 += input[7]; s2 += s1;
|
||||
|
||||
length -= 8;
|
||||
input += 8;
|
||||
|
||||
if (s1 >= BASE)
|
||||
s1 -= BASE;
|
||||
if (length % 0x8000 == 0)
|
||||
s2 %= BASE;
|
||||
}
|
||||
|
||||
assert(s1 < BASE);
|
||||
assert(s2 < BASE);
|
||||
|
||||
m_s1 = (word16)s1;
|
||||
m_s2 = (word16)s2;
|
||||
}
|
||||
|
||||
void Adler32::TruncatedFinal(byte *hash, size_t size)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
default:
|
||||
hash[3] = byte(m_s1);
|
||||
case 3:
|
||||
hash[2] = byte(m_s1 >> 8);
|
||||
case 2:
|
||||
hash[1] = byte(m_s2);
|
||||
case 1:
|
||||
hash[0] = byte(m_s2 >> 8);
|
||||
case 0:
|
||||
;
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef CRYPTOPP_ADLER32_H
|
||||
#define CRYPTOPP_ADLER32_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! ADLER-32 checksum calculations
|
||||
class Adler32 : public HashTransformation
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
|
||||
Adler32() {Reset();}
|
||||
void Update(const byte *input, size_t length);
|
||||
void TruncatedFinal(byte *hash, size_t size);
|
||||
unsigned int DigestSize() const {return DIGESTSIZE;}
|
||||
static const char * StaticAlgorithmName() {return "Adler32";}
|
||||
std::string AlgorithmName() const {return StaticAlgorithmName();}
|
||||
|
||||
private:
|
||||
void Reset() {m_s1 = 1; m_s2 = 0;}
|
||||
|
||||
word16 m_s1, m_s2;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef CRYPTOPP_AES_H
|
||||
#define CRYPTOPP_AES_H
|
||||
|
||||
#include "rijndael.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
|
||||
DOCUMENTED_TYPEDEF(Rijndael, AES);
|
||||
|
||||
typedef RijndaelEncryption AESEncryption;
|
||||
typedef RijndaelDecryption AESDecryption;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,340 +0,0 @@
|
||||
// algebra.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice
|
||||
#define CRYPTOPP_ALGEBRA_CPP
|
||||
|
||||
#include "algebra.h"
|
||||
#include "integer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
|
||||
{
|
||||
return this->Add(a, a);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
|
||||
{
|
||||
// make copy of a in case Inverse() overwrites it
|
||||
Element a1(a);
|
||||
return this->Add(a1, Inverse(b));
|
||||
}
|
||||
|
||||
template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
|
||||
{
|
||||
return a = this->Add(a, b);
|
||||
}
|
||||
|
||||
template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
|
||||
{
|
||||
return a = this->Subtract(a, b);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractRing<T>::Square(const Element &a) const
|
||||
{
|
||||
return this->Multiply(a, a);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractRing<T>::Divide(const Element &a, const Element &b) const
|
||||
{
|
||||
// make copy of a in case MultiplicativeInverse() overwrites it
|
||||
Element a1(a);
|
||||
return this->Multiply(a1, this->MultiplicativeInverse(b));
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
|
||||
{
|
||||
Element q;
|
||||
this->DivisionAlgorithm(result, q, a, b);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a, const Element &b) const
|
||||
{
|
||||
Element g[3]={b, a};
|
||||
unsigned int i0=0, i1=1, i2=2;
|
||||
|
||||
while (!this->Equal(g[i1], this->Identity()))
|
||||
{
|
||||
g[i2] = this->Mod(g[i0], g[i1]);
|
||||
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
|
||||
}
|
||||
|
||||
return result = g[i0];
|
||||
}
|
||||
|
||||
template <class T> const typename QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(const Element &a) const
|
||||
{
|
||||
Element g[3]={m_modulus, a};
|
||||
Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
|
||||
Element y;
|
||||
unsigned int i0=0, i1=1, i2=2;
|
||||
|
||||
while (!this->Equal(g[i1], this->Identity()))
|
||||
{
|
||||
// y = g[i0] / g[i1];
|
||||
// g[i2] = g[i0] % g[i1];
|
||||
m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
|
||||
// v[i2] = v[i0] - (v[i1] * y);
|
||||
v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
|
||||
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
|
||||
}
|
||||
|
||||
return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity();
|
||||
}
|
||||
|
||||
template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base, const Integer &exponent) const
|
||||
{
|
||||
Element result;
|
||||
this->SimultaneousMultiply(&result, base, &exponent, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
||||
{
|
||||
const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount());
|
||||
if (expLen==0)
|
||||
return this->Identity();
|
||||
|
||||
const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
|
||||
const unsigned tableSize = 1<<w;
|
||||
std::vector<Element> powerTable(tableSize << w);
|
||||
|
||||
powerTable[1] = x;
|
||||
powerTable[tableSize] = y;
|
||||
if (w==1)
|
||||
powerTable[3] = this->Add(x,y);
|
||||
else
|
||||
{
|
||||
powerTable[2] = this->Double(x);
|
||||
powerTable[2*tableSize] = this->Double(y);
|
||||
|
||||
unsigned i, j;
|
||||
|
||||
for (i=3; i<tableSize; i+=2)
|
||||
powerTable[i] = Add(powerTable[i-2], powerTable[2]);
|
||||
for (i=1; i<tableSize; i+=2)
|
||||
for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
|
||||
powerTable[j] = Add(powerTable[j-tableSize], y);
|
||||
|
||||
for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
|
||||
powerTable[i] = Add(powerTable[i-2*tableSize], powerTable[2*tableSize]);
|
||||
for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
|
||||
for (j=i+2; j<i+tableSize; j+=2)
|
||||
powerTable[j] = Add(powerTable[j-1], x);
|
||||
}
|
||||
|
||||
Element result;
|
||||
unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
|
||||
bool firstTime = true;
|
||||
|
||||
for (int i = expLen-1; i>=0; i--)
|
||||
{
|
||||
power1 = 2*power1 + e1.GetBit(i);
|
||||
power2 = 2*power2 + e2.GetBit(i);
|
||||
|
||||
if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
|
||||
{
|
||||
unsigned squaresBefore = prevPosition-i;
|
||||
unsigned squaresAfter = 0;
|
||||
prevPosition = i;
|
||||
while ((power1 || power2) && power1%2 == 0 && power2%2==0)
|
||||
{
|
||||
power1 /= 2;
|
||||
power2 /= 2;
|
||||
squaresBefore--;
|
||||
squaresAfter++;
|
||||
}
|
||||
if (firstTime)
|
||||
{
|
||||
result = powerTable[(power2<<w) + power1];
|
||||
firstTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (squaresBefore--)
|
||||
result = this->Double(result);
|
||||
if (power1 || power2)
|
||||
Accumulate(result, powerTable[(power2<<w) + power1]);
|
||||
}
|
||||
while (squaresAfter--)
|
||||
result = this->Double(result);
|
||||
power1 = power2 = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end)
|
||||
{
|
||||
if (end-begin == 1)
|
||||
return group.ScalarMultiply(begin->base, begin->exponent);
|
||||
else if (end-begin == 2)
|
||||
return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent);
|
||||
else
|
||||
{
|
||||
Integer q, t;
|
||||
Iterator last = end;
|
||||
--last;
|
||||
|
||||
std::make_heap(begin, end);
|
||||
std::pop_heap(begin, end);
|
||||
|
||||
while (!!begin->exponent)
|
||||
{
|
||||
// last->exponent is largest exponent, begin->exponent is next largest
|
||||
t = last->exponent;
|
||||
Integer::Divide(last->exponent, q, t, begin->exponent);
|
||||
|
||||
if (q == Integer::One())
|
||||
group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply()
|
||||
else
|
||||
group.Accumulate(begin->base, group.ScalarMultiply(last->base, q));
|
||||
|
||||
std::push_heap(begin, end);
|
||||
std::pop_heap(begin, end);
|
||||
}
|
||||
|
||||
return group.ScalarMultiply(last->base, last->exponent);
|
||||
}
|
||||
}
|
||||
|
||||
struct WindowSlider
|
||||
{
|
||||
WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
|
||||
: exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false)
|
||||
{
|
||||
if (windowSize == 0)
|
||||
{
|
||||
unsigned int expLen = exp.BitCount();
|
||||
windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7)))));
|
||||
}
|
||||
windowModulus <<= windowSize;
|
||||
}
|
||||
|
||||
void FindNextWindow()
|
||||
{
|
||||
unsigned int expLen = exp.WordCount() * WORD_BITS;
|
||||
unsigned int skipCount = firstTime ? 0 : windowSize;
|
||||
firstTime = false;
|
||||
while (!exp.GetBit(skipCount))
|
||||
{
|
||||
if (skipCount >= expLen)
|
||||
{
|
||||
finished = true;
|
||||
return;
|
||||
}
|
||||
skipCount++;
|
||||
}
|
||||
|
||||
exp >>= skipCount;
|
||||
windowBegin += skipCount;
|
||||
expWindow = word32(exp % (word(1) << windowSize));
|
||||
|
||||
if (fastNegate && exp.GetBit(windowSize))
|
||||
{
|
||||
negateNext = true;
|
||||
expWindow = (word32(1) << windowSize) - expWindow;
|
||||
exp += windowModulus;
|
||||
}
|
||||
else
|
||||
negateNext = false;
|
||||
}
|
||||
|
||||
Integer exp, windowModulus;
|
||||
unsigned int windowSize, windowBegin;
|
||||
word32 expWindow;
|
||||
bool fastNegate, negateNext, firstTime, finished;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const
|
||||
{
|
||||
std::vector<std::vector<Element> > buckets(expCount);
|
||||
std::vector<WindowSlider> exponents;
|
||||
exponents.reserve(expCount);
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<expCount; i++)
|
||||
{
|
||||
assert(expBegin->NotNegative());
|
||||
exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
|
||||
exponents[i].FindNextWindow();
|
||||
buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
|
||||
}
|
||||
|
||||
unsigned int expBitPosition = 0;
|
||||
Element g = base;
|
||||
bool notDone = true;
|
||||
|
||||
while (notDone)
|
||||
{
|
||||
notDone = false;
|
||||
for (i=0; i<expCount; i++)
|
||||
{
|
||||
if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
|
||||
{
|
||||
Element &bucket = buckets[i][exponents[i].expWindow/2];
|
||||
if (exponents[i].negateNext)
|
||||
Accumulate(bucket, Inverse(g));
|
||||
else
|
||||
Accumulate(bucket, g);
|
||||
exponents[i].FindNextWindow();
|
||||
}
|
||||
notDone = notDone || !exponents[i].finished;
|
||||
}
|
||||
|
||||
if (notDone)
|
||||
{
|
||||
g = Double(g);
|
||||
expBitPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<expCount; i++)
|
||||
{
|
||||
Element &r = *results++;
|
||||
r = buckets[i][buckets[i].size()-1];
|
||||
if (buckets[i].size() > 1)
|
||||
{
|
||||
for (int j = (int)buckets[i].size()-2; j >= 1; j--)
|
||||
{
|
||||
Accumulate(buckets[i][j], buckets[i][j+1]);
|
||||
Accumulate(r, buckets[i][j]);
|
||||
}
|
||||
Accumulate(buckets[i][0], buckets[i][1]);
|
||||
r = Add(Double(r), buckets[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> T AbstractRing<T>::Exponentiate(const Element &base, const Integer &exponent) const
|
||||
{
|
||||
Element result;
|
||||
SimultaneousExponentiate(&result, base, &exponent, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
||||
{
|
||||
return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(x, e1, y, e2);
|
||||
}
|
||||
|
||||
template <class Element, class Iterator> Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end)
|
||||
{
|
||||
return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(), begin, end);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const
|
||||
{
|
||||
MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base, exponents, expCount);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,285 +0,0 @@
|
||||
#ifndef CRYPTOPP_ALGEBRA_H
|
||||
#define CRYPTOPP_ALGEBRA_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class Integer;
|
||||
|
||||
// "const Element&" returned by member functions are references
|
||||
// to internal data members. Since each object may have only
|
||||
// one such data member for holding results, the following code
|
||||
// will produce incorrect results:
|
||||
// abcd = group.Add(group.Add(a,b), group.Add(c,d));
|
||||
// But this should be fine:
|
||||
// abcd = group.Add(a, group.Add(b, group.Add(c,d));
|
||||
|
||||
//! Abstract Group
|
||||
template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
virtual ~AbstractGroup() {}
|
||||
|
||||
virtual bool Equal(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& Identity() const =0;
|
||||
virtual const Element& Add(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& Inverse(const Element &a) const =0;
|
||||
virtual bool InversionIsFast() const {return false;}
|
||||
|
||||
virtual const Element& Double(const Element &a) const;
|
||||
virtual const Element& Subtract(const Element &a, const Element &b) const;
|
||||
virtual Element& Accumulate(Element &a, const Element &b) const;
|
||||
virtual Element& Reduce(Element &a, const Element &b) const;
|
||||
|
||||
virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
|
||||
virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
|
||||
|
||||
virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
||||
};
|
||||
|
||||
//! Abstract Ring
|
||||
template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
AbstractRing() {m_mg.m_pRing = this;}
|
||||
AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
|
||||
AbstractRing& operator=(const AbstractRing &source) {return *this;}
|
||||
|
||||
virtual bool IsUnit(const Element &a) const =0;
|
||||
virtual const Element& MultiplicativeIdentity() const =0;
|
||||
virtual const Element& Multiply(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& MultiplicativeInverse(const Element &a) const =0;
|
||||
|
||||
virtual const Element& Square(const Element &a) const;
|
||||
virtual const Element& Divide(const Element &a, const Element &b) const;
|
||||
|
||||
virtual Element Exponentiate(const Element &a, const Integer &e) const;
|
||||
virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
|
||||
|
||||
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
||||
|
||||
virtual const AbstractGroup<T>& MultiplicativeGroup() const
|
||||
{return m_mg;}
|
||||
|
||||
private:
|
||||
class MultiplicativeGroupT : public AbstractGroup<T>
|
||||
{
|
||||
public:
|
||||
const AbstractRing<T>& GetRing() const
|
||||
{return *m_pRing;}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return GetRing().Equal(a, b);}
|
||||
|
||||
const Element& Identity() const
|
||||
{return GetRing().MultiplicativeIdentity();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return GetRing().Multiply(a, b);}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{return a = GetRing().Multiply(a, b);}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return GetRing().MultiplicativeInverse(a);}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return GetRing().Divide(a, b);}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return a = GetRing().Divide(a, b);}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return GetRing().Square(a);}
|
||||
|
||||
Element ScalarMultiply(const Element &a, const Integer &e) const
|
||||
{return GetRing().Exponentiate(a, e);}
|
||||
|
||||
Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
||||
{return GetRing().CascadeExponentiate(x, e1, y, e2);}
|
||||
|
||||
void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
|
||||
{GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
|
||||
|
||||
const AbstractRing<T> *m_pRing;
|
||||
};
|
||||
|
||||
MultiplicativeGroupT m_mg;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! Base and Exponent
|
||||
template <class T, class E = Integer>
|
||||
struct BaseAndExponent
|
||||
{
|
||||
public:
|
||||
BaseAndExponent() {}
|
||||
BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
|
||||
bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
|
||||
T base;
|
||||
E exponent;
|
||||
};
|
||||
|
||||
// VC60 workaround: incomplete member template support
|
||||
template <class Element, class Iterator>
|
||||
Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
|
||||
template <class Element, class Iterator>
|
||||
Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! Abstract Euclidean Domain
|
||||
template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
|
||||
|
||||
virtual const Element& Mod(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& Gcd(const Element &a, const Element &b) const;
|
||||
|
||||
protected:
|
||||
mutable Element result;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! EuclideanDomainOf
|
||||
template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
EuclideanDomainOf() {}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return a==b;}
|
||||
|
||||
const Element& Identity() const
|
||||
{return Element::Zero();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return result = a+b;}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{return a+=b;}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return result = -a;}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return result = a-b;}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return a-=b;}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return result = a.Doubled();}
|
||||
|
||||
const Element& MultiplicativeIdentity() const
|
||||
{return Element::One();}
|
||||
|
||||
const Element& Multiply(const Element &a, const Element &b) const
|
||||
{return result = a*b;}
|
||||
|
||||
const Element& Square(const Element &a) const
|
||||
{return result = a.Squared();}
|
||||
|
||||
bool IsUnit(const Element &a) const
|
||||
{return a.IsUnit();}
|
||||
|
||||
const Element& MultiplicativeInverse(const Element &a) const
|
||||
{return result = a.MultiplicativeInverse();}
|
||||
|
||||
const Element& Divide(const Element &a, const Element &b) const
|
||||
{return result = a/b;}
|
||||
|
||||
const Element& Mod(const Element &a, const Element &b) const
|
||||
{return result = a%b;}
|
||||
|
||||
void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
|
||||
{Element::Divide(r, q, a, d);}
|
||||
|
||||
bool operator==(const EuclideanDomainOf<T> &rhs) const
|
||||
{return true;}
|
||||
|
||||
private:
|
||||
mutable Element result;
|
||||
};
|
||||
|
||||
//! Quotient Ring
|
||||
template <class T> class QuotientRing : public AbstractRing<typename T::Element>
|
||||
{
|
||||
public:
|
||||
typedef T EuclideanDomain;
|
||||
typedef typename T::Element Element;
|
||||
|
||||
QuotientRing(const EuclideanDomain &domain, const Element &modulus)
|
||||
: m_domain(domain), m_modulus(modulus) {}
|
||||
|
||||
const EuclideanDomain & GetDomain() const
|
||||
{return m_domain;}
|
||||
|
||||
const Element& GetModulus() const
|
||||
{return m_modulus;}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
|
||||
|
||||
const Element& Identity() const
|
||||
{return m_domain.Identity();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return m_domain.Add(a, b);}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{return m_domain.Accumulate(a, b);}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return m_domain.Inverse(a);}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return m_domain.Subtract(a, b);}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return m_domain.Reduce(a, b);}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return m_domain.Double(a);}
|
||||
|
||||
bool IsUnit(const Element &a) const
|
||||
{return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
|
||||
|
||||
const Element& MultiplicativeIdentity() const
|
||||
{return m_domain.MultiplicativeIdentity();}
|
||||
|
||||
const Element& Multiply(const Element &a, const Element &b) const
|
||||
{return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
|
||||
|
||||
const Element& Square(const Element &a) const
|
||||
{return m_domain.Mod(m_domain.Square(a), m_modulus);}
|
||||
|
||||
const Element& MultiplicativeInverse(const Element &a) const;
|
||||
|
||||
bool operator==(const QuotientRing<T> &rhs) const
|
||||
{return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
|
||||
|
||||
protected:
|
||||
EuclideanDomain m_domain;
|
||||
Element m_modulus;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
|
||||
#include "algebra.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,75 +0,0 @@
|
||||
// algparam.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "algparam.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
PAssignIntToInteger g_pAssignIntToInteger = NULL;
|
||||
|
||||
bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
if (strcmp(name, "ValueNames") == 0)
|
||||
return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue);
|
||||
else
|
||||
return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue);
|
||||
}
|
||||
|
||||
void AlgorithmParametersBase::operator=(const AlgorithmParametersBase& rhs)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
if (strcmp(name, "ValueNames") == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType);
|
||||
if (m_next.get())
|
||||
m_next->GetVoidValue(name, valueType, pValue);
|
||||
(*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(name, m_name) == 0)
|
||||
{
|
||||
AssignValue(name, valueType, pValue);
|
||||
m_used = true;
|
||||
return true;
|
||||
}
|
||||
else if (m_next.get())
|
||||
return m_next->GetVoidValue(name, valueType, pValue);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
AlgorithmParameters::AlgorithmParameters()
|
||||
: m_defaultThrowIfNotUsed(true)
|
||||
{
|
||||
}
|
||||
|
||||
AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x)
|
||||
: m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed)
|
||||
{
|
||||
m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
|
||||
}
|
||||
|
||||
AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x)
|
||||
{
|
||||
m_next.reset(const_cast<AlgorithmParameters &>(x).m_next.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
if (m_next.get())
|
||||
return m_next->GetVoidValue(name, valueType, pValue);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,398 +0,0 @@
|
||||
#ifndef CRYPTOPP_ALGPARAM_H
|
||||
#define CRYPTOPP_ALGPARAM_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "smartptr.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! used to pass byte array input as part of a NameValuePairs object
|
||||
/*! the deepCopy option is used when the NameValuePairs object can't
|
||||
keep a copy of the data available */
|
||||
class ConstByteArrayParameter
|
||||
{
|
||||
public:
|
||||
ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
|
||||
{
|
||||
Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
|
||||
}
|
||||
ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
|
||||
{
|
||||
Assign(data, size, deepCopy);
|
||||
}
|
||||
template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
|
||||
{
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
|
||||
Assign((const byte *)string.data(), string.size(), deepCopy);
|
||||
}
|
||||
|
||||
void Assign(const byte *data, size_t size, bool deepCopy)
|
||||
{
|
||||
if (deepCopy)
|
||||
m_block.Assign(data, size);
|
||||
else
|
||||
{
|
||||
m_data = data;
|
||||
m_size = size;
|
||||
}
|
||||
m_deepCopy = deepCopy;
|
||||
}
|
||||
|
||||
const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
|
||||
const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
|
||||
size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
|
||||
|
||||
private:
|
||||
bool m_deepCopy;
|
||||
const byte *m_data;
|
||||
size_t m_size;
|
||||
SecByteBlock m_block;
|
||||
};
|
||||
|
||||
class ByteArrayParameter
|
||||
{
|
||||
public:
|
||||
ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
|
||||
: m_data(data), m_size(size) {}
|
||||
ByteArrayParameter(SecByteBlock &block)
|
||||
: m_data(block.begin()), m_size(block.size()) {}
|
||||
|
||||
byte *begin() const {return m_data;}
|
||||
byte *end() const {return m_data + m_size;}
|
||||
size_t size() const {return m_size;}
|
||||
|
||||
private:
|
||||
byte *m_data;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
|
||||
{
|
||||
public:
|
||||
CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
|
||||
: m_pairs1(pairs1), m_pairs2(pairs2) {}
|
||||
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
||||
|
||||
private:
|
||||
const NameValuePairs &m_pairs1, &m_pairs2;
|
||||
};
|
||||
|
||||
template <class T, class BASE>
|
||||
class GetValueHelperClass
|
||||
{
|
||||
public:
|
||||
GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
|
||||
: m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
|
||||
{
|
||||
if (strcmp(m_name, "ValueNames") == 0)
|
||||
{
|
||||
m_found = m_getValueNames = true;
|
||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
|
||||
if (searchFirst)
|
||||
searchFirst->GetVoidValue(m_name, valueType, pValue);
|
||||
if (typeid(T) != typeid(BASE))
|
||||
pObject->BASE::GetVoidValue(m_name, valueType, pValue);
|
||||
((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
|
||||
}
|
||||
|
||||
if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
|
||||
*reinterpret_cast<const T **>(pValue) = pObject;
|
||||
m_found = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_found && searchFirst)
|
||||
m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
|
||||
|
||||
if (!m_found && typeid(T) != typeid(BASE))
|
||||
m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
|
||||
}
|
||||
|
||||
operator bool() const {return m_found;}
|
||||
|
||||
template <class R>
|
||||
GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
|
||||
{
|
||||
if (m_getValueNames)
|
||||
(*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
|
||||
if (!m_found && strcmp(name, m_name) == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
|
||||
*reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
|
||||
m_found = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
GetValueHelperClass<T,BASE> &Assignable()
|
||||
{
|
||||
#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
|
||||
if (m_getValueNames)
|
||||
((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
|
||||
if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
|
||||
*reinterpret_cast<T *>(m_pValue) = *m_pObject;
|
||||
m_found = true;
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const T *m_pObject;
|
||||
const char *m_name;
|
||||
const std::type_info *m_valueType;
|
||||
void *m_pValue;
|
||||
bool m_found, m_getValueNames;
|
||||
};
|
||||
|
||||
template <class BASE, class T>
|
||||
GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
|
||||
{
|
||||
return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
|
||||
{
|
||||
return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template <class R>
|
||||
R Hack_DefaultValueFromConstReferenceType(const R &)
|
||||
{
|
||||
return R();
|
||||
}
|
||||
|
||||
template <class R>
|
||||
bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
|
||||
{
|
||||
return source.GetValue(name, const_cast<R &>(value));
|
||||
}
|
||||
|
||||
template <class T, class BASE>
|
||||
class AssignFromHelperClass
|
||||
{
|
||||
public:
|
||||
AssignFromHelperClass(T *pObject, const NameValuePairs &source)
|
||||
: m_pObject(pObject), m_source(source), m_done(false)
|
||||
{
|
||||
if (source.GetThisObject(*pObject))
|
||||
m_done = true;
|
||||
else if (typeid(BASE) != typeid(T))
|
||||
pObject->BASE::AssignFrom(source);
|
||||
}
|
||||
|
||||
template <class R>
|
||||
AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
|
||||
{
|
||||
if (!m_done)
|
||||
{
|
||||
R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
|
||||
if (!Hack_GetValueIntoConstReference(m_source, name, value))
|
||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
|
||||
(m_pObject->*pm)(value);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class R, class S>
|
||||
AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
|
||||
{
|
||||
if (!m_done)
|
||||
{
|
||||
R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
|
||||
if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
|
||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
|
||||
S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
|
||||
if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
|
||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
|
||||
(m_pObject->*pm)(value1, value2);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T *m_pObject;
|
||||
const NameValuePairs &m_source;
|
||||
bool m_done;
|
||||
};
|
||||
|
||||
template <class BASE, class T>
|
||||
AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
|
||||
{
|
||||
return AssignFromHelperClass<T, BASE>(pObject, source);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
|
||||
{
|
||||
return AssignFromHelperClass<T, T>(pObject, source);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
// to allow the linker to discard Integer code if not needed.
|
||||
typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
|
||||
CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
|
||||
|
||||
CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
|
||||
|
||||
class CRYPTOPP_DLL AlgorithmParametersBase
|
||||
{
|
||||
public:
|
||||
class ParameterNotUsed : public Exception
|
||||
{
|
||||
public:
|
||||
ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
|
||||
};
|
||||
|
||||
// this is actually a move, not a copy
|
||||
AlgorithmParametersBase(const AlgorithmParametersBase &x)
|
||||
: m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
|
||||
{
|
||||
m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
|
||||
x.m_used = true;
|
||||
}
|
||||
|
||||
AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
|
||||
: m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
|
||||
|
||||
virtual ~AlgorithmParametersBase()
|
||||
{
|
||||
#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
|
||||
if (!std::uncaught_exception())
|
||||
#else
|
||||
try
|
||||
#endif
|
||||
{
|
||||
if (m_throwIfNotUsed && !m_used)
|
||||
throw ParameterNotUsed(m_name);
|
||||
}
|
||||
#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
||||
|
||||
protected:
|
||||
friend class AlgorithmParameters;
|
||||
void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
|
||||
|
||||
virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
|
||||
virtual void MoveInto(void *p) const =0; // not really const
|
||||
|
||||
const char *m_name;
|
||||
bool m_throwIfNotUsed;
|
||||
mutable bool m_used;
|
||||
member_ptr<AlgorithmParametersBase> m_next;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class AlgorithmParametersTemplate : public AlgorithmParametersBase
|
||||
{
|
||||
public:
|
||||
AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
|
||||
: AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
// special case for retrieving an Integer parameter when an int was passed in
|
||||
if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
|
||||
*reinterpret_cast<T *>(pValue) = m_value;
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInto(void *buffer) const
|
||||
{
|
||||
AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
T m_value;
|
||||
};
|
||||
|
||||
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
|
||||
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
|
||||
CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
|
||||
|
||||
class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
|
||||
{
|
||||
public:
|
||||
AlgorithmParameters();
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
template <class T>
|
||||
AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
|
||||
: m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
|
||||
, m_defaultThrowIfNotUsed(throwIfNotUsed)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
AlgorithmParameters(const AlgorithmParameters &x);
|
||||
|
||||
AlgorithmParameters & operator=(const AlgorithmParameters &x);
|
||||
|
||||
template <class T>
|
||||
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
|
||||
{
|
||||
member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
|
||||
p->m_next.reset(m_next.release());
|
||||
m_next.reset(p.release());
|
||||
m_defaultThrowIfNotUsed = throwIfNotUsed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
AlgorithmParameters & operator()(const char *name, const T &value)
|
||||
{
|
||||
return operator()(name, value, m_defaultThrowIfNotUsed);
|
||||
}
|
||||
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
||||
|
||||
protected:
|
||||
member_ptr<AlgorithmParametersBase> m_next;
|
||||
bool m_defaultThrowIfNotUsed;
|
||||
};
|
||||
|
||||
//! Create an object that implements NameValuePairs for passing parameters
|
||||
/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
|
||||
\note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
|
||||
such as MSVC 7.0 and earlier.
|
||||
\note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
|
||||
repeatedly using operator() on the object returned by MakeParameters, for example:
|
||||
AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
|
||||
*/
|
||||
#ifdef __BORLANDC__
|
||||
typedef AlgorithmParameters MakeParameters;
|
||||
#else
|
||||
template <class T>
|
||||
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
|
||||
{
|
||||
return AlgorithmParameters()(name, value, throwIfNotUsed);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
|
||||
#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
|
||||
#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,81 +0,0 @@
|
||||
#ifndef CRYPTOPP_ARGNAMES_H
|
||||
#define CRYPTOPP_ARGNAMES_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
DOCUMENTED_NAMESPACE_BEGIN(Name)
|
||||
|
||||
#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;}
|
||||
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility
|
||||
CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes
|
||||
CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes
|
||||
CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N
|
||||
CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme
|
||||
CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
|
||||
CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InputFileNameWide) //!< const wchar_t *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(OutputFileNameWide) //!< const wchar_t *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes
|
||||
CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes
|
||||
CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes
|
||||
|
||||
DOCUMENTED_NAMESPACE_END
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,597 +0,0 @@
|
||||
// asn.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "asn.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
USING_NAMESPACE(std)
|
||||
|
||||
/// DER Length
|
||||
size_t DERLengthEncode(BufferedTransformation &bt, lword length)
|
||||
{
|
||||
size_t i=0;
|
||||
if (length <= 0x7f)
|
||||
{
|
||||
bt.Put(byte(length));
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt.Put(byte(BytePrecision(length) | 0x80));
|
||||
i++;
|
||||
for (int j=BytePrecision(length); j; --j)
|
||||
{
|
||||
bt.Put(byte(length >> (j-1)*8));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
|
||||
{
|
||||
byte b;
|
||||
|
||||
if (!bt.Get(b))
|
||||
return false;
|
||||
|
||||
if (!(b & 0x80))
|
||||
{
|
||||
definiteLength = true;
|
||||
length = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int lengthBytes = b & 0x7f;
|
||||
|
||||
if (lengthBytes == 0)
|
||||
{
|
||||
definiteLength = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
definiteLength = true;
|
||||
length = 0;
|
||||
while (lengthBytes--)
|
||||
{
|
||||
if (length >> (8*(sizeof(length)-1)))
|
||||
BERDecodeError(); // length about to overflow
|
||||
|
||||
if (!bt.Get(b))
|
||||
return false;
|
||||
|
||||
length = (length << 8) | b;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
|
||||
{
|
||||
lword lw;
|
||||
bool definiteLength;
|
||||
if (!BERLengthDecode(bt, lw, definiteLength))
|
||||
BERDecodeError();
|
||||
if (!SafeConvert(lw, length))
|
||||
BERDecodeError();
|
||||
return definiteLength;
|
||||
}
|
||||
|
||||
void DEREncodeNull(BufferedTransformation &out)
|
||||
{
|
||||
out.Put(TAG_NULL);
|
||||
out.Put(0);
|
||||
}
|
||||
|
||||
void BERDecodeNull(BufferedTransformation &in)
|
||||
{
|
||||
byte b;
|
||||
if (!in.Get(b) || b != TAG_NULL)
|
||||
BERDecodeError();
|
||||
size_t length;
|
||||
if (!BERLengthDecode(in, length) || length != 0)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
/// ASN Strings
|
||||
size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
|
||||
{
|
||||
bt.Put(OCTET_STRING);
|
||||
size_t lengthBytes = DERLengthEncode(bt, strLen);
|
||||
bt.Put(str, strLen);
|
||||
return 1+lengthBytes+strLen;
|
||||
}
|
||||
|
||||
size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
|
||||
{
|
||||
return DEREncodeOctetString(bt, str.begin(), str.size());
|
||||
}
|
||||
|
||||
size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != OCTET_STRING)
|
||||
BERDecodeError();
|
||||
|
||||
size_t bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
str.resize(bc);
|
||||
if (bc != bt.Get(str, bc))
|
||||
BERDecodeError();
|
||||
return bc;
|
||||
}
|
||||
|
||||
size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != OCTET_STRING)
|
||||
BERDecodeError();
|
||||
|
||||
size_t bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
bt.TransferTo(str, bc);
|
||||
return bc;
|
||||
}
|
||||
|
||||
size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
|
||||
{
|
||||
bt.Put(asnTag);
|
||||
size_t lengthBytes = DERLengthEncode(bt, str.size());
|
||||
bt.Put((const byte *)str.data(), str.size());
|
||||
return 1+lengthBytes+str.size();
|
||||
}
|
||||
|
||||
size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
size_t bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
SecByteBlock temp(bc);
|
||||
if (bc != bt.Get(temp, bc))
|
||||
BERDecodeError();
|
||||
str.assign((char *)temp.begin(), bc);
|
||||
return bc;
|
||||
}
|
||||
|
||||
/// ASN BitString
|
||||
size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
|
||||
{
|
||||
bt.Put(BIT_STRING);
|
||||
size_t lengthBytes = DERLengthEncode(bt, strLen+1);
|
||||
bt.Put((byte)unusedBits);
|
||||
bt.Put(str, strLen);
|
||||
return 2+lengthBytes+strLen;
|
||||
}
|
||||
|
||||
size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != BIT_STRING)
|
||||
BERDecodeError();
|
||||
|
||||
size_t bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
byte unused;
|
||||
if (!bt.Get(unused))
|
||||
BERDecodeError();
|
||||
unusedBits = unused;
|
||||
str.resize(bc-1);
|
||||
if ((bc-1) != bt.Get(str, bc-1))
|
||||
BERDecodeError();
|
||||
return bc-1;
|
||||
}
|
||||
|
||||
void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
|
||||
{
|
||||
byte tag;
|
||||
source.Peek(tag);
|
||||
BERGeneralDecoder decoder(source, tag);
|
||||
DERGeneralEncoder encoder(dest, tag);
|
||||
if (decoder.IsDefiniteLength())
|
||||
decoder.TransferTo(encoder, decoder.RemainingLength());
|
||||
else
|
||||
{
|
||||
while (!decoder.EndReached())
|
||||
DERReencode(decoder, encoder);
|
||||
}
|
||||
decoder.MessageEnd();
|
||||
encoder.MessageEnd();
|
||||
}
|
||||
|
||||
void OID::EncodeValue(BufferedTransformation &bt, word32 v)
|
||||
{
|
||||
for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
|
||||
bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
|
||||
bt.Put((byte)(v & 0x7f));
|
||||
}
|
||||
|
||||
size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
|
||||
{
|
||||
byte b;
|
||||
size_t i=0;
|
||||
v = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!bt.Get(b))
|
||||
BERDecodeError();
|
||||
i++;
|
||||
if (v >> (8*sizeof(v)-7)) // v about to overflow
|
||||
BERDecodeError();
|
||||
v <<= 7;
|
||||
v += b & 0x7f;
|
||||
if (!(b & 0x80))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
void OID::DEREncode(BufferedTransformation &bt) const
|
||||
{
|
||||
assert(m_values.size() >= 2);
|
||||
ByteQueue temp;
|
||||
temp.Put(byte(m_values[0] * 40 + m_values[1]));
|
||||
for (size_t i=2; i<m_values.size(); i++)
|
||||
EncodeValue(temp, m_values[i]);
|
||||
bt.Put(OBJECT_IDENTIFIER);
|
||||
DERLengthEncode(bt, temp.CurrentSize());
|
||||
temp.TransferTo(bt);
|
||||
}
|
||||
|
||||
void OID::BERDecode(BufferedTransformation &bt)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
|
||||
BERDecodeError();
|
||||
|
||||
size_t length;
|
||||
if (!BERLengthDecode(bt, length) || length < 1)
|
||||
BERDecodeError();
|
||||
|
||||
if (!bt.Get(b))
|
||||
BERDecodeError();
|
||||
|
||||
length--;
|
||||
m_values.resize(2);
|
||||
m_values[0] = b / 40;
|
||||
m_values[1] = b % 40;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
word32 v;
|
||||
size_t valueLen = DecodeValue(bt, v);
|
||||
if (valueLen > length)
|
||||
BERDecodeError();
|
||||
m_values.push_back(v);
|
||||
length -= valueLen;
|
||||
}
|
||||
}
|
||||
|
||||
void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
|
||||
{
|
||||
OID oid(bt);
|
||||
if (*this != oid)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
|
||||
{
|
||||
if (m_flags & PUT_OBJECTS)
|
||||
return *AttachedTransformation();
|
||||
else
|
||||
return TheBitBucket();
|
||||
}
|
||||
|
||||
void EncodedObjectFilter::Put(const byte *inString, size_t length)
|
||||
{
|
||||
if (m_nCurrentObject == m_nObjects)
|
||||
{
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
return;
|
||||
}
|
||||
|
||||
LazyPutter lazyPutter(m_queue, inString, length);
|
||||
|
||||
while (m_queue.AnyRetrievable())
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case IDENTIFIER:
|
||||
if (!m_queue.Get(m_id))
|
||||
return;
|
||||
m_queue.TransferTo(CurrentTarget(), 1);
|
||||
m_state = LENGTH; // fall through
|
||||
case LENGTH:
|
||||
{
|
||||
byte b;
|
||||
if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
|
||||
{
|
||||
m_queue.TransferTo(CurrentTarget(), 1);
|
||||
m_level--;
|
||||
m_state = IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
ByteQueue::Walker walker(m_queue);
|
||||
bool definiteLength;
|
||||
if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
|
||||
return;
|
||||
m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
|
||||
if (!((m_id & CONSTRUCTED) || definiteLength))
|
||||
BERDecodeError();
|
||||
if (!definiteLength)
|
||||
{
|
||||
if (!(m_id & CONSTRUCTED))
|
||||
BERDecodeError();
|
||||
m_level++;
|
||||
m_state = IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
m_state = BODY; // fall through
|
||||
}
|
||||
case BODY:
|
||||
m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
|
||||
|
||||
if (m_lengthRemaining == 0)
|
||||
m_state = IDENTIFIER;
|
||||
}
|
||||
|
||||
if (m_state == IDENTIFIER && m_level == 0)
|
||||
{
|
||||
// just finished processing a level 0 object
|
||||
++m_nCurrentObject;
|
||||
|
||||
if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
|
||||
AttachedTransformation()->MessageEnd();
|
||||
|
||||
if (m_nCurrentObject == m_nObjects)
|
||||
{
|
||||
if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
|
||||
AttachedTransformation()->MessageEnd();
|
||||
|
||||
if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
|
||||
AttachedTransformation()->MessageSeriesEnd();
|
||||
|
||||
m_queue.TransferAllTo(*AttachedTransformation());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
|
||||
: m_inQueue(inQueue), m_finished(false)
|
||||
{
|
||||
Init(asnTag);
|
||||
}
|
||||
|
||||
BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
|
||||
: m_inQueue(inQueue), m_finished(false)
|
||||
{
|
||||
Init(asnTag);
|
||||
}
|
||||
|
||||
void BERGeneralDecoder::Init(byte asnTag)
|
||||
{
|
||||
byte b;
|
||||
if (!m_inQueue.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
|
||||
BERDecodeError();
|
||||
|
||||
if (!m_definiteLength && !(asnTag & CONSTRUCTED))
|
||||
BERDecodeError(); // cannot be primitive and have indefinite length
|
||||
}
|
||||
|
||||
BERGeneralDecoder::~BERGeneralDecoder()
|
||||
{
|
||||
try // avoid throwing in constructor
|
||||
{
|
||||
if (!m_finished)
|
||||
MessageEnd();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
bool BERGeneralDecoder::EndReached() const
|
||||
{
|
||||
if (m_definiteLength)
|
||||
return m_length == 0;
|
||||
else
|
||||
{ // check end-of-content octets
|
||||
word16 i;
|
||||
return (m_inQueue.PeekWord16(i)==2 && i==0);
|
||||
}
|
||||
}
|
||||
|
||||
byte BERGeneralDecoder::PeekByte() const
|
||||
{
|
||||
byte b;
|
||||
if (!Peek(b))
|
||||
BERDecodeError();
|
||||
return b;
|
||||
}
|
||||
|
||||
void BERGeneralDecoder::CheckByte(byte check)
|
||||
{
|
||||
byte b;
|
||||
if (!Get(b) || b != check)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
void BERGeneralDecoder::MessageEnd()
|
||||
{
|
||||
m_finished = true;
|
||||
if (m_definiteLength)
|
||||
{
|
||||
if (m_length != 0)
|
||||
BERDecodeError();
|
||||
}
|
||||
else
|
||||
{ // remove end-of-content octets
|
||||
word16 i;
|
||||
if (m_inQueue.GetWord16(i) != 2 || i != 0)
|
||||
BERDecodeError();
|
||||
}
|
||||
}
|
||||
|
||||
size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (m_definiteLength && transferBytes > m_length)
|
||||
transferBytes = m_length;
|
||||
size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
|
||||
ReduceLength(transferBytes);
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
if (m_definiteLength)
|
||||
end = STDMIN(m_length, end);
|
||||
return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
|
||||
}
|
||||
|
||||
lword BERGeneralDecoder::ReduceLength(lword delta)
|
||||
{
|
||||
if (m_definiteLength)
|
||||
{
|
||||
if (m_length < delta)
|
||||
BERDecodeError();
|
||||
m_length -= delta;
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
|
||||
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
|
||||
{
|
||||
}
|
||||
|
||||
DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
|
||||
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
|
||||
{
|
||||
}
|
||||
|
||||
DERGeneralEncoder::~DERGeneralEncoder()
|
||||
{
|
||||
try // avoid throwing in constructor
|
||||
{
|
||||
if (!m_finished)
|
||||
MessageEnd();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void DERGeneralEncoder::MessageEnd()
|
||||
{
|
||||
m_finished = true;
|
||||
lword length = CurrentSize();
|
||||
m_outQueue.Put(m_asnTag);
|
||||
DERLengthEncode(m_outQueue, length);
|
||||
TransferTo(m_outQueue);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void X509PublicKey::BERDecode(BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder subjectPublicKeyInfo(bt);
|
||||
BERSequenceDecoder algorithm(subjectPublicKeyInfo);
|
||||
GetAlgorithmID().BERDecodeAndCheck(algorithm);
|
||||
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
|
||||
subjectPublicKey.CheckByte(0); // unused bits
|
||||
BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
|
||||
subjectPublicKey.MessageEnd();
|
||||
subjectPublicKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void X509PublicKey::DEREncode(BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder subjectPublicKeyInfo(bt);
|
||||
|
||||
DERSequenceEncoder algorithm(subjectPublicKeyInfo);
|
||||
GetAlgorithmID().DEREncode(algorithm);
|
||||
DEREncodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
|
||||
subjectPublicKey.Put(0); // unused bits
|
||||
DEREncodePublicKey(subjectPublicKey);
|
||||
subjectPublicKey.MessageEnd();
|
||||
|
||||
subjectPublicKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder privateKeyInfo(bt);
|
||||
word32 version;
|
||||
BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
|
||||
|
||||
BERSequenceDecoder algorithm(privateKeyInfo);
|
||||
GetAlgorithmID().BERDecodeAndCheck(algorithm);
|
||||
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
|
||||
BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
|
||||
octetString.MessageEnd();
|
||||
|
||||
if (!privateKeyInfo.EndReached())
|
||||
BERDecodeOptionalAttributes(privateKeyInfo);
|
||||
privateKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder privateKeyInfo(bt);
|
||||
DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
|
||||
|
||||
DERSequenceEncoder algorithm(privateKeyInfo);
|
||||
GetAlgorithmID().DEREncode(algorithm);
|
||||
DEREncodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
|
||||
DEREncodePrivateKey(octetString);
|
||||
octetString.MessageEnd();
|
||||
|
||||
DEREncodeOptionalAttributes(privateKeyInfo);
|
||||
privateKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
|
||||
{
|
||||
DERReencode(bt, m_optionalAttributes);
|
||||
}
|
||||
|
||||
void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
|
||||
{
|
||||
m_optionalAttributes.CopyTo(bt);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,369 +0,0 @@
|
||||
#ifndef CRYPTOPP_ASN_H
|
||||
#define CRYPTOPP_ASN_H
|
||||
|
||||
#include "filters.h"
|
||||
#include "queue.h"
|
||||
#include <vector>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// these tags and flags are not complete
|
||||
enum ASNTag
|
||||
{
|
||||
BOOLEAN = 0x01,
|
||||
INTEGER = 0x02,
|
||||
BIT_STRING = 0x03,
|
||||
OCTET_STRING = 0x04,
|
||||
TAG_NULL = 0x05,
|
||||
OBJECT_IDENTIFIER = 0x06,
|
||||
OBJECT_DESCRIPTOR = 0x07,
|
||||
EXTERNAL = 0x08,
|
||||
REAL = 0x09,
|
||||
ENUMERATED = 0x0a,
|
||||
UTF8_STRING = 0x0c,
|
||||
SEQUENCE = 0x10,
|
||||
SET = 0x11,
|
||||
NUMERIC_STRING = 0x12,
|
||||
PRINTABLE_STRING = 0x13,
|
||||
T61_STRING = 0x14,
|
||||
VIDEOTEXT_STRING = 0x15,
|
||||
IA5_STRING = 0x16,
|
||||
UTC_TIME = 0x17,
|
||||
GENERALIZED_TIME = 0x18,
|
||||
GRAPHIC_STRING = 0x19,
|
||||
VISIBLE_STRING = 0x1a,
|
||||
GENERAL_STRING = 0x1b
|
||||
};
|
||||
|
||||
enum ASNIdFlag
|
||||
{
|
||||
UNIVERSAL = 0x00,
|
||||
// DATA = 0x01,
|
||||
// HEADER = 0x02,
|
||||
CONSTRUCTED = 0x20,
|
||||
APPLICATION = 0x40,
|
||||
CONTEXT_SPECIFIC = 0x80,
|
||||
PRIVATE = 0xc0
|
||||
};
|
||||
|
||||
inline void BERDecodeError() {throw BERDecodeErr();}
|
||||
|
||||
class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
|
||||
{
|
||||
public:
|
||||
UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
|
||||
UnknownOID(const char *err) : BERDecodeErr(err) {}
|
||||
};
|
||||
|
||||
// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length);
|
||||
// returns false if indefinite length
|
||||
CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length);
|
||||
|
||||
CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out);
|
||||
CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in);
|
||||
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen);
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
|
||||
|
||||
// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
|
||||
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0);
|
||||
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
|
||||
|
||||
// BER decode from source and DER reencode into dest
|
||||
CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest);
|
||||
|
||||
//! Object Identifier
|
||||
class CRYPTOPP_DLL OID
|
||||
{
|
||||
public:
|
||||
OID() {}
|
||||
OID(word32 v) : m_values(1, v) {}
|
||||
OID(BufferedTransformation &bt) {BERDecode(bt);}
|
||||
|
||||
inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;}
|
||||
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
|
||||
// throw BERDecodeErr() if decoded value doesn't equal this OID
|
||||
void BERDecodeAndCheck(BufferedTransformation &bt) const;
|
||||
|
||||
std::vector<word32> m_values;
|
||||
|
||||
private:
|
||||
static void EncodeValue(BufferedTransformation &bt, word32 v);
|
||||
static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
|
||||
};
|
||||
|
||||
class EncodedObjectFilter : public Filter
|
||||
{
|
||||
public:
|
||||
enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
|
||||
EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
|
||||
|
||||
void Put(const byte *inString, size_t length);
|
||||
|
||||
unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
|
||||
unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
|
||||
|
||||
private:
|
||||
BufferedTransformation & CurrentTarget();
|
||||
|
||||
word32 m_flags;
|
||||
unsigned int m_nObjects, m_nCurrentObject, m_level;
|
||||
std::vector<unsigned int> m_positions;
|
||||
ByteQueue m_queue;
|
||||
enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
|
||||
byte m_id;
|
||||
lword m_lengthRemaining;
|
||||
};
|
||||
|
||||
//! BER General Decoder
|
||||
class CRYPTOPP_DLL BERGeneralDecoder : public Store
|
||||
{
|
||||
public:
|
||||
explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
|
||||
explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
|
||||
~BERGeneralDecoder();
|
||||
|
||||
bool IsDefiniteLength() const {return m_definiteLength;}
|
||||
lword RemainingLength() const {assert(m_definiteLength); return m_length;}
|
||||
bool EndReached() const;
|
||||
byte PeekByte() const;
|
||||
void CheckByte(byte b);
|
||||
|
||||
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
|
||||
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
|
||||
|
||||
// call this to denote end of sequence
|
||||
void MessageEnd();
|
||||
|
||||
protected:
|
||||
BufferedTransformation &m_inQueue;
|
||||
bool m_finished, m_definiteLength;
|
||||
lword m_length;
|
||||
|
||||
private:
|
||||
void Init(byte asnTag);
|
||||
void StoreInitialize(const NameValuePairs ¶meters) {assert(false);}
|
||||
lword ReduceLength(lword delta);
|
||||
};
|
||||
|
||||
//! DER General Encoder
|
||||
class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
|
||||
{
|
||||
public:
|
||||
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
||||
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
||||
~DERGeneralEncoder();
|
||||
|
||||
// call this to denote end of sequence
|
||||
void MessageEnd();
|
||||
|
||||
private:
|
||||
BufferedTransformation &m_outQueue;
|
||||
bool m_finished;
|
||||
|
||||
byte m_asnTag;
|
||||
};
|
||||
|
||||
//! BER Sequence Decoder
|
||||
class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
|
||||
{
|
||||
public:
|
||||
explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! DER Sequence Encoder
|
||||
class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
|
||||
{
|
||||
public:
|
||||
explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! BER Set Decoder
|
||||
class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
|
||||
{
|
||||
public:
|
||||
explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! DER Set Encoder
|
||||
class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
|
||||
{
|
||||
public:
|
||||
explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ASNOptional : public member_ptr<T>
|
||||
{
|
||||
public:
|
||||
void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
|
||||
{
|
||||
byte b;
|
||||
if (seqDecoder.Peek(b) && (b & mask) == tag)
|
||||
reset(new T(seqDecoder));
|
||||
}
|
||||
void DEREncode(BufferedTransformation &out)
|
||||
{
|
||||
if (this->get() != NULL)
|
||||
this->get()->DEREncode(out);
|
||||
}
|
||||
};
|
||||
|
||||
//! _
|
||||
template <class BASE>
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
|
||||
{
|
||||
public:
|
||||
void Save(BufferedTransformation &bt) const
|
||||
{BEREncode(bt);}
|
||||
void Load(BufferedTransformation &bt)
|
||||
{BERDecode(bt);}
|
||||
};
|
||||
|
||||
//! encodes/decodes subjectPublicKeyInfo
|
||||
class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
|
||||
{
|
||||
public:
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
|
||||
virtual OID GetAlgorithmID() const =0;
|
||||
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
|
||||
{BERDecodeNull(bt); return false;}
|
||||
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
|
||||
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
|
||||
|
||||
//! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
|
||||
virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
|
||||
//! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header
|
||||
virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
|
||||
};
|
||||
|
||||
//! encodes/decodes privateKeyInfo
|
||||
class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
|
||||
{
|
||||
public:
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
|
||||
virtual OID GetAlgorithmID() const =0;
|
||||
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
|
||||
{BERDecodeNull(bt); return false;}
|
||||
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
|
||||
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
|
||||
|
||||
//! decode privateKey part of privateKeyInfo, without the OCTET STRING header
|
||||
virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
|
||||
//! encode privateKey part of privateKeyInfo, without the OCTET STRING header
|
||||
virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
|
||||
|
||||
//! decode optional attributes including context-specific tag
|
||||
/*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */
|
||||
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
|
||||
//! encode optional attributes including context-specific tag
|
||||
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
|
||||
|
||||
protected:
|
||||
ByteQueue m_optionalAttributes;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! DER Encode Unsigned
|
||||
/*! for INTEGER, BOOLEAN, and ENUM */
|
||||
template <class T>
|
||||
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
|
||||
{
|
||||
byte buf[sizeof(w)+1];
|
||||
unsigned int bc;
|
||||
if (asnTag == BOOLEAN)
|
||||
{
|
||||
buf[sizeof(w)] = w ? 0xff : 0;
|
||||
bc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = 0;
|
||||
for (unsigned int i=0; i<sizeof(w); i++)
|
||||
buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
|
||||
bc = sizeof(w);
|
||||
while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
|
||||
--bc;
|
||||
if (buf[sizeof(w)+1-bc] & 0x80)
|
||||
++bc;
|
||||
}
|
||||
out.Put(asnTag);
|
||||
size_t lengthBytes = DERLengthEncode(out, bc);
|
||||
out.Put(buf+sizeof(w)+1-bc, bc);
|
||||
return 1+lengthBytes+bc;
|
||||
}
|
||||
|
||||
//! BER Decode Unsigned
|
||||
// VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro
|
||||
// CW41 workaround: std::numeric_limits<T>::max causes a template error
|
||||
template <class T>
|
||||
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
|
||||
T minValue = 0, T maxValue = 0xffffffff)
|
||||
{
|
||||
byte b;
|
||||
if (!in.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
size_t bc;
|
||||
BERLengthDecode(in, bc);
|
||||
|
||||
SecByteBlock buf(bc);
|
||||
|
||||
if (bc != in.Get(buf, bc))
|
||||
BERDecodeError();
|
||||
|
||||
const byte *ptr = buf;
|
||||
while (bc > sizeof(w) && *ptr == 0)
|
||||
{
|
||||
bc--;
|
||||
ptr++;
|
||||
}
|
||||
if (bc > sizeof(w))
|
||||
BERDecodeError();
|
||||
|
||||
w = 0;
|
||||
for (unsigned int i=0; i<bc; i++)
|
||||
w = (w << 8) | ptr[i];
|
||||
|
||||
if (w < minValue || w > maxValue)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
||||
{return lhs.m_values == rhs.m_values;}
|
||||
inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
||||
{return lhs.m_values != rhs.m_values;}
|
||||
inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
||||
{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
|
||||
inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
|
||||
{return ::CryptoPP::OID(lhs)+=rhs;}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,180 +0,0 @@
|
||||
// authenc.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "authenc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
|
||||
{
|
||||
unsigned int blockSize = AuthenticationBlockSize();
|
||||
unsigned int &num = m_bufferedDataLength;
|
||||
byte* data = m_buffer.begin();
|
||||
|
||||
if (num != 0) // process left over data
|
||||
{
|
||||
if (num+len >= blockSize)
|
||||
{
|
||||
memcpy(data+num, input, blockSize-num);
|
||||
AuthenticateBlocks(data, blockSize);
|
||||
input += (blockSize-num);
|
||||
len -= (blockSize-num);
|
||||
num = 0;
|
||||
// drop through and do the rest
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(data+num, input, len);
|
||||
num += (unsigned int)len;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// now process the input data in blocks of blockSize bytes and save the leftovers to m_data
|
||||
if (len >= blockSize)
|
||||
{
|
||||
size_t leftOver = AuthenticateBlocks(input, len);
|
||||
input += (len - leftOver);
|
||||
len = leftOver;
|
||||
}
|
||||
|
||||
memcpy(data, input, len);
|
||||
num = (unsigned int)len;
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms)
|
||||
{
|
||||
m_bufferedDataLength = 0;
|
||||
m_state = State_Start;
|
||||
|
||||
SetKeyWithoutResync(userKey, keylength, params);
|
||||
m_state = State_KeySet;
|
||||
|
||||
size_t length;
|
||||
const byte *iv = GetIVAndThrowIfInvalid(params, length);
|
||||
if (iv)
|
||||
Resynchronize(iv, (int)length);
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
|
||||
{
|
||||
if (m_state < State_KeySet)
|
||||
throw BadState(AlgorithmName(), "Resynchronize", "key is set");
|
||||
|
||||
m_bufferedDataLength = 0;
|
||||
m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
|
||||
m_state = State_KeySet;
|
||||
|
||||
Resync(iv, this->ThrowIfInvalidIVLength(length));
|
||||
m_state = State_IVSet;
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
case State_Start:
|
||||
case State_KeySet:
|
||||
throw BadState(AlgorithmName(), "Update", "setting key and IV");
|
||||
case State_IVSet:
|
||||
AuthenticateData(input, length);
|
||||
m_totalHeaderLength += length;
|
||||
break;
|
||||
case State_AuthUntransformed:
|
||||
case State_AuthTransformed:
|
||||
AuthenticateLastConfidentialBlock();
|
||||
m_bufferedDataLength = 0;
|
||||
m_state = State_AuthFooter;
|
||||
// fall through
|
||||
case State_AuthFooter:
|
||||
AuthenticateData(input, length);
|
||||
m_totalFooterLength += length;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
m_totalMessageLength += length;
|
||||
if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
|
||||
throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
|
||||
|
||||
reswitch:
|
||||
switch (m_state)
|
||||
{
|
||||
case State_Start:
|
||||
case State_KeySet:
|
||||
throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
|
||||
case State_AuthFooter:
|
||||
throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
|
||||
case State_IVSet:
|
||||
AuthenticateLastHeaderBlock();
|
||||
m_bufferedDataLength = 0;
|
||||
m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
|
||||
goto reswitch;
|
||||
case State_AuthUntransformed:
|
||||
AuthenticateData(inString, length);
|
||||
AccessSymmetricCipher().ProcessData(outString, inString, length);
|
||||
break;
|
||||
case State_AuthTransformed:
|
||||
AccessSymmetricCipher().ProcessData(outString, inString, length);
|
||||
AuthenticateData(outString, length);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
|
||||
{
|
||||
if (m_totalHeaderLength > MaxHeaderLength())
|
||||
throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
|
||||
|
||||
if (m_totalFooterLength > MaxFooterLength())
|
||||
{
|
||||
if (MaxFooterLength() == 0)
|
||||
throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
|
||||
else
|
||||
throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
|
||||
}
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
case State_Start:
|
||||
case State_KeySet:
|
||||
throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
|
||||
|
||||
case State_IVSet:
|
||||
AuthenticateLastHeaderBlock();
|
||||
m_bufferedDataLength = 0;
|
||||
// fall through
|
||||
|
||||
case State_AuthUntransformed:
|
||||
case State_AuthTransformed:
|
||||
AuthenticateLastConfidentialBlock();
|
||||
m_bufferedDataLength = 0;
|
||||
// fall through
|
||||
|
||||
case State_AuthFooter:
|
||||
AuthenticateLastFooterBlock(mac, macSize);
|
||||
m_bufferedDataLength = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
m_state = State_KeySet;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifndef CRYPTOPP_AUTHENC_H
|
||||
#define CRYPTOPP_AUTHENC_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! .
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher
|
||||
{
|
||||
public:
|
||||
AuthenticatedSymmetricCipherBase() : m_state(State_Start) {}
|
||||
|
||||
bool IsRandomAccess() const {return false;}
|
||||
bool IsSelfInverting() const {return true;}
|
||||
void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);}
|
||||
|
||||
void SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms);
|
||||
void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;}
|
||||
void Resynchronize(const byte *iv, int length=-1);
|
||||
void Update(const byte *input, size_t length);
|
||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
||||
void TruncatedFinal(byte *mac, size_t macSize);
|
||||
|
||||
protected:
|
||||
void AuthenticateData(const byte *data, size_t len);
|
||||
const SymmetricCipher & GetSymmetricCipher() const {return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
|
||||
|
||||
virtual SymmetricCipher & AccessSymmetricCipher() =0;
|
||||
virtual bool AuthenticationIsOnPlaintext() const =0;
|
||||
virtual unsigned int AuthenticationBlockSize() const =0;
|
||||
virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) =0;
|
||||
virtual void Resync(const byte *iv, size_t len) =0;
|
||||
virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0;
|
||||
virtual void AuthenticateLastHeaderBlock() =0;
|
||||
virtual void AuthenticateLastConfidentialBlock() {}
|
||||
virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0;
|
||||
|
||||
enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter};
|
||||
State m_state;
|
||||
unsigned int m_bufferedDataLength;
|
||||
lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength;
|
||||
AlignedSecByteBlock m_buffer;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
// base32.cpp - written and placed in the public domain by Frank Palazzolo, based on hex.cpp by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "base32.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
static const byte s_vecUpper[] = "ABCDEFGHIJKMNPQRSTUVWXYZ23456789";
|
||||
static const byte s_vecLower[] = "abcdefghijkmnpqrstuvwxyz23456789";
|
||||
|
||||
void Base32Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true);
|
||||
m_filter->Initialize(CombinedNameValuePairs(
|
||||
parameters,
|
||||
MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 5, true)));
|
||||
}
|
||||
|
||||
void Base32Decoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
BaseN_Decoder::Initialize(CombinedNameValuePairs(
|
||||
parameters,
|
||||
MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 5, true)));
|
||||
}
|
||||
|
||||
const int *Base32Decoder::GetDefaultDecodingLookupArray()
|
||||
{
|
||||
static volatile bool s_initialized = false;
|
||||
static int s_array[256];
|
||||
|
||||
if (!s_initialized)
|
||||
{
|
||||
InitializeDecodingLookupArray(s_array, s_vecUpper, 32, true);
|
||||
s_initialized = true;
|
||||
}
|
||||
return s_array;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -1,38 +0,0 @@
|
||||
#ifndef CRYPTOPP_BASE32_H
|
||||
#define CRYPTOPP_BASE32_H
|
||||
|
||||
#include "basecode.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Converts given data to base 32, the default code is based on draft-ietf-idn-dude-02.txt
|
||||
/*! To specify alternative code, call Initialize() with EncodingLookupArray parameter. */
|
||||
class Base32Encoder : public SimpleProxyFilter
|
||||
{
|
||||
public:
|
||||
Base32Encoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
|
||||
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator)));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
};
|
||||
|
||||
//! Decode base 32 data back to bytes, the default code is based on draft-ietf-idn-dude-02.txt
|
||||
/*! To specify alternative code, call Initialize() with DecodingLookupArray parameter. */
|
||||
class Base32Decoder : public BaseN_Decoder
|
||||
{
|
||||
public:
|
||||
Base32Decoder(BufferedTransformation *attachment = NULL)
|
||||
: BaseN_Decoder(GetDefaultDecodingLookupArray(), 5, attachment) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
private:
|
||||
static const int * CRYPTOPP_API GetDefaultDecodingLookupArray();
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
// base64.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "base64.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
static const byte s_vec[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const byte s_padding = '=';
|
||||
|
||||
void Base64Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
bool insertLineBreaks = parameters.GetValueWithDefault(Name::InsertLineBreaks(), true);
|
||||
int maxLineLength = parameters.GetIntValueWithDefault(Name::MaxLineLength(), 72);
|
||||
|
||||
const char *lineBreak = insertLineBreaks ? "\n" : "";
|
||||
|
||||
m_filter->Initialize(CombinedNameValuePairs(
|
||||
parameters,
|
||||
MakeParameters(Name::EncodingLookupArray(), &s_vec[0], false)
|
||||
(Name::PaddingByte(), s_padding)
|
||||
(Name::GroupSize(), insertLineBreaks ? maxLineLength : 0)
|
||||
(Name::Separator(), ConstByteArrayParameter(lineBreak))
|
||||
(Name::Terminator(), ConstByteArrayParameter(lineBreak))
|
||||
(Name::Log2Base(), 6, true)));
|
||||
}
|
||||
|
||||
const int *Base64Decoder::GetDecodingLookupArray()
|
||||
{
|
||||
static volatile bool s_initialized = false;
|
||||
static int s_array[256];
|
||||
|
||||
if (!s_initialized)
|
||||
{
|
||||
InitializeDecodingLookupArray(s_array, s_vec, 64, false);
|
||||
s_initialized = true;
|
||||
}
|
||||
return s_array;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef CRYPTOPP_BASE64_H
|
||||
#define CRYPTOPP_BASE64_H
|
||||
|
||||
#include "basecode.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Base64 Encoder Class
|
||||
class Base64Encoder : public SimpleProxyFilter
|
||||
{
|
||||
public:
|
||||
Base64Encoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = true, int maxLineLength = 72)
|
||||
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
};
|
||||
|
||||
//! Base64 Decoder Class
|
||||
class Base64Decoder : public BaseN_Decoder
|
||||
{
|
||||
public:
|
||||
Base64Decoder(BufferedTransformation *attachment = NULL)
|
||||
: BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {}
|
||||
|
||||
private:
|
||||
static const int * CRYPTOPP_API GetDecodingLookupArray();
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,238 +0,0 @@
|
||||
// basecode.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "basecode.h"
|
||||
#include "fltrimpl.h"
|
||||
#include <ctype.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet);
|
||||
|
||||
parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar);
|
||||
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
|
||||
throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive");
|
||||
|
||||
byte padding;
|
||||
bool pad;
|
||||
if (parameters.GetValue(Name::PaddingByte(), padding))
|
||||
pad = parameters.GetValueWithDefault(Name::Pad(), true);
|
||||
else
|
||||
pad = false;
|
||||
m_padding = pad ? padding : -1;
|
||||
|
||||
m_bytePos = m_bitPos = 0;
|
||||
|
||||
int i = 8;
|
||||
while (i%m_bitsPerChar != 0)
|
||||
i += 8;
|
||||
m_outputBlockSize = i/m_bitsPerChar;
|
||||
|
||||
m_outBuf.New(m_outputBlockSize);
|
||||
}
|
||||
|
||||
size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
while (m_inputPosition < length)
|
||||
{
|
||||
if (m_bytePos == 0)
|
||||
memset(m_outBuf, 0, m_outputBlockSize);
|
||||
|
||||
{
|
||||
unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8;
|
||||
while (true)
|
||||
{
|
||||
assert(m_bitPos < m_bitsPerChar);
|
||||
unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos;
|
||||
m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget);
|
||||
if (bitsLeftInSource >= bitsLeftInTarget)
|
||||
{
|
||||
m_bitPos = 0;
|
||||
++m_bytePos;
|
||||
bitsLeftInSource -= bitsLeftInTarget;
|
||||
if (bitsLeftInSource == 0)
|
||||
break;
|
||||
b <<= bitsLeftInTarget;
|
||||
b &= 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bitPos += bitsLeftInSource;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_bytePos <= m_outputBlockSize);
|
||||
if (m_bytePos == m_outputBlockSize)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<m_bytePos; i++)
|
||||
{
|
||||
assert(m_outBuf[i] < (1 << m_bitsPerChar));
|
||||
m_outBuf[i] = m_alphabet[m_outBuf[i]];
|
||||
}
|
||||
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
|
||||
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
}
|
||||
if (messageEnd)
|
||||
{
|
||||
if (m_bitPos > 0)
|
||||
++m_bytePos;
|
||||
|
||||
int i;
|
||||
for (i=0; i<m_bytePos; i++)
|
||||
m_outBuf[i] = m_alphabet[m_outBuf[i]];
|
||||
|
||||
if (m_padding != -1 && m_bytePos > 0)
|
||||
{
|
||||
memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos);
|
||||
m_bytePos = m_outputBlockSize;
|
||||
}
|
||||
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup);
|
||||
|
||||
parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar);
|
||||
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
|
||||
throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive");
|
||||
|
||||
m_bytePos = m_bitPos = 0;
|
||||
|
||||
int i = m_bitsPerChar;
|
||||
while (i%8 != 0)
|
||||
i += m_bitsPerChar;
|
||||
m_outputBlockSize = i/8;
|
||||
|
||||
m_outBuf.New(m_outputBlockSize);
|
||||
}
|
||||
|
||||
size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
while (m_inputPosition < length)
|
||||
{
|
||||
unsigned int value;
|
||||
value = m_lookup[begin[m_inputPosition++]];
|
||||
if (value >= 256)
|
||||
continue;
|
||||
|
||||
if (m_bytePos == 0 && m_bitPos == 0)
|
||||
memset(m_outBuf, 0, m_outputBlockSize);
|
||||
|
||||
{
|
||||
int newBitPos = m_bitPos + m_bitsPerChar;
|
||||
if (newBitPos <= 8)
|
||||
m_outBuf[m_bytePos] |= value << (8-newBitPos);
|
||||
else
|
||||
{
|
||||
m_outBuf[m_bytePos] |= value >> (newBitPos-8);
|
||||
m_outBuf[m_bytePos+1] |= value << (16-newBitPos);
|
||||
}
|
||||
|
||||
m_bitPos = newBitPos;
|
||||
while (m_bitPos >= 8)
|
||||
{
|
||||
m_bitPos -= 8;
|
||||
++m_bytePos;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bytePos == m_outputBlockSize)
|
||||
{
|
||||
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
}
|
||||
if (messageEnd)
|
||||
{
|
||||
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive)
|
||||
{
|
||||
std::fill(lookup, lookup+256, -1);
|
||||
|
||||
for (unsigned int i=0; i<base; i++)
|
||||
{
|
||||
if (caseInsensitive && isalpha(alphabet[i]))
|
||||
{
|
||||
assert(lookup[toupper(alphabet[i])] == -1);
|
||||
lookup[toupper(alphabet[i])] = i;
|
||||
assert(lookup[tolower(alphabet[i])] == -1);
|
||||
lookup[tolower(alphabet[i])] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(lookup[alphabet[i]] == -1);
|
||||
lookup[alphabet[i]] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Grouper::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_groupSize = parameters.GetIntValueWithDefault(Name::GroupSize(), 0);
|
||||
ConstByteArrayParameter separator, terminator;
|
||||
if (m_groupSize)
|
||||
parameters.GetRequiredParameter("Grouper", Name::Separator(), separator);
|
||||
else
|
||||
parameters.GetValue(Name::Separator(), separator);
|
||||
parameters.GetValue(Name::Terminator(), terminator);
|
||||
|
||||
m_separator.Assign(separator.begin(), separator.size());
|
||||
m_terminator.Assign(terminator.begin(), terminator.size());
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
size_t Grouper::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
if (m_groupSize)
|
||||
{
|
||||
while (m_inputPosition < length)
|
||||
{
|
||||
if (m_counter == m_groupSize)
|
||||
{
|
||||
FILTER_OUTPUT(1, m_separator, m_separator.size(), 0);
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
FILTER_OUTPUT2(2, len = STDMIN(length-m_inputPosition, m_groupSize-m_counter),
|
||||
begin+m_inputPosition, len, 0);
|
||||
m_inputPosition += len;
|
||||
m_counter += len;
|
||||
}
|
||||
}
|
||||
else
|
||||
FILTER_OUTPUT(3, begin, length, 0);
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
FILTER_OUTPUT(4, m_terminator, m_terminator.size(), messageEnd);
|
||||
m_counter = 0;
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,86 +0,0 @@
|
||||
#ifndef CRYPTOPP_BASECODE_H
|
||||
#define CRYPTOPP_BASECODE_H
|
||||
|
||||
#include "filters.h"
|
||||
#include "algparam.h"
|
||||
#include "argnames.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! base n encoder, where n is a power of 2
|
||||
class CRYPTOPP_DLL BaseN_Encoder : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
BaseN_Encoder(BufferedTransformation *attachment=NULL)
|
||||
{Detach(attachment);}
|
||||
|
||||
BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1)
|
||||
{
|
||||
Detach(attachment);
|
||||
IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet)
|
||||
(Name::Log2Base(), log2base)
|
||||
(Name::Pad(), padding != -1)
|
||||
(Name::PaddingByte(), byte(padding)));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
||||
|
||||
private:
|
||||
const byte *m_alphabet;
|
||||
int m_padding, m_bitsPerChar, m_outputBlockSize;
|
||||
int m_bytePos, m_bitPos;
|
||||
SecByteBlock m_outBuf;
|
||||
};
|
||||
|
||||
//! base n decoder, where n is a power of 2
|
||||
class CRYPTOPP_DLL BaseN_Decoder : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
BaseN_Decoder(BufferedTransformation *attachment=NULL)
|
||||
{Detach(attachment);}
|
||||
|
||||
BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL)
|
||||
{
|
||||
Detach(attachment);
|
||||
IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
||||
|
||||
static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive);
|
||||
|
||||
private:
|
||||
const int *m_lookup;
|
||||
int m_padding, m_bitsPerChar, m_outputBlockSize;
|
||||
int m_bytePos, m_bitPos;
|
||||
SecByteBlock m_outBuf;
|
||||
};
|
||||
|
||||
//! filter that breaks input stream into groups of fixed size
|
||||
class CRYPTOPP_DLL Grouper : public Bufferless<Filter>
|
||||
{
|
||||
public:
|
||||
Grouper(BufferedTransformation *attachment=NULL)
|
||||
{Detach(attachment);}
|
||||
|
||||
Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL)
|
||||
{
|
||||
Detach(attachment);
|
||||
IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize)
|
||||
(Name::Separator(), ConstByteArrayParameter(separator))
|
||||
(Name::Terminator(), ConstByteArrayParameter(terminator)));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
|
||||
|
||||
private:
|
||||
SecByteBlock m_separator, m_terminator;
|
||||
size_t m_groupSize, m_counter;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "cbcmac.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void CBC_MAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
||||
{
|
||||
AccessCipher().SetKey(key, length, params);
|
||||
m_reg.CleanNew(AccessCipher().BlockSize());
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
void CBC_MAC_Base::Update(const byte *input, size_t length)
|
||||
{
|
||||
unsigned int blockSize = AccessCipher().BlockSize();
|
||||
|
||||
while (m_counter && length)
|
||||
{
|
||||
m_reg[m_counter++] ^= *input++;
|
||||
if (m_counter == blockSize)
|
||||
ProcessBuf();
|
||||
length--;
|
||||
}
|
||||
|
||||
if (length >= blockSize)
|
||||
{
|
||||
size_t leftOver = AccessCipher().AdvancedProcessBlocks(m_reg, input, m_reg, length, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
||||
input += (length - leftOver);
|
||||
length = leftOver;
|
||||
}
|
||||
|
||||
while (length--)
|
||||
{
|
||||
m_reg[m_counter++] ^= *input++;
|
||||
if (m_counter == blockSize)
|
||||
ProcessBuf();
|
||||
}
|
||||
}
|
||||
|
||||
void CBC_MAC_Base::TruncatedFinal(byte *mac, size_t size)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
if (m_counter)
|
||||
ProcessBuf();
|
||||
|
||||
memcpy(mac, m_reg, size);
|
||||
memset(m_reg, 0, AccessCipher().BlockSize());
|
||||
}
|
||||
|
||||
void CBC_MAC_Base::ProcessBuf()
|
||||
{
|
||||
AccessCipher().ProcessBlock(m_reg);
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,50 +0,0 @@
|
||||
#ifndef CRYPTOPP_CBCMAC_H
|
||||
#define CRYPTOPP_CBCMAC_H
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! _
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode
|
||||
{
|
||||
public:
|
||||
CBC_MAC_Base() {}
|
||||
|
||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
||||
void Update(const byte *input, size_t length);
|
||||
void TruncatedFinal(byte *mac, size_t size);
|
||||
unsigned int DigestSize() const {return const_cast<CBC_MAC_Base*>(this)->AccessCipher().BlockSize();}
|
||||
|
||||
protected:
|
||||
virtual BlockCipher & AccessCipher() =0;
|
||||
|
||||
private:
|
||||
void ProcessBuf();
|
||||
SecByteBlock m_reg;
|
||||
unsigned int m_counter;
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/mac.html#CBC-MAC">CBC-MAC</a>
|
||||
/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation.
|
||||
Secure only for fixed length messages. For variable length messages use CMAC or DMAC.
|
||||
*/
|
||||
template <class T>
|
||||
class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
|
||||
{
|
||||
public:
|
||||
CBC_MAC() {}
|
||||
CBC_MAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
|
||||
{this->SetKey(key, length);}
|
||||
|
||||
static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";}
|
||||
|
||||
private:
|
||||
BlockCipher & AccessCipher() {return m_cipher;}
|
||||
typename T::Encryption m_cipher;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,140 +0,0 @@
|
||||
// ccm.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "ccm.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms)
|
||||
{
|
||||
BlockCipher &blockCipher = AccessBlockCipher();
|
||||
|
||||
blockCipher.SetKey(userKey, keylength, params);
|
||||
|
||||
if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
|
||||
throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
|
||||
|
||||
m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
|
||||
if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
|
||||
throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
|
||||
|
||||
m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
|
||||
m_L = 8;
|
||||
}
|
||||
|
||||
void CCM_Base::Resync(const byte *iv, size_t len)
|
||||
{
|
||||
BlockCipher &cipher = AccessBlockCipher();
|
||||
|
||||
m_L = REQUIRED_BLOCKSIZE-1-(int)len;
|
||||
assert(m_L >= 2);
|
||||
if (m_L > 8)
|
||||
m_L = 8;
|
||||
|
||||
m_buffer[0] = byte(m_L-1); // flag
|
||||
memcpy(m_buffer+1, iv, len);
|
||||
memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
|
||||
|
||||
if (m_state >= State_IVSet)
|
||||
m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
|
||||
else
|
||||
m_ctr.SetCipherWithIV(cipher, m_buffer);
|
||||
|
||||
m_ctr.Seek(REQUIRED_BLOCKSIZE);
|
||||
m_aadLength = 0;
|
||||
m_messageLength = 0;
|
||||
}
|
||||
|
||||
void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
|
||||
{
|
||||
if (m_state != State_IVSet)
|
||||
throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
|
||||
|
||||
m_aadLength = headerLength;
|
||||
m_messageLength = messageLength;
|
||||
|
||||
byte *cbcBuffer = CBC_Buffer();
|
||||
const BlockCipher &cipher = GetBlockCipher();
|
||||
|
||||
cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
|
||||
PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
|
||||
memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
|
||||
cipher.ProcessBlock(cbcBuffer);
|
||||
|
||||
if (headerLength>0)
|
||||
{
|
||||
assert(m_bufferedDataLength == 0);
|
||||
|
||||
if (headerLength < ((1<<16) - (1<<8)))
|
||||
{
|
||||
PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
|
||||
m_bufferedDataLength = 2;
|
||||
}
|
||||
else if (headerLength < (W64LIT(1)<<32))
|
||||
{
|
||||
m_buffer[0] = 0xff;
|
||||
m_buffer[1] = 0xfe;
|
||||
PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
|
||||
m_bufferedDataLength = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer[0] = 0xff;
|
||||
m_buffer[1] = 0xff;
|
||||
PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
|
||||
m_bufferedDataLength = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
|
||||
{
|
||||
byte *cbcBuffer = CBC_Buffer();
|
||||
const BlockCipher &cipher = GetBlockCipher();
|
||||
return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
||||
}
|
||||
|
||||
void CCM_Base::AuthenticateLastHeaderBlock()
|
||||
{
|
||||
byte *cbcBuffer = CBC_Buffer();
|
||||
const BlockCipher &cipher = GetBlockCipher();
|
||||
|
||||
if (m_aadLength != m_totalHeaderLength)
|
||||
throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
|
||||
|
||||
if (m_bufferedDataLength > 0)
|
||||
{
|
||||
xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
|
||||
cipher.ProcessBlock(cbcBuffer);
|
||||
m_bufferedDataLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCM_Base::AuthenticateLastConfidentialBlock()
|
||||
{
|
||||
byte *cbcBuffer = CBC_Buffer();
|
||||
const BlockCipher &cipher = GetBlockCipher();
|
||||
|
||||
if (m_messageLength != m_totalMessageLength)
|
||||
throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
|
||||
|
||||
if (m_bufferedDataLength > 0)
|
||||
{
|
||||
xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
|
||||
cipher.ProcessBlock(cbcBuffer);
|
||||
m_bufferedDataLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
|
||||
{
|
||||
m_ctr.Seek(0);
|
||||
m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,101 +0,0 @@
|
||||
#ifndef CRYPTOPP_CCM_H
|
||||
#define CRYPTOPP_CCM_H
|
||||
|
||||
#include "authenc.h"
|
||||
#include "modes.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! .
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase
|
||||
{
|
||||
public:
|
||||
CCM_Base()
|
||||
: m_digestSize(0), m_L(0) {}
|
||||
|
||||
// AuthenticatedSymmetricCipher
|
||||
std::string AlgorithmName() const
|
||||
{return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
|
||||
size_t MinKeyLength() const
|
||||
{return GetBlockCipher().MinKeyLength();}
|
||||
size_t MaxKeyLength() const
|
||||
{return GetBlockCipher().MaxKeyLength();}
|
||||
size_t DefaultKeyLength() const
|
||||
{return GetBlockCipher().DefaultKeyLength();}
|
||||
size_t GetValidKeyLength(size_t n) const
|
||||
{return GetBlockCipher().GetValidKeyLength(n);}
|
||||
bool IsValidKeyLength(size_t n) const
|
||||
{return GetBlockCipher().IsValidKeyLength(n);}
|
||||
unsigned int OptimalDataAlignment() const
|
||||
{return GetBlockCipher().OptimalDataAlignment();}
|
||||
IV_Requirement IVRequirement() const
|
||||
{return UNIQUE_IV;}
|
||||
unsigned int IVSize() const
|
||||
{return 8;}
|
||||
unsigned int MinIVLength() const
|
||||
{return 7;}
|
||||
unsigned int MaxIVLength() const
|
||||
{return 13;}
|
||||
unsigned int DigestSize() const
|
||||
{return m_digestSize;}
|
||||
lword MaxHeaderLength() const
|
||||
{return W64LIT(0)-1;}
|
||||
lword MaxMessageLength() const
|
||||
{return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}
|
||||
bool NeedsPrespecifiedDataLengths() const
|
||||
{return true;}
|
||||
void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength);
|
||||
|
||||
protected:
|
||||
// AuthenticatedSymmetricCipherBase
|
||||
bool AuthenticationIsOnPlaintext() const
|
||||
{return true;}
|
||||
unsigned int AuthenticationBlockSize() const
|
||||
{return GetBlockCipher().BlockSize();}
|
||||
void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms);
|
||||
void Resync(const byte *iv, size_t len);
|
||||
size_t AuthenticateBlocks(const byte *data, size_t len);
|
||||
void AuthenticateLastHeaderBlock();
|
||||
void AuthenticateLastConfidentialBlock();
|
||||
void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
|
||||
SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
|
||||
|
||||
virtual BlockCipher & AccessBlockCipher() =0;
|
||||
virtual int DefaultDigestSize() const =0;
|
||||
|
||||
const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
|
||||
byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
|
||||
|
||||
enum {REQUIRED_BLOCKSIZE = 16};
|
||||
int m_digestSize, m_L;
|
||||
word64 m_messageLength, m_aadLength;
|
||||
CTR_Mode_ExternalCipher::Encryption m_ctr;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class T_BlockCipher, int T_DefaultDigestSize, bool T_IsEncryption>
|
||||
class CCM_Final : public CCM_Base
|
||||
{
|
||||
public:
|
||||
static std::string StaticAlgorithmName()
|
||||
{return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");}
|
||||
bool IsForwardTransformation() const
|
||||
{return T_IsEncryption;}
|
||||
|
||||
private:
|
||||
BlockCipher & AccessBlockCipher() {return m_cipher;}
|
||||
int DefaultDigestSize() const {return T_DefaultDigestSize;}
|
||||
typename T_BlockCipher::Encryption m_cipher;
|
||||
};
|
||||
|
||||
/// <a href="http://www.cryptolounge.org/wiki/CCM">CCM</a>
|
||||
template <class T_BlockCipher, int T_DefaultDigestSize = 16>
|
||||
struct CCM : public AuthenticatedSymmetricCipherDocumentation
|
||||
{
|
||||
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, true> Encryption;
|
||||
typedef CCM_Final<T_BlockCipher, T_DefaultDigestSize, false> Decryption;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,309 +0,0 @@
|
||||
// channels.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "channels.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
USING_NAMESPACE(std)
|
||||
|
||||
#if 0
|
||||
void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel)
|
||||
{
|
||||
m_defaultRoutes.push_back(Route(&destination, channel));
|
||||
}
|
||||
|
||||
void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel)
|
||||
{
|
||||
RangeRoute route(begin, end, Route(&destination, channel));
|
||||
RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route);
|
||||
m_routes.insert(it, route);
|
||||
}
|
||||
|
||||
/*
|
||||
class MessageRouteIterator
|
||||
{
|
||||
public:
|
||||
typedef MessageSwitch::RouteList::const_iterator RouteIterator;
|
||||
typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator;
|
||||
|
||||
bool m_useDefault;
|
||||
RouteIterator m_itRouteCurrent, m_itRouteEnd;
|
||||
DefaultIterator m_itDefaultCurrent, m_itDefaultEnd;
|
||||
|
||||
MessageRouteIterator(MessageSwitch &ms, const std::string &channel)
|
||||
: m_channel(channel)
|
||||
{
|
||||
pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
|
||||
if (range.first == range.second)
|
||||
{
|
||||
m_useDefault = true;
|
||||
m_itListCurrent = cs.m_defaultRoutes.begin();
|
||||
m_itListEnd = cs.m_defaultRoutes.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_useDefault = false;
|
||||
m_itMapCurrent = range.first;
|
||||
m_itMapEnd = range.second;
|
||||
}
|
||||
}
|
||||
|
||||
bool End() const
|
||||
{
|
||||
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
|
||||
}
|
||||
|
||||
void Next()
|
||||
{
|
||||
if (m_useDefault)
|
||||
++m_itListCurrent;
|
||||
else
|
||||
++m_itMapCurrent;
|
||||
}
|
||||
|
||||
BufferedTransformation & Destination()
|
||||
{
|
||||
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
|
||||
}
|
||||
|
||||
const std::string & Message()
|
||||
{
|
||||
if (m_useDefault)
|
||||
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
|
||||
else
|
||||
return m_itMapCurrent->second.second;
|
||||
}
|
||||
};
|
||||
|
||||
void MessageSwitch::Put(byte inByte);
|
||||
void MessageSwitch::Put(const byte *inString, unsigned int length);
|
||||
|
||||
void MessageSwitch::Flush(bool completeFlush, int propagation=-1);
|
||||
void MessageSwitch::MessageEnd(int propagation=-1);
|
||||
void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
||||
void MessageSwitch::MessageSeriesEnd(int propagation=-1);
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// ChannelRouteIterator
|
||||
//////////////////////////
|
||||
|
||||
void ChannelRouteIterator::Reset(const std::string &channel)
|
||||
{
|
||||
m_channel = channel;
|
||||
pair<MapIterator, MapIterator> range = m_cs.m_routeMap.equal_range(channel);
|
||||
if (range.first == range.second)
|
||||
{
|
||||
m_useDefault = true;
|
||||
m_itListCurrent = m_cs.m_defaultRoutes.begin();
|
||||
m_itListEnd = m_cs.m_defaultRoutes.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_useDefault = false;
|
||||
m_itMapCurrent = range.first;
|
||||
m_itMapEnd = range.second;
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelRouteIterator::End() const
|
||||
{
|
||||
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
|
||||
}
|
||||
|
||||
void ChannelRouteIterator::Next()
|
||||
{
|
||||
if (m_useDefault)
|
||||
++m_itListCurrent;
|
||||
else
|
||||
++m_itMapCurrent;
|
||||
}
|
||||
|
||||
BufferedTransformation & ChannelRouteIterator::Destination()
|
||||
{
|
||||
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
|
||||
}
|
||||
|
||||
const std::string & ChannelRouteIterator::Channel()
|
||||
{
|
||||
if (m_useDefault)
|
||||
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
|
||||
else
|
||||
return m_itMapCurrent->second.second;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ChannelSwitch
|
||||
///////////////////
|
||||
|
||||
size_t ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (m_blocked)
|
||||
{
|
||||
m_blocked = false;
|
||||
goto WasBlocked;
|
||||
}
|
||||
|
||||
m_it.Reset(channel);
|
||||
|
||||
while (!m_it.End())
|
||||
{
|
||||
WasBlocked:
|
||||
if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking))
|
||||
{
|
||||
m_blocked = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
m_it.Next();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChannelSwitch::IsolatedInitialize(const NameValuePairs ¶meters/* =g_nullNameValuePairs */)
|
||||
{
|
||||
m_routeMap.clear();
|
||||
m_defaultRoutes.clear();
|
||||
m_blocked = false;
|
||||
}
|
||||
|
||||
bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
||||
{
|
||||
if (m_blocked)
|
||||
{
|
||||
m_blocked = false;
|
||||
goto WasBlocked;
|
||||
}
|
||||
|
||||
m_it.Reset(channel);
|
||||
|
||||
while (!m_it.End())
|
||||
{
|
||||
WasBlocked:
|
||||
if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking))
|
||||
{
|
||||
m_blocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_it.Next();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
||||
{
|
||||
if (m_blocked)
|
||||
{
|
||||
m_blocked = false;
|
||||
goto WasBlocked;
|
||||
}
|
||||
|
||||
m_it.Reset(channel);
|
||||
|
||||
while (!m_it.End())
|
||||
{
|
||||
WasBlocked:
|
||||
if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation))
|
||||
{
|
||||
m_blocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_it.Next();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, size_t &size)
|
||||
{
|
||||
m_it.Reset(channel);
|
||||
if (!m_it.End())
|
||||
{
|
||||
BufferedTransformation &target = m_it.Destination();
|
||||
const std::string &channel = m_it.Channel();
|
||||
m_it.Next();
|
||||
if (m_it.End()) // there is only one target channel
|
||||
return target.ChannelCreatePutSpace(channel, size);
|
||||
}
|
||||
size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
ChannelRouteIterator it(*this);
|
||||
it.Reset(channel);
|
||||
|
||||
if (!it.End())
|
||||
{
|
||||
BufferedTransformation &target = it.Destination();
|
||||
const std::string &targetChannel = it.Channel();
|
||||
it.Next();
|
||||
if (it.End()) // there is only one target channel
|
||||
return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking);
|
||||
}
|
||||
|
||||
return ChannelPut2(channel, inString, length, messageEnd, blocking);
|
||||
}
|
||||
|
||||
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination)
|
||||
{
|
||||
m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr<std::string>(NULL)));
|
||||
}
|
||||
|
||||
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination)
|
||||
{
|
||||
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
|
||||
if (it->first == &destination && !it->second.get())
|
||||
{
|
||||
m_defaultRoutes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel));
|
||||
}
|
||||
|
||||
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
|
||||
if (it->first == &destination && (it->second.get() && *it->second == outChannel))
|
||||
{
|
||||
m_defaultRoutes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel)));
|
||||
}
|
||||
|
||||
void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
typedef ChannelSwitch::RouteMap::iterator MapIterator;
|
||||
pair<MapIterator, MapIterator> range = m_routeMap.equal_range(inChannel);
|
||||
|
||||
for (MapIterator it = range.first; it != range.second; ++it)
|
||||
if (it->second.first == &destination && it->second.second == outChannel)
|
||||
{
|
||||
m_routeMap.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,123 +0,0 @@
|
||||
#ifndef CRYPTOPP_CHANNELS_H
|
||||
#define CRYPTOPP_CHANNELS_H
|
||||
|
||||
#include "simple.h"
|
||||
#include "smartptr.h"
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#if 0
|
||||
//! Route input on default channel to different and/or multiple channels based on message sequence number
|
||||
class MessageSwitch : public Sink
|
||||
{
|
||||
public:
|
||||
void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel);
|
||||
void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel);
|
||||
|
||||
void Put(byte inByte);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
void Flush(bool completeFlush, int propagation=-1);
|
||||
void MessageEnd(int propagation=-1);
|
||||
void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
||||
void MessageSeriesEnd(int propagation=-1);
|
||||
|
||||
private:
|
||||
typedef std::pair<BufferedTransformation *, std::string> Route;
|
||||
struct RangeRoute
|
||||
{
|
||||
RangeRoute(unsigned int begin, unsigned int end, const Route &route)
|
||||
: begin(begin), end(end), route(route) {}
|
||||
bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;}
|
||||
unsigned int begin, end;
|
||||
Route route;
|
||||
};
|
||||
|
||||
typedef std::list<RangeRoute> RouteList;
|
||||
typedef std::list<Route> DefaultRouteList;
|
||||
|
||||
RouteList m_routes;
|
||||
DefaultRouteList m_defaultRoutes;
|
||||
unsigned int m_nCurrentMessage;
|
||||
};
|
||||
#endif
|
||||
|
||||
class ChannelSwitchTypedefs
|
||||
{
|
||||
public:
|
||||
typedef std::pair<BufferedTransformation *, std::string> Route;
|
||||
typedef std::multimap<std::string, Route> RouteMap;
|
||||
|
||||
typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute;
|
||||
typedef std::list<DefaultRoute> DefaultRouteList;
|
||||
|
||||
// SunCC workaround: can't use const_iterator here
|
||||
typedef RouteMap::iterator MapIterator;
|
||||
typedef DefaultRouteList::iterator ListIterator;
|
||||
};
|
||||
|
||||
class ChannelSwitch;
|
||||
|
||||
class ChannelRouteIterator : public ChannelSwitchTypedefs
|
||||
{
|
||||
public:
|
||||
ChannelSwitch& m_cs;
|
||||
std::string m_channel;
|
||||
bool m_useDefault;
|
||||
MapIterator m_itMapCurrent, m_itMapEnd;
|
||||
ListIterator m_itListCurrent, m_itListEnd;
|
||||
|
||||
ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {}
|
||||
void Reset(const std::string &channel);
|
||||
bool End() const;
|
||||
void Next();
|
||||
BufferedTransformation & Destination();
|
||||
const std::string & Channel();
|
||||
};
|
||||
|
||||
//! Route input to different and/or multiple channels based on channel ID
|
||||
class CRYPTOPP_DLL ChannelSwitch : public Multichannel<Sink>, public ChannelSwitchTypedefs
|
||||
{
|
||||
public:
|
||||
ChannelSwitch() : m_it(*this), m_blocked(false) {}
|
||||
ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false)
|
||||
{
|
||||
AddDefaultRoute(destination);
|
||||
}
|
||||
ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false)
|
||||
{
|
||||
AddDefaultRoute(destination, outChannel);
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs);
|
||||
|
||||
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
|
||||
size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
|
||||
|
||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true);
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
|
||||
|
||||
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
|
||||
|
||||
void AddDefaultRoute(BufferedTransformation &destination);
|
||||
void RemoveDefaultRoute(BufferedTransformation &destination);
|
||||
void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
|
||||
void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
|
||||
void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
|
||||
void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
|
||||
|
||||
private:
|
||||
RouteMap m_routeMap;
|
||||
DefaultRouteList m_defaultRoutes;
|
||||
|
||||
ChannelRouteIterator m_it;
|
||||
bool m_blocked;
|
||||
|
||||
friend class ChannelRouteIterator;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,122 +0,0 @@
|
||||
// cmac.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "cmac.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
static void MulU(byte *k, unsigned int length)
|
||||
{
|
||||
byte carry = 0;
|
||||
|
||||
for (int i=length-1; i>=1; i-=2)
|
||||
{
|
||||
byte carry2 = k[i] >> 7;
|
||||
k[i] += k[i] + carry;
|
||||
carry = k[i-1] >> 7;
|
||||
k[i-1] += k[i-1] + carry2;
|
||||
}
|
||||
|
||||
if (carry)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
case 8:
|
||||
k[7] ^= 0x1b;
|
||||
break;
|
||||
case 16:
|
||||
k[15] ^= 0x87;
|
||||
break;
|
||||
case 32:
|
||||
k[30] ^= 4;
|
||||
k[31] ^= 0x23;
|
||||
break;
|
||||
default:
|
||||
throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
||||
{
|
||||
BlockCipher &cipher = AccessCipher();
|
||||
unsigned int blockSize = cipher.BlockSize();
|
||||
|
||||
cipher.SetKey(key, length, params);
|
||||
m_reg.CleanNew(3*blockSize);
|
||||
m_counter = 0;
|
||||
|
||||
cipher.ProcessBlock(m_reg, m_reg+blockSize);
|
||||
MulU(m_reg+blockSize, blockSize);
|
||||
memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
|
||||
MulU(m_reg+2*blockSize, blockSize);
|
||||
}
|
||||
|
||||
void CMAC_Base::Update(const byte *input, size_t length)
|
||||
{
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
BlockCipher &cipher = AccessCipher();
|
||||
unsigned int blockSize = cipher.BlockSize();
|
||||
|
||||
if (m_counter > 0)
|
||||
{
|
||||
unsigned int len = UnsignedMin(blockSize - m_counter, length);
|
||||
xorbuf(m_reg+m_counter, input, len);
|
||||
length -= len;
|
||||
input += len;
|
||||
m_counter += len;
|
||||
|
||||
if (m_counter == blockSize && length > 0)
|
||||
{
|
||||
cipher.ProcessBlock(m_reg);
|
||||
m_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (length > blockSize)
|
||||
{
|
||||
assert(m_counter == 0);
|
||||
size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
||||
input += (length - leftOver);
|
||||
length = leftOver;
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
assert(m_counter + length <= blockSize);
|
||||
xorbuf(m_reg+m_counter, input, length);
|
||||
m_counter += (unsigned int)length;
|
||||
}
|
||||
|
||||
assert(m_counter > 0);
|
||||
}
|
||||
|
||||
void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
BlockCipher &cipher = AccessCipher();
|
||||
unsigned int blockSize = cipher.BlockSize();
|
||||
|
||||
if (m_counter < blockSize)
|
||||
{
|
||||
m_reg[m_counter] ^= 0x80;
|
||||
cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
||||
}
|
||||
else
|
||||
cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
|
||||
|
||||
memcpy(mac, m_reg, size);
|
||||
|
||||
m_counter = 0;
|
||||
memset(m_reg, 0, blockSize);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
#ifndef CRYPTOPP_CMAC_H
|
||||
#define CRYPTOPP_CMAC_H
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! _
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
|
||||
{
|
||||
public:
|
||||
CMAC_Base() {}
|
||||
|
||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
||||
void Update(const byte *input, size_t length);
|
||||
void TruncatedFinal(byte *mac, size_t size);
|
||||
unsigned int DigestSize() const {return GetCipher().BlockSize();}
|
||||
unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();}
|
||||
unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();}
|
||||
|
||||
protected:
|
||||
friend class EAX_Base;
|
||||
|
||||
const BlockCipher & GetCipher() const {return const_cast<CMAC_Base*>(this)->AccessCipher();}
|
||||
virtual BlockCipher & AccessCipher() =0;
|
||||
|
||||
void ProcessBuf();
|
||||
SecByteBlock m_reg;
|
||||
unsigned int m_counter;
|
||||
};
|
||||
|
||||
/// <a href="http://www.cryptolounge.org/wiki/CMAC">CMAC</a>
|
||||
/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */
|
||||
template <class T>
|
||||
class CMAC : public MessageAuthenticationCodeImpl<CMAC_Base, CMAC<T> >, public SameKeyLengthAs<T>
|
||||
{
|
||||
public:
|
||||
CMAC() {}
|
||||
CMAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
|
||||
{this->SetKey(key, length);}
|
||||
|
||||
static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";}
|
||||
|
||||
private:
|
||||
BlockCipher & AccessCipher() {return m_cipher;}
|
||||
typename T::Encryption m_cipher;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,462 +0,0 @@
|
||||
#ifndef CRYPTOPP_CONFIG_H
|
||||
#define CRYPTOPP_CONFIG_H
|
||||
|
||||
// ***************** Important Settings ********************
|
||||
|
||||
// define this if running on a big-endian CPU
|
||||
#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__MIPSEB__) || defined(__ARMEB__) || (defined(__MWERKS__) && !defined(__INTEL__)))
|
||||
# define IS_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
// define this if running on a little-endian CPU
|
||||
// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
|
||||
#ifndef IS_BIG_ENDIAN
|
||||
# define IS_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// define this if you want to disable all OS-dependent features,
|
||||
// such as sockets and OS-provided random number generators
|
||||
#define NO_OS_DEPENDENCE
|
||||
|
||||
// Define this to use features provided by Microsoft's CryptoAPI.
|
||||
// Currently the only feature used is random number generation.
|
||||
// This macro will be ignored if NO_OS_DEPENDENCE is defined.
|
||||
// #define USE_MS_CRYPTOAPI
|
||||
|
||||
// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
|
||||
#ifndef DSA_1024_BIT_MODULUS_ONLY
|
||||
# define DSA_1024_BIT_MODULUS_ONLY 1
|
||||
#endif
|
||||
|
||||
// ***************** Less Important Settings ***************
|
||||
|
||||
// define this to retain (as much as possible) old deprecated function and class names
|
||||
// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
||||
|
||||
#define GZIP_OS_CODE 0
|
||||
|
||||
// Try this if your CPU has 256K internal cache or a slow multiply instruction
|
||||
// and you want a (possibly) faster IDEA implementation using log tables
|
||||
// #define IDEA_LARGECACHE
|
||||
|
||||
// Define this if, for the linear congruential RNG, you want to use
|
||||
// the original constants as specified in S.K. Park and K.W. Miller's
|
||||
// CACM paper.
|
||||
// #define LCRNG_ORIGINAL_NUMBERS
|
||||
|
||||
// choose which style of sockets to wrap (mostly useful for cygwin which has both)
|
||||
#define PREFER_BERKELEY_STYLE_SOCKETS
|
||||
// #define PREFER_WINDOWS_STYLE_SOCKETS
|
||||
|
||||
// set the name of Rijndael cipher, was "Rijndael" before version 5.3
|
||||
#define CRYPTOPP_RIJNDAEL_NAME "AES"
|
||||
|
||||
// ***************** Important Settings Again ********************
|
||||
// But the defaults should be ok.
|
||||
|
||||
// namespace support is now required
|
||||
#ifdef NO_NAMESPACE
|
||||
# error namespace support is now required
|
||||
#endif
|
||||
|
||||
// Define this to workaround a Microsoft CryptoAPI bug where
|
||||
// each call to CryptAcquireContext causes a 100 KB memory leak.
|
||||
// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
|
||||
#define WORKAROUND_MS_BUG_Q258000
|
||||
|
||||
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
|
||||
// Avoid putting "CryptoPP::" in front of everything in Doxygen output
|
||||
# define CryptoPP
|
||||
# define NAMESPACE_BEGIN(x)
|
||||
# define NAMESPACE_END
|
||||
// Get Doxygen to generate better documentation for these typedefs
|
||||
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
|
||||
#else
|
||||
# define NAMESPACE_BEGIN(x) namespace x {
|
||||
# define NAMESPACE_END }
|
||||
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
|
||||
#endif
|
||||
#define ANONYMOUS_NAMESPACE_BEGIN namespace {
|
||||
#define USING_NAMESPACE(x) using namespace x;
|
||||
#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
|
||||
#define DOCUMENTED_NAMESPACE_END }
|
||||
|
||||
// What is the type of the third parameter to bind?
|
||||
// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
|
||||
// Unfortunately there is no way to tell whether or not socklen_t is defined.
|
||||
// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
|
||||
#ifndef TYPE_OF_SOCKLEN_T
|
||||
# if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# define TYPE_OF_SOCKLEN_T int
|
||||
# else
|
||||
# define TYPE_OF_SOCKLEN_T ::socklen_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
|
||||
# define __USE_W32_SOCKETS
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
typedef unsigned short word16;
|
||||
typedef unsigned int word32;
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef unsigned __int64 word64;
|
||||
#define W64LIT(x) x##ui64
|
||||
#else
|
||||
typedef unsigned long long word64;
|
||||
#define W64LIT(x) x##ULL
|
||||
#endif
|
||||
|
||||
// define large word type, used for file offsets and such
|
||||
typedef word64 lword;
|
||||
const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
// define hword, word, and dword. these are used for multiprecision integer arithmetic
|
||||
// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
|
||||
#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
|
||||
typedef word32 hword;
|
||||
typedef word64 word;
|
||||
#else
|
||||
#define CRYPTOPP_NATIVE_DWORD_AVAILABLE
|
||||
#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
|
||||
// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
|
||||
// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
|
||||
typedef word32 hword;
|
||||
typedef word64 word;
|
||||
typedef __uint128_t dword;
|
||||
typedef __uint128_t word128;
|
||||
#define CRYPTOPP_WORD128_AVAILABLE
|
||||
#else
|
||||
// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
|
||||
typedef word16 hword;
|
||||
typedef word32 word;
|
||||
typedef word64 dword;
|
||||
#endif
|
||||
#else
|
||||
// being here means the native register size is probably 32 bits or less
|
||||
#define CRYPTOPP_BOOL_SLOW_WORD64 1
|
||||
typedef word16 hword;
|
||||
typedef word32 word;
|
||||
typedef word64 dword;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef CRYPTOPP_BOOL_SLOW_WORD64
|
||||
#define CRYPTOPP_BOOL_SLOW_WORD64 0
|
||||
#endif
|
||||
|
||||
const unsigned int WORD_SIZE = sizeof(word);
|
||||
const unsigned int WORD_BITS = WORD_SIZE * 8;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
|
||||
// This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
|
||||
#else
|
||||
// L1 cache line size is 32 on Pentium III and earlier
|
||||
#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER == 1200
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if _MSC_VER > 1200 || defined(_mm_free)
|
||||
#define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later
|
||||
#else
|
||||
#define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CRYPTOPP_ALIGN_DATA
|
||||
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
|
||||
#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
|
||||
#elif defined(__GNUC__)
|
||||
#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
|
||||
#else
|
||||
#define CRYPTOPP_ALIGN_DATA(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CRYPTOPP_SECTION_ALIGN16
|
||||
#if defined(__GNUC__) && !defined(__APPLE__)
|
||||
// the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
|
||||
#define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
|
||||
#else
|
||||
#define CRYPTOPP_SECTION_ALIGN16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__fastcall)
|
||||
#define CRYPTOPP_FASTCALL __fastcall
|
||||
#else
|
||||
#define CRYPTOPP_FASTCALL
|
||||
#endif
|
||||
|
||||
// VC60 workaround: it doesn't allow typename in some places
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
||||
#define CPP_TYPENAME
|
||||
#else
|
||||
#define CPP_TYPENAME typename
|
||||
#endif
|
||||
|
||||
// VC60 workaround: can't cast unsigned __int64 to float or double
|
||||
#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
|
||||
#define CRYPTOPP_VC6_INT64 (__int64)
|
||||
#else
|
||||
#define CRYPTOPP_VC6_INT64
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CRYPTOPP_NO_VTABLE __declspec(novtable)
|
||||
#else
|
||||
#define CRYPTOPP_NO_VTABLE
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// 4231: nonstandard extension used : 'extern' before template explicit instantiation
|
||||
// 4250: dominance
|
||||
// 4251: member needs to have dll-interface
|
||||
// 4275: base needs to have dll-interface
|
||||
// 4660: explicitly instantiating a class that's already implicitly instantiated
|
||||
// 4661: no suitable definition provided for explicit template instantiation request
|
||||
// 4786: identifer was truncated in debug information
|
||||
// 4355: 'this' : used in base member initializer list
|
||||
// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
|
||||
# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
// 8037: non-const function called for const object. needed to work around BCB2006 bug
|
||||
# pragma warn -8037
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) || defined(ANDROID_NDK)
|
||||
#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
|
||||
#endif
|
||||
|
||||
#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
|
||||
#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings
|
||||
#define CRYPTOPP_DISABLE_ASM
|
||||
#define CRYPTOPP_DISABLE_SSE2
|
||||
#endif
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
|
||||
// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
|
||||
#define CRYPTOPP_X86_ASM_AVAILABLE
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300)
|
||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
|
||||
#endif
|
||||
|
||||
// SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed.
|
||||
// GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version.
|
||||
#if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102)
|
||||
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
|
||||
#define CRYPTOPP_X64_MASM_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
|
||||
#define CRYPTOPP_X64_ASM_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__))
|
||||
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
|
||||
#endif
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_SSSE3) && !defined(CRYPTOPP_DISABLE_AESNI) && CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE && (CRYPTOPP_GCC_VERSION >= 40400 || _MSC_FULL_VER >= 150030729 || __INTEL_COMPILER >= 1110)
|
||||
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE 0
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
|
||||
#define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
|
||||
#endif
|
||||
|
||||
// how to allocate 16-byte aligned memory (for SSE2)
|
||||
#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
|
||||
#define CRYPTOPP_MM_MALLOC_AVAILABLE
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
|
||||
#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
|
||||
#define CRYPTOPP_MEMALIGN_AVAILABLE
|
||||
#else
|
||||
#define CRYPTOPP_NO_ALIGNED_ALLOC
|
||||
#endif
|
||||
|
||||
// how to disable inlining
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||
# define CRYPTOPP_NOINLINE_DOTDOTDOT
|
||||
# define CRYPTOPP_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
# define CRYPTOPP_NOINLINE_DOTDOTDOT
|
||||
# define CRYPTOPP_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
# define CRYPTOPP_NOINLINE_DOTDOTDOT ...
|
||||
# define CRYPTOPP_NOINLINE
|
||||
#endif
|
||||
|
||||
// how to declare class constants
|
||||
#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER)
|
||||
# define CRYPTOPP_CONSTANT(x) enum {x};
|
||||
#else
|
||||
# define CRYPTOPP_CONSTANT(x) static const int x;
|
||||
#endif
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define CRYPTOPP_BOOL_X64 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_X64 0
|
||||
#endif
|
||||
|
||||
// see http://predef.sourceforge.net/prearch.html
|
||||
#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)
|
||||
#define CRYPTOPP_BOOL_X86 1
|
||||
#else
|
||||
#define CRYPTOPP_BOOL_X86 0
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
|
||||
#define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
|
||||
#endif
|
||||
|
||||
#define CRYPTOPP_VERSION 562
|
||||
|
||||
// ***************** determine availability of OS features ********************
|
||||
|
||||
#ifndef NO_OS_DEPENDENCE
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define CRYPTOPP_WIN32_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
|
||||
#define CRYPTOPP_UNIX_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
# define HIGHRES_TIMER_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
||||
# define HAS_BERKELEY_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# define HAS_WINDOWS_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS))
|
||||
# define SOCKETS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
|
||||
# define USE_WINDOWS_STYLE_SOCKETS
|
||||
#else
|
||||
# define USE_BERKELEY_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
|
||||
# define WINDOWS_PIPES_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI)
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define BLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
# define HAS_PTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# define HAS_WINTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#endif // NO_OS_DEPENDENCE
|
||||
|
||||
// ***************** DLL related ********************
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
|
||||
|
||||
#ifdef CRYPTOPP_EXPORTS
|
||||
#define CRYPTOPP_IS_DLL
|
||||
#define CRYPTOPP_DLL __declspec(dllexport)
|
||||
#elif defined(CRYPTOPP_IMPORTS)
|
||||
#define CRYPTOPP_IS_DLL
|
||||
#define CRYPTOPP_DLL __declspec(dllimport)
|
||||
#else
|
||||
#define CRYPTOPP_DLL
|
||||
#endif
|
||||
|
||||
#define CRYPTOPP_API __cdecl
|
||||
|
||||
#else // CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
#define CRYPTOPP_DLL
|
||||
#define CRYPTOPP_API
|
||||
|
||||
#endif // CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
#if defined(__MWERKS__)
|
||||
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
|
||||
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
|
||||
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
|
||||
#else
|
||||
#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
|
||||
#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
|
||||
#else
|
||||
#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
|
||||
#endif
|
||||
|
||||
#if defined(__MWERKS__)
|
||||
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
|
||||
#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
|
||||
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
|
||||
#else
|
||||
#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
|
||||
#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
|
||||
#else
|
||||
#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,199 +0,0 @@
|
||||
// cpu.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "cpu.h"
|
||||
#include "misc.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#ifdef CRYPTOPP_CPUID_AVAILABLE
|
||||
|
||||
#if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
|
||||
|
||||
bool CpuId(word32 input, word32 *output)
|
||||
{
|
||||
__cpuid((int *)output, input);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
||||
extern "C" {
|
||||
typedef void (*SigHandler)(int);
|
||||
|
||||
static jmp_buf s_jmpNoCPUID;
|
||||
static void SigIllHandlerCPUID(int)
|
||||
{
|
||||
longjmp(s_jmpNoCPUID, 1);
|
||||
}
|
||||
|
||||
static jmp_buf s_jmpNoSSE2;
|
||||
static void SigIllHandlerSSE2(int)
|
||||
{
|
||||
longjmp(s_jmpNoSSE2, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CpuId(word32 input, word32 *output)
|
||||
{
|
||||
#ifdef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
||||
__try
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, input
|
||||
cpuid
|
||||
mov edi, output
|
||||
mov [edi], eax
|
||||
mov [edi+4], ebx
|
||||
mov [edi+8], ecx
|
||||
mov [edi+12], edx
|
||||
}
|
||||
}
|
||||
__except (1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
|
||||
if (oldHandler == SIG_ERR)
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
if (setjmp(s_jmpNoCPUID))
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
asm
|
||||
(
|
||||
// save ebx in case -fPIC is being used
|
||||
#if CRYPTOPP_BOOL_X86
|
||||
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
|
||||
#else
|
||||
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
|
||||
#endif
|
||||
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
|
||||
: "a" (input)
|
||||
);
|
||||
}
|
||||
|
||||
signal(SIGILL, oldHandler);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool TrySSE2()
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
return true;
|
||||
#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
|
||||
__try
|
||||
{
|
||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
||||
AS2(por xmm0, xmm0) // executing SSE2 instruction
|
||||
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
||||
__m128i x = _mm_setzero_si128();
|
||||
return _mm_cvtsi128_si32(x) == 0;
|
||||
#endif
|
||||
}
|
||||
__except (1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
|
||||
if (oldHandler == SIG_ERR)
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
if (setjmp(s_jmpNoSSE2))
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
||||
__asm __volatile ("por %xmm0, %xmm0");
|
||||
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
||||
__m128i x = _mm_setzero_si128();
|
||||
result = _mm_cvtsi128_si32(x) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
signal(SIGILL, oldHandler);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool g_x86DetectionDone = false;
|
||||
bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_hasAESNI = false, g_hasCLMUL = false, g_isP4 = false;
|
||||
word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
||||
|
||||
void DetectX86Features()
|
||||
{
|
||||
word32 cpuid[4], cpuid1[4];
|
||||
if (!CpuId(0, cpuid))
|
||||
return;
|
||||
if (!CpuId(1, cpuid1))
|
||||
return;
|
||||
|
||||
g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
|
||||
if ((cpuid1[3] & (1 << 26)) != 0)
|
||||
g_hasSSE2 = TrySSE2();
|
||||
g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
|
||||
g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
|
||||
g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
|
||||
|
||||
if ((cpuid1[3] & (1 << 25)) != 0)
|
||||
g_hasISSE = true;
|
||||
else
|
||||
{
|
||||
word32 cpuid2[4];
|
||||
CpuId(0x080000000, cpuid2);
|
||||
if (cpuid2[0] >= 0x080000001)
|
||||
{
|
||||
CpuId(0x080000001, cpuid2);
|
||||
g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::swap(cpuid[2], cpuid[3]);
|
||||
if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
|
||||
{
|
||||
g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
|
||||
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
|
||||
}
|
||||
else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
|
||||
{
|
||||
CpuId(0x80000005, cpuid);
|
||||
g_cacheLineSize = GETBYTE(cpuid[2], 0);
|
||||
}
|
||||
|
||||
if (!g_cacheLineSize)
|
||||
g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
|
||||
|
||||
g_x86DetectionDone = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,345 +0,0 @@
|
||||
#ifndef CRYPTOPP_CPU_H
|
||||
#define CRYPTOPP_CPU_H
|
||||
|
||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
||||
|
||||
#define CRYPTOPP_X86_ASM_AVAILABLE
|
||||
#define CRYPTOPP_BOOL_X64 1
|
||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
|
||||
#define NAMESPACE_END
|
||||
|
||||
#else
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
|
||||
#if !defined(__GNUC__) || defined(__SSSE3__) || defined(__INTEL_COMPILER)
|
||||
#include <tmmintrin.h>
|
||||
#else
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_shuffle_epi8 (__m128i a, __m128i b)
|
||||
{
|
||||
asm ("pshufb %1, %0" : "+x"(a) : "xm"(b));
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
#if !defined(__GNUC__) || defined(__SSE4_1__) || defined(__INTEL_COMPILER)
|
||||
#include <smmintrin.h>
|
||||
#else
|
||||
__inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_extract_epi32 (__m128i a, const int i)
|
||||
{
|
||||
int r;
|
||||
asm ("pextrd %2, %1, %0" : "=rm"(r) : "x"(a), "i"(i));
|
||||
return r;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_insert_epi32 (__m128i a, int b, const int i)
|
||||
{
|
||||
asm ("pinsrd %2, %1, %0" : "+x"(a) : "rm"(b), "i"(i));
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
#if !defined(__GNUC__) || (defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER)
|
||||
#include <wmmintrin.h>
|
||||
#else
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_clmulepi64_si128 (__m128i a, __m128i b, const int i)
|
||||
{
|
||||
asm ("pclmulqdq %2, %1, %0" : "+x"(a) : "xm"(b), "i"(i));
|
||||
return a;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_aeskeygenassist_si128 (__m128i a, const int i)
|
||||
{
|
||||
__m128i r;
|
||||
asm ("aeskeygenassist %2, %1, %0" : "=x"(r) : "xm"(a), "i"(i));
|
||||
return r;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_aesimc_si128 (__m128i a)
|
||||
{
|
||||
__m128i r;
|
||||
asm ("aesimc %1, %0" : "=x"(r) : "xm"(a));
|
||||
return r;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_aesenc_si128 (__m128i a, __m128i b)
|
||||
{
|
||||
asm ("aesenc %1, %0" : "+x"(a) : "xm"(b));
|
||||
return a;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_aesenclast_si128 (__m128i a, __m128i b)
|
||||
{
|
||||
asm ("aesenclast %1, %0" : "+x"(a) : "xm"(b));
|
||||
return a;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_aesdec_si128 (__m128i a, __m128i b)
|
||||
{
|
||||
asm ("aesdec %1, %0" : "+x"(a) : "xm"(b));
|
||||
return a;
|
||||
}
|
||||
__inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
_mm_aesdeclast_si128 (__m128i a, __m128i b)
|
||||
{
|
||||
asm ("aesdeclast %1, %0" : "+x"(a) : "xm"(b));
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
|
||||
|
||||
#define CRYPTOPP_CPUID_AVAILABLE
|
||||
|
||||
// these should not be used directly
|
||||
extern CRYPTOPP_DLL bool g_x86DetectionDone;
|
||||
extern CRYPTOPP_DLL bool g_hasSSSE3;
|
||||
extern CRYPTOPP_DLL bool g_hasAESNI;
|
||||
extern CRYPTOPP_DLL bool g_hasCLMUL;
|
||||
extern CRYPTOPP_DLL bool g_isP4;
|
||||
extern CRYPTOPP_DLL word32 g_cacheLineSize;
|
||||
CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
|
||||
CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output);
|
||||
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
inline bool HasSSE2() {return true;}
|
||||
inline bool HasISSE() {return true;}
|
||||
inline bool HasMMX() {return true;}
|
||||
#else
|
||||
|
||||
extern CRYPTOPP_DLL bool g_hasSSE2;
|
||||
extern CRYPTOPP_DLL bool g_hasISSE;
|
||||
extern CRYPTOPP_DLL bool g_hasMMX;
|
||||
|
||||
inline bool HasSSE2()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_hasSSE2;
|
||||
}
|
||||
|
||||
inline bool HasISSE()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_hasISSE;
|
||||
}
|
||||
|
||||
inline bool HasMMX()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_hasMMX;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline bool HasSSSE3()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_hasSSSE3;
|
||||
}
|
||||
|
||||
inline bool HasAESNI()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_hasAESNI;
|
||||
}
|
||||
|
||||
inline bool HasCLMUL()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_hasCLMUL;
|
||||
}
|
||||
|
||||
inline bool IsP4()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_isP4;
|
||||
}
|
||||
|
||||
inline int GetCacheLineSize()
|
||||
{
|
||||
if (!g_x86DetectionDone)
|
||||
DetectX86Features();
|
||||
return g_cacheLineSize;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline int GetCacheLineSize()
|
||||
{
|
||||
return CRYPTOPP_L1_CACHE_LINE_SIZE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
||||
#define AS1(x) x*newline*
|
||||
#define AS2(x, y) x, y*newline*
|
||||
#define AS3(x, y, z) x, y, z*newline*
|
||||
#define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
|
||||
#define ASL(x) label##x:*newline*
|
||||
#define ASJ(x, y, z) x label##y*newline*
|
||||
#define ASC(x, y) x label##y*newline*
|
||||
#define AS_HEX(y) 0##y##h
|
||||
#elif defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
|
||||
#define AS1(x) __asm {x}
|
||||
#define AS2(x, y) __asm {x, y}
|
||||
#define AS3(x, y, z) __asm {x, y, z}
|
||||
#define ASS(x, y, a, b, c, d) __asm {x, y, (a)*64+(b)*16+(c)*4+(d)}
|
||||
#define ASL(x) __asm {label##x:}
|
||||
#define ASJ(x, y, z) __asm {x label##y}
|
||||
#define ASC(x, y) __asm {x label##y}
|
||||
#define CRYPTOPP_NAKED __declspec(naked)
|
||||
#define AS_HEX(y) 0x##y
|
||||
#else
|
||||
#define CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
|
||||
// define these in two steps to allow arguments to be expanded
|
||||
#define GNU_AS1(x) #x ";"
|
||||
#define GNU_AS2(x, y) #x ", " #y ";"
|
||||
#define GNU_AS3(x, y, z) #x ", " #y ", " #z ";"
|
||||
#define GNU_ASL(x) "\n" #x ":"
|
||||
#define GNU_ASJ(x, y, z) #x " " #y #z ";"
|
||||
#define AS1(x) GNU_AS1(x)
|
||||
#define AS2(x, y) GNU_AS2(x, y)
|
||||
#define AS3(x, y, z) GNU_AS3(x, y, z)
|
||||
#define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
|
||||
#define ASL(x) GNU_ASL(x)
|
||||
#define ASJ(x, y, z) GNU_ASJ(x, y, z)
|
||||
#define ASC(x, y) #x " " #y ";"
|
||||
#define CRYPTOPP_NAKED
|
||||
#define AS_HEX(y) 0x##y
|
||||
#endif
|
||||
|
||||
#define IF0(y)
|
||||
#define IF1(y) y
|
||||
|
||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
||||
#define ASM_MOD(x, y) ((x) MOD (y))
|
||||
#define XMMWORD_PTR XMMWORD PTR
|
||||
#else
|
||||
// GNU assembler doesn't seem to have mod operator
|
||||
#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
|
||||
// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
|
||||
#define XMMWORD_PTR
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_BOOL_X86
|
||||
#define AS_REG_1 ecx
|
||||
#define AS_REG_2 edx
|
||||
#define AS_REG_3 esi
|
||||
#define AS_REG_4 edi
|
||||
#define AS_REG_5 eax
|
||||
#define AS_REG_6 ebx
|
||||
#define AS_REG_7 ebp
|
||||
#define AS_REG_1d ecx
|
||||
#define AS_REG_2d edx
|
||||
#define AS_REG_3d esi
|
||||
#define AS_REG_4d edi
|
||||
#define AS_REG_5d eax
|
||||
#define AS_REG_6d ebx
|
||||
#define AS_REG_7d ebp
|
||||
#define WORD_SZ 4
|
||||
#define WORD_REG(x) e##x
|
||||
#define WORD_PTR DWORD PTR
|
||||
#define AS_PUSH_IF86(x) AS1(push e##x)
|
||||
#define AS_POP_IF86(x) AS1(pop e##x)
|
||||
#define AS_JCXZ jecxz
|
||||
#elif CRYPTOPP_BOOL_X64
|
||||
#ifdef CRYPTOPP_GENERATE_X64_MASM
|
||||
#define AS_REG_1 rcx
|
||||
#define AS_REG_2 rdx
|
||||
#define AS_REG_3 r8
|
||||
#define AS_REG_4 r9
|
||||
#define AS_REG_5 rax
|
||||
#define AS_REG_6 r10
|
||||
#define AS_REG_7 r11
|
||||
#define AS_REG_1d ecx
|
||||
#define AS_REG_2d edx
|
||||
#define AS_REG_3d r8d
|
||||
#define AS_REG_4d r9d
|
||||
#define AS_REG_5d eax
|
||||
#define AS_REG_6d r10d
|
||||
#define AS_REG_7d r11d
|
||||
#else
|
||||
#define AS_REG_1 rdi
|
||||
#define AS_REG_2 rsi
|
||||
#define AS_REG_3 rdx
|
||||
#define AS_REG_4 rcx
|
||||
#define AS_REG_5 r8
|
||||
#define AS_REG_6 r9
|
||||
#define AS_REG_7 r10
|
||||
#define AS_REG_1d edi
|
||||
#define AS_REG_2d esi
|
||||
#define AS_REG_3d edx
|
||||
#define AS_REG_4d ecx
|
||||
#define AS_REG_5d r8d
|
||||
#define AS_REG_6d r9d
|
||||
#define AS_REG_7d r10d
|
||||
#endif
|
||||
#define WORD_SZ 8
|
||||
#define WORD_REG(x) r##x
|
||||
#define WORD_PTR QWORD PTR
|
||||
#define AS_PUSH_IF86(x)
|
||||
#define AS_POP_IF86(x)
|
||||
#define AS_JCXZ jrcxz
|
||||
#endif
|
||||
|
||||
// helper macro for stream cipher output
|
||||
#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
|
||||
AS2( test inputPtr, inputPtr)\
|
||||
ASC( jz, labelPrefix##3)\
|
||||
AS2( test inputPtr, 15)\
|
||||
ASC( jnz, labelPrefix##7)\
|
||||
AS2( pxor xmm##x0, [inputPtr+p0*16])\
|
||||
AS2( pxor xmm##x1, [inputPtr+p1*16])\
|
||||
AS2( pxor xmm##x2, [inputPtr+p2*16])\
|
||||
AS2( pxor xmm##x3, [inputPtr+p3*16])\
|
||||
AS2( add inputPtr, increment*16)\
|
||||
ASC( jmp, labelPrefix##3)\
|
||||
ASL(labelPrefix##7)\
|
||||
AS2( movdqu xmm##t, [inputPtr+p0*16])\
|
||||
AS2( pxor xmm##x0, xmm##t)\
|
||||
AS2( movdqu xmm##t, [inputPtr+p1*16])\
|
||||
AS2( pxor xmm##x1, xmm##t)\
|
||||
AS2( movdqu xmm##t, [inputPtr+p2*16])\
|
||||
AS2( pxor xmm##x2, xmm##t)\
|
||||
AS2( movdqu xmm##t, [inputPtr+p3*16])\
|
||||
AS2( pxor xmm##x3, xmm##t)\
|
||||
AS2( add inputPtr, increment*16)\
|
||||
ASL(labelPrefix##3)\
|
||||
AS2( test outputPtr, 15)\
|
||||
ASC( jnz, labelPrefix##8)\
|
||||
AS2( movdqa [outputPtr+p0*16], xmm##x0)\
|
||||
AS2( movdqa [outputPtr+p1*16], xmm##x1)\
|
||||
AS2( movdqa [outputPtr+p2*16], xmm##x2)\
|
||||
AS2( movdqa [outputPtr+p3*16], xmm##x3)\
|
||||
ASC( jmp, labelPrefix##9)\
|
||||
ASL(labelPrefix##8)\
|
||||
AS2( movdqu [outputPtr+p0*16], xmm##x0)\
|
||||
AS2( movdqu [outputPtr+p1*16], xmm##x1)\
|
||||
AS2( movdqu [outputPtr+p2*16], xmm##x2)\
|
||||
AS2( movdqu [outputPtr+p3*16], xmm##x3)\
|
||||
ASL(labelPrefix##9)\
|
||||
AS2( add outputPtr, increment*16)
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,160 +0,0 @@
|
||||
// crc.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "crc.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/* Table of CRC-32's of all single byte values (made by makecrc.c) */
|
||||
const word32 CRC32::m_tab[] = {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
#else
|
||||
0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
|
||||
0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
|
||||
0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
|
||||
0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
|
||||
0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
|
||||
0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
|
||||
0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
|
||||
0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
|
||||
0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
|
||||
0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
|
||||
0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
|
||||
0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
|
||||
0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
|
||||
0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
|
||||
0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
|
||||
0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
|
||||
0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
|
||||
0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
|
||||
0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
|
||||
0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
|
||||
0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
|
||||
0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
|
||||
0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
|
||||
0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
|
||||
0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
|
||||
0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
|
||||
0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
|
||||
0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
|
||||
0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
|
||||
0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
|
||||
0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
|
||||
0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
|
||||
0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
|
||||
0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
|
||||
0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
|
||||
0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
|
||||
0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
|
||||
0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
|
||||
0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
|
||||
0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
|
||||
0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
|
||||
0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
|
||||
0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
|
||||
0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
|
||||
0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
|
||||
0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
|
||||
0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
|
||||
0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
|
||||
0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
|
||||
0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
|
||||
0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
|
||||
0x8def022dL
|
||||
#endif
|
||||
};
|
||||
|
||||
CRC32::CRC32()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void CRC32::Update(const byte *s, size_t n)
|
||||
{
|
||||
word32 crc = m_crc;
|
||||
|
||||
for(; !IsAligned<word32>(s) && n > 0; n--)
|
||||
crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
|
||||
|
||||
while (n >= 4)
|
||||
{
|
||||
crc ^= *(const word32 *)s;
|
||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
||||
crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
|
||||
n -= 4;
|
||||
s += 4;
|
||||
}
|
||||
|
||||
while (n--)
|
||||
crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
|
||||
|
||||
m_crc = crc;
|
||||
}
|
||||
|
||||
void CRC32::TruncatedFinal(byte *hash, size_t size)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
m_crc ^= CRC32_NEGL;
|
||||
for (size_t i=0; i<size; i++)
|
||||
hash[i] = GetCrcByte(i);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef CRYPTOPP_CRC32_H
|
||||
#define CRYPTOPP_CRC32_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
const word32 CRC32_NEGL = 0xffffffffL;
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define CRC32_INDEX(c) (c & 0xff)
|
||||
#define CRC32_SHIFTED(c) (c >> 8)
|
||||
#else
|
||||
#define CRC32_INDEX(c) (c >> 24)
|
||||
#define CRC32_SHIFTED(c) (c << 8)
|
||||
#endif
|
||||
|
||||
//! CRC Checksum Calculation
|
||||
class CRC32 : public HashTransformation
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_CONSTANT(DIGESTSIZE = 4)
|
||||
CRC32();
|
||||
void Update(const byte *input, size_t length);
|
||||
void TruncatedFinal(byte *hash, size_t size);
|
||||
unsigned int DigestSize() const {return DIGESTSIZE;}
|
||||
static const char * StaticAlgorithmName() {return "CRC32";}
|
||||
std::string AlgorithmName() const {return StaticAlgorithmName();}
|
||||
|
||||
void UpdateByte(byte b) {m_crc = m_tab[CRC32_INDEX(m_crc) ^ b] ^ CRC32_SHIFTED(m_crc);}
|
||||
byte GetCrcByte(size_t i) const {return ((byte *)&(m_crc))[i];}
|
||||
|
||||
private:
|
||||
void Reset() {m_crc = CRC32_NEGL;}
|
||||
|
||||
static const word32 m_tab[256];
|
||||
word32 m_crc;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,828 +0,0 @@
|
||||
// cryptlib.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "filters.h"
|
||||
#include "algparam.h"
|
||||
#include "fips140.h"
|
||||
#include "argnames.h"
|
||||
#include "fltrimpl.h"
|
||||
#include "trdlocal.h"
|
||||
#include "osrng.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
|
||||
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
|
||||
#endif
|
||||
|
||||
const std::string DEFAULT_CHANNEL;
|
||||
const std::string AAD_CHANNEL = "AAD";
|
||||
const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL;
|
||||
|
||||
class NullNameValuePairs : public NameValuePairs
|
||||
{
|
||||
public:
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;}
|
||||
};
|
||||
|
||||
simple_ptr<NullNameValuePairs> s_pNullNameValuePairs(new NullNameValuePairs);
|
||||
const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
|
||||
|
||||
BufferedTransformation & TheBitBucket()
|
||||
{
|
||||
static BitBucket bitBucket;
|
||||
return bitBucket;
|
||||
}
|
||||
|
||||
Algorithm::Algorithm(bool checkSelfTestStatus)
|
||||
{
|
||||
if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled())
|
||||
{
|
||||
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread())
|
||||
throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed.");
|
||||
|
||||
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED)
|
||||
throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed.");
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms)
|
||||
{
|
||||
this->ThrowIfInvalidKeyLength(length);
|
||||
this->UncheckedSetKey(key, (unsigned int)length, params);
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds)
|
||||
{
|
||||
SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
|
||||
{
|
||||
SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength)));
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length)
|
||||
{
|
||||
if (!IsValidKeyLength(length))
|
||||
throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length);
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::ThrowIfResynchronizable()
|
||||
{
|
||||
if (IsResynchronizable())
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV");
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv)
|
||||
{
|
||||
if (!iv && IVRequirement() == UNPREDICTABLE_RANDOM_IV)
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV");
|
||||
}
|
||||
|
||||
size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size)
|
||||
{
|
||||
if (size < 0)
|
||||
return IVSize();
|
||||
else if ((size_t)size < MinIVLength())
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength()));
|
||||
else if ((size_t)size > MaxIVLength())
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength()));
|
||||
else
|
||||
return size;
|
||||
}
|
||||
|
||||
const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size)
|
||||
{
|
||||
ConstByteArrayParameter ivWithLength;
|
||||
const byte *iv;
|
||||
bool found = false;
|
||||
|
||||
try {found = params.GetValue(Name::IV(), ivWithLength);}
|
||||
catch (const NameValuePairs::ValueTypeMismatch &) {}
|
||||
|
||||
if (found)
|
||||
{
|
||||
iv = ivWithLength.begin();
|
||||
ThrowIfInvalidIV(iv);
|
||||
size = ThrowIfInvalidIVLength((int)ivWithLength.size());
|
||||
return iv;
|
||||
}
|
||||
else if (params.GetValue(Name::IV(), iv))
|
||||
{
|
||||
ThrowIfInvalidIV(iv);
|
||||
size = IVSize();
|
||||
return iv;
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowIfResynchronizable();
|
||||
size = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV)
|
||||
{
|
||||
rng.GenerateBlock(IV, IVSize());
|
||||
}
|
||||
|
||||
size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
|
||||
{
|
||||
size_t blockSize = BlockSize();
|
||||
size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize;
|
||||
size_t xorIncrement = xorBlocks ? blockSize : 0;
|
||||
size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize;
|
||||
|
||||
if (flags & BT_ReverseDirection)
|
||||
{
|
||||
assert(length % blockSize == 0);
|
||||
inBlocks += length - blockSize;
|
||||
xorBlocks += length - blockSize;
|
||||
outBlocks += length - blockSize;
|
||||
inIncrement = 0-inIncrement;
|
||||
xorIncrement = 0-xorIncrement;
|
||||
outIncrement = 0-outIncrement;
|
||||
}
|
||||
|
||||
while (length >= blockSize)
|
||||
{
|
||||
if (flags & BT_XorInput)
|
||||
{
|
||||
xorbuf(outBlocks, xorBlocks, inBlocks, blockSize);
|
||||
ProcessBlock(outBlocks);
|
||||
}
|
||||
else
|
||||
ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
|
||||
if (flags & BT_InBlockIsCounter)
|
||||
const_cast<byte *>(inBlocks)[blockSize-1]++;
|
||||
inBlocks += inIncrement;
|
||||
outBlocks += outIncrement;
|
||||
xorBlocks += xorIncrement;
|
||||
length -= blockSize;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned int BlockTransformation::OptimalDataAlignment() const
|
||||
{
|
||||
return GetAlignmentOf<word32>();
|
||||
}
|
||||
|
||||
unsigned int StreamTransformation::OptimalDataAlignment() const
|
||||
{
|
||||
return GetAlignmentOf<word32>();
|
||||
}
|
||||
|
||||
unsigned int HashTransformation::OptimalDataAlignment() const
|
||||
{
|
||||
return GetAlignmentOf<word32>();
|
||||
}
|
||||
|
||||
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
assert(MinLastBlockSize() == 0); // this function should be overriden otherwise
|
||||
|
||||
if (length == MandatoryBlockSize())
|
||||
ProcessData(outString, inString, length);
|
||||
else if (length != 0)
|
||||
throw NotImplemented(AlgorithmName() + ": this object does't support a special last block");
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
|
||||
{
|
||||
if (headerLength > MaxHeaderLength())
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
|
||||
|
||||
if (messageLength > MaxMessageLength())
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength()));
|
||||
|
||||
if (footerLength > MaxFooterLength())
|
||||
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
|
||||
|
||||
UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength);
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipher::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength)
|
||||
{
|
||||
Resynchronize(iv, ivLength);
|
||||
SpecifyDataLengths(headerLength, messageLength);
|
||||
Update(header, headerLength);
|
||||
ProcessString(ciphertext, message, messageLength);
|
||||
TruncatedFinal(mac, macSize);
|
||||
}
|
||||
|
||||
bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength)
|
||||
{
|
||||
Resynchronize(iv, ivLength);
|
||||
SpecifyDataLengths(headerLength, ciphertextLength);
|
||||
Update(header, headerLength);
|
||||
ProcessString(message, ciphertext, ciphertextLength);
|
||||
return TruncatedVerify(mac, macLength);
|
||||
}
|
||||
|
||||
unsigned int RandomNumberGenerator::GenerateBit()
|
||||
{
|
||||
return GenerateByte() & 1;
|
||||
}
|
||||
|
||||
byte RandomNumberGenerator::GenerateByte()
|
||||
{
|
||||
byte b;
|
||||
GenerateBlock(&b, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
|
||||
{
|
||||
word32 range = max-min;
|
||||
const int maxBits = BitPrecision(range);
|
||||
|
||||
word32 value;
|
||||
|
||||
do
|
||||
{
|
||||
GenerateBlock((byte *)&value, sizeof(value));
|
||||
value = Crop(value, maxBits);
|
||||
} while (value > range);
|
||||
|
||||
return value+min;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::GenerateBlock(byte *output, size_t size)
|
||||
{
|
||||
ArraySink s(output, size);
|
||||
GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size);
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::DiscardBytes(size_t n)
|
||||
{
|
||||
GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n);
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
|
||||
{
|
||||
FixedSizeSecBlock<byte, 256> buffer;
|
||||
while (length)
|
||||
{
|
||||
size_t len = UnsignedMin(buffer.size(), length);
|
||||
GenerateBlock(buffer, len);
|
||||
target.ChannelPut(channel, buffer, len);
|
||||
length -= len;
|
||||
}
|
||||
}
|
||||
|
||||
//! see NullRNG()
|
||||
class ClassNullRNG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "NullRNG";}
|
||||
void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");}
|
||||
};
|
||||
|
||||
RandomNumberGenerator & NullRNG()
|
||||
{
|
||||
static ClassNullRNG s_nullRNG;
|
||||
return s_nullRNG;
|
||||
}
|
||||
|
||||
bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLength)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(digestLength);
|
||||
SecByteBlock digest(digestLength);
|
||||
TruncatedFinal(digest, digestLength);
|
||||
return VerifyBufsEqual(digest, digestIn, digestLength);
|
||||
}
|
||||
|
||||
void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const
|
||||
{
|
||||
if (size > DigestSize())
|
||||
throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
|
||||
{
|
||||
const BufferedTransformation *t = AttachedTransformation();
|
||||
return t ? t->GetMaxWaitObjectCount() : 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
BufferedTransformation *t = AttachedTransformation();
|
||||
if (t)
|
||||
t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here
|
||||
}
|
||||
|
||||
void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
IsolatedInitialize(parameters);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
return IsolatedFlush(hardFlush, blocking);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
return IsolatedMessageSeriesEnd(blocking);
|
||||
}
|
||||
|
||||
byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size)
|
||||
{
|
||||
if (channel.empty())
|
||||
return CreatePutSpace(size);
|
||||
else
|
||||
throw NoChannelSupport(AlgorithmName());
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return Put2(begin, length, messageEnd, blocking);
|
||||
else
|
||||
throw NoChannelSupport(AlgorithmName());
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return PutModifiable2(begin, length, messageEnd, blocking);
|
||||
else
|
||||
return ChannelPut2(channel, begin, length, messageEnd, blocking);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return Flush(completeFlush, propagation, blocking);
|
||||
else
|
||||
throw NoChannelSupport(AlgorithmName());
|
||||
}
|
||||
|
||||
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return MessageSeriesEnd(propagation, blocking);
|
||||
else
|
||||
throw NoChannelSupport(AlgorithmName());
|
||||
}
|
||||
|
||||
lword BufferedTransformation::MaxRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->MaxRetrievable();
|
||||
else
|
||||
return CopyTo(TheBitBucket());
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->AnyRetrievable();
|
||||
else
|
||||
{
|
||||
byte b;
|
||||
return Peek(b) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::Get(byte &outByte)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Get(outByte);
|
||||
else
|
||||
return Get(&outByte, 1);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::Get(byte *outString, size_t getMax)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Get(outString, getMax);
|
||||
else
|
||||
{
|
||||
ArraySink arraySink(outString, getMax);
|
||||
return (size_t)TransferTo(arraySink, getMax);
|
||||
}
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::Peek(byte &outByte) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Peek(outByte);
|
||||
else
|
||||
return Peek(&outByte, 1);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Peek(outString, peekMax);
|
||||
else
|
||||
{
|
||||
ArraySink arraySink(outString, peekMax);
|
||||
return (size_t)CopyTo(arraySink, peekMax);
|
||||
}
|
||||
}
|
||||
|
||||
lword BufferedTransformation::Skip(lword skipMax)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Skip(skipMax);
|
||||
else
|
||||
return TransferTo(TheBitBucket(), skipMax);
|
||||
}
|
||||
|
||||
lword BufferedTransformation::TotalBytesRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TotalBytesRetrievable();
|
||||
else
|
||||
return MaxRetrievable();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::NumberOfMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->NumberOfMessages();
|
||||
else
|
||||
return CopyMessagesTo(TheBitBucket());
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->AnyMessages();
|
||||
else
|
||||
return NumberOfMessages() != 0;
|
||||
}
|
||||
|
||||
bool BufferedTransformation::GetNextMessage()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->GetNextMessage();
|
||||
else
|
||||
{
|
||||
assert(!AnyMessages());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->SkipMessages(count);
|
||||
else
|
||||
return TransferMessagesTo(TheBitBucket(), count);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
|
||||
else
|
||||
{
|
||||
unsigned int maxMessages = messageCount;
|
||||
for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
|
||||
{
|
||||
size_t blockedBytes;
|
||||
lword transferredBytes;
|
||||
|
||||
while (AnyRetrievable())
|
||||
{
|
||||
transferredBytes = LWORD_MAX;
|
||||
blockedBytes = TransferTo2(target, transferredBytes, channel, blocking);
|
||||
if (blockedBytes > 0)
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
|
||||
return 1;
|
||||
|
||||
bool result = GetNextMessage();
|
||||
assert(result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->CopyMessagesTo(target, count, channel);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::SkipAll()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SkipAll();
|
||||
else
|
||||
{
|
||||
while (SkipMessages()) {}
|
||||
while (Skip()) {}
|
||||
}
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
|
||||
else
|
||||
{
|
||||
assert(!NumberOfMessageSeries());
|
||||
|
||||
unsigned int messageCount;
|
||||
do
|
||||
{
|
||||
messageCount = UINT_MAX;
|
||||
size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
}
|
||||
while (messageCount != 0);
|
||||
|
||||
lword byteCount;
|
||||
do
|
||||
{
|
||||
byteCount = ULONG_MAX;
|
||||
size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
}
|
||||
while (byteCount != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->CopyAllTo(target, channel);
|
||||
else
|
||||
{
|
||||
assert(!NumberOfMessageSeries());
|
||||
while (CopyMessagesTo(target, UINT_MAX, channel)) {}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SetRetrievalChannel(channel);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
PutWord(false, order, m_buf, value);
|
||||
return ChannelPut(channel, m_buf, 2, blocking);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
PutWord(false, order, m_buf, value);
|
||||
return ChannelPut(channel, m_buf, 4, blocking);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking);
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const
|
||||
{
|
||||
byte buf[2] = {0, 0};
|
||||
size_t len = Peek(buf, 2);
|
||||
|
||||
if (order)
|
||||
value = (buf[0] << 8) | buf[1];
|
||||
else
|
||||
value = (buf[1] << 8) | buf[0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const
|
||||
{
|
||||
byte buf[4] = {0, 0, 0, 0};
|
||||
size_t len = Peek(buf, 4);
|
||||
|
||||
if (order)
|
||||
value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3];
|
||||
else
|
||||
value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order)
|
||||
{
|
||||
return (size_t)Skip(PeekWord16(value, order));
|
||||
}
|
||||
|
||||
size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
|
||||
{
|
||||
return (size_t)Skip(PeekWord32(value, order));
|
||||
}
|
||||
|
||||
void BufferedTransformation::Attach(BufferedTransformation *newOut)
|
||||
{
|
||||
if (AttachedTransformation() && AttachedTransformation()->Attachable())
|
||||
AttachedTransformation()->Attach(newOut);
|
||||
else
|
||||
Detach(newOut);
|
||||
}
|
||||
|
||||
void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
|
||||
{
|
||||
GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
|
||||
}
|
||||
|
||||
class PK_DefaultEncryptionFilter : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters)
|
||||
: m_rng(rng), m_encryptor(encryptor), m_parameters(parameters)
|
||||
{
|
||||
Detach(attachment);
|
||||
}
|
||||
|
||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_plaintextQueue.Put(inString, length);
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
{
|
||||
size_t plaintextLength;
|
||||
if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength))
|
||||
throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long");
|
||||
size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
|
||||
|
||||
SecByteBlock plaintext(plaintextLength);
|
||||
m_plaintextQueue.Get(plaintext, plaintextLength);
|
||||
m_ciphertext.resize(ciphertextLength);
|
||||
m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters);
|
||||
}
|
||||
|
||||
FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd);
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Encryptor &m_encryptor;
|
||||
const NameValuePairs &m_parameters;
|
||||
ByteQueue m_plaintextQueue;
|
||||
SecByteBlock m_ciphertext;
|
||||
};
|
||||
|
||||
BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const
|
||||
{
|
||||
return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters);
|
||||
}
|
||||
|
||||
class PK_DefaultDecryptionFilter : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters)
|
||||
: m_rng(rng), m_decryptor(decryptor), m_parameters(parameters)
|
||||
{
|
||||
Detach(attachment);
|
||||
}
|
||||
|
||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_ciphertextQueue.Put(inString, length);
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
{
|
||||
size_t ciphertextLength;
|
||||
if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength))
|
||||
throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long");
|
||||
size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
|
||||
|
||||
SecByteBlock ciphertext(ciphertextLength);
|
||||
m_ciphertextQueue.Get(ciphertext, ciphertextLength);
|
||||
m_plaintext.resize(maxPlaintextLength);
|
||||
m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters);
|
||||
if (!m_result.isValidCoding)
|
||||
throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
|
||||
}
|
||||
|
||||
FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd);
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Decryptor &m_decryptor;
|
||||
const NameValuePairs &m_parameters;
|
||||
ByteQueue m_ciphertextQueue;
|
||||
SecByteBlock m_plaintext;
|
||||
DecodingResult m_result;
|
||||
};
|
||||
|
||||
BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const
|
||||
{
|
||||
return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters);
|
||||
}
|
||||
|
||||
size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
||||
return SignAndRestart(rng, *m, signature, false);
|
||||
}
|
||||
|
||||
size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
|
||||
m->Update(message, messageLen);
|
||||
return SignAndRestart(rng, *m, signature, false);
|
||||
}
|
||||
|
||||
size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength,
|
||||
const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
|
||||
InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength);
|
||||
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
|
||||
return SignAndRestart(rng, *m, signature, false);
|
||||
}
|
||||
|
||||
bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
||||
return VerifyAndRestart(*m);
|
||||
}
|
||||
|
||||
bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLength) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
|
||||
InputSignature(*m, signature, signatureLength);
|
||||
m->Update(message, messageLen);
|
||||
return VerifyAndRestart(*m);
|
||||
}
|
||||
|
||||
DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
||||
return RecoverAndRestart(recoveredMessage, *m);
|
||||
}
|
||||
|
||||
DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage,
|
||||
const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength,
|
||||
const byte *signature, size_t signatureLength) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
|
||||
InputSignature(*m, signature, signatureLength);
|
||||
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
|
||||
return RecoverAndRestart(recoveredMessage, *m);
|
||||
}
|
||||
|
||||
void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
||||
{
|
||||
GeneratePrivateKey(rng, privateKey);
|
||||
GeneratePublicKey(rng, privateKey, publicKey);
|
||||
}
|
||||
|
||||
void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
||||
{
|
||||
GenerateStaticPrivateKey(rng, privateKey);
|
||||
GenerateStaticPublicKey(rng, privateKey, publicKey);
|
||||
}
|
||||
|
||||
void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
||||
{
|
||||
GenerateEphemeralPrivateKey(rng, privateKey);
|
||||
GenerateEphemeralPublicKey(rng, privateKey, publicKey);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,258 +0,0 @@
|
||||
// default.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "default.h"
|
||||
#include "queue.h"
|
||||
#include <time.h>
|
||||
#include <memory>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
static const unsigned int MASH_ITERATIONS = 200;
|
||||
static const unsigned int SALTLENGTH = 8;
|
||||
static const unsigned int BLOCKSIZE = Default_BlockCipher::Encryption::BLOCKSIZE;
|
||||
static const unsigned int KEYLENGTH = Default_BlockCipher::Encryption::DEFAULT_KEYLENGTH;
|
||||
|
||||
// The purpose of this function Mash() is to take an arbitrary length input
|
||||
// string and *deterministicly* produce an arbitrary length output string such
|
||||
// that (1) it looks random, (2) no information about the input is
|
||||
// deducible from it, and (3) it contains as much entropy as it can hold, or
|
||||
// the amount of entropy in the input string, whichever is smaller.
|
||||
|
||||
static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
|
||||
{
|
||||
if (BytePrecision(outLen) > 2)
|
||||
throw InvalidArgument("Mash: output legnth too large");
|
||||
|
||||
size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
|
||||
byte b[2];
|
||||
SecByteBlock buf(bufSize);
|
||||
SecByteBlock outBuf(bufSize);
|
||||
DefaultHashModule hash;
|
||||
|
||||
unsigned int i;
|
||||
for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
|
||||
{
|
||||
b[0] = (byte) (i >> 8);
|
||||
b[1] = (byte) i;
|
||||
hash.Update(b, 2);
|
||||
hash.Update(in, inLen);
|
||||
hash.Final(outBuf+i);
|
||||
}
|
||||
|
||||
while (iterations-- > 1)
|
||||
{
|
||||
memcpy(buf, outBuf, bufSize);
|
||||
for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
|
||||
{
|
||||
b[0] = (byte) (i >> 8);
|
||||
b[1] = (byte) i;
|
||||
hash.Update(b, 2);
|
||||
hash.Update(buf, bufSize);
|
||||
hash.Final(outBuf+i);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(out, outBuf, outLen);
|
||||
}
|
||||
|
||||
static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, byte *key, byte *IV)
|
||||
{
|
||||
SecByteBlock temp(passphraseLength+saltLength);
|
||||
memcpy(temp, passphrase, passphraseLength);
|
||||
memcpy(temp+passphraseLength, salt, saltLength);
|
||||
SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
|
||||
Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
|
||||
memcpy(key, keyIV, KEYLENGTH);
|
||||
memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment)
|
||||
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase))
|
||||
{
|
||||
}
|
||||
|
||||
DefaultEncryptor::DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
|
||||
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DefaultEncryptor::FirstPut(const byte *)
|
||||
{
|
||||
// VC60 workaround: __LINE__ expansion bug
|
||||
CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1);
|
||||
CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2);
|
||||
|
||||
SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
|
||||
DefaultHashModule hash;
|
||||
|
||||
// use hash(passphrase | time | clock) as salt
|
||||
hash.Update(m_passphrase, m_passphrase.size());
|
||||
time_t t=time(0);
|
||||
hash.Update((byte *)&t, sizeof(t));
|
||||
clock_t c=clock();
|
||||
hash.Update((byte *)&c, sizeof(c));
|
||||
hash.Final(salt);
|
||||
|
||||
// use hash(passphrase | salt) as key check
|
||||
hash.Update(m_passphrase, m_passphrase.size());
|
||||
hash.Update(salt, SALTLENGTH);
|
||||
hash.Final(keyCheck);
|
||||
|
||||
AttachedTransformation()->Put(salt, SALTLENGTH);
|
||||
|
||||
// mash passphrase and salt together into key and IV
|
||||
SecByteBlock key(KEYLENGTH);
|
||||
SecByteBlock IV(BLOCKSIZE);
|
||||
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
|
||||
|
||||
m_cipher.SetKeyWithIV(key, key.size(), IV);
|
||||
SetFilter(new StreamTransformationFilter(m_cipher));
|
||||
|
||||
m_filter->Put(keyCheck, BLOCKSIZE);
|
||||
}
|
||||
|
||||
void DefaultEncryptor::LastPut(const byte *inString, size_t length)
|
||||
{
|
||||
m_filter->MessageEnd();
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
|
||||
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
|
||||
, m_state(WAITING_FOR_KEYCHECK)
|
||||
, m_passphrase((const byte *)p, strlen(p))
|
||||
, m_throwException(throwException)
|
||||
{
|
||||
}
|
||||
|
||||
DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
|
||||
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
|
||||
, m_state(WAITING_FOR_KEYCHECK)
|
||||
, m_passphrase(passphrase, passphraseLength)
|
||||
, m_throwException(throwException)
|
||||
{
|
||||
}
|
||||
|
||||
void DefaultDecryptor::FirstPut(const byte *inString)
|
||||
{
|
||||
CheckKey(inString, inString+SALTLENGTH);
|
||||
}
|
||||
|
||||
void DefaultDecryptor::LastPut(const byte *inString, size_t length)
|
||||
{
|
||||
if (m_filter.get() == NULL)
|
||||
{
|
||||
m_state = KEY_BAD;
|
||||
if (m_throwException)
|
||||
throw KeyBadErr();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filter->MessageEnd();
|
||||
m_state = WAITING_FOR_KEYCHECK;
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
|
||||
{
|
||||
SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
|
||||
|
||||
DefaultHashModule hash;
|
||||
hash.Update(m_passphrase, m_passphrase.size());
|
||||
hash.Update(salt, SALTLENGTH);
|
||||
hash.Final(check);
|
||||
|
||||
SecByteBlock key(KEYLENGTH);
|
||||
SecByteBlock IV(BLOCKSIZE);
|
||||
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
|
||||
|
||||
m_cipher.SetKeyWithIV(key, key.size(), IV);
|
||||
std::auto_ptr<StreamTransformationFilter> decryptor(new StreamTransformationFilter(m_cipher));
|
||||
|
||||
decryptor->Put(keyCheck, BLOCKSIZE);
|
||||
decryptor->ForceNextPut();
|
||||
decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
|
||||
|
||||
SetFilter(decryptor.release());
|
||||
|
||||
if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
|
||||
{
|
||||
m_state = KEY_BAD;
|
||||
if (m_throwException)
|
||||
throw KeyBadErr();
|
||||
}
|
||||
else
|
||||
m_state = KEY_GOOD;
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
|
||||
{
|
||||
size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
|
||||
SecByteBlock macKey(macKeyLength);
|
||||
// since the MAC is encrypted there is no reason to mash the passphrase for many iterations
|
||||
Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
|
||||
return new DefaultMAC(macKey, macKeyLength);
|
||||
}
|
||||
|
||||
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment)
|
||||
: ProxyFilter(NULL, 0, 0, attachment)
|
||||
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
|
||||
{
|
||||
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
|
||||
}
|
||||
|
||||
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
|
||||
: ProxyFilter(NULL, 0, 0, attachment)
|
||||
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
|
||||
{
|
||||
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
|
||||
}
|
||||
|
||||
void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
|
||||
{
|
||||
m_filter->MessageEnd();
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
|
||||
: ProxyFilter(NULL, 0, 0, attachment)
|
||||
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
|
||||
, m_throwException(throwException)
|
||||
{
|
||||
SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
|
||||
}
|
||||
|
||||
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
|
||||
: ProxyFilter(NULL, 0, 0, attachment)
|
||||
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
|
||||
, m_throwException(throwException)
|
||||
{
|
||||
SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
|
||||
}
|
||||
|
||||
DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
|
||||
{
|
||||
return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
|
||||
}
|
||||
|
||||
bool DefaultDecryptorWithMAC::CheckLastMAC() const
|
||||
{
|
||||
return m_hashVerifier->GetLastResult();
|
||||
}
|
||||
|
||||
void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
|
||||
{
|
||||
m_filter->MessageEnd();
|
||||
if (m_throwException && !CheckLastMAC())
|
||||
throw MACBadErr();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -1,104 +0,0 @@
|
||||
#ifndef CRYPTOPP_DEFAULT_H
|
||||
#define CRYPTOPP_DEFAULT_H
|
||||
|
||||
#include "sha.h"
|
||||
#include "hmac.h"
|
||||
#include "des.h"
|
||||
#include "filters.h"
|
||||
#include "modes.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
typedef DES_EDE2 Default_BlockCipher;
|
||||
typedef SHA DefaultHashModule;
|
||||
typedef HMAC<DefaultHashModule> DefaultMAC;
|
||||
|
||||
//! Password-Based Encryptor using DES-EDE2
|
||||
class DefaultEncryptor : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment = NULL);
|
||||
DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *);
|
||||
void LastPut(const byte *inString, size_t length);
|
||||
|
||||
private:
|
||||
SecByteBlock m_passphrase;
|
||||
CBC_Mode<Default_BlockCipher>::Encryption m_cipher;
|
||||
};
|
||||
|
||||
//! Password-Based Decryptor using DES-EDE2
|
||||
class DefaultDecryptor : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string &s)
|
||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, s) {}
|
||||
};
|
||||
class KeyBadErr : public Err {public: KeyBadErr() : Err("DefaultDecryptor: cannot decrypt message with this passphrase") {}};
|
||||
|
||||
enum State {WAITING_FOR_KEYCHECK, KEY_GOOD, KEY_BAD};
|
||||
State CurrentState() const {return m_state;}
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString);
|
||||
void LastPut(const byte *inString, size_t length);
|
||||
|
||||
State m_state;
|
||||
|
||||
private:
|
||||
void CheckKey(const byte *salt, const byte *keyCheck);
|
||||
|
||||
SecByteBlock m_passphrase;
|
||||
CBC_Mode<Default_BlockCipher>::Decryption m_cipher;
|
||||
member_ptr<FilterWithBufferedInput> m_decryptor;
|
||||
bool m_throwException;
|
||||
};
|
||||
|
||||
//! Password-Based Encryptor using DES-EDE2 and HMAC/SHA-1
|
||||
class DefaultEncryptorWithMAC : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL);
|
||||
DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL);
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString) {}
|
||||
void LastPut(const byte *inString, size_t length);
|
||||
|
||||
private:
|
||||
member_ptr<DefaultMAC> m_mac;
|
||||
};
|
||||
|
||||
//! Password-Based Decryptor using DES-EDE2 and HMAC/SHA-1
|
||||
class DefaultDecryptorWithMAC : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
class MACBadErr : public DefaultDecryptor::Err {public: MACBadErr() : DefaultDecryptor::Err("DefaultDecryptorWithMAC: MAC check failed") {}};
|
||||
|
||||
DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
|
||||
DefaultDecryptor::State CurrentState() const;
|
||||
bool CheckLastMAC() const;
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString) {}
|
||||
void LastPut(const byte *inString, size_t length);
|
||||
|
||||
private:
|
||||
member_ptr<DefaultMAC> m_mac;
|
||||
HashVerifier *m_hashVerifier;
|
||||
bool m_throwException;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -1,449 +0,0 @@
|
||||
// des.cpp - modified by Wei Dai from Phil Karn's des.c
|
||||
// The original code and all modifications are in the public domain.
|
||||
|
||||
/*
|
||||
* This is a major rewrite of my old public domain DES code written
|
||||
* circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977
|
||||
* public domain code. I pretty much kept my key scheduling code, but
|
||||
* the actual encrypt/decrypt routines are taken from from Richard
|
||||
* Outerbridge's DES code as printed in Schneier's "Applied Cryptography."
|
||||
*
|
||||
* This code is in the public domain. I would appreciate bug reports and
|
||||
* enhancements.
|
||||
*
|
||||
* Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994.
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
#include "misc.h"
|
||||
#include "des.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
||||
|
||||
// Richard Outerbridge's initial permutation algorithm
|
||||
/*
|
||||
inline void IPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
work = ((left >> 4) ^ right) & 0x0f0f0f0f;
|
||||
right ^= work;
|
||||
left ^= work << 4;
|
||||
work = ((left >> 16) ^ right) & 0xffff;
|
||||
right ^= work;
|
||||
left ^= work << 16;
|
||||
work = ((right >> 2) ^ left) & 0x33333333;
|
||||
left ^= work;
|
||||
right ^= (work << 2);
|
||||
work = ((right >> 8) ^ left) & 0xff00ff;
|
||||
left ^= work;
|
||||
right ^= (work << 8);
|
||||
right = rotl(right, 1);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
left ^= work;
|
||||
right ^= work;
|
||||
left = rotl(left, 1);
|
||||
}
|
||||
inline void FPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
right = rotr(right, 1);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
left ^= work;
|
||||
right ^= work;
|
||||
left = rotr(left, 1);
|
||||
work = ((left >> 8) ^ right) & 0xff00ff;
|
||||
right ^= work;
|
||||
left ^= work << 8;
|
||||
work = ((left >> 2) ^ right) & 0x33333333;
|
||||
right ^= work;
|
||||
left ^= work << 2;
|
||||
work = ((right >> 16) ^ left) & 0xffff;
|
||||
left ^= work;
|
||||
right ^= work << 16;
|
||||
work = ((right >> 4) ^ left) & 0x0f0f0f0f;
|
||||
left ^= work;
|
||||
right ^= work << 4;
|
||||
}
|
||||
*/
|
||||
|
||||
// Wei Dai's modification to Richard Outerbridge's initial permutation
|
||||
// algorithm, this one is faster if you have access to rotate instructions
|
||||
// (like in MSVC)
|
||||
static inline void IPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
right = rotlFixed(right, 4U);
|
||||
work = (left ^ right) & 0xf0f0f0f0;
|
||||
left ^= work;
|
||||
right = rotrFixed(right^work, 20U);
|
||||
work = (left ^ right) & 0xffff0000;
|
||||
left ^= work;
|
||||
right = rotrFixed(right^work, 18U);
|
||||
work = (left ^ right) & 0x33333333;
|
||||
left ^= work;
|
||||
right = rotrFixed(right^work, 6U);
|
||||
work = (left ^ right) & 0x00ff00ff;
|
||||
left ^= work;
|
||||
right = rotlFixed(right^work, 9U);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
left = rotlFixed(left^work, 1U);
|
||||
right ^= work;
|
||||
}
|
||||
|
||||
static inline void FPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
right = rotrFixed(right, 1U);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
right ^= work;
|
||||
left = rotrFixed(left^work, 9U);
|
||||
work = (left ^ right) & 0x00ff00ff;
|
||||
right ^= work;
|
||||
left = rotlFixed(left^work, 6U);
|
||||
work = (left ^ right) & 0x33333333;
|
||||
right ^= work;
|
||||
left = rotlFixed(left^work, 18U);
|
||||
work = (left ^ right) & 0xffff0000;
|
||||
right ^= work;
|
||||
left = rotlFixed(left^work, 20U);
|
||||
work = (left ^ right) & 0xf0f0f0f0;
|
||||
right ^= work;
|
||||
left = rotrFixed(left^work, 4U);
|
||||
}
|
||||
|
||||
void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
RawSetKey(GetCipherDirection(), userKey);
|
||||
}
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
/* Tables defined in the Data Encryption Standard documents
|
||||
* Three of these tables, the initial permutation, the final
|
||||
* permutation and the expansion operator, are regular enough that
|
||||
* for speed, we hard-code them. They're here for reference only.
|
||||
* Also, the S and P boxes are used by a separate program, gensp.c,
|
||||
* to build the combined SP box, Spbox[]. They're also here just
|
||||
* for reference.
|
||||
*/
|
||||
#ifdef notdef
|
||||
/* initial permutation IP */
|
||||
static byte ip[] = {
|
||||
58, 50, 42, 34, 26, 18, 10, 2,
|
||||
60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6,
|
||||
64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1,
|
||||
59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5,
|
||||
63, 55, 47, 39, 31, 23, 15, 7
|
||||
};
|
||||
|
||||
/* final permutation IP^-1 */
|
||||
static byte fp[] = {
|
||||
40, 8, 48, 16, 56, 24, 64, 32,
|
||||
39, 7, 47, 15, 55, 23, 63, 31,
|
||||
38, 6, 46, 14, 54, 22, 62, 30,
|
||||
37, 5, 45, 13, 53, 21, 61, 29,
|
||||
36, 4, 44, 12, 52, 20, 60, 28,
|
||||
35, 3, 43, 11, 51, 19, 59, 27,
|
||||
34, 2, 42, 10, 50, 18, 58, 26,
|
||||
33, 1, 41, 9, 49, 17, 57, 25
|
||||
};
|
||||
/* expansion operation matrix */
|
||||
static byte ei[] = {
|
||||
32, 1, 2, 3, 4, 5,
|
||||
4, 5, 6, 7, 8, 9,
|
||||
8, 9, 10, 11, 12, 13,
|
||||
12, 13, 14, 15, 16, 17,
|
||||
16, 17, 18, 19, 20, 21,
|
||||
20, 21, 22, 23, 24, 25,
|
||||
24, 25, 26, 27, 28, 29,
|
||||
28, 29, 30, 31, 32, 1
|
||||
};
|
||||
/* The (in)famous S-boxes */
|
||||
static byte sbox[8][64] = {
|
||||
/* S1 */
|
||||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
|
||||
|
||||
/* S2 */
|
||||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
|
||||
|
||||
/* S3 */
|
||||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
|
||||
|
||||
/* S4 */
|
||||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
|
||||
|
||||
/* S5 */
|
||||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
|
||||
|
||||
/* S6 */
|
||||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
|
||||
|
||||
/* S7 */
|
||||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
|
||||
|
||||
/* S8 */
|
||||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||
};
|
||||
|
||||
/* 32-bit permutation function P used on the output of the S-boxes */
|
||||
static byte p32i[] = {
|
||||
16, 7, 20, 21,
|
||||
29, 12, 28, 17,
|
||||
1, 15, 23, 26,
|
||||
5, 18, 31, 10,
|
||||
2, 8, 24, 14,
|
||||
32, 27, 3, 9,
|
||||
19, 13, 30, 6,
|
||||
22, 11, 4, 25
|
||||
};
|
||||
#endif
|
||||
|
||||
/* permuted choice table (key) */
|
||||
static const byte pc1[] = {
|
||||
57, 49, 41, 33, 25, 17, 9,
|
||||
1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27,
|
||||
19, 11, 3, 60, 52, 44, 36,
|
||||
|
||||
63, 55, 47, 39, 31, 23, 15,
|
||||
7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29,
|
||||
21, 13, 5, 28, 20, 12, 4
|
||||
};
|
||||
|
||||
/* number left rotations of pc1 */
|
||||
static const byte totrot[] = {
|
||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
|
||||
};
|
||||
|
||||
/* permuted choice key (table) */
|
||||
static const byte pc2[] = {
|
||||
14, 17, 11, 24, 1, 5,
|
||||
3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8,
|
||||
16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55,
|
||||
30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53,
|
||||
46, 42, 50, 36, 29, 32
|
||||
};
|
||||
|
||||
/* End of DES-defined tables */
|
||||
|
||||
/* bit 0 is left-most in byte */
|
||||
static const int bytebit[] = {
|
||||
0200,0100,040,020,010,04,02,01
|
||||
};
|
||||
|
||||
/* Set key (initialize key schedule array) */
|
||||
void RawDES::RawSetKey(CipherDir dir, const byte *key)
|
||||
{
|
||||
SecByteBlock buffer(56+56+8);
|
||||
byte *const pc1m=buffer; /* place to modify pc1 into */
|
||||
byte *const pcr=pc1m+56; /* place to rotate pc1 into */
|
||||
byte *const ks=pcr+56;
|
||||
register int i,j,l;
|
||||
int m;
|
||||
|
||||
for (j=0; j<56; j++) { /* convert pc1 to bits of key */
|
||||
l=pc1[j]-1; /* integer bit location */
|
||||
m = l & 07; /* find bit */
|
||||
pc1m[j]=(key[l>>3] & /* find which key byte l is in */
|
||||
bytebit[m]) /* and which bit of that byte */
|
||||
? 1 : 0; /* and store 1-bit result */
|
||||
}
|
||||
for (i=0; i<16; i++) { /* key chunk for each iteration */
|
||||
memset(ks,0,8); /* Clear key schedule */
|
||||
for (j=0; j<56; j++) /* rotate pc1 the right amount */
|
||||
pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
|
||||
/* rotate left and right halves independently */
|
||||
for (j=0; j<48; j++){ /* select bits individually */
|
||||
/* check bit that goes to ks[j] */
|
||||
if (pcr[pc2[j]-1]){
|
||||
/* mask it in if it's there */
|
||||
l= j % 6;
|
||||
ks[j/6] |= bytebit[l] >> 2;
|
||||
}
|
||||
}
|
||||
/* Now convert to odd/even interleaved form for use in F */
|
||||
k[2*i] = ((word32)ks[0] << 24)
|
||||
| ((word32)ks[2] << 16)
|
||||
| ((word32)ks[4] << 8)
|
||||
| ((word32)ks[6]);
|
||||
k[2*i+1] = ((word32)ks[1] << 24)
|
||||
| ((word32)ks[3] << 16)
|
||||
| ((word32)ks[5] << 8)
|
||||
| ((word32)ks[7]);
|
||||
}
|
||||
|
||||
if (dir==DECRYPTION) // reverse key schedule order
|
||||
for (i=0; i<16; i+=2)
|
||||
{
|
||||
std::swap(k[i], k[32-2-i]);
|
||||
std::swap(k[i+1], k[32-1-i]);
|
||||
}
|
||||
}
|
||||
|
||||
void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const
|
||||
{
|
||||
word32 l = l_, r = r_;
|
||||
const word32 *kptr=k;
|
||||
|
||||
for (unsigned i=0; i<8; i++)
|
||||
{
|
||||
word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
|
||||
l ^= Spbox[6][(work) & 0x3f]
|
||||
^ Spbox[4][(work >> 8) & 0x3f]
|
||||
^ Spbox[2][(work >> 16) & 0x3f]
|
||||
^ Spbox[0][(work >> 24) & 0x3f];
|
||||
work = r ^ kptr[4*i+1];
|
||||
l ^= Spbox[7][(work) & 0x3f]
|
||||
^ Spbox[5][(work >> 8) & 0x3f]
|
||||
^ Spbox[3][(work >> 16) & 0x3f]
|
||||
^ Spbox[1][(work >> 24) & 0x3f];
|
||||
|
||||
work = rotrFixed(l, 4U) ^ kptr[4*i+2];
|
||||
r ^= Spbox[6][(work) & 0x3f]
|
||||
^ Spbox[4][(work >> 8) & 0x3f]
|
||||
^ Spbox[2][(work >> 16) & 0x3f]
|
||||
^ Spbox[0][(work >> 24) & 0x3f];
|
||||
work = l ^ kptr[4*i+3];
|
||||
r ^= Spbox[7][(work) & 0x3f]
|
||||
^ Spbox[5][(work >> 8) & 0x3f]
|
||||
^ Spbox[3][(work >> 16) & 0x3f]
|
||||
^ Spbox[1][(work >> 24) & 0x3f];
|
||||
}
|
||||
|
||||
l_ = l; r_ = r;
|
||||
}
|
||||
|
||||
void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
m_des1.RawSetKey(GetCipherDirection(), userKey);
|
||||
m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8);
|
||||
}
|
||||
|
||||
void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 l,r;
|
||||
Block::Get(inBlock)(l)(r);
|
||||
IPERM(l,r);
|
||||
m_des1.RawProcessBlock(l, r);
|
||||
m_des2.RawProcessBlock(r, l);
|
||||
m_des1.RawProcessBlock(l, r);
|
||||
FPERM(l,r);
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16));
|
||||
m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8);
|
||||
m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0));
|
||||
}
|
||||
|
||||
void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 l,r;
|
||||
Block::Get(inBlock)(l)(r);
|
||||
IPERM(l,r);
|
||||
m_des1.RawProcessBlock(l, r);
|
||||
m_des2.RawProcessBlock(r, l);
|
||||
m_des3.RawProcessBlock(l, r);
|
||||
FPERM(l,r);
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
#endif // #ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
static inline bool CheckParity(byte b)
|
||||
{
|
||||
unsigned int a = b ^ (b >> 4);
|
||||
return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
|
||||
}
|
||||
|
||||
bool DES::CheckKeyParityBits(const byte *key)
|
||||
{
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
if (!CheckParity(key[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DES::CorrectKeyParityBits(byte *key)
|
||||
{
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
if (!CheckParity(key[i]))
|
||||
key[i] ^= 1;
|
||||
}
|
||||
|
||||
// Encrypt or decrypt a block of data in ECB mode
|
||||
void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 l,r;
|
||||
Block::Get(inBlock)(l)(r);
|
||||
IPERM(l,r);
|
||||
RawProcessBlock(l, r);
|
||||
FPERM(l,r);
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
if (!m_des.get())
|
||||
m_des.reset(new DES::Encryption);
|
||||
|
||||
memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE);
|
||||
m_des->RawSetKey(GetCipherDirection(), key + 8);
|
||||
memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE);
|
||||
}
|
||||
|
||||
void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE);
|
||||
m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock);
|
||||
xorbuf(outBlock, m_x3, BLOCKSIZE);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -1,144 +0,0 @@
|
||||
#ifndef CRYPTOPP_DES_H
|
||||
#define CRYPTOPP_DES_H
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class CRYPTOPP_DLL RawDES
|
||||
{
|
||||
public:
|
||||
void RawSetKey(CipherDir direction, const byte *userKey);
|
||||
void RawProcessBlock(word32 &l, word32 &r) const;
|
||||
|
||||
protected:
|
||||
static const word32 Spbox[8][64];
|
||||
|
||||
FixedSizeSecBlock<word32, 32> k;
|
||||
};
|
||||
|
||||
//! _
|
||||
struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8>
|
||||
{
|
||||
// disable DES in DLL version by not exporting this function
|
||||
static const char * StaticAlgorithmName() {return "DES";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DES">DES</a>
|
||||
/*! The DES implementation in Crypto++ ignores the parity bits
|
||||
(the least significant bits of each byte) in the key. However
|
||||
you can use CheckKeyParityBits() and CorrectKeyParityBits() to
|
||||
check or correct the parity bits if you wish. */
|
||||
class DES : public DES_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_Info>, public RawDES
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
};
|
||||
|
||||
public:
|
||||
//! check DES key parity bits
|
||||
static bool CheckKeyParityBits(const byte *key);
|
||||
//! correct DES key parity bits
|
||||
static void CorrectKeyParityBits(byte *key);
|
||||
|
||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
//! _
|
||||
struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
|
||||
{
|
||||
CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE2</a>
|
||||
class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<DES_EDE2_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
|
||||
protected:
|
||||
RawDES m_des1, m_des2;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
|
||||
};
|
||||