diff options
206 files changed, 55024 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4ba81d --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# setup.py can generate these directories: +/dist/ +/build/ +/Doc/apidoc/ + +# Ignore these files: +*.py[co] +.DS_Store +MANIFEST + +# Autoconf +/aclocal.m4 +/buildenv +/autom4te.cache +/autoscan.log +/config.h +/config.log +/config.status +src/config.h +src/stamp-h1 + +# Python versions +/tools/py/ + +# Backup files +*~ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f8e4942 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,55 @@ +# PyCrypto .travis.yml file, for travis-ci.org testing. +# See https://travis-ci.org/dlitz/pycrypto for build status. +env: + - PYENV_VERSION=2.1.3 + - PYENV_VERSION=2.2.3 + - PYENV_VERSION=2.3.7 + - PYENV_VERSION=2.4.6 + - PYENV_VERSION=2.5.6 + - PYENV_VERSION=2.6.9 + - PYENV_VERSION=2.7.6 + - PYENV_VERSION=2.7.6 python_flags=-Qnew + - PYENV_VERSION=2.7.6 python_flags=-OO + - PYENV_VERSION=2.7.6 preconfigure_args=--without-gmp +# pip won't install on Python 3.0 (lack of collections.OrderedDict object?) +# - PYENV_VERSION=3.0.1 + - PYENV_VERSION=3.1.5 + - PYENV_VERSION=3.2.5 + - PYENV_VERSION=3.3.5 + - PYENV_VERSION=3.4.0 + - PYENV_VERSION=3.4.0 preconfigure_args=--without-gmp +# PyCrypto does not support PyPy yet. +# See https://github.com/dlitz/pycrypto/pull/59 +# - PYENV_VERSION=pypy-2.3.1 +# - PYENV_VERSION=pypy3-2.3.1 +language: python +before_install: + # Unexport variables + - declare +x preconfigure_args python_flags + # List local virtualenvs + - ls ~/virtualenv || true + # Show environment + - if [ "$TRAVIS_SECURE_ENV_VARS" = "false" ] ; then env | sort ; fi + # Deactivate whichever virtualenv is currently in use + - deactivate + # Install some package dependencies + - sudo apt-get -qq update + - sudo apt-get -qq install libgmp-dev + # Download pyenv + - pyenv_uri=https://github.com/yyuu/pyenv/archive/59c796c138a04a315171ee3d3275222a0f3bc781.tar.gz + - pyenv_basename=$( basename "$pyenv_uri" .tar.gz ) + - wget ${pyenv_uri} + - echo "7f196bfa6fafc7944b6dcc9bf4d037f91625a677463a69a2a3be6c31dcac91bb *${pyenv_basename}.tar.gz" | sha256sum -c - + # Install pyenv into ~/.pyenv and load it + - tar -xvzf ${pyenv_basename}.tar.gz + - mv -f pyenv-${pyenv_basename} ~/.pyenv + - export PATH=~/.pyenv/bin:$PATH + - eval "$(pyenv init -)" + # If the selected Python version is installed locally, activate it. Otherwise, build it using pyenv. + - if [ -e ~/virtualenv/python"$PYENV_VERSION"/bin/activate ] ; then source ~/virtualenv/python"$PYENV_VERSION"/bin/activate ; unset PYENV_VERSION ; else pyenv install "$PYENV_VERSION" ; fi +script: + - "major_version=$( python -V 2>&1 | cut -d' ' -f2 | cut -d. -f1 )" + - if [ "$major_version" -ge 3 ] ; then extra_flags="$extra_flags -bb" ; fi + - if [ -n "$preconfigure_args" ] ; then ./configure $preconfigure_args ; fi + - python -tt $extra_flags $python_flags setup.py -q build + - python -tt $extra_flags $python_flags setup.py test @@ -0,0 +1,58 @@ +Acknowledgements +---------------- + +This list is sorted in alphabetical order, and is probably incomplete. +I'd like to thank everybody who contributed in any way, with code, bug +reports, and comments. + +This list should not be interpreted as an endorsement of PyCrypto by the +people on it. + +Please let me know if your name isn't here and should be! + +- Dwayne C. Litzenberger + + +Nevins Bartolomeo +Thorsten E. Behrens +Tim Berners-Lee +Frédéric Bertolus +Ian Bicking +Joris Bontje +Antoon Bosselaers +Andrea Bottoni +Jean-Paul Calderone +Sergey Chernov +Geremy Condra +Jan Dittberner +Andrew Eland +Philippe Frycia +Peter Gutmann +Hirendra Hindocha +Nikhil Jhingan +Sebastian Kayser +Ryan Kelly +Andrew M. Kuchling +Piers Lauder +Legrandin <gooksankoo@hoiptorrow.mailexpire.com> +M.-A. Lemburg +Wim Lewis +Mark Moraes +Lim Chee Siang +Bryan Olson +Wallace Owen +Colin Plumb +Robey Pointer +Lorenz Quack +Sebastian Ramacher +Jeethu Rao +James P. Rutledge +Matt Schreiner +Peter Simmons +Janne Snabb +Tom St. Denis +Anders Sundman +Paul Swartz +Kevin M. Turner +Barry A. Warsaw +Eric Young diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..a5bd19c --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,77 @@ +Copyright and licensing of the Python Cryptography Toolkit ("PyCrypto"): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously, the copyright and/or licensing status of the Python +Cryptography Toolkit ("PyCrypto") had been somewhat ambiguous. The +original intention of Andrew M. Kuchling and other contributors has +been to dedicate PyCrypto to the public domain, but that intention was +not necessarily made clear in the original disclaimer (see +LEGAL/copy/LICENSE.orig). + +Additionally, some files within PyCrypto had specified their own +licenses that differed from the PyCrypto license itself. For example, +the original RIPEMD.c module simply had a copyright statement and +warranty disclaimer, without clearly specifying any license terms. +(An updated version on the author's website came with a license that +contained a GPL-incompatible advertising clause.) + +To rectify this situation for PyCrypto 2.1, the following steps have +been taken: + + 1. Obtaining explicit permission from the original contributors to + dedicate their contributions to the public domain if they have not + already done so. (See the "LEGAL/copy/stmts" directory for + contributors' statements.) + + 2. Replacing some modules with clearly-licensed code from other + sources (e.g. the DES and DES3 modules were replaced with new ones + based on Tom St. Denis's public-domain LibTomCrypt library.) + + 3. Replacing some modules with code written from scratch (e.g. the + RIPEMD and Blowfish modules were re-implemented from their + respective algorithm specifications without reference to the old + implementations). + + 4. Removing some modules altogether without replacing them. + +To the best of our knowledge, with the exceptions noted below or +within the files themselves, the files that constitute PyCrypto are in +the public domain. Most are distributed with the following notice: + + The contents of this file are dedicated to the public domain. To + the extent that dedication to the public domain is not available, + everyone is granted a worldwide, perpetual, royalty-free, + non-exclusive license to exercise all rights associated with the + contents of this file for any purpose whatsoever. + No rights are reserved. + + 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 AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +Exceptions: + + - Portions of HMAC.py and setup.py are derived from Python 2.2, and + are therefore Copyright (c) 2001, 2002, 2003 Python Software + Foundation (All Rights Reserved). They are licensed by the PSF + under the terms of the Python 2.2 license. (See the file + LEGAL/copy/LICENSE.python-2.2 for details.) + + - The various GNU autotools (autoconf, automake, aclocal, etc.) are + used during the build process. This includes macros from + autoconf-archive, which are located in the m4/ directory. As is + customary, some files from the GNU autotools are included in the + source tree (in the root directory, and in the build-aux/ + directory). These files are merely part of the build process, and + are not included in binary builds of the software. + +EXPORT RESTRICTIONS: + +Note that the export or re-export of cryptographic software and/or +source code may be subject to regulation in your jurisdiction. + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..480e8a9 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,772 @@ +2.7a1 +===== + * Experimental release. This introduces a new API for AEAD modes, and + makes a few other minor API changes. These APIs should be considered + experimental, and may be changed before the final release. + * New API for authenticated encryption with associated data (AEAD): + - New block cipher modes: + - MODE_CCM + - MODE_EAX + - MODE_GCM + - MODE_SIV + - New methods: + - .encrypt_and_digest() + - .decrypt_and_verify() + - .digest() + - .verify() + - New MAC algorithm: + - Crypto.Cipher.CMAC + - New .verify() and .hexverify() methods also added to Hash and + HMAC/CMAC objects, providing constant-time hash comparison. + (Thanks: Legrandin, Lucas Garron) + * LP#1132550: Fix MODE_OPENPGP not accepting uppercase 'IV' kwarg. + * LP#1119552: Fix PKCS#1v1.5 not accepting signatures without the + optional NULL parameter + * Add support for import/export of DSA keys. (Thanks: Legrandin) + * Add support for PKCS#8-encrypted private keys. (Thanks: Legrandin) + * LP#996193: Fix MODE_OFB requiring padding (it now behaves as a stream + cipher) + * Improve C extension autodocs + * Remove pointless 'error' attribute from stream ciphers. + * Deprecate the disable_shortcut option to Crypto.Util.Counter; + Remove __PCT_CTR_SHORTCUT__ entirely. + * Fix small MODE_CTR memory leak under Python 3. + * Fix error importing winrandom on Python 3. (Thanks: Jason R. Coombs) + * FortunaAccumulator: Use time.monotonic for rate-limiting if available + (i.e. Python 3.3 and later) + * AES-NI support (Thanks: Sebastian Ramacher) + * setup.py: Fix compilation on HP-UX 11.31. (Thanks: Adam Woodbeck) + * ElGamal: Add blinding to ElGamal decryption. (Thanks: Legrandin) + * Hash: Remove pure-Python wrappers (speeds up hash init 4x-7x) + * Hash: Add generic Crypto.Hash.new(algo, [data]) function + (like hashlib.new) + * Hash: Remove 'oid' attributes; Add 'name' attributes for compatibility + with hashlib. + * Hash: Rename SHA -> SHA1 and RIPEMD -> RIPEMD160, since the original + names are frequently used as the names of other algorithms. + * setup.py: Use autoconf to generate compiler options; + Fix OpenBSD build issues. + * Fix RSA object serialization (i.e. pickle) + * LP#1061217: random.shuffle takes O(n^2) time. + (Thanks: Sujay Jayakar, Andrew Cooke) + * _fastmath: Fix leaks when errors occur. + (Thanks: Sebastian Ramacher, Andreas Stührk) + * SHA256/224/384/512: Don't export symbol 'add_length' + * setup.py: Use os.chmod instead of os.system("chmod ..."). + (Thanks: Sebastian Ramacher) + * setup.py: The 'test' command now runs the 'build' command first. + (Thanks: Sebastian Ramacher) + * New tools/create-pythons.sh and tools/test-all.sh scripts for testing + against multiple versions of Python. + * getStrongProne: Fix error handling (Thanks: Sebastian Ramacher) + * ARC4: Add ARC4-drop[n] cipher support. (Thanks: Legrandin) + * RSA.importKey: Properly catch IndexError. (Thanks: Sebastian Ramacher) + * RSA.exportKey: Raise ValueError as documented when key format is + unknown. (Thanks: Sebastian Ramacher) + * RSA.exportKey: Always return bytes (Thanks: Sebastian Ramacher) + * Fix & re-enable some broken tests (Thanks: Sebastian Ramacher) + * Improve Python 3 compatibility + * Various documentation fixes and improvements + (Thanks: Anton Rieder, Legrandin, Sebastian Ramacher, Stefano Rivera) + * Various cleanups, especially for Python 3. + + +2.6.1 +===== + * [CVE-2013-1445] Fix PRNG not correctly reseeded in some situations. + + In previous versions of PyCrypto, the Crypto.Random PRNG exhibits a + race condition that may cause forked processes to generate identical + sequences of 'random' numbers. + + This is a fairly obscure bug that will (hopefully) not affect many + applications, but the failure scenario is pretty bad. Here is some + sample code that illustrates the problem: + + from binascii import hexlify + import multiprocessing, pprint, time + import Crypto.Random + + def task_main(arg): + a = Crypto.Random.get_random_bytes(8) + time.sleep(0.1) + b = Crypto.Random.get_random_bytes(8) + rdy, ack = arg + rdy.set() + ack.wait() + return "%s,%s" % (hexlify(a).decode(), + hexlify(b).decode()) + + n_procs = 4 + manager = multiprocessing.Manager() + rdys = [manager.Event() for i in range(n_procs)] + acks = [manager.Event() for i in range(n_procs)] + Crypto.Random.get_random_bytes(1) + pool = multiprocessing.Pool(processes=n_procs, + initializer=Crypto.Random.atfork) + res_async = pool.map_async(task_main, zip(rdys, acks)) + pool.close() + [rdy.wait() for rdy in rdys] + [ack.set() for ack in acks] + res = res_async.get() + pprint.pprint(sorted(res)) + pool.join() + + The output should be random, but it looked like this: + + ['c607803ae01aa8c0,2e4de6457a304b34', + 'c607803ae01aa8c0,af80d08942b4c987', + 'c607803ae01aa8c0,b0e4c0853de927c4', + 'c607803ae01aa8c0,f0362585b3fceba4'] + + This release fixes the problem by resetting the rate-limiter when + Crypto.Random.atfork() is invoked. It also adds some tests and a + few related comments. + +2.6 +=== + * [CVE-2012-2417] Fix LP#985164: insecure ElGamal key generation. + (thanks: Legrandin) + + In the ElGamal schemes (for both encryption and signatures), g is + supposed to be the generator of the entire Z^*_p group. However, in + PyCrypto 2.5 and earlier, g is more simply the generator of a random + sub-group of Z^*_p. + + The result is that the signature space (when the key is used for + signing) or the public key space (when the key is used for encryption) + may be greatly reduced from its expected size of log(p) bits, possibly + down to 1 bit (the worst case if the order of g is 2). + + While it has not been confirmed, it has also been suggested that an + attacker might be able to use this fact to determine the private key. + + Anyone using ElGamal keys should generate new keys as soon as practical. + + Any additional information about this bug will be tracked at + https://bugs.launchpad.net/pycrypto/+bug/985164 + + * Huge documentation cleanup (thanks: Legrandin). + + * Added more tests, including test vectors from NIST 800-38A + (thanks: Legrandin) + + * Remove broken MODE_PGP, which never actually worked properly. + A new mode, MODE_OPENPGP, has been added for people wishing to write + OpenPGP implementations. Note that this does not implement the full + OpenPGP specification, only the "OpenPGP CFB mode" part of that + specification. + https://bugs.launchpad.net/pycrypto/+bug/996814 + + * Fix: getPrime with invalid input causes Python to abort with fatal error + https://bugs.launchpad.net/pycrypto/+bug/988431 + + * Fix: Segfaults within error-handling paths + (thanks: Paul Howarth & Dave Malcolm) + https://bugs.launchpad.net/pycrypto/+bug/934294 + + * Fix: Block ciphers allow empty string as IV + https://bugs.launchpad.net/pycrypto/+bug/997464 + + * Fix DevURandomRNG to work with Python3's new I/O stack. + (thanks: Sebastian Ramacher) + + * Remove automagic dependencies on libgmp and libmpir, let the caller + disable them using args. + + * Many other minor bug fixes and improvements (mostly thanks to Legrandin) + +2.5 +=== + * Added PKCS#1 encryption schemes (v1.5 and OAEP). We now have + a decent, easy-to-use non-textbook RSA implementation. Yay! + + * Added PKCS#1 signature schemes (v1.5 and PSS). v1.5 required some + extensive changes to Hash modules to contain the algorithm specific + ASN.1 OID. To that end, we now always have a (thin) Python module to + hide the one in pure C. + + * Added 2 standard Key Derivation Functions (PBKDF1 and PBKDF2). + + * Added export/import of RSA keys in OpenSSH and PKCS#8 formats. + + * Added password-protected export/import of RSA keys (one old method + for PKCS#8 PEM only). + + * Added ability to generate RSA key pairs with configurable public + exponent e. + + * Added ability to construct an RSA key pair even if only the private + exponent d is known, and not p and q. + + * Added SHA-2 C source code (fully from Lorenz Quack). + + * Unit tests for all the above. + + * Updates to documentation (both inline and in Doc/pycrypt.rst) + + * All of the above changes were put together by Legrandin (Thanks!) + + * Minor bug fixes (setup.py and tests). + +2.4.1 +===== + * Fix "error: Setup script exited with error: src/config.h: No such file or + directory" when installing via easy_install. (Sebastian Ramacher) + +2.4 +=== + * Python 3 support! (Thorsten E. Behrens, Anders Sundman) + PyCrypto now supports every version of Python from 2.1 through 3.2. + + * Timing-attack countermeasures in _fastmath: When built against + libgmp version 5 or later, we use mpz_powm_sec instead of mpz_powm. + This should prevent the timing attack described by Geremy Condra at + PyCon 2011: + http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-through-the-side-channel-timing-and-implementation-attacks-in-python-4897955 + + * New hash modules (for Python >= 2.5 only): SHA224, SHA384, and + SHA512 (Frédéric Bertolus) + + * Configuration using GNU autoconf. This should help fix a bunch of + build issues. + + * Support using MPIR as an alternative to GMP. + + * Improve the test command in setup.py, by allowing tests to be + performed on a single sub-package or module only. (Legrandin) + + You can now do something like this: + + python setup.py test -m Hash.SHA256 --skip-slow-tests + + * Fix double-decref of "counter" when Cipher object initialisation + fails (Ryan Kelly) + + * Apply patches from Debian's python-crypto 2.3-3 package (Jan + Dittberner, Sebastian Ramacher): + - fix-RSA-generate-exception.patch + - epydoc-exclude-introspect.patch + - no-usr-local.patch + + * Fix launchpad bug #702835: "Import key code is not compatible with + GMP library" (Legrandin) + + * More tests, better documentation, various bugfixes. + +2.3 +=== + * Fix NameError when attempting to use deprecated getRandomNumber() + function. + + * _slowmath: Compute RSA u parameter when it's not given to + RSA.construct. This makes _slowmath behave the same as _fastmath in + this regard. + + * Make RSA.generate raise a more user-friendly exception message when + the user tries to generate a bogus-length key. + + +2.2 +=== + + * Deprecated Crypto.Util.number.getRandomNumber(), which had confusing + semantics. It's been replaced by getRandomNBitInteger and + getRandomInteger. (Thanks: Lorenz Quack) + + * Better isPrime() and getPrime() implementations that do a real + Rabin-Miller probabilistic primality test (not the phony test we did + before with fixed bases). (Thanks: Lorenz Quack) + + * getStrongPrime() implementation for generating RSA primes. + (Thanks: Lorenz Quack) + + * Support for importing and exporting RSA keys in DER and PEM format. + (Thanks: Legrandin) + + * Fix PyCrypto when floor division (python -Qnew) is enabled. + + * When building using gcc, use -std=c99 for compilation. This should + fix building on FreeBSD and NetBSD. + + +2.1.0 +===== + + * Fix building PyCrypto on Win64 using MS Visual Studio 9. + (Thanks: Nevins Bartolomeo.) + + +2.1.0beta1 +========== + + * Modified RSA.generate() to ensure that e is coprime to p-1 and q-1. + Apparently, RSA.generate was capable of generating unusable keys. + + +2.1.0alpha2 +=========== + + * Modified isPrime() to release the global interpreter lock while + performing computations. (patch from Lorenz Quack) + + * Release the GIL while encrypting, decrypting, and hashing (but not + during initialization or finalization). + + * API changes: + + - Removed RandomPoolCompat and made Crypto.Util.randpool.RandomPool + a wrapper around Crypto.Random that emits a DeprecationWarning. + This is to discourage developers from attempting to provide + backwards compatibility for systems where there are NO strong + entropy sources available. + + - Added Crypto.Random.get_random_bytes(). This should allow people + to use something like this if they want backwards-compatibility: + + try: + from Crypto.Random import get_random_bytes + except ImportError: + try: + from os import urandom as get_random_bytes + except ImportError: + get_random_bytes = open("/dev/urandom", "rb").read + + - Implemented __ne__() on pubkey, which fixes the following broken + behaviour: + >>> pk.publickey() == pk.publickey() + True + >>> pk.publickey() != pk.publickey() + True + (patch from Lorenz Quack) + + - Block ciphers created with MODE_CTR can now operate on strings of + any size, rather than just multiples of the underlying cipher's + block size. + + - Crypto.Util.Counter objects now raise OverflowError when they wrap + around to zero. You can override this new behaviour by passing + allow_wraparound=True to Counter.new() + + +2.1.0alpha1 +=========== + + * This version supports Python versions 2.1 through 2.6. + + * Clarified copyright status of much of the existing code by tracking + down Andrew M. Kuchling, Barry A. Warsaw, Jeethu Rao, Joris Bontje, + Mark Moraes, Paul Swartz, Robey Pointer, and Wim Lewis and getting + their permission to clarify the license/public-domain status of their + contributions. Many thanks to all involved! + + * Replaced the test suite with a new, comprehensive package + (Crypto.SelfTest) that includes documentation about where its test + vectors came from, or how they were derived. + + Use "python setup.py test" to run the tests after building. + + * API changes: + + - Added Crypto.version_info, which from now on will contain version + information in a format similar to Python's sys.version_info. + + - Added a new random numbers API (Crypto.Random), and deprecated the + old one (Crypto.Util.randpool.RandomPool), which was misused more + often than not. + + The new API is used by invoking Crypto.Random.new() and then just + reading from the file-like object that is returned. + + CAVEAT: To maintain the security of the PRNG, you must call + Crypto.Random.atfork() in both the parent and the child processes + whenever you use os.fork(). Otherwise, the parent and child will + share copies of the same entropy pool, causing them to return the + same results! This is a limitation of Python, which does not + provide readily-accessible hooks to os.fork(). It's also a + limitation caused by the failure of operating systems to provide + sufficiently fast, trustworthy sources of cryptographically-strong + random numbers. + + - Crypto.PublicKey now raises ValueError/TypeError/RuntimeError + instead of the various custom "error" exceptions + + - Removed the IDEA and RC5 modules due to software patents. Debian + has been doing this for a while + + - Added Crypto.Random.random, a strong version of the standard Python + 'random' module. + + - Added Crypto.Util.Counter, providing fast counter implementations + for use with CTR-mode ciphers. + + * Bug fixes: + + - Fixed padding bug in SHA256; this resulted in bad digests whenever + (the number of bytes hashed) mod 64 == 55. + + - Fixed a 32-bit limitation on the length of messages the SHA256 module + could hash. + + - AllOrNothing: Fixed padding bug in digest() + + - Fixed a bad behaviour of the XOR cipher module: It would silently + truncate all keys to 32 bytes. Now it raises ValueError when the + key is too long. + + - DSA: Added code to enforce FIPS 186-2 requirements on the size of + the prime p + + - Fixed the winrandom module, which had been omitted from the build + process, causing security problems for programs that misuse RandomPool. + + - Fixed infinite loop when attempting to generate RSA keys with an + odd number of bits in the modulus. (Not that you should do that.) + + * Clarified the documentation for Crypto.Util.number.getRandomNumber. + + Confusingly, this function does NOT return N random bits; It returns + a random N-bit number, i.e. a random number between 2**(N-1) and (2**N)-1. + + Note that getRandomNumber is for internal use only and may be + renamed or removed in future releases. + + * Replaced RIPEMD.c with a new implementation (RIPEMD160.c) to + alleviate copyright concerns. + + * Replaced the DES/DES3 modules with ones based on libtomcrypt-1.16 to + alleviate copyright concerns. + + * Replaced Blowfish.c with a new implementation to alleviate copyright + concerns. + + * Added a string-XOR implementation written in C (Crypto.Util.strxor) + and used it to speed up Crypto.Hash.HMAC + + * Converted documentation to reStructured Text. + + * Added epydoc configuration Doc/epydoc-config + + * setup.py now emits a warning when building without GMP. + + * Added pct-speedtest.py to the source tree for doing performance + testing on the new code. + + * Cleaned up the code in several places. + + +2.0.1 +===== + + * Fix SHA256 and RIPEMD on AMD64 platform. + * Deleted Demo/ directory. + * Add PublicKey to Crypto.__all__ + + +2.0 +=== + + * Added SHA256 module contributed by Jeethu Rao, with test data + from Taylor Boon. + + * Fixed AES.c compilation problems with Borland C. + (Contributed by Jeethu Rao.) + + * Fix ZeroDivisionErrors on Windows, caused by the system clock + not having enough resolution. + + * Fix 2.1/2.2-incompatible use of (key not in dict), + pointed out by Ian Bicking. + + * Fix FutureWarning in Crypto.Util.randpool, noted by James P Rutledge. + + +1.9alpha6 +========= + + * Util.number.getPrime() would inadvertently round off the bit + size; if you asked for a 129-bit prime or 135-bit prime, you + got a 128-bit prime. + + * Added Util/test/prime_speed.py to measure the speed of prime + generation, and PublicKey/test/rsa_speed.py to measure + the speed of RSA operations. + + * Merged the _rsa.c and _dsa.c files into a single accelerator + module, _fastmath.c. + + * Speed improvements: Added fast isPrime() function to _fastmath, + cutting the time to generate a 1024-bit prime by a factor of 10. + Optimized the C version of RSA decryption to use a longer series + of operations that's roughly 3x faster than a single + exponentiation. (Contributed by Joris Bontje.) + + * Added support to RSA key objects for blinding and unblinding + data. (Contributed by Joris Bontje.) + + * Simplified RSA key generation: hard-wired the encryption + exponent to 65537 instead of generating a random prime; + generate prime factors in a loop until the product + is large enough. + + * Renamed cansign(), canencrypt(), hasprivate(), to + can_sign, can_encrypt, has_private. If people shriek about + this change very loudly, I'll add aliases for the old method + names that log a warning and call the new method. + + +1.9alpha5 +========= + + * Many randpool changes. RandomPool now has a + randomize(N:int) method that can be called to get N + bytes of entropy for the pool (N defaults to 0, + which 'fills up' the pool's entropy) KeyboardRandom + overloads this method. + + * Added src/winrand.c for Crypto.Util.winrandom and + now use winrandom for _randomize if possible. + (Calls Windows CryptoAPI CryptGenRandom) + + * Several additional places for stirring the pool, + capturing inter-event entropy when reading/writing, + stirring before and after saves. + + * RandomPool.add_event now returns the number of + estimated bits of added entropy, rather than the + pool entropy itself (since the pool entropy is + capped at the number of bits in the pool) + + * Moved termios code from KeyboardRandomPool into a + KeyboardEntry class, provided a version for Windows + using msvcrt. + + * Fix randpool.py crash on machines with poor timer resolution. + (Reported by Mark Moraes and others.) + + * If the GNU GMP library is available, two C extensions will be + compiled to speed up RSA and DSA operations. (Contributed by + Paul Swartz.) + + * DES3 with a 24-byte key was broken; now fixed. + (Patch by Philippe Frycia.) + + +1.9alpha4 +========= + + * Fix compilation problem on Windows. + + * HMAC.py fixed to work with pre-2.2 Pythons + + * setup.py now dies if built with Python 1.x + + +1.9alpha3 +========= + + * Fix a ref-counting bug that caused core dumps. + (Reported by Piers Lauder and an anonymous SF poster.) + + +1.9alpha2 +========= + + * (Backwards incompatible) The old Crypto.Hash.HMAC module is + gone, replaced by a copy of hmac.py from Python 2.2's standard + library. It will display a warning on interpreter versions + older than 2.2. + + * (Backwards incompatible) Restored the Crypto.Protocol package, + and modernized and tidied up the two modules in it, + AllOrNothing.py and Chaffing.py, renaming various methods + and changing the interface. + + * (Backwards incompatible) Changed the function names in + Crypto.Util.RFC1751. + + * Restored the Crypto.PublicKey package at user request. I + think I'll leave it in the package and warn about it in the + documentation. I hope that eventually I can point to + someone else's better public-key code, and at that point I + may insert warnings and begin the process of deprecating + this code. + + * Fix use of a Python 2.2 C function, replacing it with a + 2.1-compatible equivalent. (Bug report and patch by Andrew + Eland.) + + * Fix endianness bugs that caused test case failures on Sparc, + PPC, and doubtless other platforms. + + * Fixed compilation problem on FreeBSD and MacOS X. + + * Expanded the test suite (requires Sancho, from + http://www.mems-exchange.org/software/sancho/) + + * Added lots of docstrings, so 'pydoc Crypto' now produces + helpful output. (Open question: maybe *all* of the documentation + should be moved into docstrings?) + + * Make test.py automatically add the build/* directory to sys.path. + + * Removed 'inline' declaration from C functions. Some compilers + don't support it, and Python's pyconfig.h no longer tells you whether + it's supported or not. After this change, some ciphers got slower, + but others got faster. + + * The C-level API has been changed to reduce the amount of + memory-to-memory copying. This makes the code neater, but + had ambiguous performance effects; again, some ciphers got slower + and others became faster. Probably this is due to my compiler + optimizing slightly worse or better as a result. + + * Moved C source implementations into src/ from block/, hash/, + and stream/. Having Hash/ and hash/ directories causes problems + on case-insensitive filesystems such as Mac OS. + + * Cleaned up the C code for the extensions. + + +1.9alpha1 +========= + + * Added Crypto.Cipher.AES. + + * Added the CTR mode and the variable-sized CFB mode from the + NIST standard on feedback modes. + + * Removed Diamond, HAVAL, MD5, Sapphire, SHA, and Skipjack. MD5 + and SHA are included with Python; the others are all of marginal + usefulness in the real world. + + * Renamed the module-level constants ECB, CFB, &c., to MODE_ECB, + MODE_CFB, as part of making the block encryption modules + compliant with PEP 272. (I'm not sure about this change; + if enough users complain about it, I might back it out.) + + * Made the hashing modules compliant with PEP 247 (not backward + compatible -- the major changes are that the constructor is now + MD2.new and not MD2.MD2, and the size of the digest is now + given as 'digest_size', not 'digestsize'. + + * The Crypto.PublicKey package is no longer installed; the + interfaces are all wrong, and I have no idea what the right + interfaces should be. + + +1.1alpha2 +========= + * Most importantly, the distribution has been broken into two +parts: exportable, and export-controlled. The exportable part +contains all the hashing algorithms, signature-only public key +algorithms, chaffing & winnowing, random number generation, various +utility modules, and the documentation. + + The export-controlled part contains public-key encryption +algorithms such as RSA and ElGamal, and bulk encryption algorithms +like DES, IDEA, or Skipjack. Getting this code still requires that +you go through an access control CGI script, and denies you access if +you're outside the US or Canada. + + * Added the RIPEMD hashing algorithm. (Contributed by +Hirendra Hindocha.) + + * Implemented the recently declassified Skipjack block +encryption algorithm. My implementation runs at 864 K/sec on a +PII/266, which isn't particularly fast, but you're probably better off +using another algorithm anyway. :) + + * A simple XOR cipher has been added, mostly for use by the +chaffing/winnowing code. (Contributed by Barry Warsaw.) + + * Added Protocol.Chaffing and Hash.HMAC.py. (Contributed by +Barry Warsaw.) + + Protocol.Chaffing implements chaffing and winnowing, recently +proposed by R. Rivest, which hides a message (the wheat) by adding +many noise messages to it (the chaff). The chaff can be discarded by +the receiver through a message authentication code. The neat thing +about this is that it allows secret communication without actually +having an encryption algorithm, and therefore this falls within the +exportable subset. + + * Tidied up randpool.py, and removed its use of a block +cipher; this makes it work with only the export-controlled subset +available. + + * Various renamings and reorganizations, mostly internal. + + +1.0.2 +===== + + * Changed files to work with Python 1.5; everything has been +re-arranged into a hierarchical package. (Not backward compatible.) +The package organization is: +Crypto. + Hash. + MD2, MD4, MD5, SHA, HAVAL + Cipher. + ARC2, ARC4, Blowfish, CAST, DES, DES3, Diamond, + IDEA, RC5, Sapphire + PublicKey. + DSA, ElGamal, qNEW, RSA + Util. + number, randpool, RFC1751 + + Since this is backward-incompatible anyway, I also changed +module names from all lower-case to mixed-case: diamond -> Diamond, +rc5 -> RC5, etc. That had been an annoying inconsistency for a while. + + * Added CAST5 module contributed by <wiml@hhhh.org>. + + * Added qNEW digital signature algorithm (from the digisign.py +I advertised a while back). (If anyone would like to suggest new +algorithms that should be implemented, please do; I think I've got +everything that's really useful at the moment, but...) + + * Support for keyword arguments has been added. This allowed +removing the obnoxious key handling for Diamond and RC5, where the +first few bytes of the key indicated the number of rounds to use, and +various other parameters. Now you need only do something like: + +from Crypto.Cipher import RC5 +obj = RC5.new(key, RC5.ECB, rounds=8) + +(Not backward compatible.) + + * Various function names have been changed, and parameter +names altered. None of these were part of the public interface, so it +shouldn't really matter much. + + * Various bugs fixed, the test suite has been expanded, and +the build process simplified. + + * Updated the documentation accordingly. + + +1.0.1 +===== + + * Changed files to work with Python 1.4 . + + * The DES and DES3 modules now automatically correct the +parity of their keys. + + * Added R. Rivest's DES test (see http://theory.lcs.mit.edu/~rivest/destest.txt) + + +1.0.0 +===== + + * REDOC III succumbed to differential cryptanalysis, and has +been removed. + + * The crypt and rotor modules have been dropped; they're still +available in the standard Python distribution. + + * The Ultra-Fast crypt() module has been placed in a separate +distribution. + + * Various bugs fixed. diff --git a/Doc/AEAD_API.txt b/Doc/AEAD_API.txt new file mode 100644 index 0000000..8a4c363 --- /dev/null +++ b/Doc/AEAD_API.txt @@ -0,0 +1,304 @@ +AEAD (Authenticated Encryption with Associated Data) modes of operations +for symmetric block ciphers provide authentication and integrity in addition +to confidentiality. + +Traditional modes like CBC or CTR only guarantee confidentiality; one +has to combine them with cryptographic MACs in order to have assurance of +authenticity. It is not trivial to implement such generic composition +without introducing subtle security flaws. + +AEAD modes are designed to be more secure and often more efficient than +ad-hoc constructions. Widespread AEAD modes are GCM, CCM, EAX, SIV, OCB. + +Most AEAD modes allow to optionally authenticate the plaintext with some +piece of arbitrary data that will not be encrypted, for instance a +packet header. + +In this file, that is called "associated data" (AD) even though terminology +may vary from mode to mode. + +The term "MAC" is used to indicate the authentication tag generated as part +of the encryption process. The MAC is consumed by the receiver to tell +whether the message has been tampered with. + +=== Goals of the AEAD API + +1. Any piece of data (AD, ciphertext, plaintext, MAC) is passed only once. +2. It is possible to encrypt/decrypt huge files withe little memory cost. + To this end, authentication, encryption, and decryption are always + incremental. That is, the caller may split data in any way, and the end + result does not depend on how splitting is done. + Data is processed immediately without being internally buffered. +3. API is similar to a Crypto.Hash MAC object, to the point that when only + AD is present, the object behaves exactly like a MAC. +4. API is similar to a classic cipher object, to the point that when no AD is present, + the object behaves exactly like a classic cipher mode (e.g. CBC). +5. MACs are produced and handled separately from ciphertext/plaintext. +6. The API is intuitive and hard to misuse. Exceptions are raised immediately + in case of misuse. +7. Caller does not have to add or remove padding. + +The following state diagram shows the proposed API for AEAD modes. +In general, it is applicable to all block ciphers in the Crypto.Cipher +module, even though certain modes may put restrictions on certain +cipher properties (e.g. block size). + + .--------. + | START | + '--------' + | + | .new(key, mode, iv, ...) + v + .-------------. +.-------------.-------------| INITIALIZED |---------------+-------------. +| | '-------------' | | +| | | | | +| |.encrypt() |.update() |.decrypt() | +| | | | | +| | v | | +| | .--------------.___ .update() | | +| | | CLEAR HEADER |<--' | | +| | '--------------' | | +| | | | | | | | +| | .encrypt()| | | |.decrypt() | | +| v | | | | v | +| .--------------. | | | | .--------------. | +| | ENCRYPTING |<----' | | '---->| DECRYPTING | | +| '--------------' | | '--------------' | +| | ^ | | | | ^ | | +| hex/digest()| | |.encrypt()* | | | | |.decrypt()* | +| | ''' | | | ''' | +| | / \ | | +| | hex/digest()/ \hex/verify()|hex/verify() | +|hex/digest() | / \ | | +| | / \ | hex/verify()| +| v / \ v | +| .--------------. / \ .--------------. | +'------->| FINISHED/ENC |<-- -->| FINISHED/DEC |<---------' + '--------------' '--------------' + ^ | ^ | + | |hex/digest() | |hex/verify() + ''' ''' + + [*] this transition is not always allowed for non-online or 2-pass modes + +The following states are defined: + + - INITIALIZED. The cipher has been instantiated with a key, possibly + a nonce (or IV), and other parameters. + The cipher object may be used for encryption or decryption. + + - CLEAR HEADER. The cipher is authenticating the associated data. + + - ENCRYPTING. It has been decided that the cipher has to be used for + encrypting data. At least one piece of ciphertext has been produced. + + - DECRYPTING. It has been decided that the cipher has to be used for + decrypting data. At least one piece of candidate plaintext has + been produced. + + - FINISHED/ENC. Authenticated encryption has completed. + The final MAC has been produced. + + - FINISHED/DEC. Authenticated decryption has completed. + It is now established if the associated data together the plaintext + are authentic. + +In addition to the existing Cipher methods new(), encrypt() and decrypt(), +5 new methods are added to a Cipher object: + + - update() to consume all associated data. It takes as input + a byte string, and it can be invoked multiple times. + Ciphertext / plaintext must not be passed to update(). + For simplicity, update() can only be called before encryption + or decryption starts. If no associated data is used, update() + is not called. + + - digest() to output the binary MAC. It can only be called at the end + of the encryption. + + - hexdigest() as digest(), but the output is ASCII hexadecimal. + + - verify() to evaluate if the binary MAC is correct. It can only be + called at the end of decryption. It takes the MAC as input. + + - hexverify() as verify(), but the input is ASCII hexadecimal. + +The syntax of update(), digest(), and hexdigest() are consistent with +the API of a Hash object. + +IMPORTANT: method copy() is not present. Since most AEAD modes require +IV/nonce to never repeat, this method may be misused and lead to security +holes. + +Since MAC validation (decryption mode) is subject to timing attacks, +the (hex)verify() method internally performs comparison of received +and computed MACs using time-independent code. +A ValueError exception is issued if the MAC does not match. + +=== Padding + +The proposed API only supports AEAD modes that do not require padding +of the plaintext. Adding support for that would make the API more complex +(for instance, an external "finished" flag to pass encrypt()). + +=== Pre-processing of associated data + +The proposed API does not support pre-processing of AD. + +Sometimes, a lot of encryptions/decryptions are performed with +the same key and the same AD, and different nonces and plaintext. + +Certain modes like GCM allow to cache processing of AD, and reuse +it such results across several encryptions/decryptions. + +=== Singe/2-pass modes and online/non-online modes + +The proposed API supports single-pass, online AEAD modes. + +A "single-pass" mode processes each block of AD or data only once. +Compare that to "2-pass" modes, where each block of data (not AD) +is processed twice: once for authentication and once for enciphering. + +An "online" mode does not need to know the size of the message before +encryption starts. As a consequence: + - memory usage doesn't depend on the plaintext/ciphertext size. + - when encrypting, partial ciphertexts can be immediately sent to the receiver. + - when decrypting, partial (unauthenticated) plaintexts can be obtained from + the cipher. + +Most single-pass modes are patented, and only the less efficient 2-pass modes +are in widespread use. + +That is still OK, provided that encryption can start *before* authentication is +completed. If that's the case (e.g. GCM, EAX) encrypt()/decrypt() will also +take care of completing the authentication over the plaintext. + +A similar problem arises with non-online modes (e.g. CCM): they have to wait to see +the end of the plaintext before encryption can start. The only way to achieve +that is to only allow encrypt()/decrypt() to be called once. + +To summarize: + +Single-pass and online: + Fully supported by the API. The mode is most likely patented. + +Single-pass and not-online: + encrypt()/decrypt() can only be called once. The mode is most likely patented. + +2-pass and online: + Fully supported by the API, but only if encryption or decryption can start + *before* authentication is finished. + +2-pass and not-online: + Fully supported by the API, but only if encryption or decryption can start + *before* authentication is finished. encrypt()/decrypt() can only be called once. + +=== Associated Data + +Depending on the mode, the associated data AD can be defined as: + 1. a single binary string or + 2. a vector of binary strings + +For modes of the 1st type (e.g. CCM), the API allows the AD to be split +in any number of segments, and fed to update() in multiple calls. +The resulting AD does not depend on how splitting is performed. +It is responsability of the caller to ensure that concatenation of strings +is secure. For instance, there is no difference between: + + c.update(b"builtin") + c.update(b"securely") + +and: + + c.update(b"built") + c.update(b"insecurely") + +For modes of the 2nd type (e.g. SIV), the API assumes that each call +to update() ingests one full item of the vector. The two examples above +are now different. + +=== MAC + +During encryption, the MAC is computed and returned by digest(). + +During decryption, the received MAC is passed as a parameter to verify() +at the very end. + +=== CCM mode +Number of keys required: 1 +Compatible with ciphers: AES (may be used with others if block length + is 128 bits) +Counter/IV/nonce: 1 nonce required (length 8..13 bytes) +Single-pass: no +Online: no +Encryption can start before +authentication is complete: yes +Term for AD: "associate data" (NIST) or "additional + authenticated data" (RFC) +Term for MAC: part of ciphertext (NIST) or + "encrypted authentication value" (RFC). +Padding required: no +Pre-processing of AD: not possible + +In order to allow encrypt()/decrypt() to be called multiple times, +and to reduce the memory usage, the new() method of the Cipher module +optionally accepts the following parameters: + + - 'assoc_len', the total length (in bytes) of the AD + + - 'msg_len', the total length (in bytes) of the plaintext or ciphertext + +=== GCM mode +Number of keys required: 1 +Compatible with ciphers: AES (may be used with others if block length + is 128 bits) +Counter/IV/nonce: 1 IV required (any length) +Single-pass: no +Online: yes +Encryption can start before +authentication is complete: yes +Term for AD: "additional authenticated data" +Term for MAC: "authentication tag" or "tag" +Padding required: no +Pre-processing of AD: possible + +=== EAX mode +Number of keys required: 1 +Compatible with ciphers: any +Counter/IV/nonce: 1 IV required (any length) +Single-pass: no +Online: yes +Encryption can start before +authentication is complete: yes +Term for AD: "header" +Term for MAC: "tag" +Padding required: no +Pre-processing of AD: possible + +=== SIV +Number of keys required: 2 +Compatible with ciphers: AES +Counter/IV/nonce: 1 IV required (any length) +Single-pass: no +Online: no +Encryption can start before +authentication is complete: no +Term for AD: "associated data" (vector) +Term for MAC: "tag" +Padding required: no +Pre-processing of AD: possible + +AD is a vector of strings. One item in the vector is the (optional) IV. + +One property of SIV is that encryption or decryption can only start +as soon as the MAC is available. + +That is not a problem for encryption: since encrypt() can only be called +once, it can internally compute the MAC first, perform the encryption, +and return the ciphertext. The MAC is cached for the subsequent call to digest(). + +The major problem is decryption: decrypt() cannot produce any output because +the MAC is meant to be passed to verify() only later. +To overcome this limitation, decrypt() *exceptionally* accepts the ciphertext +concatenated to the MAC. The MAC check is still performed with verify(). diff --git a/Doc/epydoc-config b/Doc/epydoc-config new file mode 100644 index 0000000..207db13 --- /dev/null +++ b/Doc/epydoc-config @@ -0,0 +1,26 @@ +# epydoc configuration file for PyCrypto. +# See http://epydoc.sourceforge.net/configfile.html for sample configuration. + +[epydoc] +modules: Crypto +docformat: restructuredtext +output: html +target: Doc/apidoc/ +sourcecode: no + +# Do not include private variables +private: no + +# Include the complete set of inherited methods, but grouped in a special +# section +inheritance: grouped + +name: PyCrypto API Documentation +url: http://www.pycrypto.org/ + +link: <a href="http://www.pycrypto.org/">PyCrypto.org</a> + +# The documentation is usually built on a Linux machine; nt.py tries to +# import the winrandom module. +exclude-introspect: ^Crypto\.Random\.OSRNG\.nt|Crypto\.Util\.winrandom|Crypto\.Util\.osentropy\.nt$ +exclude: ^Crypto\.SelfTest diff --git a/Doc/pycrypt.rst b/Doc/pycrypt.rst new file mode 100644 index 0000000..e9bd6a6 --- /dev/null +++ b/Doc/pycrypt.rst @@ -0,0 +1,1188 @@ +==================================== +Python Cryptography Toolkit +==================================== + +**Version 2.7a1** + +The Python Cryptography Toolkit describes a package containing various +cryptographic modules for the Python programming language. This +documentation assumes you have some basic knowledge about the Python +language, but not necessarily about cryptography. + +.. contents:: + +Introduction +------------------- + +Design Goals +=================== + +The Python cryptography toolkit is intended to provide a reliable and +stable base for writing Python programs that require cryptographic +functions. + +A central goal has been to provide a simple, consistent interface for +similar classes of algorithms. For example, all block cipher objects +have the same methods and return values, and support the same feedback +modes. Hash functions have a different interface, but it too is +consistent over all the hash functions available. Some of these +interfaces have been codified as Python Enhancement Proposal +documents, as PEP 247, "API for Cryptographic Hash Functions", and +PEP 272, "API for Block Encryption Algorithms". + +This is intended to make it easy to replace old algorithms with newer, +more secure ones. If you're given a bit of portably-written Python +code that uses the DES encryption algorithm, you should be able to use +AES instead by simply changing ``from Crypto.Cipher import DES`` to +``from Crypto.Cipher import AES``, and changing all references to +``DES.new()`` to ``AES.new()``. It's also fairly simple to +write your own modules that mimic this interface, thus letting you use +combinations or permutations of algorithms. + +Some modules are implemented in C for performance; others are written +in Python for ease of modification. Generally, low-level functions +like ciphers and hash functions are written in C, while less +speed-critical functions have been written in Python. This division +may change in future releases. When speeds are quoted in this +document, they were measured on a 500 MHz Pentium II running Linux. +The exact speeds will obviously vary with different machines, +different compilers, and the phase of the moon, but they provide a +crude basis for comparison. Currently the cryptographic +implementations are acceptably fast, but not spectacularly good. I +welcome any suggestions or patches for faster code. + +I have placed the code under no restrictions; you can redistribute the +code freely or commercially, in its original form or with any +modifications you make, subject to whatever local laws may apply in your +jurisdiction. Note that you still have to come to some agreement with +the holders of any patented algorithms you're using. If you're +intensively using these modules, please tell me about it; there's little +incentive for me to work on this package if I don't know of anyone using +it. + +I also make no guarantees as to the usefulness, correctness, or legality +of these modules, nor does their inclusion constitute an endorsement of +their effectiveness. Many cryptographic algorithms are patented; +inclusion in this package does not necessarily mean you are allowed to +incorporate them in a product and sell it. Some of these algorithms may +have been cryptanalyzed, and may no longer be secure. While I will +include commentary on the relative security of the algorithms in the +sections entitled "Security Notes", there may be more recent analyses +I'm not aware of. (Or maybe I'm just clueless.) If you're implementing +an important system, don't just grab things out of a toolbox and put +them together; do some research first. On the other hand, if you're +just interested in keeping your co-workers or your relatives out of your +files, any of the components here could be used. + +This document is very much a work in progress. If you have any +questions, comments, complaints, or suggestions, please send them to me. + +Acknowledgements +================================================== + +Much of the code that actually implements the various cryptographic +algorithms was not written by me. I'd like to thank all the people who +implemented them, and released their work under terms which allowed me +to use their code. These individuals are credited in the relevant +chapters of this documentation. Bruce Schneier's book +:title-reference:`Applied Cryptography` was also very useful in writing this toolkit; I highly +recommend it if you're interested in learning more about cryptography. + +Good luck with your cryptography hacking! + + +Crypto.Hash: Hash Functions +-------------------------------------------------- + +Hash functions take arbitrary strings as input, and produce an output +of fixed size that is dependent on the input; it should never be +possible to derive the input data given only the hash function's +output. One simple hash function consists of simply adding together +all the bytes of the input, and taking the result modulo 256. For a +hash function to be cryptographically secure, it must be very +difficult to find two messages with the same hash value, or to find a +message with a given hash value. The simple additive hash function +fails this criterion miserably and the hash functions described below +meet this criterion (as far as we know). Examples of +cryptographically secure hash functions include MD2, MD5, and SHA1. + +Hash functions can be used simply as a checksum, or, in association with a +public-key algorithm, can be used to implement digital signatures. + +The hashing algorithms currently implemented are: + +============= ============= ======== +Hash function Digest length Security +============= ============= ======== +MD2 128 bits Insecure, do not use +MD4 128 bits Insecure, do not use +MD5 128 bits Insecure, do not use +RIPEMD160 160 bits Secure. +SHA1 160 bits SHA1 is shaky. Walk, do not run, away from SHA1. +SHA256 256 bits Secure. +============= ============= ======== + +Resources: +On SHA1 (in)security: http://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html +SHA1 phase-out by 2010: http://csrc.nist.gov/groups/ST/toolkit/documents/shs/hash_standards_comments.pdf +On MD5 insecurity: http://www.schneier.com/blog/archives/2008/12/forging_ssl_cer.html + +Crypto.Hash.HMAC implements the RFC-2104 HMAC algorithm. The HMAC module is +a copy of Python 2.2's module, and works on Python 2.1 as well. +HMAC's security depends on the cryptographic strength of the key handed to it, +and on the underlying hashing method used. HMAC-MD5 and HMAC-SHA1 are used in +IPSEC and TLS. + +All hashing modules with the exception of HMAC share the same interface. +After importing a given hashing module, call the ``new()`` function to create +a new hashing object. You can now feed arbitrary strings into the object +with the ``update()`` method, and can ask for the hash value at +any time by calling the ``digest()`` or ``hexdigest()`` +methods. The ``new()`` function can also be passed an optional +string parameter that will be immediately hashed into the object's +state. + +To create a HMAC object, call HMAC's ```new()`` function with the key (as +a string or bytes object) to be used, an optional message, and the hash +function to use. HMAC defaults to using MD5. This is not a secure default, +please use SHA256 or better instead in new implementations. + +Hash function modules define one variable: + +**digest_size**: +An integer value; the size of the digest +produced by the hashing objects. You could also obtain this value by +creating a sample object, and taking the length of the digest string +it returns, but using ``digest_size`` is faster. + +The methods for hashing objects are always the following: + +**copy()**: +Return a separate copy of this hashing object. An ``update`` to +this copy won't affect the original object. + + +**digest()**: +Return the hash value of this hashing object, as a string containing +8-bit data. The object is not altered in any way by this function; +you can continue updating the object after calling this function. +Python 3.x: digest() returns a bytes object + +**hexdigest()**: +Return the hash value of this hashing object, as a string containing +the digest data as hexadecimal digits. The resulting string will be +twice as long as that returned by ``digest()``. The object is not +altered in any way by this function; you can continue updating the +object after calling this function. + + +**update(arg)**: +Update this hashing object with the string ``arg``. +Python 3.x: The passed argument must be an object interpretable as +a buffer of bytes + + +Here's an example, using the SHA-256 algorithm:: + + >>> from Crypto.Hash import SHA256 + >>> m = SHA256.new() + >>> m.update('abc') + >>> m.digest() + '\xbax\x16\xbf\x8f\x01\xcf\xeaAA@\xde]\xae"#\xb0\x03a\xa3\x96\x17z\x9c\xb4\x10\xffa\xf2\x00\x15\xad' + >>> m.hexdigest() + 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' + +Here's an example of using HMAC:: + + >>> from Crypto.Hash import HMAC, SHA256 + >>> m = HMAC.new('Please do not use this key in your code, with sugar on top', + '', SHA256) + >>> m.update('abc') + >>> m.digest() + 'F\xaa\x83\t\x97<\x8c\x12\xff\xe8l\xca:\x1d\xb4\xfc7\xfa\x84tK-\xb0\x00v*\xc2\x90\x19\xaa\xfaz' + >>> m.hexdigest() + '46aa8309973c8c12ffe86cca3a1db4fc37fa84744b2db000762ac29019aafa7a' + +Security Notes +========================== + +Hashing algorithms are broken by developing an algorithm to compute a +string that produces a given hash value, or to find two messages that +produce the same hash value. Consider an example where Alice and Bob +are using digital signatures to sign a contract. Alice computes the +hash value of the text of the contract and signs the hash value with +her private key. Bob could then compute a different contract that has +the same hash value, and it would appear that Alice signed that bogus +contract; she'd have no way to prove otherwise. Finding such a +message by brute force takes ``pow(2, b-1)`` operations, where the +hash function produces *b*-bit hashes. + +If Bob can only find two messages with the same hash value but can't +choose the resulting hash value, he can look for two messages with +different meanings, such as "I will mow Bob's lawn for $10" and "I owe +Bob $1,000,000", and ask Alice to sign the first, innocuous contract. +This attack is easier for Bob, since finding two such messages by brute +force will take ``pow(2, b/2)`` operations on average. However, +Alice can protect herself by changing the protocol; she can simply +append a random string to the contract before hashing and signing it; +the random string can then be kept with the signature. + +Some of the algorithms implemented here have been completely broken. +The MD2, MD4 and MD5 hash functions are widely considered insecure +hash functions, as it has been proven that meaningful hash collisions +can be generated for them, in the case of MD4 and MD5 in mere seconds. +MD2 is rather slow at 1250 K/sec. MD4 is faster at 44,500 K/sec. +MD5 is a strengthened version of MD4 with four rounds; beginning in 2004, +a series of attacks were discovered and it's now possible to create pairs +of files that result in the same MD5 hash. The MD5 +implementation is moderately well-optimized and thus faster on x86 +processors, running at 35,500 K/sec. MD5 may even be faster than MD4, +depending on the processor and compiler you use. +MD5 is still supported for compatibility with existing protocols, but +implementors should use SHA256 in new software because there are no known +attacks against SHA256. + +All the MD* algorithms produce 128-bit hashes. +SHA1 produces a 160-bit hash. Because of recent theoretical attacks against SHA1, +NIST recommended phasing out use of SHA1 by 2010. +SHA256 produces a larger 256-bit hash, and there are no known attacks against it. +It operates at 10,500 K/sec. +RIPEMD has a 160-bit output, the same output size as SHA1, and operates at 17,600 +K/sec. + +Credits +=============== + +The MD2 and MD4 implementations were written by A.M. Kuchling, and the MD5 +code was implemented by Colin Plumb. The SHA1 code was originally written by +Peter Gutmann. The RIPEMD160 code as of version 2.1.0 was written by Dwayne +Litzenberger. The SHA256 code was written by Tom St. Denis and is part of the +LibTomCrypt library (http://www.libtomcrypt.org/); it was adapted for the +toolkit by Jeethu Rao and Taylor Boon. + + + +Crypto.Cipher: Encryption Algorithms +-------------------------------------------------- + +Encryption algorithms transform their input data, or **plaintext**, +in some way that is dependent on a variable **key**, producing +**ciphertext**. This transformation can easily be reversed, if (and, +hopefully, only if) one knows the key. The key can be varied by the +user or application and chosen from some very large space of possible +keys. + +For a secure encryption algorithm, it should be very difficult to +determine the original plaintext without knowing the key; usually, no +clever attacks on the algorithm are known, so the only way of breaking +the algorithm is to try all possible keys. Since the number of possible +keys is usually of the order of 2 to the power of 56 or 128, this is not +a serious threat, although 2 to the power of 56 is now considered +insecure in the face of custom-built parallel computers and distributed +key guessing efforts. + +**Block ciphers** take multibyte inputs of a fixed size +(frequently 8 or 16 bytes long) and encrypt them. Block ciphers can +be operated in various modes. The simplest is Electronic Code Book +(or ECB) mode. In this mode, each block of plaintext is simply +encrypted to produce the ciphertext. This mode can be dangerous, +because many files will contain patterns greater than the block size; +for example, the comments in a C program may contain long strings of +asterisks intended to form a box. All these identical blocks will +encrypt to identical ciphertext; an adversary may be able to use this +structure to obtain some information about the text. + +To eliminate this weakness, there are various feedback modes in which +the plaintext is combined with the previous ciphertext before +encrypting; this eliminates any repetitive structure in the +ciphertext. + +One mode is Cipher Block Chaining (CBC mode); another is Cipher +FeedBack (CFB mode). CBC mode still encrypts in blocks, and thus is +only slightly slower than ECB mode. CFB mode encrypts on a +byte-by-byte basis, and is much slower than either of the other two +modes. The chaining feedback modes require an initialization value to +start off the encryption; this is a string of the same length as the +ciphering algorithm's block size, and is passed to the ``new()`` +function. + +The currently available block ciphers are listed in the following table, +and are in the ``Crypto.Cipher`` package: + +================= ============================ +Cipher Key Size/Block Size +================= ============================ +AES 16, 24, or 32 bytes/16 bytes +ARC2 Variable/8 bytes +Blowfish Variable/8 bytes +CAST Variable/8 bytes +DES 8 bytes/8 bytes +DES3 (Triple DES) 16 bytes/8 bytes +================= ============================ + + +In a strict formal sense, **stream ciphers** encrypt data bit-by-bit; +practically, stream ciphers work on a character-by-character basis. +Stream ciphers use exactly the same interface as block ciphers, with a block +length that will always be 1; this is how block and stream ciphers can be +distinguished. +The only feedback mode available for stream ciphers is ECB mode. + +The currently available stream ciphers are listed in the following table: + +======= ========= +Cipher Key Size +======= ========= + ARC4 Variable + XOR Variable +======= ========= + +ARC4 is short for "Alleged RC4". In September of 1994, someone posted +C code to both the Cypherpunks mailing list and to the Usenet +newsgroup ``sci.crypt``, claiming that it implemented the RC4 +algorithm. This claim turned out to be correct. Note that there's a +damaging class of weak RC4 keys; this module won't warn you about such keys. + +.. % XXX are there other analyses of RC4? + +A similar anonymous posting was made for Alleged RC2 in January, 1996. + +An example usage of the DES module:: + + >>> from Crypto.Cipher import DES + >>> obj=DES.new('abcdefgh', DES.MODE_ECB) + >>> plain="Guido van Rossum is a space alien." + >>> len(plain) + 34 + >>> obj.encrypt(plain) + Traceback (innermost last): + File "<stdin>", line 1, in ? + ValueError: Strings for DES must be a multiple of 8 in length + >>> ciph=obj.encrypt(plain+'XXXXXX') + >>> ciph + '\021,\343Nq\214DY\337T\342pA\372\255\311s\210\363,\300j\330\250\312\347\342I\3215w\03561\303dgb/\006' + >>> obj.decrypt(ciph) + 'Guido van Rossum is a space alien.XXXXXX' + +All cipher algorithms share a common interface. After importing a +given module, there is exactly one function and two variables +available. + +**new(key, mode[, IV])**: +Returns a ciphering object, using ``key`` and feedback mode +``mode``. +If ``mode`` is ``MODE_CBC`` or ``MODE_CFB``, ``IV`` must be provided, + and must be a string of the same length as the block size. +Some algorithms support additional keyword arguments to this function; see +the "Algorithm-specific Notes for Encryption Algorithms" section below for the details. +Python 3.x: ```mode`` is a string object; ```key``` and ```IV``` must be +objects interpretable as a buffer of bytes. + +**block_size**: +An integer value; the size of the blocks encrypted by this module. +Strings passed to the ``encrypt`` and ``decrypt`` functions +must be a multiple of this length. For stream ciphers, +``block_size`` will be 1. + +**key_size**: +An integer value; the size of the keys required by this module. If +``key_size`` is zero, then the algorithm accepts arbitrary-length +keys. You cannot pass a key of length 0 (that is, the null string +``""`` as such a variable-length key. + +All cipher objects have at least three attributes: + +**block_size**: +An integer value equal to the size of the blocks encrypted by this object. +Identical to the module variable of the same name. + + +**IV**: +Contains the initial value which will be used to start a cipher +feedback mode. After encrypting or decrypting a string, this value +will reflect the modified feedback text; it will always be one block +in length. It is read-only, and cannot be assigned a new value. +Python 3.x: ```IV``` is a bytes object. + +**key_size**: +An integer value equal to the size of the keys used by this object. If +``key_size`` is zero, then the algorithm accepts arbitrary-length +keys. For algorithms that support variable length keys, this will be 0. +Identical to the module variable of the same name. + + +All ciphering objects have the following methods: + +**decrypt(string)**: +Decrypts ``string``, using the key-dependent data in the object, and +with the appropriate feedback mode. The string's length must be an exact +multiple of the algorithm's block size. Returns a string containing +the plaintext. +Python 3.x: decrypt() will return a bytes object. + +Note: Do not use the same cipher object for both encryption an +decryption, since both operations share the same IV buffer, so the results +will probably not be what you expect. + + +**encrypt(string)**: +Encrypts a non-null ``string``, using the key-dependent data in the +object, and with the appropriate feedback mode. The string's length +must be an exact multiple of the algorithm's block size; for stream +ciphers, the string can be of any length. Returns a string containing +the ciphertext. +Python 3.x: ```string``` must be an object interpretable as a buffer of bytes. +encrypt() will return a bytes object. + +Note: Do not use the same cipher object for both encryption an +decryption, since both operations share the same IV buffer, so the results +will probably not be what you expect. + + +Security Notes +======================= + +Encryption algorithms can be broken in several ways. If you have some +ciphertext and know (or can guess) the corresponding plaintext, you can +simply try every possible key in a **known-plaintext** attack. Or, it +might be possible to encrypt text of your choice using an unknown key; +for example, you might mail someone a message intending it to be +encrypted and forwarded to someone else. This is a +**chosen-plaintext** attack, which is particularly effective if it's +possible to choose plaintexts that reveal something about the key when +encrypted. + +Stream ciphers are only secure if any given key is never used twice. +If two (or more) messages are encrypted using the same key in a stream +cipher, the cipher can be broken fairly easily. + +DES (5100 K/sec) has a 56-bit key; this is starting to become too small +for safety. It has been shown in 2009 that a ~$10,000 machine can break +DES in under a day on average. NIST has withdrawn FIPS 46-3 in 2005. +DES3 (1830 K/sec) uses three DES encryptions for greater security and a 112-bit +or 168-bit key, but is correspondingly slower. Attacks against DES3 are +not currently feasible, and it has been estimated to be useful until 2030. +Bruce Schneier endorses DES3 for its security because of the decades of +study applied against it. It is, however, slow. + +There are no known attacks against Blowfish (9250 K/sec) or CAST (2960 K/sec), +but they're all relatively new algorithms and there hasn't been time for much +analysis to be performed; use them for serious applications only after careful +research. + +pycrypto implements CAST with up to 128 bits key length (CAST-128). This +algorithm is considered obsoleted by CAST-256. CAST is patented by Entrust +Technologies and free for non-commercial use. + +Bruce Schneier recommends his newer Twofish algorithm over Blowfish where +a fast, secure symmetric cipher is desired. Twofish was an AES candidate. It +is slightly slower than Rijndael (the chosen algorithm for AES) for 128-bit +keys, and slightly faster for 256-bit keys. + +AES, the Advanced Encryption Standard, was chosen by the US National +Institute of Standards and Technology from among 6 competitors, and is +probably your best choice. It runs at 7060 K/sec, so it's among the +faster algorithms around. + +ARC4 ("Alleged" RC4) (8830 K/sec) has been weakened. Specifically, it has been +shown that the first few bytes of the ARC4 keystream are strongly non-random, +leaking information about the key. When the long-term key and nonce are merely +concatenated to form the ARC4 key, such as is done in WEP, this weakness can be +used to discover the long-term key by observing a large number of messages +encrypted with this key. +Because of these possible related-key attacks, ARC4 should only be used with +keys generated by a strong RNG, or from a source of sufficiently uncorrelated +bits, such as the output of a hash function. +A further possible defense is to discard the initial portion of the keystream. +This altered algorithm is called RC4-drop(n). +While ARC4 is in wide-spread use in several protocols, its use in new protocols +or applications is discouraged. + +ARC2 ("Alleged" RC2) is vulnerable to a related-key attack, 2^34 chosen +plaintexts are needed. +Because of these possible related-key attacks, ARC2 should only be used with +keys generated by a strong RNG, or from a source of sufficiently uncorrelated +bits, such as the output of a hash function. + +Credits +============= + +The code for Blowfish was written from scratch by Dwayne Litzenberger, based +on a specification by Bruce Schneier, who also invented the algorithm; the +Blowfish algorithm has been placed in the public domain and can be used +freely. (See http://www.schneier.com/paper-blowfish-fse.html for more +information about Blowfish.) The CAST implementation was written by Wim Lewis. +The DES implementation uses libtomcrypt, which was written by Tom St Denis. + +The Alleged RC4 code was posted to the ``sci.crypt`` newsgroup by an +unknown party, and re-implemented by A.M. Kuchling. + + +Crypto.Protocol: Various Protocols +-------------------------------------------------- + +Crypto.Protocol.AllOrNothing +========================================== + +This module implements all-or-nothing package transformations. +An all-or-nothing package transformation is one in which some text is +transformed into message blocks, such that all blocks must be obtained before +the reverse transformation can be applied. Thus, if any blocks are corrupted +or lost, the original message cannot be reproduced. + +An all-or-nothing package transformation is not encryption, although a block +cipher algorithm is used. The encryption key is randomly generated and is +extractable from the message blocks. + +**AllOrNothing(ciphermodule, mode=None, IV=None)**: +Class implementing the All-or-Nothing package transform. + +``ciphermodule`` is a module implementing the cipher algorithm to +use. Optional arguments ``mode`` and ``IV`` are passed directly +through to the ``ciphermodule.new()`` method; they are the +feedback mode and initialization vector to use. All three arguments +must be the same for the object used to create the digest, and to +undigest'ify the message blocks. + +The module passed as ``ciphermodule`` must provide the PEP 272 +interface. An encryption key is randomly generated automatically when +needed. + + +The methods of the ``AllOrNothing`` class are: + +**digest(text)**: +Perform the All-or-Nothing package transform on the +string ``text``. Output is a list of message blocks describing the +transformed text, where each block is a string of bit length equal +to the cipher module's block_size. + + +**undigest(mblocks)**: +Perform the reverse package transformation on a list of message +blocks. Note that the cipher module used for both transformations +must be the same. ``mblocks`` is a list of strings of bit length +equal to ``ciphermodule``'s block_size. The output is a string object. + + + +Crypto.Protocol.Chaffing +================================================== + +Winnowing and chaffing is a technique for enhancing privacy without requiring +strong encryption. In short, the technique takes a set of authenticated +message blocks (the wheat) and adds a number of chaff blocks which have +randomly chosen data and MAC fields. This means that to an adversary, the +chaff blocks look as valid as the wheat blocks, and so the authentication +would have to be performed on every block. By tailoring the number of chaff +blocks added to the message, the sender can make breaking the message +computationally infeasible. There are many other interesting properties of +the winnow/chaff technique. + +For example, say Alice is sending a message to Bob. She packetizes the +message and performs an all-or-nothing transformation on the packets. Then +she authenticates each packet with a message authentication code (MAC). The +MAC is a hash of the data packet, and there is a secret key which she must +share with Bob (key distribution is an exercise left to the reader). She then +adds a serial number to each packet, and sends the packets to Bob. + +Bob receives the packets, and using the shared secret authentication key, +authenticates the MACs for each packet. Those packets that have bad MACs are +simply discarded. The remainder are sorted by serial number, and passed +through the reverse all-or-nothing transform. The transform means that an +eavesdropper (say Eve) must acquire all the packets before any of the data can +be read. If even one packet is missing, the data is useless. + +There's one twist: by adding chaff packets, Alice and Bob can make Eve's job +much harder, since Eve now has to break the shared secret key, or try every +combination of wheat and chaff packet to read any of the message. The cool +thing is that Bob doesn't need to add any additional code; the chaff packets +are already filtered out because their MACs don't match (in all likelihood -- +since the data and MACs for the chaff packets are randomly chosen it is +possible, but very unlikely that a chaff MAC will match the chaff data). And +Alice need not even be the party adding the chaff! She could be completely +unaware that a third party, say Charles, is adding chaff packets to her +messages as they are transmitted. + +**Chaff(factor=1.0, blocksper=1)**: +Class implementing the chaff adding algorithm. +``factor`` is the number of message blocks +to add chaff to, expressed as a percentage between 0.0 and 1.0; the default value is 1.0. +``blocksper`` is the number of chaff blocks to include for each block +being chaffed, and defaults to 1. The default settings +add one chaff block to every +message block. By changing the defaults, you can adjust how +computationally difficult it could be for an adversary to +brute-force crack the message. The difficulty is expressed as:: + + pow(blocksper, int(factor * number-of-blocks)) + +For ease of implementation, when ``factor`` < 1.0, only the first +``int(factor*number-of-blocks)`` message blocks are chaffed. + +``Chaff`` instances have the following methods: + +**chaff(blocks)**: +Add chaff to message blocks. ``blocks`` is a list of 3-tuples of the +form ``(serial-number, data, MAC)``. + +Chaff is created by choosing a random number of the same +byte-length as ``data``, and another random number of the same +byte-length as ``MAC``. The message block's serial number is placed +on the chaff block and all the packet's chaff blocks are randomly +interspersed with the single wheat block. This method then +returns a list of 3-tuples of the same form. Chaffed blocks will +contain multiple instances of 3-tuples with the same serial +number, but the only way to figure out which blocks are wheat and +which are chaff is to perform the MAC hash and compare values. + + + +Crypto.PublicKey: Public-Key Algorithms +-------------------------------------------------- + +So far, the encryption algorithms described have all been *private key* +ciphers. The same key is used for both encryption and decryption +so all correspondents must know it. This poses a problem: you may +want encryption to communicate sensitive data over an insecure +channel, but how can you tell your correspondent what the key is? You +can't just e-mail it to her because the channel is insecure. One +solution is to arrange the key via some other way: over the phone or +by meeting in person. + +Another solution is to use **public-key** cryptography. In a public +key system, there are two different keys: one for encryption and one for +decryption. The encryption key can be made public by listing it in a +directory or mailing it to your correspondent, while you keep the +decryption key secret. Your correspondent then sends you data encrypted +with your public key, and you use the private key to decrypt it. While +the two keys are related, it's very difficult to derive the private key +given only the public key; however, deriving the private key is always +possible given enough time and computing power. This makes it very +important to pick keys of the right size: large enough to be secure, but +small enough to be applied fairly quickly. + +Many public-key algorithms can also be used to sign messages; simply +run the message to be signed through a decryption with your private +key key. Anyone receiving the message can encrypt it with your +publicly available key and read the message. Some algorithms do only +one thing, others can both encrypt and authenticate. + +The currently available public-key algorithms are listed in the +following table: + +============= ========================================== +Algorithm Capabilities +============= ========================================== +RSA Encryption, authentication/signatures +ElGamal Encryption, authentication/signatures +DSA Authentication/signatures +============= ========================================== + +Many of these algorithms are patented. Before using any of them in a +commercial product, consult a patent attorney; you may have to arrange +a license with the patent holder. + +An example of using the RSA module to sign a message:: + + >>> from Crypto.Hash import MD5 + >>> from Crypto.PublicKey import RSA + >>> from Crypto import Random + >>> rng = Random.new().read + >>> RSAkey = RSA.generate(2048, rng) # This will take a while... + >>> hash = MD5.new(plaintext).digest() + >>> signature = RSAkey.sign(hash, rng) + >>> signature # Print what an RSA sig looks like--you don't really care. + ('\021\317\313\336\264\315' ...,) + >>> RSAkey.verify(hash, signature) # This sig will check out + 1 + >>> RSAkey.verify(hash[:-1], signature)# This sig will fail + 0 + +Public-key modules make the following functions available: + +**construct(tuple)**: +Constructs a key object from a tuple of data. This is +algorithm-specific; look at the source code for the details. (To be +documented later.) + +**generate(size, randfunc, progress_func=None, e=65537)**: +Generate a fresh public/private key pair. ``size`` is a +algorithm-dependent size parameter, usually measured in bits; the +larger it is, the more difficult it will be to break the key. Safe +key sizes vary from algorithm to algorithm; you'll have to research +the question and decide on a suitable key size for your application. +An N-bit keys can encrypt messages up to N-1 bits long. + +``randfunc`` is a random number generation function; it should +accept a single integer ``N`` and return a string of random data +``N`` bytes long. You should always use a cryptographically secure +random number generator, such as the one defined in the +``Crypto.Random`` module; **don't** just use the +current time and the ``random`` module. + +``progress_func`` is an optional function that will be called with a short +string containing the key parameter currently being generated; it's +useful for interactive applications where a user is waiting for a key +to be generated. + +``e`` is the public RSA exponent, and must be an odd positive integer. +It is typically a small number with very few ones in its binary representation. +The default value 65537 (=0b10000000000000001) is a safe choice: other +common values are 5, 7, 17, and 257. Exponent 3 is also widely used, +but it requires very special care when padding the message. + +If you want to interface with some other program, you will have to know +the details of the algorithm being used; this isn't a big loss. If you +don't care about working with non-Python software, simply use the +``pickle`` module when you need to write a key or a signature to a +file. It's portable across all the architectures that Python supports, +and it's simple to use. + +In case interoperability were important, RSA key objects can be exported +and imported in two standard formats: the DER binary encoding specified in +PKCS#1 (see RFC3447) or the ASCII textual encoding specified by the +old Privacy Enhanced Mail services (PEM, see RFC1421). + + +The RSA module makes the following function available for importing keys: + +**importKey(externKey)**: +Import an RSA key (pubic or private) encoded as a string ``externKey``. +The key can follow either the PKCS#1/DER format (binary) or the PEM format +(7-bit ASCII). + +For instance: + >>> from Crypto.PublicKey import RSA + >>> f = open("mykey.pem") + >>> RSAkey = RSA.importKey(f.read()) + >>> if RSAkey.has_private(): print "Private key" + +Every RSA object supports the following method to export itself: + +**exportKey(format='PEM')**: +Return the key encoded as a string, according to the specified ``format``: +``'PEM'`` (default) or ``'DER'`` (also known as PKCS#1). + +For instance: + >>> from Crypto.PublicKey import RSA + >>> from Crypto import Random + >>> rng = Random.new().read + >>> RSAkey = RSA.generate(1024, rng) + >>> f = open("keyPrivate.der","w+") + >>> f.write(RSAkey.exportKey("DER")) + >>> f.close() + >>> f = open("keyPublic.pem","w+") + >>> f.write(RSAkey.publickey().exportKey("PEM")) + >>> f.close() + +Public-key objects always support the following methods. Some of them +may raise exceptions if their functionality is not supported by the +algorithm. + + +**can_blind()**: +Returns true if the algorithm is capable of blinding data; +returns false otherwise. + + +**can_encrypt()**: +Returns true if the algorithm is capable of encrypting and decrypting +data; returns false otherwise. To test if a given key object can encrypt +data, use ``key.can_encrypt() and key.has_private()``. + + +**can_sign()**: +Returns true if the algorithm is capable of signing data; returns false +otherwise. To test if a given key object can sign data, use +``key.can_sign() and key.has_private()``. + + +**decrypt(tuple)**: +Decrypts ``tuple`` with the private key, returning another string. +This requires the private key to be present, and will raise an exception +if it isn't present. It will also raise an exception if ``string`` is +too long. + + +**encrypt(string, K)**: +Encrypts ``string`` with the private key, returning a tuple of +strings; the length of the tuple varies from algorithm to algorithm. +``K`` should be a string of random data that is as long as +possible. Encryption does not require the private key to be present +inside the key object. It will raise an exception if ``string`` is +too long. For ElGamal objects, the value of ``K`` expressed as a +big-endian integer must be relatively prime to ``self.p-1``; an +exception is raised if it is not. +Python 3.x: ```string``` must be an object interpretable as a buffer of bytes. + + +**has_private()**: +Returns true if the key object contains the private key data, which +will allow decrypting data and generating signatures. +Otherwise this returns false. + + +**publickey()**: +Returns a new public key object that doesn't contain the private key +data. + + +**sign(string, K)**: +Sign ``string``, returning a signature, which is just a tuple; in +theory the signature may be made up of any Python objects at all; in +practice they'll be either strings or numbers. ``K`` should be a +string of random data that is as long as possible. Different algorithms +will return tuples of different sizes. ``sign()`` raises an +exception if ``string`` is too long. For ElGamal objects, the value +of ``K`` expressed as a big-endian integer must be relatively prime to +``self.p-1``; an exception is raised if it is not. +Python 3.x: ```string``` must be an object interpretable as a buffer of bytes. + + +**size()**: +Returns the maximum size of a string that can be encrypted or signed, +measured in bits. String data is treated in big-endian format; the most +significant byte comes first. (This seems to be a **de facto** standard +for cryptographical software.) If the size is not a multiple of 8, then +some of the high order bits of the first byte must be zero. Usually +it's simplest to just divide the size by 8 and round down. + + +**verify(string, signature)**: +Returns true if the signature is valid, and false otherwise. +``string`` is not processed in any way; ``verify`` does +not run a hash function over the data, but you can easily do that yourself. +Python 3.x: ```string``` must be an object interpretable as a buffer of bytes. + + +The ElGamal and DSA algorithms +================================================== + +For RSA, the ``K`` parameters are unused; if you like, you can just +pass empty strings. The ElGamal and DSA algorithms require a real +``K`` value for technical reasons; see Schneier's book for a detailed +explanation of the respective algorithms. This presents a possible +hazard that can inadvertently reveal the private key. Without going into the +mathematical details, the danger is as follows. ``K`` is never derived +or needed by others; theoretically, it can be thrown away once the +encryption or signing operation is performed. However, revealing +``K`` for a given message would enable others to derive the secret key +data; worse, reusing the same value of ``K`` for two different +messages would also enable someone to derive the secret key data. An +adversary could intercept and store every message, and then try deriving +the secret key from each pair of messages. + +This places implementors on the horns of a dilemma. On the one hand, +you want to store the ``K`` values to avoid reusing one; on the other +hand, storing them means they could fall into the hands of an adversary. +One can randomly generate ``K`` values of a suitable length such as +128 or 144 bits, and then trust that the random number generator +probably won't produce a duplicate anytime soon. This is an +implementation decision that depends on the desired level of security +and the expected usage lifetime of a private key. I can't choose and +enforce one policy for this, so I've added the ``K`` parameter to the +``encrypt`` and ``sign`` methods. You must choose ``K`` by +generating a string of random data; for ElGamal, when interpreted as a +big-endian number (with the most significant byte being the first byte +of the string), ``K`` must be relatively prime to ``self.p-1``; any +size will do, but brute force searches would probably start with small +primes, so it's probably good to choose fairly large numbers. It might be +simplest to generate a prime number of a suitable length using the +``Crypto.Util.number`` module. + + +Security Notes for Public-key Algorithms +================================================== + +Any of these algorithms can be trivially broken; for example, RSA can be +broken by factoring the modulus *n* into its two prime factors. +This is easily done by the following code:: + + for i in range(2, n): + if (n%i)==0: + print i, 'is a factor' + break + +However, ``n`` is usually a few hundred bits long, so this simple +program wouldn't find a solution before the universe comes to an end. +Smarter algorithms can factor numbers more quickly, but it's still +possible to choose keys so large that they can't be broken in a +reasonable amount of time. For ElGamal and DSA, discrete logarithms are +used instead of factoring, but the principle is the same. + +Safe key sizes depend on the current state of number theory and +computer technology. At the moment, one can roughly define three +levels of security: low-security commercial, high-security commercial, +and military-grade. For RSA, these three levels correspond roughly to +768, 1024, and 2048-bit keys. + +When exporting private keys you should always carefully ensure that the +chosen storage location cannot be accessed by adversaries. + +Crypto.Util: Odds and Ends +-------------------------------------------------- + +This chapter contains all the modules that don't fit into any of the +other chapters. + + +Crypto.Util.number +========================== + +This module contains various number-theoretic functions. + +**GCD(x,y)**: +Return the greatest common divisor of ``x`` and ``y``. + +**getPrime(N, randfunc)**: +Return an ``N``-bit random prime number, using random data obtained +from the function ``randfunc``. ``randfunc`` must take a single +integer argument, and return a string of random data of the +corresponding length; the ``get_bytes()`` method of a +``RandomPool`` object will serve the purpose nicely, as will the +``read()`` method of an opened file such as ``/dev/random``. + +**getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None)**: +Return a random strong ``N``-bit prime number. +In this context p is a strong prime if p-1 and p+1 have at +least one large prime factor. +``N`` should be a multiple of 128 and > 512. + +If ``e`` is provided the returned prime p-1 will be coprime to ``e`` +and thus suitable for RSA where e is the public exponent. + +The optional ``false_positive_prob`` is the statistical probability +that true is returned even though it is not (pseudo-prime). +It defaults to 1e-6 (less than 1:1000000). +Note that the real probability of a false-positive is far less. This is +just the mathematically provable limit. + +``randfunc`` should take a single int parameter and return that +many random bytes as a string. +If randfunc is omitted, then ``Random.new().read`` is used. + +**getRandomNBitInteger(N, randfunc)**: +Return an ``N``-bit random number, using random data obtained from the +function ``randfunc``. As usual, ``randfunc`` must take a single +integer argument and return a string of random data of the +corresponding length. + +**getRandomNBitInteger(N, randfunc)**: +Return an ``N``-bit random number, using random data obtained from the +function ``randfunc``. As usual, ``randfunc`` must take a single +integer argument and return a string of random data of the +corresponding length. + +**inverse(u, v)**: +Return the inverse of ``u`` modulo ``v``. + +**isPrime(N)**: +Returns true if the number ``N`` is prime, as determined by a +Rabin-Miller test. + + +Crypto.Random +================================================== + +For cryptographic purposes, ordinary random number generators are +frequently insufficient, because if some of their output is known, it +is frequently possible to derive the generator's future (or past) +output. Given the generator's state at some point in time, someone +could try to derive any keys generated using it. The solution is to +use strong encryption or hashing algorithms to generate successive +data; this makes breaking the generator as difficult as breaking the +algorithms used. + +Understanding the concept of **entropy** is important for using the +random number generator properly. In the sense we'll be using it, +entropy measures the amount of randomness; the usual unit is in bits. +So, a single random bit has an entropy of 1 bit; a random byte has an +entropy of 8 bits. Now consider a one-byte field in a database containing a +person's sex, represented as a single character ``'M'`` or ``'F'``. +What's the entropy of this field? Since there are only two possible +values, it's not 8 bits, but one; if you were trying to guess the value, +you wouldn't have to bother trying ``'Q'`` or ``'@'``. + +Now imagine running that single byte field through a hash function that +produces 128 bits of output. Is the entropy of the resulting hash value +128 bits? No, it's still just 1 bit. The entropy is a measure of how many +possible states of the data exist. For English +text, the entropy of a five-character string is not 40 bits; it's +somewhat less, because not all combinations would be seen. ``'Guido'`` +is a possible string, as is ``'In th'``; ``'zJwvb'`` is not. + +The relevance to random number generation? We want enough bits of +entropy to avoid making an attack on our generator possible. An +example: One computer system had a mechanism which generated nonsense +passwords for its users. This is a good idea, since it would prevent +people from choosing their own name or some other easily guessed string. +Unfortunately, the random number generator used only had 65536 states, +which meant only 65536 different passwords would ever be generated, and +it was easy to compute all the possible passwords and try them. The +entropy of the random passwords was far too low. By the same token, if +you generate an RSA key with only 32 bits of entropy available, there +are only about 4.2 billion keys you could have generated, and an +adversary could compute them all to find your private key. See +RFC 1750, +"Randomness Recommendations for Security", for an interesting discussion +of the issues related to random number generation. + +The ``Random`` module builds strong random number generators that look +like generic files a user can read data from. The internal state consists +of entropy accumulators based on the best randomness sources the underlying +operating is capable to provide. + +The ``Random`` module defines the following methods: + +**new()**: +Builds a file-like object that outputs cryptographically random bytes. + +**atfork()**: +This methods has to be called whenever os.fork() is invoked. Forking +undermines the security of any random generator based on the operating +system, as it duplicates all structures a program has. In order to +thwart possible attacks, this method shoud be called soon after forking, +and before any cryptographic operation. + +**get_random_bytes(num)**: +Returns a string containing ``num`` bytes of random data. + +Objects created by the ``Random`` module define the following variables and methods: + +**read(num)**: +Returns a string containing ``num`` bytes of random data. + +**close()**: +**flush()**: +Do nothing. Provided for consistency. + +Crypto.Util.RFC1751 +================================================== + +The keys for private-key algorithms should be arbitrary binary data. +Many systems err by asking the user to enter a password, and then +using the password as the key. This limits the space of possible +keys, as each key byte is constrained within the range of possible +ASCII characters, 32-127, instead of the whole 0-255 range possible +with ASCII. Unfortunately, it's difficult for humans to remember 16 +or 32 hex digits. + +One solution is to request a lengthy passphrase from the user, and +then run it through a hash function such as SHA1 or MD5. Another +solution is discussed in RFC 1751, "A Convention for Human-Readable +128-bit Keys", by Daniel L. McDonald. Binary keys are transformed +into a list of short English words that should be easier to remember. +For example, the hex key EB33F77EE73D4053 is transformed to "TIDE ITCH +SLOW REIN RULE MOT". + +**key_to_english(key)**: +Accepts a string of arbitrary data ``key``, and returns a string +containing uppercase English words separated by spaces. ``key``'s +length must be a multiple of 8. + +**english_to_key(string)**: +Accepts ``string`` containing English words, and returns a string of +binary data representing the key. Words must be separated by +whitespace, and can be any mixture of uppercase and lowercase +characters. 6 words are required for 8 bytes of key data, so +the number of words in ``string`` must be a multiple of 6. + + +Extending the Toolkit +-------------------------------------------------- + +Preserving a common interface for cryptographic routines is a good +idea. This chapter explains how to write new modules for the Toolkit. + +The basic process is as follows: + +1. Add a new ``.c`` file containing an implementation of the new +algorithm. +This file must define 3 or 4 standard functions, +a few constants, and a C ``struct`` encapsulating the state +variables required by the algorithm. + +2. Add the new algorithm to ``setup.py``. + +3. Send a copy of the code to me, if you like; code for new +algorithms will be gratefully accepted. + + +Adding Hash Algorithms +================================================== + +The required constant definitions are as follows:: + + #define MODULE_NAME MD2 /* Name of algorithm */ + #define DIGEST_SIZE 16 /* Size of resulting digest in bytes */ + +The C structure must be named ``hash_state``:: + + typedef struct { + ... whatever state variables you need ... + } hash_state; + +There are four functions that need to be written: to initialize the +algorithm's state, to hash a string into the algorithm's state, to get +a digest from the current state, and to copy a state. + +* ``void hash_init(hash_state *self);`` +* ``void hash_update(hash_state *self, unsigned char *buffer, int length);`` +* ``PyObject *hash_digest(hash_state *self);`` +* ``void hash_copy(hash_state *source, hash_state *dest);`` + +Put ``#include "hash_template.c"`` at the end of the file to +include the actual implementation of the module. + + +Adding Block Encryption Algorithms +================================================== + +The required constant definitions are as follows:: + +#define MODULE_NAME AES /* Name of algorithm */ +#define BLOCK_SIZE 16 /* Size of encryption block */ +#define KEY_SIZE 0 /* Size of key in bytes (0 if not fixed size) */ + +The C structure must be named ``block_state``:: + + typedef struct { + ... whatever state variables you need ... + } block_state; + +There are three functions that need to be written: to initialize the +algorithm's state, and to encrypt and decrypt a single block. + +* ``void block_init(block_state *self, unsigned char *key, int keylen);`` +* ``void block_encrypt(block_state *self, unsigned char *in, unsigned char *out);`` +* ``void block_decrypt(block_state *self, unsigned char *in, unsigned char *out);`` + +Put ``#include "block_template.c"`` at the end of the file to +include the actual implementation of the module. + + +Adding Stream Encryption Algorithms +================================================== + +The required constant definitions are as follows:: + + #define MODULE_NAME ARC4 /* Name of algorithm */ + #define BLOCK_SIZE 1 /* Will always be 1 for a stream cipher */ + #define KEY_SIZE 0 /* Size of key in bytes (0 if not fixed size) */ + +The C structure must be named ``stream_state``:: + + typedef struct { + ... whatever state variables you need ... + } stream_state; + +There are three functions that need to be written: to initialize the +algorithm's state, and to encrypt and decrypt a single block. + +* ``void stream_init(stream_state *self, unsigned char *key, int keylen);`` +* ``void stream_encrypt(stream_state *self, unsigned char *block, int length);`` +* ``void stream_decrypt(stream_state *self, unsigned char *block, int length);`` + +Put ``#include "stream_template.c"`` at the end of the file to +include the actual implementation of the module. diff --git a/LEGAL/00INDEX b/LEGAL/00INDEX new file mode 100644 index 0000000..ae237d7 --- /dev/null +++ b/LEGAL/00INDEX @@ -0,0 +1,3 @@ +00INDEX - This file +tsu-notify.mbox - Notification sent per U.S. export regulations +copy/ - Copyright info & public-domain dedications diff --git a/LEGAL/CodeSubmissionRequirements.txt b/LEGAL/CodeSubmissionRequirements.txt new file mode 100644 index 0000000..e86ad61 --- /dev/null +++ b/LEGAL/CodeSubmissionRequirements.txt @@ -0,0 +1,49 @@ +PyCrypto Code Submission Requirements - Rev. C + +Last updated: 2009-02-28 + +In an effort to further clarify PyCrypto's licensing terms, anyone submitting +code to PyCrypto must be able to certify the following (taken from the Linux +kernel's SubmittingPatches file): + + Developer's Certificate of Origin 1.1 + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +In addition, the code's author must not be a national, citizen, or resident of +the United States of America. + +In addition, the code must not be of U.S. origin. + +In addition, all new code contributed to PyCrypto must be dedicated to the +public domain as follows: + + The contents of this file are dedicated to the public domain. To the extent + that dedication to the public domain is not available, everyone is granted a + worldwide, perpetual, royalty-free, non-exclusive license to exercise all + rights associated with the contents of this file for any purpose whatsoever. + No rights are reserved. + +=== EOF === diff --git a/LEGAL/copy/00INDEX b/LEGAL/copy/00INDEX new file mode 100644 index 0000000..fbdca18 --- /dev/null +++ b/LEGAL/copy/00INDEX @@ -0,0 +1,4 @@ +00INDEX This file +LICENSE.orig Original (deprecated) license for the Python Cryptography Toolkit +LICENSE.libtom LICENSE file from LibTomCrypt +stmts/ Statements by contributors diff --git a/LEGAL/copy/LICENSE.libtom b/LEGAL/copy/LICENSE.libtom new file mode 100644 index 0000000..5d678c5 --- /dev/null +++ b/LEGAL/copy/LICENSE.libtom @@ -0,0 +1,5 @@ +LibTomCrypt is public domain. As should all quality software be. + +Tom St Denis + + diff --git a/LEGAL/copy/LICENSE.orig b/LEGAL/copy/LICENSE.orig new file mode 100644 index 0000000..ad3ae41 --- /dev/null +++ b/LEGAL/copy/LICENSE.orig @@ -0,0 +1,15 @@ +=================================================================== +Distribute and use freely; there are no restrictions on further +dissemination and usage except those imposed by the laws of your +country of residence. This software is provided "as is" without +warranty of fitness for use or suitability for any purpose, express +or implied. Use at your own risk or not at all. +=================================================================== + +Incorporating the code into commercial products is permitted; you do +not have to make source available or contribute your changes back +(though that would be nice). + +--amk (www.amk.ca) + + diff --git a/LEGAL/copy/LICENSE.python-2.2 b/LEGAL/copy/LICENSE.python-2.2 new file mode 100644 index 0000000..ca4d98e --- /dev/null +++ b/LEGAL/copy/LICENSE.python-2.2 @@ -0,0 +1,253 @@ +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations (now Zope +Corporation, see http://www.zope.com). In 2001, the Python Software +Foundation (PSF, see http://www.python.org/psf/) was formed, a +non-profit organization created specifically to own Python-related +Intellectual Property. Zope Corporation is a sponsoring member of +the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI no + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.2 2.1.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2.1 2.2 2002 PSF yes + 2.2.2 2.2.1 2002 PSF yes + 2.2.3 2.2.2 2003 PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PSF LICENSE AGREEMENT FOR PYTHON 2.2.3 +-------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using Python 2.2.3 software in source or binary form and its +associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 2.2.3 +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001, 2002, 2003 Python Software Foundation; All Rights Reserved" are +retained in Python 2.2.3 alone or in any derivative version prepared +by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 2.2.3 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 2.2.3. + +4. PSF is making Python 2.2.3 available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.2.3 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +2.2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.2.3, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python 2.2.3, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the Internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the Internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/LEGAL/copy/stmts/Andrew_M_Kuchling.mbox b/LEGAL/copy/stmts/Andrew_M_Kuchling.mbox new file mode 100644 index 0000000..a0dcb78 --- /dev/null +++ b/LEGAL/copy/stmts/Andrew_M_Kuchling.mbox @@ -0,0 +1,156 @@ +From dlitz@dlitz.net Sun Nov 23 00:17:22 2008 +Date: Sun, 23 Nov 2008 00:17:22 -0500 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: "A. M. Kuchling" <amk@amk.ca> +Subject: PyCrypto license clarification +Message-ID: <20081123051722.GA29253@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: multipart/signed; micalg=pgp-sha1; + protocol="application/pgp-signature"; boundary="YiEDa0DAkWCtVeE4" +Content-Disposition: inline +X-Primary-Address: dlitz@dlitz.net +X-Homepage: http://www.dlitz.net/ +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=19E11FE8B3CFF273ED174A24928CEC1339C25CF7 (only for key signing); + preference=unprotected +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=4B2AFD82FC7D9E3838D9179F1C11B877E7804B45 (2008); + preference=signencrypt +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 3461 +Lines: 78 + + +--YiEDa0DAkWCtVeE4 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +Content-Transfer-Encoding: quoted-printable + +Hi Andrew, + +People often ask me what license PyCrypto is covered by, if it's=20 +GPL-compatible, etc. Right now, I'm not really sure what to tell them. =20 +The text in the current LICENSE file (quoted below) is not entirely clear= +=20 +on the point of whether distributing modified versions is allowed. (It=20 +says "distribute and use", but not "modify".) + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + Distribute and use freely; there are no restrictions on further + dissemination and usage except those imposed by the laws of your + country of residence. This software is provided "as is" without + warranty of fitness for use or suitability for any purpose, express + or implied. Use at your own risk or not at all. + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + + Incorporating the code into commercial products is permitted; you do + not have to make source available or contribute your changes back + (though that would be nice). + + --amk (www.amk.ca) + +For the next PyCrypto release, I'd like to take steps to move toward a=20 +clearer licensing regime. I'm asking as many copyright holders as I can=20 +find, starting with you, if I can release PyCrypto under something clearer= +=20 +and more standard. Below, I have quoted a public domain dedication that=20 +was recommended in _Intellectual Property and Open Source: A Practical=20 +Guide to Protecting Code_, by Van Lindberg. + +May I, on your behalf, dedicate to the public domain your considerable=20 +contributions to PyCrypto, with the following notice? + + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + The contents of this file are dedicated to the public domain. To the + extent that dedication to the public domain is not available, everyone + is granted a worldwide, perpetual, royalty-free, non-exclusive license + to exercise all rights associated with the contents of this file for + any purpose whatsoever. No rights are reserved. + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Regards, + - Dwayne + +--=20 +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + Annual key (2008) - 4B2A FD82 FC7D 9E38 38D9 179F 1C11 B877 E780 4B45 + +--YiEDa0DAkWCtVeE4 +Content-Type: application/pgp-signature; name="signature.asc" +Content-Description: Digital signature +Content-Disposition: inline + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.5 (GNU/Linux) + +iEYEARECAAYFAkko52IACgkQHBG4d+eAS0XPPQCfcyQ2DdAXKg9N7Z+jeSFFD5EZ +yloAn33a3ZjkteyJaTbzEqImOEW8JGpf +=aBEW +-----END PGP SIGNATURE----- + +--YiEDa0DAkWCtVeE4-- + +From amk@amk.ca Sun Nov 23 07:51:59 2008 +X-Maildir-Dup-Checked: Yes +Return-Path: <amk@amk.ca> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id 5C2C75047D + for <dwon@rivest.dlitz.net>; Sun, 23 Nov 2008 07:51:59 -0500 (EST) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id D632D10111 + for <dwon@rivest.dlitz.net>; Sun, 23 Nov 2008 06:51:58 -0600 (CST) +Received: (vmailmgr-postfix 12026 invoked by uid 1003); 23 Nov 2008 06:51:58 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: none (goedel.dlitz.net: domain of amk@amk.ca does not designate permitted sender hosts) +Received: from mail5.sea5.speakeasy.net (mail5.sea5.speakeasy.net [69.17.117.7]) + by goedel.dlitz.net (Postfix) with ESMTP id 97DC710105 + for <dlitz@dlitz.net>; Sun, 23 Nov 2008 06:51:58 -0600 (CST) +Received: (qmail 3992 invoked from network); 23 Nov 2008 12:51:52 -0000 +Received: from dsl092-163-165.wdc2.dsl.speakeasy.net (HELO localhost) (akuchling@[66.92.163.165]) + (envelope-sender <amk@amk.ca>) + by mail5.sea5.speakeasy.net (qmail-ldap-1.03) with AES256-SHA encrypted SMTP + for <dlitz@dlitz.net>; 23 Nov 2008 12:51:52 -0000 +Date: Sun, 23 Nov 2008 07:51:34 -0500 +From: "A.M. Kuchling" <amk@amk.ca> +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +Subject: Re: PyCrypto license clarification +Message-ID: <20081123125134.GA21239@amk.local> +Reply-To: amk@amk.ca +References: <20081123051722.GA29253@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20081123051722.GA29253@rivest.dlitz.net> +User-Agent: Mutt/1.5.13 (2006-08-11) +Status: RO +Content-Length: 537 +Lines: 15 + +> People often ask me what license PyCrypto is covered by, if it's +> GPL-compatible, etc. Right now, I'm not really sure what to tell them. +> The text in the current LICENSE file (quoted below) is not entirely clear +> on the point of whether distributing modified versions is allowed. (It +> says "distribute and use", but not "modify".) + +The intention is that it be public domain. + +> May I, on your behalf, dedicate to the public domain your considerable +> contributions to PyCrypto, with the following notice? + +You may. + +--amk + + diff --git a/LEGAL/copy/stmts/Barry_A_Warsaw.mbox b/LEGAL/copy/stmts/Barry_A_Warsaw.mbox new file mode 100644 index 0000000..ed03b6d --- /dev/null +++ b/LEGAL/copy/stmts/Barry_A_Warsaw.mbox @@ -0,0 +1,135 @@ +From dlitz@dlitz.net Sat Feb 28 21:45:09 2009 +Date: Sat, 28 Feb 2009 21:45:09 -0500 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: Barry A Warsaw <barry@python.org> +Subject: PyCrypto license clarification +Message-ID: <20090301024509.GA13195@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 2535 + +Hi Barry, + +I am the new maintainer of the Python Cryptography Toolkit, and I am +working on a new release at http://www.pycrypto.org/. + +People often ask me what license PyCrypto is covered by, if it's +GPL-compatible, etc. Right now, I'm not really sure what to tell them. +The text in the current LICENSE file (quoted below) is not entirely clear +on the point of whether distributing modified versions is allowed. (It +says "distribute and use", but not "modify".) + + =================================================================== + Distribute and use freely; there are no restrictions on further + dissemination and usage except those imposed by the laws of your + country of residence. This software is provided "as is" without + warranty of fitness for use or suitability for any purpose, express + or implied. Use at your own risk or not at all. + =================================================================== + + Incorporating the code into commercial products is permitted; you do + not have to make source available or contribute your changes back + (though that would be nice). + + --amk (www.amk.ca) + +For the next PyCrypto release, I would like to take steps to move toward a +clearer licensing regime. I am asking as many copyright holders as I can +find if I can release PyCrypto under something clearer and more standard. +Below, I have quoted a public domain dedication that was recommended in +_Intellectual Property and Open Source: A Practical Guide to Protecting +Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +Pointer, and Wim Lewis, and they have all approved the following dedication +for their contributions. + +I understand that you have made contributions to PyCrypto. May I, on your +behalf, dedicate to the public domain all your contributions to PyCrypto, +with the following notice? + + ======================================================================= + The contents of this file are dedicated to the public domain. To the + extent that dedication to the public domain is not available, everyone + is granted a worldwide, perpetual, royalty-free, non-exclusive license + to exercise all rights associated with the contents of this file for + any purpose whatsoever. No rights are reserved. + ======================================================================= + +Regards, + - Dwayne + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + +From barry@python.org Mon Mar 2 11:29:39 2009 +X-Maildir-Dup-Checked: Yes +Return-Path: <barry@python.org> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id 6E01AC6640B + for <dwon@rivest.dlitz.net>; Mon, 2 Mar 2009 11:29:39 -0500 (EST) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id 0644E1007A + for <dwon@rivest.dlitz.net>; Mon, 2 Mar 2009 10:29:39 -0600 (CST) +Received: (vmailmgr-postfix 8668 invoked by uid 1003); 2 Mar 2009 10:29:39 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: none (python.org: No applicable sender policy available) receiver=goedel.dlitz.net; identity=mfrom; envelope-from="barry@python.org"; helo=mail.wooz.org; client-ip=216.15.33.230 +Received: from mail.wooz.org (216-15-33-230.c3-0.slvr-ubr2.lnh-slvr.md.static.cable.rcn.com [216.15.33.230]) + by goedel.dlitz.net (Postfix) with ESMTP id CCEA110073 + for <dlitz@dlitz.net>; Mon, 2 Mar 2009 10:29:38 -0600 (CST) +Received: from snowdog.wooz.org (snowdog.wooz.org [192.168.11.202]) + by mail.wooz.org (Postfix) with ESMTPSA id ACE30E3C9F + for <dlitz@dlitz.net>; Mon, 2 Mar 2009 11:29:35 -0500 (EST) +Message-Id: <09BF1A39-B015-4820-97A3-8642490C8254@python.org> +From: Barry Warsaw <barry@python.org> +To: Dwayne C. Litzenberger <dlitz@dlitz.net> +In-Reply-To: <20090301024509.GA13195@rivest.dlitz.net> +Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes +Content-Transfer-Encoding: quoted-printable +Mime-Version: 1.0 (Apple Message framework v930.3) +Subject: Re: PyCrypto license clarification +Date: Mon, 2 Mar 2009 11:29:34 -0500 +References: <20090301024509.GA13195@rivest.dlitz.net> +X-Pgp-Agent: GPGMail d55 (v55, Leopard) +X-Mailer: Apple Mail (2.930.3) +Status: RO +Content-Length: 869 + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +On Feb 28, 2009, at 9:45 PM, Dwayne C. Litzenberger wrote: + +> I am the new maintainer of the Python Cryptography Toolkit, and I am =20= + +> working on a new release at http://www.pycrypto.org/. + +Great! I'm glad to see someone taking up the mantle of this important =20= + +Python library. + +> I understand that you have made contributions to PyCrypto. May I, =20 +> on your behalf, dedicate to the public domain all your contributions =20= + +> to PyCrypto, with the following notice? + +Absolutely yes. + +Cheers, +Barry + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.9 (Darwin) + +iQCVAwUBSawJbnEjvBPtnXfVAQLZjgP/ecG+JdZwNvPJRfsa6rhY6+MHLDHI6agk +evkJnSJQAcVHlZnVlVeR5IXgvDUMakZjU4SOV7MqkhsKA9lIet7PaD9VSYgn3ra5 +gElwI2DQDoOy5GExXMm74gqrrb1PCCbCRmpaYNo+DZohwHkeFBjbwDRA3wItOrH7 +SK4w9VBJtfY=3D +=3DQduY +-----END PGP SIGNATURE----- + + diff --git a/LEGAL/copy/stmts/Jeethu_Rao.mbox b/LEGAL/copy/stmts/Jeethu_Rao.mbox new file mode 100644 index 0000000..6147bee --- /dev/null +++ b/LEGAL/copy/stmts/Jeethu_Rao.mbox @@ -0,0 +1,277 @@ +From dlitz@dlitz.net Sat Feb 28 23:24:14 2009 +Date: Sat, 28 Feb 2009 23:24:14 -0500 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: Jeethu Rao <jeethurao@gmail.com> +Subject: PyCrypto license clarification +Message-ID: <20090301042414.GA15122@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 2513 + +Hi Jeethu, + +I am the new maintainer of the Python Cryptography Toolkit, and I am +working on a new release at http://www.pycrypto.org/. + +People often ask me what license PyCrypto is covered by, if it's +GPL-compatible, etc. Right now, I'm not really sure what to tell them. +The text in the current LICENSE file (quoted below) is not entirely clear +on the point of whether distributing modified versions is allowed. (It +says "distribute and use", but not "modify".) + + =================================================================== + Distribute and use freely; there are no restrictions on further + dissemination and usage except those imposed by the laws of your + country of residence. This software is provided "as is" without + warranty of fitness for use or suitability for any purpose, express + or implied. Use at your own risk or not at all. + =================================================================== + + Incorporating the code into commercial products is permitted; you do + not have to make source available or contribute your changes back + (though that would be nice). + + --amk (www.amk.ca) + +For the next PyCrypto release, I would like to take steps to move toward a +clearer licensing regime. I am asking as many copyright holders as I can +find if I can release PyCrypto under something clearer and more standard. +Below, I have quoted a public domain dedication that was recommended in +_Intellectual Property and Open Source: A Practical Guide to Protecting +Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +Pointer, and Wim Lewis, and they have all approved the following text for +their contributions. + +I understand that you have made contributions to PyCrypto. May I, on your +behalf, dedicate to the public domain all your contributions to PyCrypto, +with the following notice? + + ======================================================================= + The contents of this file are dedicated to the public domain. To the + extent that dedication to the public domain is not available, everyone + is granted a worldwide, perpetual, royalty-free, non-exclusive license + to exercise all rights associated with the contents of this file for + any purpose whatsoever. No rights are reserved. + ======================================================================= + +Regards, + - Dwayne + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + +From jeethurao@gmail.com Sun Mar 8 17:28:16 2009 +X-Maildir-Dup-Checked: Yes +Return-Path: <jeethurao@gmail.com> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id 0CC83515D9 + for <dwon@rivest.dlitz.net>; Sun, 8 Mar 2009 17:28:16 -0400 (EDT) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id 4E58F450CB + for <dwon@rivest.dlitz.net>; Sun, 8 Mar 2009 15:28:15 -0600 (CST) +Received: (vmailmgr-postfix 5011 invoked by uid 1003); 8 Mar 2009 15:28:15 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: pass (gmail.com ... _spf.google.com: 209.85.198.249 is authorized to use 'jeethurao@gmail.com' in 'mfrom' identity (mechanism 'ip4:209.85.128.0/17' matched)) receiver=goedel.dlitz.net; identity=mfrom; envelope-from="jeethurao@gmail.com"; helo=rv-out-0708.google.com; client-ip=209.85.198.249 +Received: from rv-out-0708.google.com (unknown [209.85.198.249]) + by goedel.dlitz.net (Postfix) with ESMTP id 3C097449E7 + for <dlitz@dlitz.net>; Sun, 8 Mar 2009 15:28:12 -0600 (CST) +Received: by rv-out-0708.google.com with SMTP id k29so1252333rvb.26 + for <dlitz@dlitz.net>; Sun, 08 Mar 2009 14:27:56 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=gamma; + h=domainkey-signature:mime-version:received:in-reply-to:references + :date:message-id:subject:from:to:content-type; + bh=YWy9U32WCU/ksRqukHwaOZyJQBUs4Yvt5mI20U6mI/g=; + b=oMjI22lIxYiJKge2zNJW3rRiUi9LqFXmey5Wp0pLItuNF+X3duyfhopTuBAKw7MwVY + B5E6VQuGVEyzBbNsctyVgq6DhQiQtouCLZymSViobmuDmKn5DtUKoxpDk0xCxQmHYaas + L9/A6D3/J66kKrNBgX9mc0GPcZTviVFYkPR0Q= +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=gmail.com; s=gamma; + h=mime-version:in-reply-to:references:date:message-id:subject:from:to + :content-type; + b=Ym7CStuDEfJKay1AJyWZkZmJA1lnTcwCG6akBHAXLld8ht6PFcmlsffzZG8hJCIVJ8 + vljqcT+G6cywVTBw1pyGX7ECYzr0+vhGvgdpACGrs24zikHfpSSd5GFogzXaLVvGVH8p + bqSHpfWKKtEP4gAQkiNeIq1GNtR2j8U3fnRyg= +MIME-Version: 1.0 +Received: by 10.141.176.13 with SMTP id d13mr2656028rvp.231.1236547674677; + Sun, 08 Mar 2009 14:27:54 -0700 (PDT) +In-Reply-To: <20090301042414.GA15122@rivest.dlitz.net> +References: <20090301042414.GA15122@rivest.dlitz.net> +Date: Mon, 9 Mar 2009 02:57:54 +0530 +Message-ID: <e3c0ddba0903081427p3a7b1058g417dd8624df68d6d@mail.gmail.com> +Subject: Re: PyCrypto license clarification +From: Jeethu Rao <jeethurao@gmail.com> +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +Content-Type: multipart/alternative; boundary=000e0cd209d0e5a3d40464a23054 +Status: RO +Content-Length: 7668 + +--000e0cd209d0e5a3d40464a23054 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit + +Hi Dwayne,My contribution to pycrypto are very very minimal (The sha256 +module, IIRC). +I'd be fine with the public domain license for PyCrypto. + +Jeethu Rao +PS: Apologies for the delay in my response. +I don't really check this email address all that often, +please direct any further correspondence to jeethu@jeethurao.com + +On Sun, Mar 1, 2009 at 9:54 AM, Dwayne C. Litzenberger <dlitz@dlitz.net>wrote: + +> Hi Jeethu, +> +> I am the new maintainer of the Python Cryptography Toolkit, and I am +> working on a new release at http://www.pycrypto.org/. +> +> People often ask me what license PyCrypto is covered by, if it's +> GPL-compatible, etc. Right now, I'm not really sure what to tell them. The +> text in the current LICENSE file (quoted below) is not entirely clear on the +> point of whether distributing modified versions is allowed. (It says +> "distribute and use", but not "modify".) +> +> =================================================================== +> Distribute and use freely; there are no restrictions on further +> dissemination and usage except those imposed by the laws of your +> country of residence. This software is provided "as is" without +> warranty of fitness for use or suitability for any purpose, express +> or implied. Use at your own risk or not at all. +> =================================================================== +> +> Incorporating the code into commercial products is permitted; you do +> not have to make source available or contribute your changes back +> (though that would be nice). +> +> --amk (www.amk.ca) +> +> For the next PyCrypto release, I would like to take steps to move toward a +> clearer licensing regime. I am asking as many copyright holders as I can +> find if I can release PyCrypto under something clearer and more standard. +> Below, I have quoted a public domain dedication that was recommended in +> _Intellectual Property and Open Source: A Practical Guide to Protecting +> Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +> Pointer, and Wim Lewis, and they have all approved the following text for +> their contributions. +> +> I understand that you have made contributions to PyCrypto. May I, on your +> behalf, dedicate to the public domain all your contributions to PyCrypto, +> with the following notice? +> +> ======================================================================= +> The contents of this file are dedicated to the public domain. To the +> extent that dedication to the public domain is not available, everyone +> is granted a worldwide, perpetual, royalty-free, non-exclusive license +> to exercise all rights associated with the contents of this file for +> any purpose whatsoever. No rights are reserved. +> ======================================================================= +> +> Regards, +> - Dwayne +> +> -- +> Dwayne C. Litzenberger <dlitz@dlitz.net> +> Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 +> + + + +-- +Jeethu Rao + +--000e0cd209d0e5a3d40464a23054 +Content-Type: text/html; charset=ISO-8859-1 +Content-Transfer-Encoding: quoted-printable + +Hi Dwayne,<div>My contribution to pycrypto are very very minimal (The sha25= +6 module, IIRC).</div><div>I'd be fine with the public domain license f= +or PyCrypto.</div><div><br></div><div>Jeethu Rao</div><div>PS: Apologies fo= +r the delay in my response.=A0</div> +<div>I don't really check this email address all that often,</div><div>= +please direct any further correspondence to <a href=3D"mailto:jeethu@jeethu= +rao.com">jeethu@jeethurao.com</a><br><div><br><div class=3D"gmail_quote">On= + Sun, Mar 1, 2009 at 9:54 AM, Dwayne C. Litzenberger <span dir=3D"ltr"><= +<a href=3D"mailto:dlitz@dlitz.net">dlitz@dlitz.net</a>></span> wrote:<br= +> +<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= +x #ccc solid;padding-left:1ex;">Hi Jeethu,<br> +<br> +I am the new maintainer of the Python Cryptography Toolkit, and I am workin= +g on a new release at <a href=3D"http://www.pycrypto.org/" target=3D"_blank= +">http://www.pycrypto.org/</a>.<br> +<br> +People often ask me what license PyCrypto is covered by, if it's GPL-co= +mpatible, etc. =A0Right now, I'm not really sure what to tell them. =A0= +The text in the current LICENSE file (quoted below) is not entirely clear o= +n the point of whether distributing modified versions is allowed. =A0(It sa= +ys "distribute and use", but not "modify".)<br> + +<br> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br> +Distribute and use freely; there are no restrictions on further<br> +dissemination and usage except those imposed by the laws of your<br> +country of residence. =A0This software is provided "as is" withou= +t<br> +warranty of fitness for use or suitability for any purpose, express<br> +or implied. Use at your own risk or not at all.<br> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br> +<br> +Incorporating the code into commercial products is permitted; you do<br> +not have to make source available or contribute your changes back<br> +(though that would be nice).<br> +<br> +--amk =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = +=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(<a href=3D"http://www.amk.ca" target=3D= +"_blank">www.amk.ca</a>)<br> +<br> +For the next PyCrypto release, I would like to take steps to move toward a = +clearer licensing regime. =A0I am asking as many copyright holders as I can= + find if I can release PyCrypto under something clearer and more standard. = +=A0Below, I have quoted a public domain dedication that was recommended in = +_Intellectual Property and Open Source: A Practical Guide to Protecting Cod= +e_, by Van Lindberg. =A0I have already contacted A. M. Kuchling, Robey Poin= +ter, and Wim Lewis, and they have all approved the following text for their= + contributions.<br> + +<br> +I understand that you have made contributions to PyCrypto. =A0May I, on you= +r behalf, dedicate to the public domain all your contributions to PyCrypto,= + with the following notice?<br> +<br> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br> +The contents of this file are dedicated to the public domain. =A0To the<br> +extent that dedication to the public domain is not available, everyone<br> +is granted a worldwide, perpetual, royalty-free, non-exclusive license<br> +to exercise all rights associated with the contents of this file for<br> +any purpose whatsoever. =A0No rights are reserved.<br> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br> +<br> +Regards,<br> +- Dwayne<br><font color=3D"#888888"> +<br> +-- <br> +Dwayne C. Litzenberger <<a href=3D"mailto:dlitz@dlitz.net" target=3D"_bl= +ank">dlitz@dlitz.net</a>><br> + =A0 =A0 =A0Key-signing key =A0 - 19E1 1FE8 B3CF F273 ED17 =A04A24 928C EC1= +3 39C2 5CF7<br> +</font></blockquote></div><br><br clear=3D"all"><br>-- <br>Jeethu Rao<br> +</div></div> + +--000e0cd209d0e5a3d40464a23054-- + + diff --git a/LEGAL/copy/stmts/Joris_Bontje.mbox b/LEGAL/copy/stmts/Joris_Bontje.mbox new file mode 100644 index 0000000..b60dba5 --- /dev/null +++ b/LEGAL/copy/stmts/Joris_Bontje.mbox @@ -0,0 +1,298 @@ +From dlitz@dlitz.net Mon May 4 22:49:14 2009 +Date: Mon, 4 May 2009 22:49:14 -0400 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: Joris Bontje <joris@bontje.nl> +Subject: PyCrypto license clarification +Message-ID: <20090505024914.GA9219@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 2553 + +Hi Joris, + +I am the new maintainer of the Python Cryptography Toolkit, and I am +working on a new release at http://www.pycrypto.org/. + +People often ask me what license PyCrypto is covered by, if it's +GPL-compatible, etc. Right now, I'm not really sure what to tell them. +The text in the current LICENSE file (quoted below) is not entirely clear +on the point of whether distributing modified versions is allowed. (It +says "distribute and use", but not "modify".) + + =================================================================== + Distribute and use freely; there are no restrictions on further + dissemination and usage except those imposed by the laws of your + country of residence. This software is provided "as is" without + warranty of fitness for use or suitability for any purpose, express + or implied. Use at your own risk or not at all. + =================================================================== + + Incorporating the code into commercial products is permitted; you do + not have to make source available or contribute your changes back + (though that would be nice). + + --amk (www.amk.ca) + +For the next PyCrypto release, I would like to take steps to move toward a +clearer licensing regime. I am asking as many copyright holders as I can +find if I can release PyCrypto under something clearer and more standard. +Below, I have quoted a public domain dedication that was recommended in +_Intellectual Property and Open Source: A Practical Guide to Protecting +Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +Pointer, Barry Warsaw, Wim Lewis, Jeethu Rao, and Mark Moraes, and they +have all approved the following dedication for their contributions. + +I understand that you have made contributions to PyCrypto. May I, on your +behalf, dedicate to the public domain all your contributions to PyCrypto, +with the following notice? + + ======================================================================= + The contents of this file are dedicated to the public domain. To the + extent that dedication to the public domain is not available, everyone + is granted a worldwide, perpetual, royalty-free, non-exclusive license + to exercise all rights associated with the contents of this file for + any purpose whatsoever. No rights are reserved. + ======================================================================= + +Regards, + - Dwayne + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + +From joris@bontje.nl Tue May 5 03:08:32 2009 +X-Maildir-Dup-Checked: Yes +Return-Path: <joris@bontje.nl> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id 7AA4B9E5078 + for <dwon@rivest.dlitz.net>; Tue, 5 May 2009 03:08:32 -0400 (EDT) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id 2315B40583 + for <dwon@rivest.dlitz.net>; Tue, 5 May 2009 01:08:32 -0600 (CST) +Received: (vmailmgr-postfix 16890 invoked by uid 1003); 5 May 2009 01:08:32 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: none (bontje.nl: No applicable sender policy available) receiver=goedel.dlitz.net; identity=mfrom; envelope-from="joris@bontje.nl"; helo=smtp6.versatel.nl; client-ip=62.58.50.97 +Received: from smtp6.versatel.nl (smtp6.versatel.nl [62.58.50.97]) + by goedel.dlitz.net (Postfix) with ESMTP id 2D76A4052C + for <dlitz@dlitz.net>; Tue, 5 May 2009 01:08:30 -0600 (CST) +Received: (qmail 4224 invoked by uid 0); 5 May 2009 07:08:25 -0000 +Received: from qmail06.zonnet.nl (HELO dell062.admin.zonnet.nl) ([10.170.1.123]) + (envelope-sender <joris@bontje.nl>) + by 10.170.1.96 (qmail-ldap-1.03) with SMTP + for < >; 5 May 2009 07:08:25 -0000 +Received: by dell062.admin.zonnet.nl (Postfix, from userid 33) + id 9BE9B15759B; Tue, 5 May 2009 09:08:25 +0200 (CEST) +Received: from firewall66.interaccess.nl (firewall66.interaccess.nl + [193.173.35.66]) by www.webmail.vuurwerk.nl (Horde MIME library) with HTTP; + Tue, 05 May 2009 09:08:25 +0200 +Message-ID: <20090505090825.gsq1ps7hg08wwwok@www.webmail.vuurwerk.nl> +Date: Tue, 05 May 2009 09:08:25 +0200 +From: joris@bontje.nl +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +Subject: Re: PyCrypto license clarification +References: <20090505024914.GA9219@rivest.dlitz.net> +In-Reply-To: <20090505024914.GA9219@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; + charset=ISO-8859-1; + format="flowed" +Content-Disposition: inline +Content-Transfer-Encoding: 7bit +User-Agent: Internet Messaging Program (IMP) H3 (4.1.3) +Status: RO +X-Status: A +Content-Length: 3488 + +Hi Dwayne, + +Thanks for taking over the PyCrypto library and putting in the required +effort to keep this going. +I was very excited to read that it is now one of the installed +libraries for Google AppsEngine! + +You have my full permission to dedicate all my contributions to +PyCrypto to the public domain with your suggested notice: +======================================================================= +The contents of this file are dedicated to the public domain. To the +extent that dedication to the public domain is not available, everyone +is granted a worldwide, perpetual, royalty-free, non-exclusive license +to exercise all rights associated with the contents of this file for +any purpose whatsoever. No rights are reserved. +======================================================================= + + +Regards, +Joris + +Citeren "Dwayne C. Litzenberger" <dlitz@dlitz.net>: + +> Hi Joris, +> +> I am the new maintainer of the Python Cryptography Toolkit, and I am +> working on a new release at http://www.pycrypto.org/. +> +> People often ask me what license PyCrypto is covered by, if it's +> GPL-compatible, etc. Right now, I'm not really sure what to tell them. +> The text in the current LICENSE file (quoted below) is not entirely clear +> on the point of whether distributing modified versions is allowed. (It +> says "distribute and use", but not "modify".) +> +> =================================================================== +> Distribute and use freely; there are no restrictions on further +> dissemination and usage except those imposed by the laws of your +> country of residence. This software is provided "as is" without +> warranty of fitness for use or suitability for any purpose, express +> or implied. Use at your own risk or not at all. +> =================================================================== +> +> Incorporating the code into commercial products is permitted; you do +> not have to make source available or contribute your changes back +> (though that would be nice). +> +> --amk (www.amk.ca) +> +> For the next PyCrypto release, I would like to take steps to move toward a +> clearer licensing regime. I am asking as many copyright holders as I can +> find if I can release PyCrypto under something clearer and more standard. +> Below, I have quoted a public domain dedication that was recommended in +> _Intellectual Property and Open Source: A Practical Guide to Protecting +> Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +> Pointer, Barry Warsaw, Wim Lewis, Jeethu Rao, and Mark Moraes, and they +> have all approved the following dedication for their contributions. +> +> I understand that you have made contributions to PyCrypto. May I, on your +> behalf, dedicate to the public domain all your contributions to PyCrypto, +> with the following notice? +> +> ======================================================================= +> The contents of this file are dedicated to the public domain. To the +> extent that dedication to the public domain is not available, everyone +> is granted a worldwide, perpetual, royalty-free, non-exclusive license +> to exercise all rights associated with the contents of this file for +> any purpose whatsoever. No rights are reserved. +> ======================================================================= +> +> Regards, +> - Dwayne +> +> -- +> Dwayne C. Litzenberger <dlitz@dlitz.net> +> Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + + + +From dlitz@dlitz.net Tue May 5 17:53:47 2009 +Date: Tue, 5 May 2009 17:53:47 -0400 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: joris@bontje.nl +Subject: Re: PyCrypto license clarification +Message-ID: <20090505215347.GB9933@rivest.dlitz.net> +References: <20090505024914.GA9219@rivest.dlitz.net> <20090505090825.gsq1ps7hg08wwwok@www.webmail.vuurwerk.nl> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +In-Reply-To: <20090505090825.gsq1ps7hg08wwwok@www.webmail.vuurwerk.nl> +X-Primary-Address: dlitz@dlitz.net +X-Homepage: http://www.dlitz.net/ +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=19E11FE8B3CFF273ED174A24928CEC1339C25CF7 (only for key signing); + preference=unprotected +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=4B2AFD82FC7D9E3838D9179F1C11B877E7804B45 (2008); + preference=signencrypt +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 3863 + +Excellent! Thank you! + +On Tue, May 05, 2009 at 09:08:25AM +0200, joris@bontje.nl wrote: +> Hi Dwayne, +> +> Thanks for taking over the PyCrypto library and putting in the required +> effort to keep this going. +> I was very excited to read that it is now one of the installed libraries +> for Google AppsEngine! +> +> You have my full permission to dedicate all my contributions to PyCrypto to +> the public domain with your suggested notice: +> ======================================================================= +> The contents of this file are dedicated to the public domain. To the +> extent that dedication to the public domain is not available, everyone +> is granted a worldwide, perpetual, royalty-free, non-exclusive license +> to exercise all rights associated with the contents of this file for +> any purpose whatsoever. No rights are reserved. +> ======================================================================= +> +> +> Regards, +> Joris +> +> Citeren "Dwayne C. Litzenberger" <dlitz@dlitz.net>: +> +>> Hi Joris, +>> +>> I am the new maintainer of the Python Cryptography Toolkit, and I am +>> working on a new release at http://www.pycrypto.org/. +>> +>> People often ask me what license PyCrypto is covered by, if it's +>> GPL-compatible, etc. Right now, I'm not really sure what to tell them. +>> The text in the current LICENSE file (quoted below) is not entirely clear +>> on the point of whether distributing modified versions is allowed. (It +>> says "distribute and use", but not "modify".) +>> +>> =================================================================== +>> Distribute and use freely; there are no restrictions on further +>> dissemination and usage except those imposed by the laws of your +>> country of residence. This software is provided "as is" without +>> warranty of fitness for use or suitability for any purpose, express +>> or implied. Use at your own risk or not at all. +>> =================================================================== +>> +>> Incorporating the code into commercial products is permitted; you do +>> not have to make source available or contribute your changes back +>> (though that would be nice). +>> +>> --amk (www.amk.ca) +>> +>> For the next PyCrypto release, I would like to take steps to move toward a +>> clearer licensing regime. I am asking as many copyright holders as I can +>> find if I can release PyCrypto under something clearer and more standard. +>> Below, I have quoted a public domain dedication that was recommended in +>> _Intellectual Property and Open Source: A Practical Guide to Protecting +>> Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +>> Pointer, Barry Warsaw, Wim Lewis, Jeethu Rao, and Mark Moraes, and they +>> have all approved the following dedication for their contributions. +>> +>> I understand that you have made contributions to PyCrypto. May I, on your +>> behalf, dedicate to the public domain all your contributions to PyCrypto, +>> with the following notice? +>> +>> ======================================================================= +>> The contents of this file are dedicated to the public domain. To the +>> extent that dedication to the public domain is not available, everyone +>> is granted a worldwide, perpetual, royalty-free, non-exclusive license +>> to exercise all rights associated with the contents of this file for +>> any purpose whatsoever. No rights are reserved. +>> ======================================================================= +>> +>> Regards, +>> - Dwayne +>> +>> -- +>> Dwayne C. Litzenberger <dlitz@dlitz.net> +>> Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 +> +> + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + Annual key (2008) - 4B2A FD82 FC7D 9E38 38D9 179F 1C11 B877 E780 4B45 + diff --git a/LEGAL/copy/stmts/Mark_Moraes.mbox b/LEGAL/copy/stmts/Mark_Moraes.mbox new file mode 100644 index 0000000..11cb715 --- /dev/null +++ b/LEGAL/copy/stmts/Mark_Moraes.mbox @@ -0,0 +1,340 @@ +From dlitz@dlitz.net Sat Apr 18 09:14:20 2009 +Date: Sat, 18 Apr 2009 09:14:20 -0400 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: Mark Moraes <moraes@computer.org> +Subject: PyCrypto license clarification +Message-ID: <20090418131419.GA14494@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 2635 + +Hi Mark, + +I am the new maintainer of the Python Cryptography Toolkit, and I am +working on a new release at http://www.pycrypto.org/. + +People often ask me what license PyCrypto is covered by, if it's +GPL-compatible, etc. Right now, I'm not really sure what to tell them. +The text in the current LICENSE file (quoted below) is not entirely clear +on the point of whether distributing modified versions is allowed. (It +says "distribute and use", but not "modify".) + + =================================================================== + Distribute and use freely; there are no restrictions on further + dissemination and usage except those imposed by the laws of your + country of residence. This software is provided "as is" without + warranty of fitness for use or suitability for any purpose, express + or implied. Use at your own risk or not at all. + =================================================================== + + Incorporating the code into commercial products is permitted; you do + not have to make source available or contribute your changes back + (though that would be nice). + + --amk (www.amk.ca) + +For the next PyCrypto release, I would like to take steps to move toward a +clearer licensing regime. I am asking as many copyright holders as I can +find if I can release PyCrypto under something clearer and more standard. +Below, I have quoted a public domain dedication that was recommended in +_Intellectual Property and Open Source: A Practical Guide to Protecting +Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +Pointer, Wim Lewis, Jeethu Rao, and Barry Warsaw, and they have all +approved the following dedication for their contributions. + +I understand that you have made contributions to PyCrypto. May I, on your +behalf, dedicate to the public domain all your contributions to PyCrypto, +with the following notice? + + ======================================================================= + The contents of this file are dedicated to the public domain. To the + extent that dedication to the public domain is not available, everyone + is granted a worldwide, perpetual, royalty-free, non-exclusive license + to exercise all rights associated with the contents of this file for + any purpose whatsoever. No rights are reserved. + ======================================================================= + +Regards, + - Dwayne + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + +From markmoraes@yahoo.com Mon Apr 20 19:25:37 2009 +X-Maildir-Dup-Checked: Yes +Return-Path: <markmoraes@yahoo.com> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id 5D9AE984FDD + for <dwon@rivest.dlitz.net>; Mon, 20 Apr 2009 19:25:37 -0400 (EDT) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id DE41F4025F + for <dwon@rivest.dlitz.net>; Mon, 20 Apr 2009 17:25:36 -0600 (CST) +Received: (vmailmgr-postfix 7604 invoked by uid 1003); 20 Apr 2009 17:25:36 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: none (yahoo.com: No applicable sender policy available) receiver=goedel.dlitz.net; identity=mfrom; envelope-from="markmoraes@yahoo.com"; helo=web32405.mail.mud.yahoo.com; client-ip=68.142.207.198 +Received: from web32405.mail.mud.yahoo.com (web32405.mail.mud.yahoo.com [68.142.207.198]) + by goedel.dlitz.net (Postfix) with SMTP id B5EAF401EE + for <dlitz@dlitz.net>; Mon, 20 Apr 2009 17:25:36 -0600 (CST) +Received: (qmail 34697 invoked by uid 60001); 20 Apr 2009 23:25:33 -0000 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s1024; t=1240269933; bh=OvxqbYnCg7R6tUN3YmlgFURM3CuHh1JeHyXhDzkaThU=; h=Message-ID:X-YMail-OSG:Received:X-Mailer:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; b=F2h2bFzpQxyKFZ8BhenniyupGw4Zvlekb9BSk91qKU+51W/TkSGBij5YZIhkLQdkQk0qLz5f4g8dT6bOME3sEY1j10hlx0K0u2UD0yoYTINBCmsdMQRoJ7ph9bmt+p/EJhRpe+FiV6aoLV0FONWiHfGDghPT1dulWXfVTqgB2aU= +DomainKey-Signature:a=rsa-sha1; q=dns; c=nofws; + s=s1024; d=yahoo.com; + h=Message-ID:X-YMail-OSG:Received:X-Mailer:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; + b=r6RShFF5VzQLg+9tcn1xKuo4Rs4IVvXF6fdqOpQrMyRCxeFooebhuTE35grGqlomOJLwM0+mZwRb6rGkDj763caOAlo8Ect/qlADW5izXfmVQaDchTbTqmpsJBmQnTQs9iZ+InrG+3UIwtUSGfX7fhEWmI9P/HBzxf9Wp4b3jeo=; +Message-ID: <551071.34569.qm@web32405.mail.mud.yahoo.com> +X-YMail-OSG: FrK8aWMVM1mFJtLpMGbUbCLjbUQC.i.JkIAKUHSFsFn7t9PbtewAewXJ2uhZGCOlGCX6oVnG3u.CgqzAffY4vZSnfTT8wnCkzZNZ_g6k.XUc3ipo_6e.92TXl4p8MxDGAf1tpNF5nXPwcQ7aREs7jGoWWVJYVytp50clsUFSHzf7Zbpa8P1Yoe_xSzf3OAgRSh5fCrbFCC8sHPCuwrL3YhasbtHmkWffteSS.x6gEcBaxf03oz4FeDb5mpJ54g11Xonq8h_TmzX9g84Bin9g_3fJ4WSXm6g6.tohLyfXcUxoz4j036wyWpTKPrWEzIUQaN83Sv_bj_Ghxw-- +Received: from [69.124.140.74] by web32405.mail.mud.yahoo.com via HTTP; Mon, 20 Apr 2009 16:25:32 PDT +X-Mailer: YahooMailClassic/5.2.15 YahooMailWebService/0.7.289.1 +Date: Mon, 20 Apr 2009 16:25:32 -0700 (PDT) +From: M Moraes <markmoraes@yahoo.com> +Reply-To: moraes@computer.org +Subject: Re: PyCrypto license clarification +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Status: RO +X-Status: A +Content-Length: 3222 + + +Hi Dwayne. + +Sure, the new license sounds fine for all my contributions to PyCrypto, and thanks for taking it on. My apologies for not responding to your previous e-mail. + +Regards, +Mark. + +--- On Sat, 4/18/09, Dwayne C. Litzenberger <dlitz@dlitz.net> wrote: + +> From: Dwayne C. Litzenberger <dlitz@dlitz.net> +> Subject: PyCrypto license clarification +> To: "Mark Moraes" <moraes@computer.org> +> Date: Saturday, April 18, 2009, 9:14 AM +> Hi Mark, +> +> I am the new maintainer of the Python Cryptography Toolkit, +> and I am +> working on a new release at http://www.pycrypto.org/. +> +> People often ask me what license PyCrypto is covered by, if +> it's +> GPL-compatible, etc. Right now, I'm not really sure +> what to tell them. +> The text in the current LICENSE file (quoted below) is not +> entirely clear +> on the point of whether distributing modified versions is +> allowed. (It +> says "distribute and use", but not "modify".) +> +> +> =================================================================== +> Distribute and use freely; there are +> no restrictions on further +> dissemination and usage except those +> imposed by the laws of your +> country of residence. This +> software is provided "as is" without +> warranty of fitness for use or +> suitability for any purpose, express +> or implied. Use at your own risk or +> not at all. +> +> =================================================================== +> +> Incorporating the code into commercial +> products is permitted; you do +> not have to make source available or +> contribute your changes back +> (though that would be nice). +> +> --amk +> +> +> (www.amk.ca) +> +> For the next PyCrypto release, I would like to take steps +> to move toward a +> clearer licensing regime. I am asking as many +> copyright holders as I can +> find if I can release PyCrypto under something clearer and +> more standard. +> Below, I have quoted a public domain dedication that was +> recommended in +> _Intellectual Property and Open Source: A Practical Guide +> to Protecting +> Code_, by Van Lindberg. I have already contacted A. +> M. Kuchling, Robey +> Pointer, Wim Lewis, Jeethu Rao, and Barry Warsaw, and they +> have all +> approved the following dedication for their contributions. +> +> I understand that you have made contributions to +> PyCrypto. May I, on your +> behalf, dedicate to the public domain all your +> contributions to PyCrypto, +> with the following notice? +> +> +> ======================================================================= +> The contents of this file are +> dedicated to the public domain. To the +> extent that dedication to the public +> domain is not available, everyone +> is granted a worldwide, perpetual, +> royalty-free, non-exclusive license +> to exercise all rights associated with +> the contents of this file for +> any purpose whatsoever. No +> rights are reserved. +> +> ======================================================================= +> +> Regards, +> - Dwayne +> +> -- Dwayne C. Litzenberger <dlitz@dlitz.net> +> Key-signing key - 19E1 +> 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 +> + + +From dlitz@dlitz.net Mon Apr 20 20:01:37 2009 +Date: Mon, 20 Apr 2009 20:01:37 -0400 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: moraes@computer.org +Subject: Re: PyCrypto license clarification +Message-ID: <20090421000137.GA29012@rivest.dlitz.net> +References: <551071.34569.qm@web32405.mail.mud.yahoo.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +In-Reply-To: <551071.34569.qm@web32405.mail.mud.yahoo.com> +X-Primary-Address: dlitz@dlitz.net +X-Homepage: http://www.dlitz.net/ +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=19E11FE8B3CFF273ED174A24928CEC1339C25CF7 (only for key signing); + preference=unprotected +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=4B2AFD82FC7D9E3838D9179F1C11B877E7804B45 (2008); + preference=signencrypt +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 3677 + +Thanks a lot, and don't worry about not responding to previous emails. I +do that too much myself. :) + +On Mon, Apr 20, 2009 at 04:25:32PM -0700, M Moraes wrote: +> +>Hi Dwayne. +> +>Sure, the new license sounds fine for all my contributions to PyCrypto, and thanks for taking it on. My apologies for not responding to your previous e-mail. +> +>Regards, +>Mark. +> +>--- On Sat, 4/18/09, Dwayne C. Litzenberger <dlitz@dlitz.net> wrote: +> +>> From: Dwayne C. Litzenberger <dlitz@dlitz.net> +>> Subject: PyCrypto license clarification +>> To: "Mark Moraes" <moraes@computer.org> +>> Date: Saturday, April 18, 2009, 9:14 AM +>> Hi Mark, +>> +>> I am the new maintainer of the Python Cryptography Toolkit, +>> and I am +>> working on a new release at http://www.pycrypto.org/. +>> +>> People often ask me what license PyCrypto is covered by, if +>> it's +>> GPL-compatible, etc. Right now, I'm not really sure +>> what to tell them. +>> The text in the current LICENSE file (quoted below) is not +>> entirely clear +>> on the point of whether distributing modified versions is +>> allowed. (It +>> says "distribute and use", but not "modify".) +>> +>> +>> =================================================================== +>> Distribute and use freely; there are +>> no restrictions on further +>> dissemination and usage except those +>> imposed by the laws of your +>> country of residence. This +>> software is provided "as is" without +>> warranty of fitness for use or +>> suitability for any purpose, express +>> or implied. Use at your own risk or +>> not at all. +>> +>> =================================================================== +>> +>> Incorporating the code into commercial +>> products is permitted; you do +>> not have to make source available or +>> contribute your changes back +>> (though that would be nice). +>> +>> --amk +>> +>> +>> (www.amk.ca) +>> +>> For the next PyCrypto release, I would like to take steps +>> to move toward a +>> clearer licensing regime. I am asking as many +>> copyright holders as I can +>> find if I can release PyCrypto under something clearer and +>> more standard. +>> Below, I have quoted a public domain dedication that was +>> recommended in +>> _Intellectual Property and Open Source: A Practical Guide +>> to Protecting +>> Code_, by Van Lindberg. I have already contacted A. +>> M. Kuchling, Robey +>> Pointer, Wim Lewis, Jeethu Rao, and Barry Warsaw, and they +>> have all +>> approved the following dedication for their contributions. +>> +>> I understand that you have made contributions to +>> PyCrypto. May I, on your +>> behalf, dedicate to the public domain all your +>> contributions to PyCrypto, +>> with the following notice? +>> +>> +>> ======================================================================= +>> The contents of this file are +>> dedicated to the public domain. To the +>> extent that dedication to the public +>> domain is not available, everyone +>> is granted a worldwide, perpetual, +>> royalty-free, non-exclusive license +>> to exercise all rights associated with +>> the contents of this file for +>> any purpose whatsoever. No +>> rights are reserved. +>> +>> ======================================================================= +>> +>> Regards, +>> - Dwayne +>> +>> -- Dwayne C. Litzenberger <dlitz@dlitz.net> +>> Key-signing key - 19E1 +>> 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 +>> +> + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + Annual key (2008) - 4B2A FD82 FC7D 9E38 38D9 179F 1C11 B877 E780 4B45 + diff --git a/LEGAL/copy/stmts/Paul_Swartz.mbox b/LEGAL/copy/stmts/Paul_Swartz.mbox new file mode 100644 index 0000000..0c3be4b --- /dev/null +++ b/LEGAL/copy/stmts/Paul_Swartz.mbox @@ -0,0 +1,211 @@ +From dlitz@dlitz.net Sun Aug 2 21:48:25 2009 +Date: Sun, 2 Aug 2009 21:48:25 -0400 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: Paul Swartz <paulswartz@gmail.com> +Subject: PyCrypto license clarification +Message-ID: <20090803014825.GA1326@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 2631 + +Hi Paul, + +I am the new maintainer of the Python Cryptography Toolkit, and I am +working on a new release at http://www.pycrypto.org/. + +People often ask me what license PyCrypto is covered by, if it's +GPL-compatible, etc. Right now, I'm not really sure what to tell them. +The text in the current LICENSE file (quoted below) is not entirely clear +on the point of whether distributing modified versions is allowed. (It +says "distribute and use", but not "modify".) + + =================================================================== + Distribute and use freely; there are no restrictions on further + dissemination and usage except those imposed by the laws of your + country of residence. This software is provided "as is" without + warranty of fitness for use or suitability for any purpose, express + or implied. Use at your own risk or not at all. + =================================================================== + + Incorporating the code into commercial products is permitted; you do + not have to make source available or contribute your changes back + (though that would be nice). + + --amk (www.amk.ca) + +For the next PyCrypto release, I would like to take steps to move toward a +clearer licensing regime. I am asking as many copyright holders as I can +find if I can release PyCrypto under something clearer and more standard. +Below, I have quoted a public domain dedication that was recommended in +_Intellectual Property and Open Source: A Practical Guide to Protecting +Code_, by Van Lindberg. I have already contacted A. M. Kuchling, Robey +Pointer, Barry Warsaw, Wim Lewis, Jeethu Rao, Joris Bontje, and Mark +Moraes, and they have all approved the following dedication for their +contributions. + +I understand that you have made contributions to PyCrypto, under nickname +"z3p" and/or other names. May I, on your behalf, dedicate to the public +domain all your contributions to PyCrypto, with the following notice? + + ======================================================================= + The contents of this file are dedicated to the public domain. To the + extent that dedication to the public domain is not available, everyone + is granted a worldwide, perpetual, royalty-free, non-exclusive license + to exercise all rights associated with the contents of this file for + any purpose whatsoever. No rights are reserved. + ======================================================================= + +Regards, + - Dwayne + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + +From paulswartz@gmail.com Mon Aug 3 12:14:07 2009 +X-Maildir-Dup-Checked: Yes +Return-Path: <paulswartz@gmail.com> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id 30B9D984FC4 + for <dwon@rivest.dlitz.net>; Mon, 3 Aug 2009 12:14:07 -0400 (EDT) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id AD9AE81068 + for <dwon@rivest.dlitz.net>; Mon, 3 Aug 2009 10:14:06 -0600 (CST) +Received: (vmailmgr-postfix 32055 invoked by uid 1003); 3 Aug 2009 10:14:06 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: pass (gmail.com ... _spf.google.com: 72.14.220.159 is authorized to use 'paulswartz@gmail.com' in 'mfrom' identity (mechanism 'ip4:72.14.192.0/18' matched)) receiver=goedel.dlitz.net; identity=mfrom; envelope-from="paulswartz@gmail.com"; helo=fg-out-1718.google.com; client-ip=72.14.220.159 +Received: from fg-out-1718.google.com (fg-out-1718.google.com [72.14.220.159]) + by goedel.dlitz.net (Postfix) with ESMTP id 4E63881066 + for <dlitz@dlitz.net>; Mon, 3 Aug 2009 10:14:05 -0600 (CST) +Received: by fg-out-1718.google.com with SMTP id d23so1076840fga.3 + for <dlitz@dlitz.net>; Mon, 03 Aug 2009 09:14:04 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=gamma; + h=domainkey-signature:mime-version:received:in-reply-to:references + :from:date:message-id:subject:to:content-type + :content-transfer-encoding; + bh=A0RHBf0TnribKS5qOHJ3WYbkZ+b0cuPeuoKAvpApWcc=; + b=gyTqkRhKlHadFKIZCBWsRbnMNVDq1PWlJbyC0EvxPskaoHr3HAR96MWQNBePu/40Ac + Vn55qlIqTdom4e9zlUEE6MwZo9kqi/Qw0L/SLib0DlQeNqo/eHYqPmuVswltaYwNAyMJ + Y9++76rPGzqYdALsfvsmwv7Q3/bEmjVTr0tQE= +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=gmail.com; s=gamma; + h=mime-version:in-reply-to:references:from:date:message-id:subject:to + :content-type:content-transfer-encoding; + b=jze7KSMkUGilfVCXKXaaXMi5NAtGdMQOtVZZfRNyGSy68xOd2sxefjyyig3EfT6Nv6 + Q3opUMsT96Q6zjZND55w446kTh2uBTNz4d3NwIeEWJnG3xcliRQu/mXPFp8AzPI3CefL + 1ornJLM1eQ2XyuZA73jem+SJtfdHUcSD1UhgI= +MIME-Version: 1.0 +Received: by 10.239.157.147 with SMTP id q19mr601802hbc.61.1249316043185; Mon, + 03 Aug 2009 09:14:03 -0700 (PDT) +In-Reply-To: <20090803014825.GA1326@rivest.dlitz.net> +References: <20090803014825.GA1326@rivest.dlitz.net> +From: Paul Swartz <paulswartz@gmail.com> +Date: Mon, 3 Aug 2009 12:13:43 -0400 +Message-ID: <324cfb540908030913x71d331f0kb069052f74e5ae6b@mail.gmail.com> +Subject: Re: PyCrypto license clarification +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable +Status: RO +X-Status: A +Content-Length: 1450 + +On Sun, Aug 2, 2009 at 9:48 PM, Dwayne C. Litzenberger<dlitz@dlitz.net> wro= +te: +> Hi Paul, +> +> I am the new maintainer of the Python Cryptography Toolkit, and I am +> working on a new release at http://www.pycrypto.org/. + +That's great! + +> I understand that you have made contributions to PyCrypto, under nickname +> "z3p" and/or other names. =C2=A0May I, on your behalf, dedicate to the pu= +blic +> domain all your contributions to PyCrypto, with the following notice? +> +> =C2=A0=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +> =C2=A0The contents of this file are dedicated to the public domain. =C2= +=A0To the +> =C2=A0extent that dedication to the public domain is not available, every= +one +> =C2=A0is granted a worldwide, perpetual, royalty-free, non-exclusive lice= +nse +> =C2=A0to exercise all rights associated with the contents of this file fo= +r +> =C2=A0any purpose whatsoever. =C2=A0No rights are reserved. +> =C2=A0=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Yes, that's fine. Good luck with the new release! + +-p +--=20 +Paul Swartz +paulswartz at gmail dot com +http://paulswartz.net/ +AIM: z3penguin + + +From dlitz@dlitz.net Mon Aug 3 14:35:01 2009 +Date: Mon, 3 Aug 2009 14:35:01 -0400 +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +To: Paul Swartz <paulswartz@gmail.com> +Subject: Re: PyCrypto license clarification +Message-ID: <20090803183501.GA17472@rivest.dlitz.net> +References: <20090803014825.GA1326@rivest.dlitz.net> <324cfb540908030913x71d331f0kb069052f74e5ae6b@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1; format=flowed +Content-Disposition: inline +Content-Transfer-Encoding: 8bit +In-Reply-To: <324cfb540908030913x71d331f0kb069052f74e5ae6b@mail.gmail.com> +X-Primary-Address: dlitz@dlitz.net +X-Homepage: http://www.dlitz.net/ +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=19E11FE8B3CFF273ED174A24928CEC1339C25CF7 (only for key signing); + preference=unprotected +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=4B2AFD82FC7D9E3838D9179F1C11B877E7804B45 (2008); + preference=signencrypt +User-Agent: Mutt/1.5.16 (2007-06-11) +Status: RO +Content-Length: 1250 + +On Mon, Aug 03, 2009 at 12:13:43PM -0400, Paul Swartz wrote: +>On Sun, Aug 2, 2009 at 9:48 PM, Dwayne C. Litzenberger<dlitz@dlitz.net> wrote: +>> Hi Paul, +>> +>> I am the new maintainer of the Python Cryptography Toolkit, and I am +>> working on a new release at http://www.pycrypto.org/. +> +>That's great! +> +>> I understand that you have made contributions to PyCrypto, under nickname +>> "z3p" and/or other names. May I, on your behalf, dedicate to the public +>> domain all your contributions to PyCrypto, with the following notice? +>> +>> ======================================================================= +>> The contents of this file are dedicated to the public domain. To the +>> extent that dedication to the public domain is not available, everyone +>> is granted a worldwide, perpetual, royalty-free, non-exclusive license +>> to exercise all rights associated with the contents of this file for +>> any purpose whatsoever. No rights are reserved. +>> ======================================================================= +> +>Yes, that's fine. Good luck with the new release! + +Perfect! Thanks for the quick response! + +-- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + diff --git a/LEGAL/copy/stmts/Robey_Pointer.asc b/LEGAL/copy/stmts/Robey_Pointer.asc new file mode 100644 index 0000000..fa49e5a --- /dev/null +++ b/LEGAL/copy/stmts/Robey_Pointer.asc @@ -0,0 +1,53 @@ +Date: Mon, 16 Feb 2009 12:58:00 -0800 +From: Robey Pointer <robey@lag.net> +Subject: Re: PyCrypto license clarification +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +Received-SPF: pass (goedel.dlitz.net: domain of robey@lag.net designates 69.61.78.186 as permitted sender) +Message-Id: <F469A078-6305-4484-BEA8-F4EC38A4154F@lag.net> + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +On 23 Nov 2008, at 07:42, Dwayne C. Litzenberger wrote: + +> For the next PyCrypto release, I would like to take steps to move +> toward a clearer licensing regime. I am asking as many copyright +> holders as I can find if I can release PyCrypto under something +> clearer and more standard. Below, I have quoted a public domain +> dedication that was recommended in _Intellectual Property and Open +> Source: A Practical Guide to Protecting Code_, by Van Lindberg. I +> have already contacted A. M. Kuchling, and he has approved the +> following dedication for his contributions. +> +> May I, on your behalf, dedicate to the public domain all your +> contributions to PyCrypto, with the following notice? +> +> +> = +> ====================================================================== +> The contents of this file are dedicated to the public domain. To +> the +> extent that dedication to the public domain is not available, +> everyone +> is granted a worldwide, perpetual, royalty-free, non-exclusive +> license +> to exercise all rights associated with the contents of this file +> for +> any purpose whatsoever. No rights are reserved. +> +> = +> ====================================================================== +> + +In case I haven't replied to this yet: Yes, this is fine with me. + +robey + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.8 (Darwin) + +iEYEARECAAYFAkmZ01gACgkQQQDkKvyJ6cOLvQCfQmYYuVODvIlyLg0hgCI9LAbQ +SH8AoLJgaq1lIi7/ZYDc+/Cd8VO0xLbr +=Mv6g +-----END PGP SIGNATURE----- + diff --git a/LEGAL/copy/stmts/Wim_Lewis.asc b/LEGAL/copy/stmts/Wim_Lewis.asc new file mode 100644 index 0000000..3969994 --- /dev/null +++ b/LEGAL/copy/stmts/Wim_Lewis.asc @@ -0,0 +1,45 @@ +Date: Sun, 23 Nov 2008 15:54:35 -0800 +From: Wim Lewis <wiml@hhhh.org> +Subject: Re: PyCrypto license clarification +To: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +Cc: Wim Lewis <wiml@hhhh.org> +Message-Id: <9D5C3135-7414-47D7-9D41-0AC6C3A84D97@hhhh.org> + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +On November 23, 2008, you wrote: +>Hi Wim, +> +>I am the new maintainer of the Python Cryptography Toolkit, and I am +>working on a new release at http://www.pycrypto.org/. +> +>I understand that you have made contributions to PyCrypto. May I, on +>your behalf, dedicate to the public domain all your contributions to +>PyCrypto, with the following notice? +> +> ======================================================================= +> The contents of this file are dedicated to the public domain. To the +> extent that dedication to the public domain is not available, everyone +> is granted a worldwide, perpetual, royalty-free, non-exclusive license +> to exercise all rights associated with the contents of this file for +> any purpose whatsoever. No rights are reserved. +> ======================================================================= + +Certainly! I think the only code of mine in PyCrypto is the CAST-5 / CAST-128 +implementation, which already has a public-domain notice at the top of +the file. But I am happy to have that, any any other code of mine that +might have wandered in there under an unclear open sourcish license, +distributed under the public-domain dedication you quote. + +Wim. + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (Darwin) + +iQCVAwUBSSnnAl8UnN8n93LBAQLp/gQAhr7x8Av1mstc2kxEJDWTm26PTAZxMz4B +FektbDOzkxgc5580MGGeeX/MVn8aw+1BHg0YD85gsntlDzkcQtb+BR/xAvJ5zKyA +J/Mn/I+I6ekJQ3juh8IPHLAduOXM9Rtguas/yR+Doaq0xOPKoBx+/5+t1lLJtBcZ +wrPEa9Oui9s= +=zSY9 +-----END PGP SIGNATURE----- diff --git a/LEGAL/tsu-notify.mbox b/LEGAL/tsu-notify.mbox new file mode 100644 index 0000000..c9fcfb2 --- /dev/null +++ b/LEGAL/tsu-notify.mbox @@ -0,0 +1,130 @@ +From dlitz@dlitz.net Wed Aug 27 20:54:38 EDT 2008 +X-Maildir-Dup-Checked: Yes +Return-Path: <dlitz@dlitz.net> +X-Original-To: dwon@rivest.dlitz.net +Delivered-To: dwon@rivest.dlitz.net +Received: from goedel.dlitz.net (unknown [10.159.255.6]) + by rivest.dlitz.net (Postfix) with ESMTP id ECFDFC6641D + for <dwon@rivest.dlitz.net>; Wed, 27 Aug 2008 20:45:06 -0400 (EDT) +Received: from localhost (localhost [127.0.0.1]) + by goedel.dlitz.net (Postfix) with QMQP id 99A9D100AA + for <dwon@rivest.dlitz.net>; Wed, 27 Aug 2008 18:45:05 -0600 (CST) +Received: (vmailmgr-postfix 3270 invoked by uid 1003); 27 Aug 2008 18:45:05 -0600 +Delivered-To: m-dlitz-dlitz@dlitz.net +Received-SPF: pass (goedel.dlitz.net: domain of dlitz@dlitz.net designates 193.201.42.13 as permitted sender) +Received: from m14.itconsult.net (m14.itconsult.net [193.201.42.13]) + by goedel.dlitz.net (Postfix) with ESMTP id 1D3B510088 + for <dlitz@dlitz.net>; Wed, 27 Aug 2008 18:45:04 -0600 (CST) +Received: from stamper.itconsult.co.uk (stamper.itconsult.co.uk + [193.201.42.31]) by m14.stamper.itconsult.co.uk (GMS + 15.01.3664/NT8923.00.54dca388) with SMTP id jfxsjqaa for dlitz@dlitz.net; + Thu, 28 Aug 2008 01:45:02 +0100 +To: crypt@bis.doc.gov, + enc@nsa.gov, + web_site@bis.doc.gov, + pycrypto@lists.dlitz.net, + PYTHON-CRYPTO@NIC.SURFNET.NL, + dlitz@dlitz.net +Received-SPF: Pass (m14.stamper.itconsult.co.uk: domain of dlitz@dlitz.net + designates 64.5.53.201 as permitted sender) identity=mailfrom; + client-ip=64.5.53.201; receiver=m14.stamper.itconsult.co.uk; + helo=goedel.dlitz.net; mechanism=-all; envelope-from=dlitz@dlitz.net; +Received: from goedel.dlitz.net (goedel.dlitz.net [64.5.53.201]) by + m14.stamper.itconsult.co.uk (GMS 15.01.3664/NT8923.00.54dca388) with ESMTP id + taxsjqaa for post@stamper.itconsult.co.uk; Thu, 28 Aug 2008 01:42:58 +0100 +Received: from rivest.dlitz.net (rivest.dlitz.net [IPv6:2002:4c0a:9133:1104::1]) + by goedel.dlitz.net (Postfix) with ESMTP id 667C7100B1 + for <post@stamper.itconsult.co.uk>; Wed, 27 Aug 2008 18:42:56 -0600 (CST) +Received: by rivest.dlitz.net (Postfix, from userid 1000) + id B92F8C66420; Wed, 27 Aug 2008 20:42:55 -0400 (EDT) +Received: by rivest.dlitz.net (tmda-sendmail, from uid 1000); + Wed, 27 Aug 2008 20:42:54 -0400 +Date: Wed, 27 Aug 2008 20:42:54 -0400 +Cc: post@stamper.itconsult.co.uk +Subject: PyCrypto TSU NOTIFICATION +Message-ID: <20080828004254.GA31214@rivest.dlitz.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii; format=flowed +Content-Disposition: inline +X-Primary-Address: dlitz@dlitz.net +X-Homepage: http://www.dlitz.net/ +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=19E11FE8B3CFF273ED174A24928CEC1339C25CF7 (only for key signing); + preference=unprotected +X-OpenPGP: url=http://www.dlitz.net/go/gpgkey/; + id=4B2AFD82FC7D9E3838D9179F1C11B877E7804B45 (2008); + preference=signencrypt +User-Agent: Mutt/1.5.16 (2007-06-11) +X-Delivery-Agent: TMDA/1.1.9 (Jura) +From: "Dwayne C. Litzenberger" <dlitz@dlitz.net> +X-DNSBL: 0 +Status: O +Content-Length: 2182 +Lines: 65 + +-----BEGIN PGP SIGNED MESSAGE----- + +######################################################## +# +# This is a proof of posting certificate from +# stamper.itconsult.co.uk certifying that a user +# claiming to be:- +# dlitz@dlitz.net +# requested that this message be sent to:- +# crypt@bis.doc.gov +# enc@nsa.gov +# web_site@bis.doc.gov +# pycrypto@lists.dlitz.net +# PYTHON-CRYPTO@NIC.SURFNET.NL +# dlitz@dlitz.net +# +# This certificate was issued at 00:45 (GMT) +# on Thursday 28 August 2008 with reference 0520978 +# +# CAUTION: while the message may well be from the sender +# indicated in the "From:" header, the sender +# has NOT been authenticated by this service +# +# For information about the Stamper service see +# http://www.itconsult.co.uk/stamper.htm +# +######################################################## + +SUBMISSION TYPE: TSU +SUBMITTED BY: Dwayne C. Litzenberger +SUBMITTED FOR: Dwayne C. Litzenberger +POINT OF CONTACT: Dwayne C. Litzenberger +PHONE and/or FAX: +1-613-693-1296 +MANUFACTURER: n/a +PRODUCT NAME/MODEL #: The Python Cryptography Toolkit ("PyCrypto") +ECCN: 5D002 + +NOTIFICATION: http://www.pycrypto.org/ + +Note: I am a Canadian citizen posting software to my website located in +Canada. I am not certain whether PyCrypto contains enough US-origin +cryptography to be covered by U.S. export controls, but I am submitting +this anyway. + +(Sorry for spamming the lists, but I want there to be a record of this.) + +- -- +Dwayne C. Litzenberger <dlitz@dlitz.net> + Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7 + Annual key (2008) - 4B2A FD82 FC7D 9E38 38D9 179F 1C11 B877 E780 4B45 + + +-----BEGIN PGP SIGNATURE----- +Version: 2.6.3i +Charset: noconv +Comment: Stamper Reference Id: 0520978 + +iQEVAgUBSLX1DYGVnbVwth+BAQEcuwf9EWnXLqSO5bPzR9K9QnTPcsKbTljKjPxr +d+q0E7eE8VtnvvijUcTAR9o27yvzOPxdFT864MQA7OTSbPK39aGAgA4fgAgvYH9t +UNjJ/kv8QLz/aq2fi/HNjyrwnqFnUl0uqwpOrQGbz8Y+SGpVh1gKqy1Ju45L+doq +sxbzCOpjgRv2zDdNR/2SnFmDWQXv8dSeonwIHpQDft8/LVA/gHiTDmteQlOhJQ6o +XYhY+HbRjsD741/GSpOt9IlN5ln0UgshFoLIndnNSAvWf4aPyh5KCN7ho+/BC0v/ +W/pqSSlPkwmbhlPHoOltTkNc0qKLAHXqMGJNhO8AkrYZOyJksb0HsA== +=3oIX +-----END PGP SIGNATURE----- + diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..bbb10fd --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,8 @@ +include MANIFEST.in +include ACKS build-aux/* ChangeLog COPYRIGHT Doc/* TODO +graft LEGAL +recursive-include src *.h *.c +include buildenv.in +include src/config.h.in +include *.py +include configure @@ -0,0 +1,104 @@ +Python Cryptography Toolkit (pycrypto) +====================================== + +This is a collection of both secure hash functions (such as SHA256 and +RIPEMD160), and various encryption algorithms (AES, DES, RSA, ElGamal, +etc.). The package is structured to make adding new modules easy. +This section is essentially complete, and the software interface will +almost certainly not change in an incompatible way in the future; all +that remains to be done is to fix any bugs that show up. If you +encounter a bug, please report it in the GitHub issue tracker at + + https://github.com/dlitz/pycrypto/issues + +An example usage of the SHA256 module is: + +>>> from Crypto.Hash import SHA256 +>>> hash = SHA256.new() +>>> hash.update('message') +>>> hash.digest() +'\xabS\n\x13\xe4Y\x14\x98+y\xf9\xb7\xe3\xfb\xa9\x94\xcf\xd1\xf3\xfb"\xf7\x1c\xea\x1a\xfb\xf0+F\x0cm\x1d' + +An example usage of an encryption algorithm (AES, in this case) is: + +>>> from Crypto.Cipher import AES +>>> obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456') +>>> message = "The answer is no" +>>> ciphertext = obj.encrypt(message) +>>> ciphertext +'\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1' +>>> obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456') +>>> obj2.decrypt(ciphertext) +'The answer is no' + +One possible application of the modules is writing secure +administration tools. Another application is in writing daemons and +servers. Clients and servers can encrypt the data being exchanged and +mutually authenticate themselves; daemons can encrypt private data for +added security. Python also provides a pleasant framework for +prototyping and experimentation with cryptographic algorithms; thanks +to its arbitrary-length integers, public key algorithms are easily +implemented. + +As of PyCrypto 2.1.0, PyCrypto provides an easy-to-use random number +generator: + +>>> from Crypto import Random +>>> rndfile = Random.new() +>>> rndfile.read(16) +'\xf7.\x838{\x85\xa0\xd3>#}\xc6\xc2jJU' + +A stronger version of Python's standard "random" module is also +provided: + +>>> from Crypto.Random import random +>>> random.choice(['dogs', 'cats', 'bears']) +'bears' + +Caveat: For the random number generator to work correctly, you must +call Random.atfork() in both the parent and child processes after +using os.fork() + + +Installation +============ + +PyCrypto is written and tested using Python version 2.1 through 3.3. Python +1.5.2 is not supported. + +The modules are packaged using the Distutils, so you can simply run +"python setup.py build" to build the package, and "python setup.py +install" to install it. + +Linux installation requires the Python developer tools to be installed. These +can be found in the ``python-dev`` package on Debian/Ubuntu and the +``python2-devel`` package on Red Hat/Fedora. If you are using a non-standard +Python version for your distribution, you may require a different package. +Consult your package manager's documentation for instructions on how to +install these packages. Other distributions may have different package names. + +To verify that everything is in order, run "python setup.py test". It +will test all the cryptographic modules, skipping ones that aren't +available. If the test script reports an error on your machine, +please report the bug using the bug tracker (URL given above). If +possible, track down the bug and include a patch that fixes it, +provided that you are able to meet the eligibility requirements at +http://www.pycrypto.org/submission-requirements/. + +It is possible to test a single sub-package or a single module only, for instance +when you investigate why certain tests fail and don't want to run the whole +suite each time. Use "python setup.py test --module=name", where 'name' +is either a sub-package (Cipher, PublicKey, etc) or a module (Cipher.DES, +PublicKey.RSA, etc). +To further cut test coverage, pass also the option "--skip-slow-tests". + +To install the package under the site-packages directory of +your Python installation, run "python setup.py install". + +If you have any comments, corrections, or improvements for this +package, please report them to our mailing list, accessible via the +PyCrypto website: + + http://www.pycrypto.org/ + https://www.dlitz.net/software/pycrypto/ + @@ -0,0 +1,30 @@ +- Clean up and stabilize the Crypto.PublicKey API. The previous attempt to + unify fundamentally different algorithms, such as RSA and DSA, should be + avoided, since it simply adds confusion. + +- Add algorithms: + - Camellia + - SHA512 + - Diffie-Hellmen key agreement + - Authenticated Diffie-Hellmen key agreement + - RSA PKCS#1 v1.5 + - RSA PKCS#1 v2 (OAEP) + +- Add a *complete* DSA implementation. (The current implementation doesn't do + the necessary hashing, for example.) + +- Coverage testing + +- Run lint on the C code + +- Separate the exported API from the internal implementation details. + +- Provide drop-in support for extensions/drivers like amkCrypto/mxCrypto. + There should be some way to register these drivers in your package, e.g. by + defining a certain subdirectory to be a place where pycrypto looks for these + drivers at startup time. + +- Merge Crypto.Cipher.XOR and Crypto.Util.strxor somehow + +- Document our experiences with RandomPool and why it was bad. + diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..bf2fae6 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Generates ./src/config.h.in and ./configure + +set -e +aclocal --force -I m4 +autoconf --force +autoheader --force + +# The following line is needed to generate build-aux/*, but it will fail +# because we have no Makefile.am +mkdir -p build-aux +echo "** You can ignore the following error about a missing Makefile.am" +automake --add-missing --copy || true diff --git a/build-aux/compile b/build-aux/compile new file mode 100755 index 0000000..531136b --- /dev/null +++ b/build-aux/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Written by Tom Tromey <tromey@cygnus.com>. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 0000000..d622a44 --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1530 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to <config-patches@gnu.org> and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 0000000..c894da4 --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1773 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..377bb86 --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..9a55648 --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,330 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2012-01-06.18; # UTC + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, 'missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle 'PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file 'aclocal.m4' + autoconf touch file 'configure' + autoheader touch file 'config.h.in' + autom4te touch the output file, or create a stub one + automake touch all 'Makefile.in' files + bison create 'y.tab.[ch]', if possible, from existing .[ch] + flex create 'lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create 'lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create 'y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to <bug-automake@gnu.org>." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running '$TOOL --version' or '$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'acinclude.m4' or '${configure_ac}'. You might want + to install the Automake and Perl packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified '${configure_ac}'. You might want to install the + Autoconf and GNU m4 packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'acconfig.h' or '${configure_ac}'. You might want + to install the Autoconf and GNU m4 packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'Makefile.am', 'acinclude.m4' or '${configure_ac}'. + You might want to install the Automake and Perl packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: '$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get '$1' as part of Autoconf from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: '$1' $msg. You should only need it if + you modified a '.y' file. You may need the Bison package + in order for those modifications to take effect. You can get + Bison from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a '.l' file. You may need the Flex package + in order for those modifications to take effect. You can get + Flex from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + Help2man package in order for those modifications to take + effect. You can get Help2man from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a '.texi' or '.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy 'make' (AIX, + DU, IRIX). You might want to install the Texinfo package or + the GNU make package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: '$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the 'README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing '$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/buildenv.in b/buildenv.in new file mode 100644 index 0000000..1bfbcd0 --- /dev/null +++ b/buildenv.in @@ -0,0 +1,4 @@ +# @configure_input@ +CC = @CC@ +CFLAGS = @CFLAGS@ @DEFS@ +LDFLAGS = @LDFLAGS@ diff --git a/configure b/configure new file mode 100755 index 0000000..6656298 --- /dev/null +++ b/configure @@ -0,0 +1,6847 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for FULL-PACKAGE-NAME VERSION. +# +# Report bugs to <BUG-REPORT-ADDRESS>. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and BUG-REPORT-ADDRESS +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='FULL-PACKAGE-NAME' +PACKAGE_TARNAME='full-package-name' +PACKAGE_VERSION='VERSION' +PACKAGE_STRING='FULL-PACKAGE-NAME VERSION' +PACKAGE_BUGREPORT='BUG-REPORT-ADDRESS' +PACKAGE_URL='' + +ac_unique_file="src/pycrypto_compat.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +EGREP +GREP +CPP +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +with_gmp +with_mpir +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures FULL-PACKAGE-NAME VERSION to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root + [DATAROOTDIR/doc/full-package-name] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of FULL-PACKAGE-NAME VERSION:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --without-gmp Build without gmp library (default: test) + --without-mpir Build without mpir library (default: test) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to <BUG-REPORT-ADDRESS>. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +FULL-PACKAGE-NAME configure VERSION +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## --------------------------------- ## +## Report this to BUG-REPORT-ADDRESS ## +## --------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_find_intX_t LINENO BITS VAR +# ----------------------------------- +# Finds a signed integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_intX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 +$as_echo_n "checking for int$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in int$2_t 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) + < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + case $ac_type in #( + int$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_intX_t + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_find_uintX_t LINENO BITS VAR +# ------------------------------------ +# Finds an unsigned integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_uintX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 +$as_echo_n "checking for uint$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + case $ac_type in #( + uint$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_uintX_t + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by FULL-PACKAGE-NAME $as_me VERSION, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_config_headers="$ac_config_headers src/config.h" + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +ac_config_files="$ac_config_files buildenv" + + +am__api_version='1.14' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='full-package-name' + VERSION='VERSION' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <http://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Checks for programs. +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + +fi + + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +case "$host_os" in # XXX - Does this break cross-compiling? +openbsd*) + # According to gcc-local(1), OpenBSD's gcc is modified to ignore /usr/local + # by default. However, libgmp is usually installed to /usr/local, so we + # want to look there for the libraries. + CFLAGS="$CFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + ;; +*) + ;; +esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wall" >&5 +$as_echo_n "checking whether C compiler accepts -Wall... " >&6; } +if ${ax_cv_check_cflags___Wall+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wall" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wall=yes +else + ax_cv_check_cflags___Wall=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wall" >&5 +$as_echo "$ax_cv_check_cflags___Wall" >&6; } +if test x"$ax_cv_check_cflags___Wall" = xyes; then : + if ${CFLAGS+:} false; then : + case " $CFLAGS " in + *" -Wall "*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wall"; } >&5 + (: CFLAGS already contains -Wall) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; + *) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS -Wall\""; } >&5 + (: CFLAGS="$CFLAGS -Wall") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + CFLAGS="$CFLAGS -Wall" + ;; + esac +else + CFLAGS="-Wall" +fi + +else + : +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wextra" >&5 +$as_echo_n "checking whether C compiler accepts -Wextra... " >&6; } +if ${ax_cv_check_cflags___Wextra+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wextra" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wextra=yes +else + ax_cv_check_cflags___Wextra=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wextra" >&5 +$as_echo "$ax_cv_check_cflags___Wextra" >&6; } +if test x"$ax_cv_check_cflags___Wextra" = xyes; then : + if ${CFLAGS+:} false; then : + case " $CFLAGS " in + *" -Wextra "*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wextra"; } >&5 + (: CFLAGS already contains -Wextra) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; + *) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS -Wextra\""; } >&5 + (: CFLAGS="$CFLAGS -Wextra") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + CFLAGS="$CFLAGS -Wextra" + ;; + esac +else + CFLAGS="-Wextra" +fi + +else + : +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wno-missing-field-initializers" >&5 +$as_echo_n "checking whether C compiler accepts -Wno-missing-field-initializers... " >&6; } +if ${ax_cv_check_cflags___Wno_missing_field_initializers+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wno-missing-field-initializers" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wno_missing_field_initializers=yes +else + ax_cv_check_cflags___Wno_missing_field_initializers=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wno_missing_field_initializers" >&5 +$as_echo "$ax_cv_check_cflags___Wno_missing_field_initializers" >&6; } +if test x"$ax_cv_check_cflags___Wno_missing_field_initializers" = xyes; then : + if ${CFLAGS+:} false; then : + case " $CFLAGS " in + *" -Wno-missing-field-initializers "*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wno-missing-field-initializers"; } >&5 + (: CFLAGS already contains -Wno-missing-field-initializers) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; + *) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS -Wno-missing-field-initializers\""; } >&5 + (: CFLAGS="$CFLAGS -Wno-missing-field-initializers") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + CFLAGS="$CFLAGS -Wno-missing-field-initializers" + ;; + esac +else + CFLAGS="-Wno-missing-field-initializers" +fi + +else + : +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wno-unused-parameter" >&5 +$as_echo_n "checking whether C compiler accepts -Wno-unused-parameter... " >&6; } +if ${ax_cv_check_cflags___Wno_unused_parameter+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wno-unused-parameter" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wno_unused_parameter=yes +else + ax_cv_check_cflags___Wno_unused_parameter=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wno_unused_parameter" >&5 +$as_echo "$ax_cv_check_cflags___Wno_unused_parameter" >&6; } +if test x"$ax_cv_check_cflags___Wno_unused_parameter" = xyes; then : + if ${CFLAGS+:} false; then : + case " $CFLAGS " in + *" -Wno-unused-parameter "*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wno-unused-parameter"; } >&5 + (: CFLAGS already contains -Wno-unused-parameter) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; + *) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS -Wno-unused-parameter\""; } >&5 + (: CFLAGS="$CFLAGS -Wno-unused-parameter") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + CFLAGS="$CFLAGS -Wno-unused-parameter" + ;; + esac +else + CFLAGS="-Wno-unused-parameter" +fi + +else + : +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -maes" >&5 +$as_echo_n "checking whether C compiler accepts -maes... " >&6; } +if ${ax_cv_check_cflags___maes+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -maes" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___maes=yes +else + ax_cv_check_cflags___maes=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___maes" >&5 +$as_echo "$ax_cv_check_cflags___maes" >&6; } +if test x"$ax_cv_check_cflags___maes" = xyes; then : + + have_maes=yes + +$as_echo "#define HAVE_MAES 1" >>confdefs.h + + +else + : +fi + + +# Checks for libraries. + +# Check whether --with-gmp was given. +if test "${with_gmp+set}" = set; then : + withval=$with_gmp; +fi + +if test "x$with_gmp" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_init in -lgmp" >&5 +$as_echo_n "checking for __gmpz_init in -lgmp... " >&6; } +if ${ac_cv_lib_gmp___gmpz_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgmp $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __gmpz_init (); +int +main () +{ +return __gmpz_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gmp___gmpz_init=yes +else + ac_cv_lib_gmp___gmpz_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_init" >&5 +$as_echo "$ac_cv_lib_gmp___gmpz_init" >&6; } +if test "x$ac_cv_lib_gmp___gmpz_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGMP 1 +_ACEOF + + LIBS="-lgmp $LIBS" + +fi + + +fi + + +# Check whether --with-mpir was given. +if test "${with_mpir+set}" = set; then : + withval=$with_mpir; +fi + +if test "x$with_mpir" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_init in -lmpir" >&5 +$as_echo_n "checking for __gmpz_init in -lmpir... " >&6; } +if ${ac_cv_lib_mpir___gmpz_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmpir $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __gmpz_init (); +int +main () +{ +return __gmpz_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_mpir___gmpz_init=yes +else + ac_cv_lib_mpir___gmpz_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mpir___gmpz_init" >&5 +$as_echo "$ac_cv_lib_mpir___gmpz_init" >&6; } +if test "x$ac_cv_lib_mpir___gmpz_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBMPIR 1 +_ACEOF + + LIBS="-lmpir $LIBS" + +fi + + +fi + +ac_fn_c_check_decl "$LINENO" "mpz_powm" "ac_cv_have_decl_mpz_powm" " +#if HAVE_LIBGMP +# include <gmp.h> +#elif HAVE_LIBMPIR +# include <mpir.h> +#endif + +" +if test "x$ac_cv_have_decl_mpz_powm" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MPZ_POWM $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "mpz_powm_sec" "ac_cv_have_decl_mpz_powm_sec" " +#if HAVE_LIBGMP +# include <gmp.h> +#elif HAVE_LIBMPIR +# include <mpir.h> +#endif + +" +if test "x$ac_cv_have_decl_mpz_powm_sec" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MPZ_POWM_SEC $ac_have_decl +_ACEOF + + +# Checks for header files. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in inttypes.h sys/inttypes.h cpuid.h limits.h stddef.h stdint.h stdlib.h string.h wchar.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +old_CPPFLAGS="$CPPFLAGS" +if test "x$have_maes" = "xyes"; then : + + CPPFLAGS="$CPPFLAGS -maes" + +fi +for ac_header in wmmintrin.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "wmmintrin.h" "ac_cv_header_wmmintrin_h" "$ac_includes_default" +if test "x$ac_cv_header_wmmintrin_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WMMINTRIN_H 1 +_ACEOF + +fi + +done + +CPPFLAGS="$old_CPPFLAGS" + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" +case $ac_cv_c_int16_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int16_t $ac_cv_c_int16_t +_ACEOF +;; +esac + +ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" +case $ac_cv_c_int32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int32_t $ac_cv_c_int32_t +_ACEOF +;; +esac + +ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" +case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; +esac + +ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t" +case $ac_cv_c_int8_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int8_t $ac_cv_c_int8_t +_ACEOF +;; +esac + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" +case $ac_cv_c_uint16_t in #( + no|yes) ;; #( + *) + + +cat >>confdefs.h <<_ACEOF +#define uint16_t $ac_cv_c_uint16_t +_ACEOF +;; + esac + +ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" +case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT32_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + +ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" +case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT64_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + +ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" +case $ac_cv_c_uint8_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT8_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint8_t $ac_cv_c_uint8_t +_ACEOF +;; + esac + + +# Checks for library functions. +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include <stdlib.h> +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_func in memmove memset +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in posix_memalign aligned_alloc _aligned_malloc +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by FULL-PACKAGE-NAME $as_me VERSION, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to <BUG-REPORT-ADDRESS>." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +FULL-PACKAGE-NAME config.status VERSION +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; + "buildenv") CONFIG_FILES="$CONFIG_FILES buildenv" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..5f22d00 --- /dev/null +++ b/configure.ac @@ -0,0 +1,108 @@ +# -*- Autoconf -*- +# PyCrypto's configure.ac file. +# Process this file with autoconf to produce a configure script. +# +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +AC_PREREQ([2.67]) +AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) +AC_CONFIG_SRCDIR([src/pycrypto_compat.h]) +AC_CONFIG_HEADERS([src/config.h]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_FILES([buildenv]) + +AM_INIT_AUTOMAKE([foreign no-define no-dist]) + +# Checks for programs. +AC_PROG_CC_C99 + +AC_CANONICAL_HOST() +case "$host_os" in # XXX - Does this break cross-compiling? +openbsd*) + # According to gcc-local(1), OpenBSD's gcc is modified to ignore /usr/local + # by default. However, libgmp is usually installed to /usr/local, so we + # want to look there for the libraries. + CFLAGS="$CFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + ;; +*) + ;; +esac + +AX_CHECK_COMPILE_FLAG([-Wall], [AX_APPEND_FLAG([-Wall])]) +AX_CHECK_COMPILE_FLAG([-Wextra], [AX_APPEND_FLAG([-Wextra])]) +AX_CHECK_COMPILE_FLAG([-Wno-missing-field-initializers], [AX_APPEND_FLAG([-Wno-missing-field-initializers])]) +AX_CHECK_COMPILE_FLAG([-Wno-unused-parameter], [AX_APPEND_FLAG([-Wno-unused-parameter])]) +AX_CHECK_COMPILE_FLAG([-maes], [ + have_maes=yes + AC_DEFINE(HAVE_MAES, [1], [Define if CC supports -maes]) +]) + +# Checks for libraries. +AC_ARG_WITH([gmp], AS_HELP_STRING([--without-gmp], [Build without gmp library (default: test)])) +AS_IF([test "x$with_gmp" != "xno"], [ + AC_CHECK_LIB([gmp], [__gmpz_init]) +]) + +AC_ARG_WITH([mpir], AS_HELP_STRING([--without-mpir], [Build without mpir library (default: test)])) +AS_IF([test "x$with_mpir" != "xno"], [ + AC_CHECK_LIB([mpir], [__gmpz_init]) +]) + +AC_CHECK_DECLS([mpz_powm], [], [], [ +[#if HAVE_LIBGMP +# include <gmp.h> +#elif HAVE_LIBMPIR +# include <mpir.h> +#endif +]]) +AC_CHECK_DECLS([mpz_powm_sec], [], [], [ +[#if HAVE_LIBGMP +# include <gmp.h> +#elif HAVE_LIBMPIR +# include <mpir.h> +#endif +]]) + +# Checks for header files. +AC_CHECK_HEADERS([inttypes.h sys/inttypes.h cpuid.h limits.h stddef.h stdint.h stdlib.h string.h wchar.h]) +old_CPPFLAGS="$CPPFLAGS" +AS_IF([test "x$have_maes" = "xyes"], [ + CPPFLAGS="$CPPFLAGS -maes" +]) +AC_CHECK_HEADERS([wmmintrin.h]) +CPPFLAGS="$old_CPPFLAGS" + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_INLINE +AC_TYPE_INT16_T +AC_TYPE_INT32_T +AC_TYPE_INT64_T +AC_TYPE_INT8_T +AC_TYPE_SIZE_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AC_TYPE_UINT8_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS([memmove memset]) +AC_CHECK_FUNCS([posix_memalign aligned_alloc _aligned_malloc]) + +AC_OUTPUT diff --git a/lib/Crypto/Cipher/AES.py b/lib/Crypto/Cipher/AES.py new file mode 100644 index 0000000..c484846 --- /dev/null +++ b/lib/Crypto/Cipher/AES.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# +# Cipher/AES.py : AES +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""AES symmetric cipher + +AES `(Advanced Encryption Standard)`__ is a symmetric block cipher standardized +by NIST_ . It has a fixed data block size of 16 bytes. +Its keys can be 128, 192, or 256 bits long. + +AES is very fast and secure, and it is the de facto standard for symmetric +encryption. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import AES + >>> from Crypto.Random import get_random_bytes + >>> + >>> key = b'Sixteen byte key' + >>> iv = get_random_bytes(16) + >>> cipher = AES.new(key, AES.MODE_CFB, iv) + >>> msg = iv + cipher.encrypt(b'Attack at dawn') + +A more complicated example is based on CCM, (see `MODE_CCM`) an `AEAD`_ mode +that provides both confidentiality and authentication for a message. + +It optionally allows the header of the message to remain in the clear, whilst still +being authenticated. The encryption is done as follows: + + >>> from Crypto.Cipher import AES + >>> from Crypto.Random import get_random_bytes + >>> + >>> + >>> hdr = b'To your eyes only' + >>> plaintext = b'Attack at dawn' + >>> key = b'Sixteen byte key' + >>> nonce = get_random_bytes(11) + >>> cipher = AES.new(key, AES.MODE_CCM, nonce) + >>> cipher.update(hdr) + >>> msg = nonce, hdr, cipher.encrypt(plaintext), cipher.digest() + +We assume that the tuple ``msg`` is transmitted to the receiver: + + >>> nonce, hdr, ciphertext, mac = msg + >>> key = b'Sixteen byte key' + >>> cipher = AES.new(key, AES.MODE_CCM, nonce) + >>> cipher.update(hdr) + >>> plaintext = cipher.decrypt(ciphertext) + >>> try: + >>> cipher.verify(mac) + >>> print "The message is authentic: hdr=%s, pt=%s" % (hdr, plaintext) + >>> except ValueError: + >>> print "Key incorrect or message corrupted" + +.. __: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard +.. _NIST: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf +.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _AES +from Crypto.Util import cpuid +# Import _AESNI. If AES-NI is not available or _AESNI has not been built, set +# _AESNI to None. +try: + if cpuid.have_aes_ni(): + from Crypto.Cipher import _AESNI + else: + _AESNI = None +except ImportError: + _AESNI = None + +class AESCipher (blockalgo.BlockAlgo): + """AES cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize an AES cipher object + + See also `new()` at the module level.""" + + # Check if the use_aesni was specified. + use_aesni = True + if kwargs.has_key('use_aesni'): + use_aesni = kwargs['use_aesni'] + del kwargs['use_aesni'] + + # Use _AESNI if the user requested AES-NI and it's available + if _AESNI is not None and use_aesni: + blockalgo.BlockAlgo.__init__(self, _AESNI, key, *args, **kwargs) + else: + blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new AES cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It must be 16 (*AES-128*), 24 (*AES-192*), or 32 (*AES-256*) bytes long. + + Only in `MODE_SIV`, it needs to be 32, 48, or 64 bytes long. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). + + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be 16 bytes long. + nonce : byte string + (*Only* `MODE_CCM`, `MODE_EAX`, `MODE_GCM`, `MODE_SIV`). + + A mandatory value that must never be reused for any other encryption. + + For `MODE_CCM`, its length must be in the range ``[7..13]``. + 11 or 12 bytes are reasonable values in general. Bear in + mind that with CCM there is a trade-off between nonce length and + maximum message size. + + For the other modes, there are no restrictions on its length, + but it is recommended to use at least 16 bytes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + mac_len : integer + (*Only* `MODE_CCM`). Length of the MAC, in bytes. It must be even and in + the range ``[4..16]``. The default is 16. + + (*Only* `MODE_EAX` and `MODE_GCM`). Length of the MAC, in bytes. It must be no + larger than 16 bytes (which is the default). + msg_len : integer + (*Only* `MODE_CCM`). Length of the message to (de)cipher. + If not specified, ``encrypt`` or ``decrypt`` may only be called once. + assoc_len : integer + (*Only* `MODE_CCM`). Length of the associated data. + If not specified, all data is internally buffered. + use_aesni : boolean + Use AES-NI if available. + + :Return: an `AESCipher` object + """ + return AESCipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Counter with CBC-MAC (CCM) Mode. See `blockalgo.MODE_CCM`. +MODE_CCM = 8 +#: EAX Mode. See `blockalgo.MODE_EAX`. +MODE_EAX = 9 +#: Syntethic Initialization Vector (SIV). See `blockalgo.MODE_SIV`. +MODE_SIV = 10 +#: Galois Counter Mode (GCM). See `blockalgo.MODE_GCM`. +MODE_GCM = 11 +#: Size of a data block (in bytes) +block_size = 16 +#: Size of a key (in bytes) +key_size = ( 16, 24, 32 ) + diff --git a/lib/Crypto/Cipher/ARC2.py b/lib/Crypto/Cipher/ARC2.py new file mode 100644 index 0000000..1b3fa4e --- /dev/null +++ b/lib/Crypto/Cipher/ARC2.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# +# Cipher/ARC2.py : ARC2.py +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""RC2 symmetric cipher + +RC2_ (Rivest's Cipher version 2) is a symmetric block cipher designed +by Ron Rivest in 1987. The cipher started as a proprietary design, +that was reverse engineered and anonymously posted on Usenet in 1996. +For this reason, the algorithm was first called *Alleged* RC2 (ARC2), +since the company that owned RC2 (RSA Data Inc.) did not confirm whether +the details leaked into public domain were really correct. + +The company eventually published its full specification in RFC2268_. + +RC2 has a fixed data block size of 8 bytes. Length of its keys can vary from +8 to 128 bits. One particular property of RC2 is that the actual +cryptographic strength of the key (*effective key length*) can be reduced +via a parameter. + +Even though RC2 is not cryptographically broken, it has not been analyzed as +thoroughly as AES, which is also faster than RC2. + +New designs should not use RC2. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import ARC2 + >>> from Crypto import Random + >>> + >>> key = b'Sixteen byte key' + >>> iv = Random.new().read(ARC2.block_size) + >>> cipher = ARC2.new(key, ARC2.MODE_CFB, iv) + >>> msg = iv + cipher.encrypt(b'Attack at dawn') + +.. _RC2: http://en.wikipedia.org/wiki/RC2 +.. _RFC2268: http://tools.ietf.org/html/rfc2268 + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _ARC2 + +class RC2Cipher (blockalgo.BlockAlgo): + """RC2 cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize an ARC2 cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _ARC2, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new RC2 cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length can vary from 1 to 128 bytes. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). + + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be 8 bytes long. + nonce : byte string + (*Only* `MODE_EAX`). + A mandatory value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to + use at least 16 bytes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + mac_len : integer + (*Only* `MODE_EAX`). Length of the MAC, in bytes. + It must be no larger than 8 (which is the default). + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + effective_keylen : integer + Maximum cryptographic strength of the key, in bits. + It can vary from 0 to 1024. The default value is 1024. + + :Return: an `RC2Cipher` object + """ + return RC2Cipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: EAX Mode. See `blockalgo.MODE_EAX`. +MODE_EAX = 9 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = xrange(1,16+1) + diff --git a/lib/Crypto/Cipher/ARC4.py b/lib/Crypto/Cipher/ARC4.py new file mode 100644 index 0000000..48d39f1 --- /dev/null +++ b/lib/Crypto/Cipher/ARC4.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# +# Cipher/ARC4.py : ARC4 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""ARC4 symmetric cipher + +ARC4_ (Alleged RC4) is an implementation of RC4 (Rivest's Cipher version 4), +a symmetric stream cipher designed by Ron Rivest in 1987. + +The cipher started as a proprietary design, that was reverse engineered and +anonymously posted on Usenet in 1994. The company that owns RC4 (RSA Data +Inc.) never confirmed the correctness of the leaked algorithm. + +Unlike RC2, the company has never published the full specification of RC4, +of whom it still holds the trademark. + +ARC4 keys can vary in length from 40 to 2048 bits. + +One problem of ARC4 is that it does not take a nonce or an IV. If it is required +to encrypt multiple messages with the same long-term key, a distinct +independent nonce must be created for each message, and a short-term key must +be derived from the combination of the long-term key and the nonce. +Due to the weak key scheduling algorithm of RC2, the combination must be carried +out with a complex function (e.g. a cryptographic hash) and not by simply +concatenating key and nonce. + +New designs should not use ARC4. A good alternative is AES +(`Crypto.Cipher.AES`) in any of the modes that turn it into a stream cipher (OFB, CFB, or CTR). + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import ARC4 + >>> from Crypto.Hash import SHA + >>> from Crypto import Random + >>> + >>> key = b'Very long and confidential key' + >>> nonce = Random.new().read(16) + >>> tempkey = SHA.new(key+nonce).digest() + >>> cipher = ARC4.new(tempkey) + >>> msg = nonce + cipher.encrypt(b'Open the pod bay doors, HAL') + +.. _ARC4: http://en.wikipedia.org/wiki/RC4 + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * +from Crypto.Cipher import _ARC4 + +class ARC4Cipher: + """ARC4 cipher object""" + + + def __init__(self, key, *args, **kwargs): + """Initialize an ARC4 cipher object + + See also `new()` at the module level.""" + + if len(args)>0: + ndrop = args[0] + args = args[1:] + else: + ndrop = kwargs.get('drop', 0) + if ndrop: del kwargs['drop'] + self._cipher = _ARC4.new(key, *args, **kwargs) + if ndrop: + # This is OK even if the cipher is used for decryption, since encrypt + # and decrypt are actually the same thing with ARC4. + self._cipher.encrypt(b('\x00')*ndrop) + + self.block_size = self._cipher.block_size + self.key_size = self._cipher.key_size + + def encrypt(self, plaintext): + """Encrypt a piece of data. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. It can be of any size. + :Return: the encrypted data (byte string, as long as the + plaintext). + """ + return self._cipher.encrypt(plaintext) + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :Parameters: + ciphertext : byte string + The piece of data to decrypt. It can be of any size. + :Return: the decrypted data (byte string, as long as the + ciphertext). + """ + return self._cipher.decrypt(ciphertext) + +def new(key, *args, **kwargs): + """Create a new ARC4 cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It can have any length, with a minimum of 40 bytes. + Its cryptograpic strength is always capped to 2048 bits (256 bytes). + :Keywords: + drop : integer + The amount of bytes to discard from the initial part of the keystream. + In fact, such part has been found to be distinguishable from random + data (while it shouldn't) and also correlated to key. + + The recommended value is 3072_ bytes. The default value is 0. + + :Return: an `ARC4Cipher` object + + .. _3072: http://eprint.iacr.org/2002/067.pdf + """ + return ARC4Cipher(key, *args, **kwargs) + +#: Size of a data block (in bytes) +block_size = 1 +#: Size of a key (in bytes) +key_size = xrange(1,256+1) + diff --git a/lib/Crypto/Cipher/Blowfish.py b/lib/Crypto/Cipher/Blowfish.py new file mode 100644 index 0000000..92fad7f --- /dev/null +++ b/lib/Crypto/Cipher/Blowfish.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# +# Cipher/Blowfish.py : Blowfish +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Blowfish symmetric cipher + +Blowfish_ is a symmetric block cipher designed by Bruce Schneier. + +It has a fixed data block size of 8 bytes and its keys can vary in length +from 32 to 448 bits (4 to 56 bytes). + +Blowfish is deemed secure and it is fast. However, its keys should be chosen +to be big enough to withstand a brute force attack (e.g. at least 16 bytes). + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import Blowfish + >>> from Crypto import Random + >>> from struct import pack + >>> + >>> bs = Blowfish.block_size + >>> key = b'An arbitrarily long key' + >>> iv = Random.new().read(bs) + >>> cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv) + >>> plaintext = b'docendo discimus ' + >>> plen = bs - divmod(len(plaintext),bs)[1] + >>> padding = [plen]*plen + >>> padding = pack('b'*plen, *padding) + >>> msg = iv + cipher.encrypt(plaintext + padding) + +.. _Blowfish: http://www.schneier.com/blowfish.html + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _Blowfish + +class BlowfishCipher (blockalgo.BlockAlgo): + """Blowfish cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a Blowfish cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _Blowfish, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new Blowfish cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length can vary from 4 to 56 bytes. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). + + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be 8 bytes long. + nonce : byte string + (*Only* `MODE_EAX`). + A mandatory value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to + use at least 16 bytes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + mac_len : integer + (*Only* `MODE_EAX`). Length of the MAC, in bytes. + It must be no larger than 8 (which is the default). + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: a `BlowfishCipher` object + """ + return BlowfishCipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: EAX Mode. See `blockalgo.MODE_EAX`. +MODE_EAX = 9 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = xrange(4,56+1) + diff --git a/lib/Crypto/Cipher/CAST.py b/lib/Crypto/Cipher/CAST.py new file mode 100644 index 0000000..6e136a3 --- /dev/null +++ b/lib/Crypto/Cipher/CAST.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# +# Cipher/CAST.py : CAST +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""CAST-128 symmetric cipher + +CAST-128_ (or CAST5) is a symmetric block cipher specified in RFC2144_. + +It has a fixed data block size of 8 bytes. Its key can vary in length +from 40 to 128 bits. + +CAST is deemed to be cryptographically secure, but its usage is not widespread. +Keys of sufficient length should be used to prevent brute force attacks +(128 bits are recommended). + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import CAST + >>> from Crypto import Random + >>> + >>> key = b'Sixteen byte key' + >>> iv = Random.new().read(CAST.block_size) + >>> cipher = CAST.new(key, CAST.MODE_OPENPGP, iv) + >>> plaintext = b'sona si latine loqueris ' + >>> msg = cipher.encrypt(plaintext) + >>> + ... + >>> eiv = msg[:CAST.block_size+2] + >>> ciphertext = msg[CAST.block_size+2:] + >>> cipher = CAST.new(key, CAST.MODE_OPENPGP, eiv) + >>> print cipher.decrypt(ciphertext) + +.. _CAST-128: http://en.wikipedia.org/wiki/CAST-128 +.. _RFC2144: http://tools.ietf.org/html/rfc2144 + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _CAST + +class CAST128Cipher(blockalgo.BlockAlgo): + """CAST-128 cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a CAST-128 cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _CAST, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new CAST-128 cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length may vary from 5 to 16 bytes. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). + + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be 8 bytes long. + nonce : byte string + (*Only* `MODE_EAX`). + A mandatory value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to + use at least 16 bytes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + mac_len : integer + (*Only* `MODE_EAX`). Length of the MAC, in bytes. + It must be no larger than 8 (which is the default). + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: an `CAST128Cipher` object + """ + return CAST128Cipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: EAX Mode. See `blockalgo.MODE_EAX`. +MODE_EAX = 9 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = xrange(5,16+1) diff --git a/lib/Crypto/Cipher/DES.py b/lib/Crypto/Cipher/DES.py new file mode 100644 index 0000000..18a7bd1 --- /dev/null +++ b/lib/Crypto/Cipher/DES.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# +# Cipher/DES.py : DES +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""DES symmetric cipher + +DES `(Data Encryption Standard)`__ is a symmetric block cipher standardized +by NIST_ . It has a fixed data block size of 8 bytes. +Its keys are 64 bits long, even though 8 bits were used for integrity (now they +are ignored) and do not contribute to securty. + +DES is cryptographically secure, but its key length is too short by nowadays +standards and it could be brute forced with some effort. + +DES should not be used for new designs. Use `AES`. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import DES + >>> from Crypto import Random + >>> + >>> key = b'-8B key-' + >>> iv = Random.new().read(DES.block_size) + >>> cipher = DES.new(key, DES.MODE_OFB, iv) + >>> plaintext = b'sona si latine loqueris ' + >>> msg = iv + cipher.encrypt(plaintext) + +.. __: http://en.wikipedia.org/wiki/Data_Encryption_Standard +.. _NIST: http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _DES + +class DESCipher(blockalgo.BlockAlgo): + """DES cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a DES cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _DES, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new DES cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It must be 8 byte long. The parity bits will be ignored. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). + + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be 8 bytes long. + nonce : byte string + (*Only* `MODE_EAX`). + A mandatory value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to + use at least 16 bytes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + mac_len : integer + (*Only* `MODE_EAX`). Length of the MAC, in bytes. + It must be no larger than 8 (which is the default). + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: an `DESCipher` object + """ + return DESCipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: EAX Mode. See `blockalgo.MODE_EAX`. +MODE_EAX = 9 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = 8 diff --git a/lib/Crypto/Cipher/DES3.py b/lib/Crypto/Cipher/DES3.py new file mode 100644 index 0000000..eae2dcc --- /dev/null +++ b/lib/Crypto/Cipher/DES3.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# +# Cipher/DES3.py : DES3 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Triple DES symmetric cipher + +`Triple DES`__ (or TDES or TDEA or 3DES) is a symmetric block cipher standardized by NIST_. +It has a fixed data block size of 8 bytes. Its keys are 128 (*Option 1*) or 192 +bits (*Option 2*) long. +However, 1 out of 8 bits is used for redundancy and do not contribute to +security. The effective key length is respectively 112 or 168 bits. + +TDES consists of the concatenation of 3 simple `DES` ciphers. + +The plaintext is first DES encrypted with *K1*, then decrypted with *K2*, +and finally encrypted again with *K3*. The ciphertext is decrypted in the reverse manner. + +The 192 bit key is a bundle of three 64 bit independent subkeys: *K1*, *K2*, and *K3*. + +The 128 bit key is split into *K1* and *K2*, whereas *K1=K3*. + +It is important that all subkeys are different, otherwise TDES would degrade to +single `DES`. + +TDES is cryptographically secure, even though it is neither as secure nor as fast +as `AES`. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import DES3 + >>> from Crypto import Random + >>> from Crypto.Util import Counter + >>> + >>> key = b'Sixteen byte key' + >>> nonce = Random.new().read(DES3.block_size/2) + >>> ctr = Counter.new(DES3.block_size*8/2, prefix=nonce) + >>> cipher = DES3.new(key, DES3.MODE_CTR, counter=ctr) + >>> plaintext = b'We are no longer the knights who say ni!' + >>> msg = nonce + cipher.encrypt(plaintext) + +.. __: http://en.wikipedia.org/wiki/Triple_DES +.. _NIST: http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _DES3 + +class DES3Cipher(blockalgo.BlockAlgo): + """TDES cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a TDES cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new TDES cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It must be 16 or 24 bytes long. The parity bits will be ignored. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). + + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be 8 bytes long. + nonce : byte string + (*Only* `MODE_EAX`). + A mandatory value that must never be reused for any other encryption. + There are no restrictions on its length, but it is recommended to + use at least 16 bytes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of 8 bytes. + For better performance, use `Crypto.Util.Counter`. + mac_len : integer + (*Only* `MODE_EAX`). Length of the MAC, in bytes. + It must be no larger than 8 (which is the default). + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Attention: it is important that all 8 byte subkeys are different, + otherwise TDES would degrade to single `DES`. + :Return: an `DES3Cipher` object + """ + return DES3Cipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: EAX Mode. See `blockalgo.MODE_EAX`. +MODE_EAX = 9 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = ( 16, 24 ) diff --git a/lib/Crypto/Cipher/PKCS1_OAEP.py b/lib/Crypto/Cipher/PKCS1_OAEP.py new file mode 100644 index 0000000..ff45719 --- /dev/null +++ b/lib/Crypto/Cipher/PKCS1_OAEP.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +# +# Cipher/PKCS1_OAEP.py : PKCS#1 OAEP +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""RSA encryption protocol according to PKCS#1 OAEP + +See RFC3447__ or the `original RSA Labs specification`__ . + +This scheme is more properly called ``RSAES-OAEP``. + +As an example, a sender may encrypt a message in this way: + + >>> from Crypto.Cipher import PKCS1_OAEP + >>> from Crypto.PublicKey import RSA + >>> + >>> message = b'To be encrypted' + >>> key = RSA.importKey(open('pubkey.der').read()) + >>> cipher = PKCS1_OAEP.new(key) + >>> ciphertext = cipher.encrypt(message) + +At the receiver side, decryption can be done using the private part of +the RSA key: + + >>> key = RSA.importKey(open('privkey.der').read()) + >>> cipher = PKCS1_OAP.new(key) + >>> message = cipher.decrypt(ciphertext) + +:undocumented: __revision__, __package__ + +.. __: http://www.ietf.org/rfc/rfc3447.txt +.. __: http://www.rsa.com/rsalabs/node.asp?id=2125. +""" + +from __future__ import nested_scopes + +__revision__ = "$Id$" +__all__ = [ 'new', 'PKCS1OAEP_Cipher' ] + +import Crypto.Signature.PKCS1_PSS +import Crypto.Hash.SHA1 + +from Crypto.Util.py3compat import * +import Crypto.Util.number +from Crypto.Util.number import ceil_div +from Crypto.Util.strxor import strxor + +class PKCS1OAEP_Cipher: + """This cipher can perform PKCS#1 v1.5 OAEP encryption or decryption.""" + + def __init__(self, key, hashAlgo, mgfunc, label): + """Initialize this PKCS#1 OAEP cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + hashAlgo : hash object + The hash function to use. This can be a module under `Crypto.Hash` + or an existing hash object created from any of such modules. If not specified, + `Crypto.Hash.SHA1` is used. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 is used (a safe choice). + label : byte string + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + + :attention: Modify the mask generation function only if you know what you are doing. + Sender and receiver must use the same one. + """ + self._key = key + + if hashAlgo: + self._hashObj = hashAlgo + else: + self._hashObj = Crypto.Hash.SHA1 + + if mgfunc: + self._mgf = mgfunc + else: + self._mgf = lambda x,y: Crypto.Signature.PKCS1_PSS.MGF1(x,y,self._hashObj) + + self._label = label + + def can_encrypt(self): + """Return True/1 if this cipher object can be used for encryption.""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Return True/1 if this cipher object can be used for decryption.""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Produce the PKCS#1 OAEP encryption of a message. + + This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in + section 7.1.1 of RFC3447. + + :Parameters: + message : byte string + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) + minus 2, minus twice the hash output size. + + :Return: A byte string, the ciphertext in which the message is encrypted. + It is as long as the RSA modulus (in bytes). + :Raise ValueError: + If the RSA key length is not sufficiently long to deal with the given + message. + """ + # TODO: Verify the key is RSA + + randFunc = self._key._randfunc + + # See 7.1.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + mLen = len(message) + + # Step 1b + ps_len = k-mLen-2*hLen-2 + if ps_len<0: + raise ValueError("Plaintext is too long.") + # Step 2a + lHash = self._hashObj.new(self._label).digest() + # Step 2b + ps = bchr(0x00)*ps_len + # Step 2c + db = lHash + ps + bchr(0x01) + message + # Step 2d + ros = randFunc(hLen) + # Step 2e + dbMask = self._mgf(ros, k-hLen-1) + # Step 2f + maskedDB = strxor(db, dbMask) + # Step 2g + seedMask = self._mgf(maskedDB, hLen) + # Step 2h + maskedSeed = strxor(ros, seedMask) + # Step 2i + em = bchr(0x00) + maskedSeed + maskedDB + # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP) + m = self._key.encrypt(em, 0)[0] + # Complete step 3c (I2OSP) + c = bchr(0x00)*(k-len(m)) + m + return c + + def decrypt(self, ct): + """Decrypt a PKCS#1 OAEP ciphertext. + + This function is named ``RSAES-OAEP-DECRYPT``, and is specified in + section 7.1.2 of RFC3447. + + :Parameters: + ct : byte string + The ciphertext that contains the message to recover. + + :Return: A byte string, the original message. + :Raise ValueError: + If the ciphertext length is incorrect, or if the decryption does not + succeed. + :Raise TypeError: + If the RSA key has no private half. + """ + # TODO: Verify the key is RSA + + # See 7.1.2 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + + # Step 1b and 1c + if len(ct) != k or k<hLen+2: + raise ValueError("Ciphertext with incorrect length.") + # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP) + m = self._key.decrypt(ct) + # Complete step 2c (I2OSP) + em = bchr(0x00)*(k-len(m)) + m + # Step 3a + lHash = self._hashObj.new(self._label).digest() + # Step 3b + y = em[0] + # y must be 0, but we MUST NOT check it here in order not to + # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) + maskedSeed = em[1:hLen+1] + maskedDB = em[hLen+1:] + # Step 3c + seedMask = self._mgf(maskedDB, hLen) + # Step 3d + seed = strxor(maskedSeed, seedMask) + # Step 3e + dbMask = self._mgf(seed, k-hLen-1) + # Step 3f + db = strxor(maskedDB, dbMask) + # Step 3g + valid = 1 + one = db[hLen:].find(bchr(0x01)) + lHash1 = db[:hLen] + if lHash1!=lHash: + valid = 0 + if one<0: + valid = 0 + if bord(y)!=0: + valid = 0 + if not valid: + raise ValueError("Incorrect decryption.") + # Step 4 + return db[hLen+one+1:] + +def new(key, hashAlgo=None, mgfunc=None, label=b('')): + """Return a cipher object `PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption. + + :Parameters: + key : RSA key object + The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object. + Decryption is only possible if *key* is a private RSA key. + hashAlgo : hash object + The hash function to use. This can be a module under `Crypto.Hash` + or an existing hash object created from any of such modules. If not specified, + `Crypto.Hash.SHA1` is used. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 is used (a safe choice). + label : byte string + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + + :attention: Modify the mask generation function only if you know what you are doing. + Sender and receiver must use the same one. + """ + return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label) + diff --git a/lib/Crypto/Cipher/PKCS1_v1_5.py b/lib/Crypto/Cipher/PKCS1_v1_5.py new file mode 100644 index 0000000..345ffc2 --- /dev/null +++ b/lib/Crypto/Cipher/PKCS1_v1_5.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- +# +# Cipher/PKCS1-v1_5.py : PKCS#1 v1.5 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""RSA encryption protocol according to PKCS#1 v1.5 + +See RFC3447__ or the `original RSA Labs specification`__ . + +This scheme is more properly called ``RSAES-PKCS1-v1_5``. + +**If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.** + +As an example, a sender may encrypt a message in this way: + + >>> from Crypto.Cipher import PKCS1_v1_5 + >>> from Crypto.PublicKey import RSA + >>> from Crypto.Hash import SHA + >>> + >>> message = b'To be encrypted' + >>> h = SHA.new(message) + >>> + >>> key = RSA.importKey(open('pubkey.der').read()) + >>> cipher = PKCS1_v1_5.new(key) + >>> ciphertext = cipher.encrypt(message+h.digest()) + +At the receiver side, decryption can be done using the private part of +the RSA key: + + >>> From Crypto.Hash import SHA + >>> from Crypto import Random + >>> + >>> key = RSA.importKey(open('privkey.der').read()) + >>> + >>> dsize = SHA.digest_size + >>> sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15 + >>> + >>> cipher = PKCS1_v1_5.new(key) + >>> message = cipher.decrypt(ciphertext, sentinel) + >>> + >>> digest = SHA.new(message[:-dsize]).digest() + >>> if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel + >>> print "Encryption was correct." + >>> else: + >>> print "Encryption was not correct." + +:undocumented: __revision__, __package__ + +.. __: http://www.ietf.org/rfc/rfc3447.txt +.. __: http://www.rsa.com/rsalabs/node.asp?id=2125. +""" + +__revision__ = "$Id$" +__all__ = [ 'new', 'PKCS115_Cipher' ] + +from Crypto.Util.number import ceil_div +from Crypto.Util.py3compat import * +import Crypto.Util.number + +class PKCS115_Cipher: + """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption.""" + + def __init__(self, key): + """Initialize this PKCS#1 v1.5 cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + """ + self._key = key + + def can_encrypt(self): + """Return True if this cipher object can be used for encryption.""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Return True if this cipher object can be used for decryption.""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Produce the PKCS#1 v1.5 encryption of a message. + + This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in + section 7.2.1 of RFC3447. + For a complete example see `Crypto.Cipher.PKCS1_v1_5`. + + :Parameters: + message : byte string + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) minus 11. + + :Return: A byte string, the ciphertext in which the message is encrypted. + It is as long as the RSA modulus (in bytes). + :Raise ValueError: + If the RSA key length is not sufficiently long to deal with the given + message. + + """ + # TODO: Verify the key is RSA + + randFunc = self._key._randfunc + + # See 7.2.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + mLen = len(message) + + # Step 1 + if mLen > k-11: + raise ValueError("Plaintext is too long.") + # Step 2a + class nonZeroRandByte: + def __init__(self, rf): self.rf=rf + def __call__(self, c): + while bord(c)==0x00: c=self.rf(1)[0] + return c + ps = tobytes(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3))) + # Step 2b + em = b('\x00\x02') + ps + bchr(0x00) + message + # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP) + m = self._key.encrypt(em, 0)[0] + # Complete step 3c (I2OSP) + c = bchr(0x00)*(k-len(m)) + m + return c + + def decrypt(self, ct, sentinel): + """Decrypt a PKCS#1 v1.5 ciphertext. + + This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in + section 7.2.2 of RFC3447. + For a complete example see `Crypto.Cipher.PKCS1_v1_5`. + + :Parameters: + ct : byte string + The ciphertext that contains the message to recover. + sentinel : any type + The object to return to indicate that an error was detected during decryption. + + :Return: A byte string. It is either the original message or the ``sentinel`` (in case of an error). + :Raise ValueError: + If the ciphertext length is incorrect + :Raise TypeError: + If the RSA key has no private half. + + :attention: + You should **never** let the party who submitted the ciphertext know that + this function returned the ``sentinel`` value. + Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts), + an attacker is able to recontruct the plaintext of any other encryption that were carried out + with the same RSA public key (see `Bleichenbacher's`__ attack). + + In general, it should not be possible for the other party to distinguish + whether processing at the server side failed because the value returned + was a ``sentinel`` as opposed to a random, invalid message. + + In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5 + embeds no good integrity check. There is roughly one chance + in 2^16 for a random ciphertext to be returned as a valid message + (although random looking). + + It is therefore advisabled to: + + 1. Select as ``sentinel`` a value that resembles a plausable random, invalid message. + 2. Not report back an error as soon as you detect a ``sentinel`` value. + Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not. + 3. Cover all possible errors with a single, generic error indicator. + 4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``). + It is recommended for it to be the rightmost part ``message``. + 5. Where possible, monitor the number of errors due to ciphertexts originating from the same party, + and slow down the rate of the requests from such party (or even blacklist it altogether). + + **If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.** + + .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps + + """ + + # TODO: Verify the key is RSA + + # See 7.2.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + + # Step 1 + if len(ct) != k: + raise ValueError("Ciphertext with incorrect length.") + # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP) + m = self._key.decrypt(ct) + # Complete step 2c (I2OSP) + em = bchr(0x00)*(k-len(m)) + m + # Step 3 + sep = em.find(bchr(0x00),2) + if not em.startswith(b('\x00\x02')) or sep<10: + return sentinel + # Step 4 + return em[sep+1:] + +def new(key): + """Return a cipher object `PKCS115_Cipher` that can be used to perform PKCS#1 v1.5 encryption or decryption. + + :Parameters: + key : RSA key object + The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object. + Decryption is only possible if *key* is a private RSA key. + + """ + return PKCS115_Cipher(key) + diff --git a/lib/Crypto/Cipher/XOR.py b/lib/Crypto/Cipher/XOR.py new file mode 100644 index 0000000..26ec1b1 --- /dev/null +++ b/lib/Crypto/Cipher/XOR.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# +# Cipher/XOR.py : XOR +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""XOR toy cipher + +XOR is one the simplest stream ciphers. Encryption and decryption are +performed by XOR-ing data with a keystream made by contatenating +the key. + +Do not use it for real applications! + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import _XOR + +class XORCipher: + """XOR cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a XOR cipher object + + See also `new()` at the module level.""" + self._cipher = _XOR.new(key, *args, **kwargs) + self.block_size = self._cipher.block_size + self.key_size = self._cipher.key_size + + def encrypt(self, plaintext): + """Encrypt a piece of data. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. It can be of any size. + :Return: the encrypted data (byte string, as long as the + plaintext). + """ + return self._cipher.encrypt(plaintext) + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :Parameters: + ciphertext : byte string + The piece of data to decrypt. It can be of any size. + :Return: the decrypted data (byte string, as long as the + ciphertext). + """ + return self._cipher.decrypt(ciphertext) + +def new(key, *args, **kwargs): + """Create a new XOR cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length may vary from 1 to 32 bytes. + + :Return: an `XORCipher` object + """ + return XORCipher(key, *args, **kwargs) + +#: Size of a data block (in bytes) +block_size = 1 +#: Size of a key (in bytes) +key_size = xrange(1,32+1) + diff --git a/lib/Crypto/Cipher/__init__.py b/lib/Crypto/Cipher/__init__.py new file mode 100644 index 0000000..7afed2d --- /dev/null +++ b/lib/Crypto/Cipher/__init__.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Symmetric- and asymmetric-key encryption algorithms. + +Encryption algorithms transform plaintext in some way that +is dependent on a key or key pair, producing ciphertext. + +Symmetric algorithms +-------------------- + +Encryption can easily be reversed, if (and, hopefully, only if) +one knows the same key. +In other words, sender and receiver share the same key. + +The symmetric encryption modules here all support the interface described in PEP +272, "API for Block Encryption Algorithms". + +If you don't know which algorithm to choose, use AES because it's +standard and has undergone a fair bit of examination. + +======================== ======= ======================== +Module name Type Description +======================== ======= ======================== +`Crypto.Cipher.AES` Block Advanced Encryption Standard +`Crypto.Cipher.ARC2` Block Alleged RC2 +`Crypto.Cipher.ARC4` Stream Alleged RC4 +`Crypto.Cipher.Blowfish` Block Blowfish +`Crypto.Cipher.CAST` Block CAST +`Crypto.Cipher.DES` Block The Data Encryption Standard. + Very commonly used in the past, + but today its 56-bit keys are too small. +`Crypto.Cipher.DES3` Block Triple DES. +`Crypto.Cipher.XOR` Stream The simple XOR cipher. +======================== ======= ======================== + + +Asymmetric algorithms +--------------------- + +For asymmetric algorithms, the key to be used for decryption is totally +different and cannot be derived in a feasible way from the key used +for encryption. Put differently, sender and receiver each own one half +of a key pair. The encryption key is often called ``public`` whereas +the decryption key is called ``private``. + +========================== ======================= +Module name Description +========================== ======================= +`Crypto.Cipher.PKCS1_v1_5` PKCS#1 v1.5 encryption, based on RSA key pairs +`Crypto.Cipher.PKCS1_OAEP` PKCS#1 OAEP encryption, based on RSA key pairs +========================== ======================= + +:undocumented: __revision__, __package__, _AES, _ARC2, _ARC4, _Blowfish + _CAST, _DES, _DES3, _XOR +""" + +__all__ = ['AES', 'ARC2', 'ARC4', + 'Blowfish', 'CAST', 'DES', 'DES3', + 'XOR', + 'PKCS1_v1_5', 'PKCS1_OAEP' + ] + +__revision__ = "$Id$" + + diff --git a/lib/Crypto/Cipher/blockalgo.py b/lib/Crypto/Cipher/blockalgo.py new file mode 100644 index 0000000..84b9bc3 --- /dev/null +++ b/lib/Crypto/Cipher/blockalgo.py @@ -0,0 +1,1036 @@ +# -*- coding: utf-8 -*- +# +# Cipher/blockalgo.py +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Module with definitions common to all block ciphers.""" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +from Crypto.Util.py3compat import * + +from binascii import unhexlify + +from Crypto.Util import Counter +from Crypto.Util.strxor import strxor +from Crypto.Util.number import long_to_bytes, bytes_to_long +import Crypto.Util.Counter +from Crypto.Hash import CMAC +from Crypto.Hash.CMAC import _SmoothMAC +from Crypto.Protocol.KDF import _S2V + +from Crypto.Util import galois + +#: *Electronic Code Book (ECB)*. +#: This is the simplest encryption mode. Each of the plaintext blocks +#: is directly encrypted into a ciphertext block, independently of +#: any other block. This mode exposes frequency of symbols +#: in your plaintext. Other modes (e.g. *CBC*) should be used instead. +#: +#: See `NIST SP800-38A`_ , Section 6.1 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_ECB = 1 + +#: *Cipher-Block Chaining (CBC)*. Each of the ciphertext blocks depends +#: on the current and all previous plaintext blocks. An Initialization Vector +#: (*IV*) is required. +#: +#: The *IV* is a data block to be transmitted to the receiver. +#: The *IV* can be made public, but it must be authenticated by the receiver +#: and it should be picked randomly. +#: +#: See `NIST SP800-38A`_ , Section 6.2 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_CBC = 2 + +#: *Cipher FeedBack (CFB)*. This mode is similar to CBC, but it transforms +#: the underlying block cipher into a stream cipher. Plaintext and ciphertext +#: are processed in *segments* of **s** bits. The mode is therefore sometimes +#: labelled **s**-bit CFB. An Initialization Vector (*IV*) is required. +#: +#: When encrypting, each ciphertext segment contributes to the encryption of +#: the next plaintext segment. +#: +#: This *IV* is a data block to be transmitted to the receiver. +#: The *IV* can be made public, but it should be picked randomly. +#: Reusing the same *IV* for encryptions done with the same key lead to +#: catastrophic cryptographic failures. +#: +#: See `NIST SP800-38A`_ , Section 6.3 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_CFB = 3 + +#: This mode should not be used. +MODE_PGP = 4 + +#: *Output FeedBack (OFB)*. This mode is very similar to CBC, but it +#: transforms the underlying block cipher into a stream cipher. +#: The keystream is the iterated block encryption of an +#: Initialization Vector (*IV*). +#: +#: The *IV* is a data block to be transmitted to the receiver. +#: The *IV* can be made public, but it should be picked randomly. +#: +#: Reusing the same *IV* for encryptions done with the same key lead to +#: catastrophic cryptograhic failures. +#: +#: See `NIST SP800-38A`_ , Section 6.4 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_OFB = 5 + +#: *CounTeR (CTR)*. This mode is very similar to ECB, in that +#: encryption of one block is done independently of all other blocks. +#: Unlike ECB, the block *position* contributes to the encryption and no +#: information leaks about symbol frequency. +#: +#: Each message block is associated to a *counter* which must be unique +#: across all messages that get encrypted with the same key (not just within +#: the same message). The counter is as big as the block size. +#: +#: Counters can be generated in several ways. The most straightword one is +#: to choose an *initial counter block* (which can be made public, similarly +#: to the *IV* for the other modes) and increment its lowest **m** bits by +#: one (modulo *2^m*) for each block. In most cases, **m** is chosen to be half +#: the block size. +#: +#: Reusing the same *initial counter block* for encryptions done with the same +#: key lead to catastrophic cryptograhic failures. +#: +#: See `NIST SP800-38A`_ , Section 6.5 (for the mode) and Appendix B (for how +#: to manage the *initial counter block*). +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_CTR = 6 + +#: *OpenPGP CFB*. This mode is a variant of CFB, and it is only used in PGP and +#: OpenPGP_ applications. An Initialization Vector (*IV*) is required. +#: +#: Unlike CFB, the IV is not transmitted to the receiver. +#: Instead, the *encrypted* IV is. +#: The IV is a random data block. Two of its bytes are duplicated to act +#: as a checksum for the correctness of the key. The encrypted IV is +#: therefore 2 bytes longer than the clean IV. +#: +#: .. _OpenPGP: http://tools.ietf.org/html/rfc4880 +MODE_OPENPGP = 7 + +#: *Counter with CBC-MAC (CCM)*. This is an Authenticated Encryption with +#: Associated Data (`AEAD`_) mode. It provides both confidentiality and +#: authenticity. +#: The header of the message may be left in the clear, if needed, and it will +#: still be subject to authentication. The decryption step tells the receiver +#: if the message comes from a source that really knowns the secret key. +#: Additionally, decryption detects if any part of the message - including the +#: header - has been modified or corrupted. +#: +#: This mode requires a nonce. The nonce shall never repeat for two +#: different messages encrypted with the same key, but it does not need +#: to be random. +#: Note that there is a trade-off between the size of the nonce and the +#: maximum size of a single message you can encrypt. +#: +#: It is important to use a large nonce if the key is reused across several +#: messages and the nonce is chosen randomly. +#: +#: It is acceptable to us a short nonce if the key is only used a few times or +#: if the nonce is taken from a counter. +#: +#: The following table shows the trade-off when the nonce is chosen at +#: random. The column on the left shows how many messages it takes +#: for the keystream to repeat **on average**. In practice, you will want to +#: stop using the key way before that. +#: +#: +--------------------+---------------+-------------------+ +#: | Avg. # of messages | nonce | Max. message | +#: | before keystream | size | size | +#: | repeats | (bytes) | (bytes) | +#: +====================+===============+===================+ +#: | 2**52 | 13 | 64K | +#: +--------------------+---------------+-------------------+ +#: | 2**48 | 12 | 16M | +#: +--------------------+---------------+-------------------+ +#: | 2**44 | 11 | 4G | +#: +--------------------+---------------+-------------------+ +#: | 2**40 | 10 | 1T | +#: +--------------------+---------------+-------------------+ +#: | 2**36 | 9 | 64P | +#: +--------------------+---------------+-------------------+ +#: | 2**32 | 8 | 16E | +#: +--------------------+---------------+-------------------+ +#: +#: This mode is only available for ciphers that operate on 128 bits blocks +#: (e.g. AES but not TDES). +#: +#: See `NIST SP800-38C`_ or RFC3610_ . +#: +#: .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf +#: .. _RFC3610: https://tools.ietf.org/html/rfc3610 +#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html +MODE_CCM = 8 + +#: *EAX*. This is an Authenticated Encryption with Associated Data +#: (`AEAD`_) mode. It provides both confidentiality and authenticity. +#: +#: The header of the message may be left in the clear, if needed, and it will +#: still be subject to authentication. +#: +#: The decryption step tells the receiver if the message comes from a source +#: that really knowns the secret key. +#: Additionally, decryption detects if any part of the message - including the +#: header - has been modified or corrupted. +#: +#: This mode requires a nonce. The nonce shall never repeat for two +#: different messages encrypted with the same key, but it does not need to +#: be random. +# +#: This mode is only available for ciphers that operate on 64 or +#: 128 bits blocks. +#: +#: There are no official standards defining EAX. The implementation is based on +#: `a proposal`__ that was presented to NIST. +#: +#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html +#: .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf +MODE_EAX = 9 + +#: *Synthetic Initialization Vector*. This is an Authenticated Encryption with +#: Associated Data (`AEAD`_) mode. It provides both confidentiality and +#: authenticity. +#: The header of the message may be left in the clear, if needed, and it will +#: still be subject to authentication. The decryption step tells the receiver +#: if the message comes from a source that really knowns the secret key. +#: Additionally, decryption detects if any part of the message - including the +#: header - has been modified or corrupted. +#: +#: If the data being encrypted is completely unpredictable to an adversary +#: (e.g. a secret key, for key wrapping purposes) a nonce is not strictly +#: required. +#: +#: Otherwise, a nonce has to be provided; the nonce shall never repeat +#: for two different messages encrypted with the same key, but it does not +#: need to be random. +#: +#: Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a +#: nonce is not catastrophic for the confidentiality of the message. The only +#: effect is that an attacker can tell when the same plaintext (and same +#: associated data) is protected with the same key. +#: +#: The length of the MAC is fixed to the block size of the underlying cipher. +#: The key size is twice the length of the key of the underlying cipher. +#: +#: This mode is only available for AES ciphers. +#: +#: +--------------------+---------------+-------------------+ +#: | Cipher | SIV MAC size | SIV key length | +#: | | (bytes) | (bytes) | +#: +====================+===============+===================+ +#: | AES-128 | 16 | 32 | +#: +--------------------+---------------+-------------------+ +#: | AES-192 | 16 | 48 | +#: +--------------------+---------------+-------------------+ +#: | AES-256 | 16 | 64 | +#: +--------------------+---------------+-------------------+ +#: +#: See `RFC5297`_ and the `original paper`__. +#: +#: .. _RFC5297: https://tools.ietf.org/html/rfc5297 +#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html +#: .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf +MODE_SIV = 10 + +#: *Galois/Counter Mode (GCM)*. This is an Authenticated Encryption with +#: Associated Data (`AEAD`_) mode. It provides both confidentiality and +#: authenticity. +#: The header of the message may be left in the clear, if needed, and it will +#: still be subject to authentication. The decryption step tells the receiver +#: if the message comes from a source that really knowns the secret key. +#: Additionally, decryption detects if any part of the message - including the +#: header - has been modified or corrupted. +#: +#: This mode requires a nonce. The nonce shall never repeat for two +#: different messages encrypted with the same key, but it does not need to +#: be random. +#: +#: This mode is only available for ciphers that operate on 128 bits blocks +#: (e.g. AES but not TDES). +#: +#: See `NIST SP800-38D`_ . +#: +#: .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf +#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html +MODE_GCM = 11 + + +def _getParameter(name, index, args, kwargs, default=None): + """Find a parameter in tuple and dictionary arguments a function receives""" + + param = kwargs.get(name) + if len(args) > index: + if param: + raise TypeError("Parameter '%s' is specified twice" % name) + param = args[index] + return param or default + + +class _CBCMAC(_SmoothMAC): + + def __init__(self, key, ciphermod): + _SmoothMAC.__init__(self, ciphermod.block_size, None, 0) + self._key = key + self._factory = ciphermod + + def _ignite(self, data): + if self._mac: + raise TypeError("_ignite() cannot be called twice") + + self._buffer.insert(0, data) + self._buffer_len += len(data) + self._mac = self._factory.new(self._key, MODE_CBC, bchr(0) * 16) + self.update(b("")) + + def _update(self, block_data): + self._t = self._mac.encrypt(block_data)[-16:] + + def _digest(self, left_data): + return self._t + + +class _GHASH(_SmoothMAC): + """GHASH function defined in NIST SP 800-38D, Algorithm 2. + + If X_1, X_2, .. X_m are the blocks of input data, the function + computes: + + X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H + + in the Galois field GF(2^256) using the reducing polynomial + (x^128 + x^7 + x^2 + x + 1). + """ + + def __init__(self, hash_subkey, block_size, table_size='64K'): + _SmoothMAC.__init__(self, block_size, None, 0) + if table_size == '64K': + self._hash_subkey = galois._ghash_expand(hash_subkey) + else: + self._hash_subkey = hash_subkey + self._last_y = bchr(0) * 16 + self._mac = galois._ghash + + def copy(self): + clone = _GHASH(self._hash_subkey, self._bs, table_size='0K') + _SmoothMAC._deep_copy(self, clone) + clone._last_y = self._last_y + return clone + + def _update(self, block_data): + self._last_y = galois._ghash(block_data, self._last_y, + self._hash_subkey) + + def _digest(self, left_data): + return self._last_y + + +class BlockAlgo: + """Class modelling an abstract block cipher.""" + + def __init__(self, factory, key, *args, **kwargs): + self.mode = _getParameter('mode', 0, args, kwargs, default=MODE_ECB) + self.block_size = factory.block_size + self._factory = factory + self._tag = None + + if self.mode == MODE_CCM: + if self.block_size != 16: + raise TypeError("CCM mode is only available for ciphers that operate on 128 bits blocks") + + self._mac_len = kwargs.get('mac_len', 16) # t + if self._mac_len not in (4, 6, 8, 10, 12, 14, 16): + raise ValueError("Parameter 'mac_len' must be even and in the range 4..16") + + self.nonce = _getParameter('nonce', 1, args, kwargs) # N + if not (self.nonce and 7 <= len(self.nonce) <= 13): + raise ValueError("Length of parameter 'nonce' must be" + " in the range 7..13 bytes") + + self._key = key + self._msg_len = kwargs.get('msg_len', None) # p + self._assoc_len = kwargs.get('assoc_len', None) # a + + self._cipherMAC = _CBCMAC(key, factory) + self._done_assoc_data = False # True when all associated data + # has been processed + + # Allowed transitions after initialization + self._next = [self.update, self.encrypt, self.decrypt, + self.digest, self.verify] + + # Try to start CCM + self._start_ccm() + + elif self.mode == MODE_OPENPGP: + self._start_PGP(factory, key, *args, **kwargs) + elif self.mode == MODE_EAX: + self._start_eax(factory, key, *args, **kwargs) + elif self.mode == MODE_SIV: + self._start_siv(factory, key, *args, **kwargs) + elif self.mode == MODE_GCM: + self._start_gcm(factory, key, *args, **kwargs) + else: + self._cipher = factory.new(key, *args, **kwargs) + self.IV = self._cipher.IV + + def _start_gcm(self, factory, key, *args, **kwargs): + + if self.block_size != 16: + raise TypeError("GCM mode is only available for ciphers that operate on 128 bits blocks") + + self.nonce = _getParameter('nonce', 1, args, kwargs) + if not self.nonce: + raise TypeError("MODE_GCM requires a nonce") + + self._mac_len = kwargs.get('mac_len', 16) + if not (self._mac_len and 4 <= self._mac_len <= 16): + raise ValueError("Parameter 'mac_len' must not be larger than 16 bytes") + + # Allowed transitions after initialization + self._next = [self.update, self.encrypt, self.decrypt, + self.digest, self.verify] + + self._done_assoc_data = False + + # Length of the ciphertext or plaintext + self._msg_len = 0 + + # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H + # See also Algorithm 5 (decryption) + hash_subkey = factory.new(key).encrypt(bchr(0) * 16) + + # Step 2 - Compute J0 (integer, not byte string!) + if len(self.nonce) == 12: + self._j0 = bytes_to_long(self.nonce + b("\x00\x00\x00\x01")) + else: + fill = (16 - (len(self.nonce) % 16)) % 16 + 8 + ghash_in = (self.nonce + + bchr(0) * fill + + long_to_bytes(8 * len(self.nonce), 8)) + + mac = _GHASH(hash_subkey, factory.block_size, '0K') + mac.update(ghash_in) + self._j0 = bytes_to_long(mac.digest()) + + # Step 3 - Prepare GCTR cipher for encryption/decryption + ctr = Counter.new(128, initial_value=self._j0 + 1, + allow_wraparound=True) + self._cipher = self._factory.new(key, MODE_CTR, counter=ctr) + + # Step 5 - Bootstrat GHASH + self._cipherMAC = _GHASH(hash_subkey, factory.block_size, '64K') + + # Step 6 - Prepare GCTR cipher for GMAC + ctr = Counter.new(128, initial_value=self._j0, allow_wraparound=True) + self._tag_cipher = self._factory.new(key, MODE_CTR, counter=ctr) + + def _start_siv(self, factory, key, *args, **kwargs): + + subkey_size, rem = divmod(len(key), 2) + if rem: + raise ValueError("MODE_SIV requires a key twice as long as for the underlying cipher") + + # IV is optional + self.nonce = _getParameter('nonce', 1, args, kwargs) + + self._cipherMAC = _S2V(key[:subkey_size], ciphermod=factory) + self._subkey_ctr = key[subkey_size:] + self._mac_len = factory.block_size + + self._cipherMAC = self._cipherMAC + + # Allowed transitions after initialization + self._next = [self.update, self.encrypt, self.decrypt, + self.digest, self.verify] + + def _siv_ctr_cipher(self, tag): + """Create a new CTR cipher from the MAC in SIV mode""" + + tag_int = bytes_to_long(tag) + init_counter = tag_int ^ (tag_int & 0x8000000080000000L) + ctr = Counter.new(self._factory.block_size * 8, + initial_value=init_counter, + allow_wraparound=True) + + return self._factory.new(self._subkey_ctr, MODE_CTR, counter=ctr) + + def _start_eax(self, factory, key, *args, **kwargs): + + self.nonce = _getParameter('nonce', 1, args, kwargs) + if not self.nonce: + raise TypeError("MODE_EAX requires a nonce") + + # Allowed transitions after initialization + self._next = [self.update, self.encrypt, self.decrypt, + self.digest, self.verify] + + self._mac_len = kwargs.get('mac_len', self.block_size) + if not (self._mac_len and 4 <= self._mac_len <= self.block_size): + raise ValueError("Parameter 'mac_len' must not be larger than %d" + % self.block_size) + + self._omac = [ + CMAC.new(key, bchr(0) * (self.block_size - 1) + bchr(i), + ciphermod=factory) + for i in xrange(0, 3) + ] + + # Compute MAC of nonce + self._omac[0].update(self.nonce) + + self._cipherMAC = self._omac[1] + + # MAC of the nonce is also the initial counter for CTR encryption + counter_int = bytes_to_long(self._omac[0].digest()) + counter_obj = Crypto.Util.Counter.new( + self.block_size * 8, + initial_value=counter_int, + allow_wraparound=True) + self._cipher = factory.new(key, MODE_CTR, counter=counter_obj) + + def _start_PGP(self, factory, key, *args, **kwargs): + # OPENPGP mode. For details, see 13.9 in RCC4880. + # + # A few members are specifically created for this mode: + # - _encrypted_iv, set in this constructor + # - _done_first_block, set to True after the first encryption + # - _done_last_block, set to True after a partial block is processed + + self._done_first_block = False + self._done_last_block = False + self.IV = _getParameter('IV', 1, args, kwargs) + if self.IV is None: + # TODO: Decide whether 'IV' or 'iv' should be used going forward, + # and deprecate the other. 'IV' is consistent with the rest of + # PyCrypto, but 'iv' is more common in Python generally. For now, + # we'll support both here. When in doubt, use a positional + # parameter for now. + self.IV = _getParameter('iv', 1, args, kwargs) + if not self.IV: + raise ValueError("MODE_OPENPGP requires an IV") + + # Instantiate a temporary cipher to process the IV + IV_cipher = factory.new( + key, + MODE_CFB, + b('\x00') * self.block_size, # IV for CFB + segment_size=self.block_size * 8) + + # The cipher will be used for... + if len(self.IV) == self.block_size: + # ... encryption + self._encrypted_IV = IV_cipher.encrypt( + self.IV + self.IV[-2:] + # Plaintext + b('\x00') * (self.block_size - 2) # Padding + )[:self.block_size + 2] + elif len(self.IV) == self.block_size + 2: + # ... decryption + self._encrypted_IV = self.IV + self.IV = IV_cipher.decrypt( + self.IV + # Ciphertext + b('\x00') * (self.block_size - 2) # Padding + )[:self.block_size + 2] + if self.IV[-2:] != self.IV[-4:-2]: + raise ValueError("Failed integrity check for OPENPGP IV") + self.IV = self.IV[:-2] + else: + raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP" + % (self.block_size, self.block_size+2)) + + # Instantiate the cipher for the real PGP data + self._cipher = factory.new( + key, + MODE_CFB, + self._encrypted_IV[-self.block_size:], + segment_size=self.block_size * 8 + ) + + def _start_ccm(self, assoc_len=None, msg_len=None): + # CCM mode. This method creates the 2 ciphers used for the MAC + # (self._cipherMAC) and for the encryption/decryption (self._cipher). + # + # Member _assoc_buffer may already contain user data that needs to be + # authenticated. + + if self._cipherMAC.can_reduce(): + # Already started + return + if assoc_len is not None: + self._assoc_len = assoc_len + if msg_len is not None: + self._msg_len = msg_len + if None in (self._assoc_len, self._msg_len): + return + + # q is the length of Q, the encoding of the message length + q = 15 - len(self.nonce) + + ## Compute B_0 + flags = ( + 64 * (self._assoc_len > 0) + + 8 * divmod(self._mac_len - 2, 2)[0] + + (q - 1) + ) + b_0 = bchr(flags) + self.nonce + long_to_bytes(self._msg_len, q) + + # Start CBC MAC with zero IV + assoc_len_encoded = b('') + if self._assoc_len > 0: + if self._assoc_len < (2 ** 16 - 2 ** 8): + enc_size = 2 + elif self._assoc_len < (2L ** 32): + assoc_len_encoded = b('\xFF\xFE') + enc_size = 4 + else: + assoc_len_encoded = b('\xFF\xFF') + enc_size = 8 + assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) + self._cipherMAC._ignite(b_0 + assoc_len_encoded) + + # Start CTR cipher + prefix = bchr(q - 1) + self.nonce + ctr = Counter.new(128 - len(prefix) * 8, prefix, initial_value=0) + self._cipher = self._factory.new(self._key, MODE_CTR, counter=ctr) + # Will XOR against CBC MAC + self._s_0 = self._cipher.encrypt(bchr(0) * 16) + + def update(self, assoc_data): + """Protect associated data + + When using an AEAD mode like CCM, EAX, GCM or SIV, and + if there is any associated data, the caller has to invoke + this function one or more times, before using + ``decrypt`` or ``encrypt``. + + By *associated data* it is meant any data (e.g. packet headers) that + will not be encrypted and will be transmitted in the clear. + However, the receiver is still able to detect any modification to it. + In CCM and GCM, the *associated data* is also called + *additional authenticated data* (AAD). + In EAX, the *associated data* is called *header*. + + If there is no associated data, this method must not be called. + + The caller may split associated data in segments of any size, and + invoke this method multiple times, each time with the next segment. + + :Parameters: + assoc_data : byte string + A piece of associated data. There are no restrictions on its size. + """ + + if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): + raise TypeError("update() not supported by this mode of operation") + + if self.update not in self._next: + raise TypeError("update() can only be called immediately after initialization") + + self._next = [self.update, self.encrypt, self.decrypt, + self.digest, self.verify] + + return self._cipherMAC.update(assoc_data) + + def encrypt(self, plaintext): + """Encrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have encrypted a message + you cannot encrypt (or decrypt) another message using the same + object. + + For `MODE_SIV` (always) and `MODE_CCM` (when ``msg_len`` was not + passed at initialization), this method can be called only **once**. + + For all other modes, the data to encrypt can be broken up in two or + more pieces and `encrypt` can be called multiple times. + + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is equivalent to: + + >>> c.encrypt(a+b) + + That also means that you cannot reuse an object for encrypting + or decrypting other data with the same key. + + This function does not add any padding to the plaintext. + + - For `MODE_ECB` and `MODE_CBC`, *plaintext* length (in bytes) must be + a multiple of *block_size*. + + - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple + of *segment_size*/8. + + - For `MODE_OFB`, `MODE_CTR` and all AEAD modes + *plaintext* can be of any length. + + - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, + unless it is the last chunk of the message. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. + :Return: + the encrypted data, as a byte string. It is as long as + *plaintext* with one exception: when encrypting the first message + chunk with `MODE_OPENPGP`, the encypted IV is prepended to the + returned ciphertext. + """ + + if self.mode == MODE_OPENPGP: + padding_length = (self.block_size - len(plaintext) % self.block_size) % self.block_size + if padding_length > 0: + # CFB mode requires ciphertext to have length multiple + # of block size, + # but PGP mode allows the last block to be shorter + if self._done_last_block: + raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes", + self.block_size) + self._done_last_block = True + padded = plaintext + b('\x00') * padding_length + res = self._cipher.encrypt(padded)[:len(plaintext)] + else: + res = self._cipher.encrypt(plaintext) + if not self._done_first_block: + res = self._encrypted_IV + res + self._done_first_block = True + return res + + if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): + if self.encrypt not in self._next: + raise TypeError("encrypt() can only be called after initialization or an update()") + self._next = [self.encrypt, self.digest] + + if self.mode == MODE_CCM: + if self._assoc_len is None: + self._start_ccm(assoc_len=self._cipherMAC.get_len()) + if self._msg_len is None: + self._start_ccm(msg_len=len(plaintext)) + self._next = [self.digest] + if not self._done_assoc_data: + self._cipherMAC.zero_pad() + self._done_assoc_data = True + + self._cipherMAC.update(plaintext) + + if self.mode == MODE_SIV: + self._next = [self.digest] + + if self.nonce: + self._cipherMAC.update(self.nonce) + + self._cipherMAC.update(plaintext) + self._cipher = self._siv_ctr_cipher(self._cipherMAC.derive()) + + ct = self._cipher.encrypt(plaintext) + + if self.mode == MODE_EAX: + self._omac[2].update(ct) + + if self.mode == MODE_GCM: + if not self._done_assoc_data: + self._cipherMAC.zero_pad() + self._done_assoc_data = True + self._cipherMAC.update(ct) + self._msg_len += len(plaintext) + + return ct + + def decrypt(self, ciphertext): + """Decrypt data with the key and the parameters set at initialization. + + A cipher object is stateful: once you have decrypted a message + you cannot decrypt (or encrypt) another message with the same + object. + + For `MODE_SIV` (always) and `MODE_CCM` (when ``msg_len`` was not + passed at initialization), this method can be called only **once**. + + For all other modes, the data to decrypt can be broken up in two or + more pieces and `decrypt` can be called multiple times. + + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is equivalent to: + + >>> c.decrypt(a+b) + + That also means that you cannot reuse an object for encrypting + or decrypting other data with the same key. + + This function does not remove any padding from the plaintext. + + - For `MODE_ECB` and `MODE_CBC`, *ciphertext* length (in bytes) must + be a multiple of *block_size*. + + - For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple + of *segment_size*/8. + + - For `MODE_OFB`, `MODE_CTR` and all AEAD modes + *ciphertext* can be of any length. + + - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, + unless it is the last chunk of the message. + + - For `MODE_SIV`, *ciphertext* can be of any length, but it must also + include the MAC (concatenated at the end). + + :Parameters: + ciphertext : byte string + The piece of data to decrypt (plus the MAC, for `MODE_SIV` only). + + :Return: the decrypted data (byte string). + """ + + if self.mode == MODE_OPENPGP: + padding_length = (self.block_size - len(ciphertext) % self.block_size) % self.block_size + if padding_length > 0: + # CFB mode requires ciphertext to have length multiple + # of block size, + # but PGP mode allows the last block to be shorter + if self._done_last_block: + raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes", + self.block_size) + self._done_last_block = True + padded = ciphertext + b('\x00') * padding_length + res = self._cipher.decrypt(padded)[:len(ciphertext)] + else: + res = self._cipher.decrypt(ciphertext) + return res + + if self.mode == MODE_SIV: + raise TypeError("decrypt() not allowed for SIV mode." + " Use decrypt_and_verify() instead.") + + if self.mode in (MODE_CCM, MODE_EAX, MODE_GCM): + + if self.decrypt not in self._next: + raise TypeError("decrypt() can only be called after initialization or an update()") + self._next = [self.decrypt, self.verify] + + if self.mode == MODE_CCM: + if self._assoc_len is None: + self._start_ccm(assoc_len=self._cipherMAC.get_len()) + if self._msg_len is None: + self._start_ccm(msg_len=len(ciphertext)) + self._next = [self.verify] + if not self._done_assoc_data: + self._cipherMAC.zero_pad() + self._done_assoc_data = True + + if self.mode == MODE_GCM: + if not self._done_assoc_data: + self._cipherMAC.zero_pad() + self._done_assoc_data = True + + self._cipherMAC.update(ciphertext) + self._msg_len += len(ciphertext) + + if self.mode == MODE_EAX: + self._omac[2].update(ciphertext) + + pt = self._cipher.decrypt(ciphertext) + + if self.mode == MODE_CCM: + self._cipherMAC.update(pt) + + return pt + + def digest(self): + """Compute the *binary* MAC tag in an AEAD mode. + + When using an AEAD mode like CCM or EAX, the caller invokes + this function at the very end. + + This method returns the MAC that shall be sent to the receiver, + together with the ciphertext. + + :Return: the MAC, as a byte string. + """ + + if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): + raise TypeError("digest() not supported by this mode of operation") + + if self.digest not in self._next: + raise TypeError("digest() cannot be called when decrypting or validating a message") + self._next = [self.digest] + + return self._compute_mac() + + def _compute_mac(self): + """Compute MAC without any FSM checks.""" + + if self._tag: + return self._tag + + if self.mode == MODE_CCM: + + if self._assoc_len is None: + self._start_ccm(assoc_len=self._cipherMAC.get_len()) + if self._msg_len is None: + self._start_ccm(msg_len=0) + self._cipherMAC.zero_pad() + self._tag = strxor(self._cipherMAC.digest(), + self._s_0)[:self._mac_len] + + if self.mode == MODE_GCM: + + # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S + self._cipherMAC.zero_pad() + auth_len = self._cipherMAC.get_len() - self._msg_len + for tlen in (auth_len, self._msg_len): + self._cipherMAC.update(long_to_bytes(8 * tlen, 8)) + s_tag = self._cipherMAC.digest() + + # Step 6 - Compute T + self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len] + + if self.mode == MODE_EAX: + tag = bchr(0) * self.block_size + for i in xrange(3): + tag = strxor(tag, self._omac[i].digest()) + self._tag = tag[:self._mac_len] + + if self.mode == MODE_SIV: + self._tag = self._cipherMAC.derive() + + return self._tag + + def hexdigest(self): + """Compute the *printable* MAC tag in an AEAD mode. + + This method is like `digest`. + + :Return: the MAC, as a hexadecimal string. + """ + return "".join(["%02x" % bord(x) for x in self.digest()]) + + def verify(self, mac_tag): + """Validate the *binary* MAC tag in an AEAD mode. + + When using an AEAD mode like CCM or EAX, the caller invokes + this function at the very end. + + This method checks if the decrypted message is indeed valid + (that is, if the key is correct) and it has not been + tampered with while in transit. + + :Parameters: + mac_tag : byte string + This is the *binary* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): + raise TypeError("verify() not supported by this mode of operation") + + if self.verify not in self._next: + raise TypeError("verify() cannot be called when encrypting a message") + self._next = [self.verify] + + res = 0 + # Constant-time comparison + for x, y in zip(self._compute_mac(), mac_tag): + res |= bord(x) ^ bord(y) + if res or len(mac_tag) != self._mac_len: + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Validate the *printable* MAC tag in an AEAD mode. + + This method is like `verify`. + + :Parameters: + hex_mac_tag : string + This is the *printable* MAC, as received from the sender. + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + self.verify(unhexlify(hex_mac_tag)) + + def encrypt_and_digest(self, plaintext): + """Perform encrypt() and digest() in one step. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. + :Return: + a tuple with two byte strings: + + - the encrypted data + - the MAC + """ + + return self.encrypt(plaintext), self.digest() + + def decrypt_and_verify(self, ciphertext, mac_tag): + """Perform decrypt() and verify() in one step. + + :Parameters: + ciphertext : byte string + The piece of data to decrypt. + mac_tag : byte string + This is the *binary* MAC, as received from the sender. + + :Return: the decrypted data (byte string). + :Raises ValueError: + if the MAC does not match. The message has been tampered with + or the key is incorrect. + """ + + if self.mode == MODE_SIV: + if self.decrypt not in self._next: + raise TypeError("decrypt() can only be called" + " after initialization or an update()") + self._next = [self.verify] + + # Take the MAC and start the cipher for decryption + self._mac = mac_tag + self._cipher = self._siv_ctr_cipher(self._mac) + + pt = self._cipher.decrypt(ciphertext) + + if self.nonce: + self._cipherMAC.update(self.nonce) + if pt: + self._cipherMAC.update(pt) + else: + pt = self.decrypt(ciphertext) + + self.verify(mac_tag) + return pt diff --git a/lib/Crypto/Hash/CMAC.py b/lib/Crypto/Hash/CMAC.py new file mode 100644 index 0000000..6305054 --- /dev/null +++ b/lib/Crypto/Hash/CMAC.py @@ -0,0 +1,343 @@ +# -*- coding: utf-8 -*- +# +# Hash/CMAC.py - Implements the CMAC algorithm +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""CMAC (Cipher-based Message Authentication Code) algorithm + +CMAC is a MAC defined in `NIST SP 800-38B`_ and in RFC4493_ (for AES only) +and constructed using a block cipher. It was originally known as `OMAC1`_. + +The algorithm is sometimes named *X-CMAC* where *X* is the name +of the cipher (e.g. AES-CMAC). + +This is an example showing how to *create* an AES-CMAC: + + >>> from Crypto.Hash import CMAC + >>> from Crypto.Cipher import AES + >>> + >>> secret = b'Sixteen byte key' + >>> cobj = CMAC.new(secret, ciphermod=AES) + >>> cobj.update(b'Hello') + >>> print cobj.hexdigest() + +And this is an example showing how to *check* an AES-CMAC: + + >>> from Crypto.Hash import CMAC + >>> from Crypto.Cipher import AES + >>> + >>> # We have received a message 'msg' together + >>> # with its MAC 'mac' + >>> + >>> secret = b'Sixteen byte key' + >>> cobj = CMAC.new(secret, ciphermod=AES) + >>> cobj.update(msg) + >>> try: + >>> cobj.verify(mac) + >>> print "The message '%s' is authentic" % msg + >>> except ValueError: + >>> print "The message or the key is wrong" + +.. _`NIST SP 800-38B`: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf +.. _RFC4493: http://www.ietf.org/rfc/rfc4493.txt +.. _OMAC1: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html +""" + +__all__ = ['new', 'digest_size', 'CMAC' ] + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from binascii import unhexlify + +from Crypto.Util.strxor import strxor +from Crypto.Util.number import long_to_bytes, bytes_to_long + +#: The size of the authentication tag produced by the MAC. +digest_size = None + +def _shift_bytes(bs, xor_lsb=0): + num = (bytes_to_long(bs)<<1) ^ xor_lsb + return long_to_bytes(num, len(bs))[-len(bs):] + +class _SmoothMAC(object): + """Turn a MAC that only operates on aligned blocks of data + into a MAC with granularity of 1 byte.""" + + def __init__(self, block_size, msg=b(""), min_digest=0): + self._bs = block_size + #: Data waiting to be MAC-ed + self._buffer = [] + self._buffer_len = 0 + #: Data received via update() + self._total_len = 0 + #: Minimum amount of bytes required by the final digest step + self._min_digest = min_digest + #: Block MAC object + self._mac = None + #: Cached digest + self._tag = None + if msg: + self.update(msg) + + def can_reduce(self): + return (self._mac is not None) + + def get_len(self): + return self._total_len + + def zero_pad(self): + if self._buffer_len & (self._bs-1): + npad = self._bs - self._buffer_len & (self._bs-1) + self._buffer.append(bchr(0)*npad) + self._buffer_len += npad + + def update(self, data): + # Optimization (try not to copy data if possible) + if self._buffer_len==0 and self.can_reduce() and\ + self._min_digest==0 and len(data)%self._bs==0: + self._update(data) + self._total_len += len(data) + return + + self._buffer.append(data) + self._buffer_len += len(data) + self._total_len += len(data) + + # Feed data into MAC + blocks, rem = divmod(self._buffer_len, self._bs) + if rem<self._min_digest: + blocks -= 1 + if blocks>0 and self.can_reduce(): + aligned_data = blocks*self._bs + buf = b("").join(self._buffer) + self._update(buf[:aligned_data]) + self._buffer = [ buf[aligned_data:] ] + self._buffer_len -= aligned_data + + def _deep_copy(self, target): + # Copy everything by self._mac, since we don't know how to + target._buffer = self._buffer[:] + for m in [ '_bs', '_buffer_len', '_total_len', '_min_digest', '_tag' ]: + setattr(target, m, getattr(self, m)) + + def _update(self, data_block): + """Delegate to the implementation the update + of the MAC state given some new *block aligned* data.""" + raise NotImplementedError("_update() must be still implemented") + + def _digest(self, left_data): + """Delegate to the implementation the computation + of the final MAC given the current MAC state + and the last piece of data (not block aligned).""" + raise NotImplementedError("_digest() must be still implemented") + + def digest(self): + if self._tag: + return self._tag + if self._buffer_len>0: + self.update(b("")) + left_data = b("").join(self._buffer) + self._tag = self._digest(left_data) + return self._tag + +class CMAC(_SmoothMAC): + """Class that implements CMAC""" + + #: The size of the authentication tag produced by the MAC. + digest_size = None + + def __init__(self, key, msg = None, ciphermod = None): + """Create a new CMAC object. + + :Parameters: + key : byte string + secret key for the CMAC object. + The key must be valid for the underlying cipher algorithm. + For instance, it must be 16 bytes long for AES-128. + msg : byte string + The very first chunk of the message to authenticate. + It is equivalent to an early call to `update`. Optional. + ciphermod : module + A cipher module from `Crypto.Cipher`. + The cipher's block size must be 64 or 128 bits. + It is recommended to use `Crypto.Cipher.AES`. + """ + + if ciphermod is None: + raise TypeError("ciphermod must be specified (try AES)") + + _SmoothMAC.__init__(self, ciphermod.block_size, msg, 1) + + self._key = key + self._factory = ciphermod + + # Section 5.3 of NIST SP 800 38B + if ciphermod.block_size==8: + const_Rb = 0x1B + elif ciphermod.block_size==16: + const_Rb = 0x87 + else: + raise TypeError("CMAC requires a cipher with a block size of 8 or 16 bytes, not %d" % + (ciphermod.block_size,)) + self.digest_size = ciphermod.block_size + + # Compute sub-keys + cipher = ciphermod.new(key, ciphermod.MODE_ECB) + l = cipher.encrypt(bchr(0)*ciphermod.block_size) + if bord(l[0]) & 0x80: + self._k1 = _shift_bytes(l, const_Rb) + else: + self._k1 = _shift_bytes(l) + if bord(self._k1[0]) & 0x80: + self._k2 = _shift_bytes(self._k1, const_Rb) + else: + self._k2 = _shift_bytes(self._k1) + + # Initialize CBC cipher with zero IV + self._IV = bchr(0)*ciphermod.block_size + self._mac = ciphermod.new(key, ciphermod.MODE_CBC, self._IV) + + def update(self, msg): + """Continue authentication of a message by consuming the next chunk of data. + + Repeated calls are equivalent to a single call with the concatenation + of all the arguments. In other words: + + >>> m.update(a); m.update(b) + + is equivalent to: + + >>> m.update(a+b) + + :Parameters: + msg : byte string + The next chunk of the message being authenticated + """ + + _SmoothMAC.update(self, msg) + + def _update(self, data_block): + self._IV = self._mac.encrypt(data_block)[-self._mac.block_size:] + + def copy(self): + """Return a copy ("clone") of the MAC object. + + The copy will have the same internal state as the original MAC + object. + This can be used to efficiently compute the MAC of strings that + share a common initial substring. + + :Returns: A `CMAC` object + """ + obj = CMAC(self._key, ciphermod=self._factory) + + _SmoothMAC._deep_copy(self, obj) + obj._mac = self._factory.new(self._key, self._factory.MODE_CBC, self._IV) + for m in [ '_tag', '_k1', '_k2', '_IV']: + setattr(obj, m, getattr(self, m)) + return obj + + def digest(self): + """Return the **binary** (non-printable) MAC of the message that has + been authenticated so far. + + This method does not change the state of the MAC object. + You can continue updating the object after calling this function. + + :Return: A byte string of `digest_size` bytes. It may contain non-ASCII + characters, including null bytes. + """ + return _SmoothMAC.digest(self) + + def _digest(self, last_data): + if len(last_data)==self._bs: + last_block = strxor(last_data, self._k1) + else: + last_block = strxor(last_data+bchr(128)+ + bchr(0)*(self._bs-1-len(last_data)), self._k2) + tag = self._mac.encrypt(last_block) + return tag + + def hexdigest(self): + """Return the **printable** MAC of the message that has been + authenticated so far. + + This method does not change the state of the MAC object. + + :Return: A string of 2* `digest_size` bytes. It contains only + hexadecimal ASCII digits. + """ + return "".join(["%02x" % bord(x) + for x in tuple(self.digest())]) + + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) is valid. + + :Parameters: + mac_tag : byte string + The expected MAC of the message. + :Raises ValueError: + if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + mac = self.digest() + res = 0 + # Constant-time comparison + for x,y in zip(mac, mac_tag): + res |= bord(x) ^ bord(y) + if res or len(mac_tag)!=self.digest_size: + raise ValueError("MAC check failed") + + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) is valid. + + :Parameters: + hex_mac_tag : string + The expected MAC of the message, as a hexadecimal string. + :Raises ValueError: + if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + self.verify(unhexlify(tobytes(hex_mac_tag))) + +def new(key, msg = None, ciphermod = None): + """Create a new CMAC object. + + :Parameters: + key : byte string + secret key for the CMAC object. + The key must be valid for the underlying cipher algorithm. + For instance, it must be 16 bytes long for AES-128. + msg : byte string + The very first chunk of the message to authenticate. + It is equivalent to an early call to `CMAC.update`. Optional. + ciphermod : module + A cipher module from `Crypto.Cipher`. + The cipher's block size must be 64 or 128 bits. + Default is `Crypto.Cipher.AES`. + + :Returns: A `CMAC` object + """ + return CMAC(key, msg, ciphermod) diff --git a/lib/Crypto/Hash/HMAC.py b/lib/Crypto/Hash/HMAC.py new file mode 100644 index 0000000..8865411 --- /dev/null +++ b/lib/Crypto/Hash/HMAC.py @@ -0,0 +1,263 @@ +# HMAC.py - Implements the HMAC algorithm as described by RFC 2104. +# +# =================================================================== +# Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation; +# All Rights Reserved +# +# This file contains code from the Python 2.2 hmac.py module (the +# "Original Code"), with modifications made after it was incorporated +# into PyCrypto (the "Modifications"). +# +# To the best of our knowledge, the Python Software Foundation is the +# copyright holder of the Original Code, and has licensed it under the +# Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for +# details. +# +# The Modifications to this file are dedicated to the public domain. +# To the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. No rights are +# reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + + +"""HMAC (Hash-based Message Authentication Code) algorithm + +HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using +a cryptograpic hash algorithm. +It is usually named *HMAC-X*, where *X* is the hash algorithm; for +instance *HMAC-SHA1* or *HMAC-MD5*. + +The strength of an HMAC depends on: + + - the strength of the hash algorithm + - the length and entropy of the secret key + +This is an example showing how to *create* a MAC: + + >>> from Crypto.Hash import HMAC + >>> + >>> secret = b'Swordfish' + >>> h = HMAC.new(secret) + >>> h.update(b'Hello') + >>> print h.hexdigest() + +This is an example showing how to *check* a MAC: + + >>> from Crypto.Hash import HMAC + >>> + >>> # We have received a message 'msg' together + >>> # with its MAC 'mac' + >>> + >>> secret = b'Swordfish' + >>> h = HMAC.new(secret) + >>> h.update(msg) + >>> try: + >>> h.verify(mac) + >>> print "The message '%s' is authentic" % msg + >>> except ValueError: + >>> print "The message or the key is wrong" + +.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt +.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf +""" + +# This is just a copy of the Python 2.2 HMAC module, modified to work when +# used on versions of Python before 2.2. + +__revision__ = "$Id$" + +__all__ = ['new', 'digest_size', 'HMAC' ] + +from binascii import unhexlify + +from Crypto.Util.strxor import strxor_c +from Crypto.Util.py3compat import * + +#: The size of the authentication tag produced by the MAC. +#: It matches the digest size on the underlying +#: hashing module used. +digest_size = None + +class HMAC: + """Class that implements HMAC""" + + #: The size of the authentication tag produced by the MAC. + #: It matches the digest size on the underlying + #: hashing module used. + digest_size = None + + def __init__(self, key, msg = None, digestmod = None): + """Create a new HMAC object. + + :Parameters: + key : byte string + secret key for the MAC object. + It must be long enough to match the expected security level of the + MAC. However, there is no benefit in using keys longer than the + `digest_size` of the underlying hash algorithm. + msg : byte string + The very first chunk of the message to authenticate. + It is equivalent to an early call to `update()`. Optional. + :Parameter digestmod: + The hash algorithm the HMAC is based on. + Default is `Crypto.Hash.MD5`. + :Type digestmod: + A hash module or object instantiated from `Crypto.Hash` + """ + if digestmod is None: + import MD5 + digestmod = MD5 + + self.digestmod = digestmod + self.outer = digestmod.new() + self.inner = digestmod.new() + try: + self.digest_size = digestmod.digest_size + except AttributeError: + self.digest_size = len(self.outer.digest()) + + try: + # The block size is 128 bytes for SHA384 and SHA512 and 64 bytes + # for the others hash function + blocksize = digestmod.block_size + except AttributeError: + blocksize = 64 + + ipad = 0x36 + opad = 0x5C + + if len(key) > blocksize: + key = digestmod.new(key).digest() + + key = key + bchr(0) * (blocksize - len(key)) + self.outer.update(strxor_c(key, opad)) + self.inner.update(strxor_c(key, ipad)) + if (msg): + self.update(msg) + + def update(self, msg): + """Continue authentication of a message by consuming the next chunk of data. + + Repeated calls are equivalent to a single call with the concatenation + of all the arguments. In other words: + + >>> m.update(a); m.update(b) + + is equivalent to: + + >>> m.update(a+b) + + :Parameters: + msg : byte string + The next chunk of the message being authenticated + """ + + self.inner.update(msg) + + def copy(self): + """Return a copy ("clone") of the MAC object. + + The copy will have the same internal state as the original MAC + object. + This can be used to efficiently compute the MAC of strings that + share a common initial substring. + + :Returns: An `HMAC` object + """ + other = HMAC(b("")) + other.digestmod = self.digestmod + other.inner = self.inner.copy() + other.outer = self.outer.copy() + return other + + def digest(self): + """Return the **binary** (non-printable) MAC of the message that has + been authenticated so far. + + This method does not change the state of the MAC object. + You can continue updating the object after calling this function. + + :Return: A byte string of `digest_size` bytes. It may contain non-ASCII + characters, including null bytes. + """ + + h = self.outer.copy() + h.update(self.inner.digest()) + return h.digest() + + def verify(self, mac_tag): + """Verify that a given **binary** MAC (computed by another party) is valid. + + :Parameters: + mac_tag : byte string + The expected MAC of the message. + :Raises ValueError: + if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + mac = self.digest() + res = 0 + # Constant-time comparison + for x,y in zip(mac, mac_tag): + res |= bord(x) ^ bord(y) + if res or len(mac_tag)!=self.digest_size: + raise ValueError("MAC check failed") + + def hexdigest(self): + """Return the **printable** MAC of the message that has been + authenticated so far. + + This method does not change the state of the MAC object. + + :Return: A string of 2* `digest_size` bytes. It contains only + hexadecimal ASCII digits. + """ + return "".join(["%02x" % bord(x) + for x in tuple(self.digest())]) + + def hexverify(self, hex_mac_tag): + """Verify that a given **printable** MAC (computed by another party) is valid. + + :Parameters: + hex_mac_tag : string + The expected MAC of the message, as a hexadecimal string. + :Raises ValueError: + if the MAC does not match. It means that the message + has been tampered with or that the MAC key is incorrect. + """ + + self.verify(unhexlify(tobytes(hex_mac_tag))) + +def new(key, msg = None, digestmod = None): + """Create a new HMAC object. + + :Parameters: + key : byte string + key for the MAC object. + It must be long enough to match the expected security level of the + MAC. However, there is no benefit in using keys longer than the + `digest_size` of the underlying hash algorithm. + msg : byte string + The very first chunk of the message to authenticate. + It is equivalent to an early call to `HMAC.update()`. + Optional. + :Parameter digestmod: + The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`. + :Type digestmod: + A hash module or instantiated object from `Crypto.Hash` + :Returns: An `HMAC` object + """ + return HMAC(key, msg, digestmod) + diff --git a/lib/Crypto/Hash/MD5.py b/lib/Crypto/Hash/MD5.py new file mode 100644 index 0000000..c5df793 --- /dev/null +++ b/lib/Crypto/Hash/MD5.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""MD5 cryptographic hash algorithm. + +MD5 is specified in RFC1321_ and produces the 128 bit digest of a message. + + >>> from Crypto.Hash import MD5 + >>> + >>> h = MD5.new() + >>> h.update(b'Hello') + >>> print h.hexdigest() + +MD5 stand for Message Digest version 5, and it was invented by Rivest in 1991. + +This algorithm is insecure. Do not use it for new designs. + +.. _RFC1321: http://tools.ietf.org/html/rfc1321 +""" + +from __future__ import nested_scopes + +_revision__ = "$Id$" + +__all__ = ['new', 'block_size', 'digest_size'] + +from Crypto.Util.py3compat import * +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +def __make_constructor(): + try: + # The md5 module is deprecated in Python 2.6, so use hashlib when possible. + from hashlib import md5 as _hash_new + except ImportError: + from md5 import new as _hash_new + + h = _hash_new() + if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'): + # The module from stdlib has the API that we need. Just use it. + return _hash_new + else: + # Wrap the hash object in something that gives us the expected API. + _copy_sentinel = object() + class _MD5(object): + digest_size = 16 + block_size = 64 + name = "md5" + def __init__(self, *args): + if args and args[0] is _copy_sentinel: + self._h = args[1] + else: + self._h = _hash_new(*args) + def copy(self): + return _MD5(_copy_sentinel, self._h.copy()) + def update(self, *args): + f = self.update = self._h.update + f(*args) + def digest(self): + f = self.digest = self._h.digest + return f() + def hexdigest(self): + f = self.hexdigest = self._h.hexdigest + return f() + _MD5.new = _MD5 + return _MD5 + +new = __make_constructor() +del __make_constructor + +#: The size of the resulting hash in bytes. +digest_size = new().digest_size + +#: The internal block size of the hash algorithm in bytes. +block_size = new().block_size diff --git a/lib/Crypto/Hash/RIPEMD.py b/lib/Crypto/Hash/RIPEMD.py new file mode 100644 index 0000000..4e80235 --- /dev/null +++ b/lib/Crypto/Hash/RIPEMD.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +# This file exists for backward compatibility with old code that refers to +# Crypto.Hash.RIPEMD + +"""Deprecated alias for `Crypto.Hash.RIPEMD160`""" + +from Crypto.Hash.RIPEMD160 import new, block_size, digest_size diff --git a/lib/Crypto/Hash/SHA.py b/lib/Crypto/Hash/SHA.py new file mode 100644 index 0000000..0cc141c --- /dev/null +++ b/lib/Crypto/Hash/SHA.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +# This file exists for backward compatibility with old code that refers to +# Crypto.Hash.SHA + +from Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/lib/Crypto/Hash/SHA1.py b/lib/Crypto/Hash/SHA1.py new file mode 100644 index 0000000..9ad9f1e --- /dev/null +++ b/lib/Crypto/Hash/SHA1.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""SHA-1 cryptographic hash algorithm. + +SHA-1_ produces the 160 bit digest of a message. + + >>> from Crypto.Hash import SHA1 + >>> + >>> h = SHA1.new() + >>> h.update(b'Hello') + >>> print h.hexdigest() + +*SHA* stands for Secure Hash Algorithm. + +This algorithm is not considered secure. Do not use it for new designs. + +.. _SHA-1: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf +""" + +from __future__ import nested_scopes + +_revision__ = "$Id$" + +__all__ = ['new', 'block_size', 'digest_size'] + +from Crypto.Util.py3compat import * +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +def __make_constructor(): + try: + # The sha module is deprecated in Python 2.6, so use hashlib when possible. + from hashlib import sha1 as _hash_new + except ImportError: + from sha import new as _hash_new + + h = _hash_new() + if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'): + # The module from stdlib has the API that we need. Just use it. + return _hash_new + else: + # Wrap the hash object in something that gives us the expected API. + _copy_sentinel = object() + class _SHA1(object): + digest_size = 20 + block_size = 64 + name = "sha1" + def __init__(self, *args): + if args and args[0] is _copy_sentinel: + self._h = args[1] + else: + self._h = _hash_new(*args) + def copy(self): + return _SHA1(_copy_sentinel, self._h.copy()) + def update(self, *args): + f = self.update = self._h.update + f(*args) + def digest(self): + f = self.digest = self._h.digest + return f() + def hexdigest(self): + f = self.hexdigest = self._h.hexdigest + return f() + _SHA1.new = _SHA1 + return _SHA1 + +new = __make_constructor() +del __make_constructor + +#: The size of the resulting hash in bytes. +digest_size = new().digest_size + +#: The internal block size of the hash algorithm in bytes. +block_size = new().block_size diff --git a/lib/Crypto/Hash/__init__.py b/lib/Crypto/Hash/__init__.py new file mode 100644 index 0000000..f16e253 --- /dev/null +++ b/lib/Crypto/Hash/__init__.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Hashing algorithms + +Hash functions take arbitrary binary strings as input, and produce a random-like output +of fixed size that is dependent on the input; it should be practically infeasible +to derive the original input data given only the hash function's +output. In other words, the hash function is *one-way*. + +It should also not be practically feasible to find a second piece of data +(a *second pre-image*) whose hash is the same as the original message +(*weak collision resistance*). + +Finally, it should not be feasible to find two arbitrary messages with the +same hash (*strong collision resistance*). + +The output of the hash function is called the *digest* of the input message. +In general, the security of a hash function is related to the length of the +digest. If the digest is *n* bits long, its security level is roughly comparable +to the the one offered by an *n/2* bit encryption algorithm. + +Hash functions can be used simply as a integrity check, or, in +association with a public-key algorithm, can be used to implement +digital signatures. + +The hashing modules here all support the interface described in `PEP +247`_ , "API for Cryptographic Hash Functions". + +.. _`PEP 247` : http://www.python.org/dev/peps/pep-0247/ + +:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512 +""" + +__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1', + 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC'] + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +def new(algo, *args): + """Initialize a new hash object. + + The first argument to this function may be an algorithm name or another + hash object. + + This function has significant overhead. It's recommended that you instead + import and use the individual hash modules directly. + """ + + # Try just invoking algo.new() + # We do this first so that this is the fastest. + try: + new_func = algo.new + except AttributeError: + pass + else: + return new_func(*args) + + # Try getting the algorithm name. + if isinstance(algo, str): + name = algo + else: + try: + name = algo.name + except AttributeError: + raise ValueError("unsupported hash type %r" % (algo,)) + + # Got the name. Let's see if we have a PyCrypto implementation. + try: + new_func = _new_funcs[name] + except KeyError: + # No PyCrypto implementation. Try hashlib. + try: + import hashlib + except ImportError: + # There is no hashlib. + raise ValueError("unsupported hash type %s" % (name,)) + return hashlib.new(name, *args) + else: + # We have a PyCrypto implementation. Instantiate it. + return new_func(*args) + +# This dict originally gets the following _*_new methods, but its members get +# replaced with the real new() methods of the various hash modules as they are +# used. We do it without locks to improve performance, which is safe in +# CPython because dict access is atomic in CPython. This might break PyPI. +_new_funcs = {} + +def _md2_new(*args): + from Crypto.Hash import MD2 + _new_funcs['MD2'] = _new_funcs['md2'] = MD2.new + return MD2.new(*args) +_new_funcs['MD2'] = _new_funcs['md2'] = _md2_new +del _md2_new + +def _md4_new(*args): + from Crypto.Hash import MD4 + _new_funcs['MD4'] = _new_funcs['md4'] = MD4.new + return MD4.new(*args) +_new_funcs['MD4'] = _new_funcs['md4'] = _md4_new +del _md4_new + +def _md5_new(*args): + from Crypto.Hash import MD5 + _new_funcs['MD5'] = _new_funcs['md5'] = MD5.new + return MD5.new(*args) +_new_funcs['MD5'] = _new_funcs['md5'] = _md5_new +del _md5_new + +def _ripemd160_new(*args): + from Crypto.Hash import RIPEMD160 + _new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \ + _new_funcs['RIPEMD'] = _new_funcs['ripemd'] = RIPEMD160.new + return RIPEMD160.new(*args) +_new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \ + _new_funcs['RIPEMD'] = _new_funcs['ripemd'] = _ripemd160_new +del _ripemd160_new + +def _sha1_new(*args): + from Crypto.Hash import SHA1 + _new_funcs['SHA1'] = _new_funcs['sha1'] = \ + _new_funcs['SHA'] = _new_funcs['sha'] = SHA1.new + return SHA1.new(*args) +_new_funcs['SHA1'] = _new_funcs['sha1'] = \ + _new_funcs['SHA'] = _new_funcs['sha'] = _sha1_new +del _sha1_new + +def _sha224_new(*args): + from Crypto.Hash import SHA224 + _new_funcs['SHA224'] = _new_funcs['sha224'] = SHA224.new + return SHA224.new(*args) +_new_funcs['SHA224'] = _new_funcs['sha224'] = _sha224_new +del _sha224_new + +def _sha256_new(*args): + from Crypto.Hash import SHA256 + _new_funcs['SHA256'] = _new_funcs['sha256'] = SHA256.new + return SHA256.new(*args) +_new_funcs['SHA256'] = _new_funcs['sha256'] = _sha256_new +del _sha256_new + +def _sha384_new(*args): + from Crypto.Hash import SHA384 + _new_funcs['SHA384'] = _new_funcs['sha384'] = SHA384.new + return SHA384.new(*args) +_new_funcs['SHA384'] = _new_funcs['sha384'] = _sha384_new +del _sha384_new + +def _sha512_new(*args): + from Crypto.Hash import SHA512 + _new_funcs['SHA512'] = _new_funcs['sha512'] = SHA512.new + return SHA512.new(*args) +_new_funcs['SHA512'] = _new_funcs['sha512'] = _sha512_new +del _sha512_new diff --git a/lib/Crypto/IO/PEM.py b/lib/Crypto/IO/PEM.py new file mode 100644 index 0000000..89a5689 --- /dev/null +++ b/lib/Crypto/IO/PEM.py @@ -0,0 +1,163 @@ +# -*- coding: ascii -*- +# +# Util/PEM.py : Privacy Enhanced Mail utilities +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Set of functions for encapsulating data according to the PEM format. + +PEM (Privacy Enhanced Mail) was an IETF standard for securing emails via a +Public Key Infrastructure. It is specified in RFC 1421-1424. + +Even though it has been abandoned, the simple message encapsulation it defined +is still widely used today for encoding *binary* cryptographic objects like +keys and certificates into text. +""" + +__all__ = ['encode', 'decode'] + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +import re +from binascii import hexlify, unhexlify, a2b_base64, b2a_base64 + +from Crypto.Hash import MD5 +from Crypto.Util.Padding import pad, unpad +from Crypto.Cipher import DES, DES3, AES +from Crypto.Protocol.KDF import PBKDF1 +from Crypto.Random import get_random_bytes + + +def encode(data, marker, passphrase=None, randfunc=None): + """Encode a piece of binary data into PEM format. + + :Parameters: + data : byte string + The piece of binary data to encode. + marker : string + The marker for the PEM block (e.g. "PUBLIC KEY"). + Note that there is no official master list for all allowed markers. + Still, you can refer to the OpenSSL_ source code. + passphrase : byte string + If given, the PEM block will be encrypted. The key is derived from + the passphrase. + randfunc : callable + Random number generation function; it accepts an integer N and returns + a byte string of random data, N bytes long. If not given, a new one is + instantiated. + :Returns: + The PEM block, as a string. + + .. _OpenSSL: http://cvs.openssl.org/fileview?f=openssl/crypto/pem/pem.h&v=1.66.2.1.4.2 + """ + + if randfunc is None: + randfunc = get_random_bytes + + out = "-----BEGIN %s-----\n" % marker + if passphrase: + # We only support 3DES for encryption + salt = randfunc(8) + key = PBKDF1(passphrase, salt, 16, 1, MD5) + key += PBKDF1(key + passphrase, salt, 8, 1, MD5) + objenc = DES3.new(key, DES3.MODE_CBC, salt) + out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\ + tostr(hexlify(salt).upper()) + # Encrypt with PKCS#7 padding + data = objenc.encrypt(pad(data, objenc.block_size)) + + # Each BASE64 line can take up to 64 characters (=48 bytes of data) + # b2a_base64 adds a new line character! + chunks = [tostr(b2a_base64(data[i:i + 48])) + for i in range(0, len(data), 48)] + out += "".join(chunks) + out += "-----END %s-----" % marker + return out + + +def decode(pem_data, passphrase=None): + """Decode a PEM block into binary. + + :Parameters: + pem_data : string + The PEM block. + passphrase : byte string + If given and the PEM block is encrypted, + the key will be derived from the passphrase. + :Returns: + A tuple with the binary data, the marker string, and a boolean to + indicate if decryption was performed. + :Raises ValueError: + If decoding fails, if the PEM file is encrypted and no passphrase has + been provided or if the passphrase is incorrect. + """ + + # Verify Pre-Encapsulation Boundary + r = re.compile("\s*-----BEGIN (.*)-----\n") + m = r.match(pem_data) + if not m: + raise ValueError("Not a valid PEM pre boundary") + marker = m.group(1) + + # Verify Post-Encapsulation Boundary + r = re.compile("-----END (.*)-----\s*$") + m = r.search(pem_data) + if not m or m.group(1) != marker: + raise ValueError("Not a valid PEM post boundary") + + # Removes spaces and slit on lines + lines = pem_data.replace(" ", '').split() + + # Decrypts, if necessary + if lines[1].startswith('Proc-Type:4,ENCRYPTED'): + if not passphrase: + raise ValueError("PEM is encrypted, but no passphrase available") + DEK = lines[2].split(':') + if len(DEK) != 2 or DEK[0] != 'DEK-Info': + raise ValueError("PEM encryption format not supported.") + algo, salt = DEK[1].split(',') + salt = unhexlify(tobytes(salt)) + if algo == "DES-CBC": + # This is EVP_BytesToKey in OpenSSL + key = PBKDF1(passphrase, salt, 8, 1, MD5) + objdec = DES.new(key, DES.MODE_CBC, salt) + elif algo == "DES-EDE3-CBC": + # Note that EVP_BytesToKey is note exactly the same as PBKDF1 + key = PBKDF1(passphrase, salt, 16, 1, MD5) + key += PBKDF1(key + passphrase, salt, 8, 1, MD5) + objdec = DES3.new(key, DES3.MODE_CBC, salt) + elif algo == "AES-128-CBC": + key = PBKDF1(passphrase, salt[:8], 16, 1, MD5) + objdec = AES.new(key, AES.MODE_CBC, salt) + else: + raise ValueError("Unsupport PEM encryption algorithm.") + lines = lines[2:] + else: + objdec = None + + # Decode body + data = a2b_base64(b(''.join(lines[1:-1]))) + enc_flag = False + if objdec: + data = unpad(objdec.decrypt(data), objdec.block_size) + enc_flag = True + + return (data, marker, enc_flag) diff --git a/lib/Crypto/IO/PKCS8.py b/lib/Crypto/IO/PKCS8.py new file mode 100644 index 0000000..ceb0f5a --- /dev/null +++ b/lib/Crypto/IO/PKCS8.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# +# PublicKey/PKCS8.py : PKCS#8 functions +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +""" +Module for handling private keys wrapped according to `PKCS#8`_. + +PKCS8 is a standard for storing and transferring private key information. +The wrapped key can either be clear or encrypted. + +All encryption algorithms are based on passphrase-based key derivation. +The following mechanisms are fully supported: + +* *PBKDF2WithHMAC-SHA1AndAES128-CBC* +* *PBKDF2WithHMAC-SHA1AndAES192-CBC* +* *PBKDF2WithHMAC-SHA1AndAES256-CBC* +* *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC* + +The following mechanisms are only supported for importing keys. +They are much weaker than the ones listed above, and they are provided +for backward compatibility only: + +* *pbeWithMD5AndRC2-CBC* +* *pbeWithMD5AndDES-CBC* +* *pbeWithSHA1AndRC2-CBC* +* *pbeWithSHA1AndDES-CBC* + +.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + +""" + +import sys + +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from Crypto.Util.asn1 import * + +from Crypto.IO._PBES import PBES1, PBES2 + +__all__ = ['wrap', 'unwrap'] + + +def decode_der(obj_class, binstr): + """Instantiate a DER object class, decode a DER binary string in it, and + return the object.""" + der = obj_class() + der.decode(binstr) + return der + + +def wrap(private_key, key_oid, passphrase=None, protection=None, + prot_params=None, key_params=None, randfunc=None): + """Wrap a private key into a PKCS#8 blob (clear or encrypted). + + :Parameters: + + private_key : byte string + The private key encoded in binary form. The actual encoding is + algorithm specific. In most cases, it is DER. + + key_oid : string + The object identifier (OID) of the private key to wrap. + It is a dotted string, like "``1.2.840.113549.1.1.1``" (for RSA keys). + + passphrase : (binary) string + The secret passphrase from which the wrapping key is derived. + Set it only if encryption is required. + + protection : string + The identifier of the algorithm to use for securely wrapping the key. + The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. + + prot_params : dictionary + Parameters for the protection algorithm. + + +------------------+-----------------------------------------------+ + | Key | Description | + +==================+===============================================+ + | iteration_count | The KDF algorithm is repeated several times to| + | | slow down brute force attacks on passwords. | + | | The default value is 1 000. | + +------------------+-----------------------------------------------+ + | salt_size | Salt is used to thwart dictionary and rainbow | + | | attacks on passwords. The default value is 8 | + | | bytes. | + +------------------+-----------------------------------------------+ + + key_params : DER object + The algorithm parameters associated to the private key. + It is required for algorithms like DSA, but not for others like RSA. + + randfunc : callable + Random number generation function; it should accept a single integer + N and return a string of random data, N bytes long. + If not specified, a new RNG will be instantiated + from ``Crypto.Random``. + + :Return: + The PKCS#8-wrapped private key (possibly encrypted), + as a binary string. + """ + + if key_params is None: + key_params = DerNull() + + # + # PrivateKeyInfo ::= SEQUENCE { + # version Version, + # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + # privateKey PrivateKey, + # attributes [0] IMPLICIT Attributes OPTIONAL + # } + # + pk_info = newDerSequence( + 0, + newDerSequence( + DerObjectId(key_oid), + key_params + ), + newDerOctetString(private_key) + ) + pk_info_der = pk_info.encode() + + if not passphrase: + return pk_info_der + + # Encryption with PBES2 + passphrase = tobytes(passphrase) + if protection is None: + protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' + return PBES2.encrypt(pk_info_der, passphrase, + protection, prot_params, randfunc) + + +def unwrap(p8_private_key, passphrase=None): + """Unwrap a private key from a PKCS#8 blob (clear or encrypted). + + :Parameters: + p8_private_key : byte string + The private key wrapped into a PKCS#8 blob + passphrase : (byte) string + The passphrase to use to decrypt the blob (if it is encrypted). + :Return: + A tuple containing: + + #. the algorithm identifier of the wrapped key (OID, dotted string) + #. the private key (byte string, DER encoded) + #. the associated parameters (byte string, DER encoded) or ``None`` + + :Raises ValueError: + If decoding fails + """ + + if passphrase: + passphrase = tobytes(passphrase) + found = False + for pbes in PBES1, PBES2: + try: + p8_private_key = pbes.decrypt(p8_private_key, passphrase) + except ValueError: + pass + else: + found = True + break + if not found: + raise ValueError("Unsupported PKCS#5 Object ID ") + + pk_info = decode_der(DerSequence, p8_private_key) + if len(pk_info) == 2 and not passphrase: + raise ValueError("Not a valid clear PKCS#8 structure " + "(maybe it is encrypted?)") + if not 3 <= len(pk_info) <= 4 or pk_info[0] != 0: + raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") + + # + # AlgorithmIdentifier ::= SEQUENCE { + # algorithm OBJECT IDENTIFIER, + # parameters ANY DEFINED BY algorithm OPTIONAL + # } + # + algo_id = decode_der(DerSequence, pk_info[1]) + if not 1 <= len(algo_id) <= 2: + raise ValueError("Not a valid AlgorithmIdentifier SEQUENCE") + algo = decode_der(DerObjectId, algo_id[0]).value + private_key = decode_der(DerOctetString, pk_info[2]).payload + if len(algo_id) == 2 and algo_id[1] != b('\x05\x00'): + params = algo_id[1] + else: + params = None + return (algo, private_key, params) diff --git a/lib/Crypto/IO/_PBES.py b/lib/Crypto/IO/_PBES.py new file mode 100644 index 0000000..42d5dbc --- /dev/null +++ b/lib/Crypto/IO/_PBES.py @@ -0,0 +1,348 @@ +# +# PublicKey/_PBES.py : Password-Based Encryption functions +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from Crypto import Random +from Crypto.Util.asn1 import * + +from Crypto.Util.Padding import pad, unpad +from Crypto.Hash import MD5, SHA1 +from Crypto.Cipher import DES, ARC2, DES3, AES +from Crypto.Protocol.KDF import PBKDF1, PBKDF2 + + +# These are the ASN.1 definitions used by the PBES1/2 logic: +# +# EncryptedPrivateKeyInfo ::= SEQUENCE { +# encryptionAlgorithm EncryptionAlgorithmIdentifier, +# encryptedData EncryptedData +# } +# +# EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier +# +# EncryptedData ::= OCTET STRING +# +# AlgorithmIdentifier ::= SEQUENCE { +# algorithm OBJECT IDENTIFIER, +# parameters ANY DEFINED BY algorithm OPTIONAL +# } +# +# PBEParameter ::= SEQUENCE { +# salt OCTET STRING (SIZE(8)), +# iterationCount INTEGER +# } +# +# PBES2-params ::= SEQUENCE { +# keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, +# encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} +# } +# +# PBKDF2-params ::= SEQUENCE { +# salt CHOICE { +# specified OCTET STRING, +# otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} +# }, +# iterationCount INTEGER (1..MAX), +# keyLength INTEGER (1..MAX) OPTIONAL, +# prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 +# } +# + + +def decode_der(obj_class, binstr): + """Instantiate a DER object class, decode a DER binary string in it, and + return the object.""" + der = obj_class() + der.decode(binstr) + return der + + +class PBES1(object): + """Deprecated encryption scheme with password-based key derivation + (originally defined in PKCS#5 v1.5, but still present in `v2.0`__). + + .. __: http://www.ietf.org/rfc/rfc2898.txt + """ + + def decrypt(data, passphrase): + """Decrypt a piece of data using a passphrase and *PBES1*. + + The algorithm to use is automatically detected. + + :Parameters: + data : byte string + The piece of data to decrypt. + passphrase : byte string + The passphrase to use for decrypting the data. + :Returns: + The decrypted data, as a binary string. + """ + + encrypted_private_key_info = decode_der(DerSequence, data) + encrypted_algorithm = decode_der( + DerSequence, + encrypted_private_key_info[0] + ) + encrypted_data = decode_der( + DerOctetString, + encrypted_private_key_info[1] + ).payload + + pbe_oid = decode_der(DerObjectId, encrypted_algorithm[0]).value + cipher_params = {} + if pbe_oid == "1.2.840.113549.1.5.3": + # PBE_MD5_DES_CBC + hashmod = MD5 + ciphermod = DES + elif pbe_oid == "1.2.840.113549.1.5.6": + # PBE_MD5_RC2_CBC + hashmod = MD5 + ciphermod = ARC2 + cipher_params['effective_keylen'] = 64 + elif pbe_oid == "1.2.840.113549.1.5.10": + # PBE_SHA1_DES_CBC + hashmod = SHA1 + ciphermod = DES + elif pbe_oid == "1.2.840.113549.1.5.11": + # PBE_SHA1_RC2_CBC + hashmod = SHA1 + ciphermod = ARC2 + cipher_params['effective_keylen'] = 64 + else: + raise ValueError("Unknown OID") + + pbe_params = decode_der(DerSequence, encrypted_algorithm[1]) + salt = decode_der(DerOctetString, pbe_params[0]).payload + iterations = pbe_params[1] + + key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) + key, iv = key_iv[:8], key_iv[8:] + + cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params) + pt = cipher.decrypt(encrypted_data) + return unpad(pt, cipher.block_size) + decrypt = staticmethod(decrypt) + + +class PBES2(object): + """Encryption scheme with password-based key derivation + (defined in `PKCS#5 v2.0`__). + + .. __: http://www.ietf.org/rfc/rfc2898.txt.""" + + def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): + """Encrypt a piece of data using a passphrase and *PBES2*. + + :Parameters: + data : byte string + The piece of data to encrypt. + passphrase : byte string + The passphrase to use for encrypting the data. + protection : string + The identifier of the encryption algorithm to use. + The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. + prot_params : dictionary + Parameters of the protection algorithm. + + +------------------+-----------------------------------------------+ + | Key | Description | + +==================+===============================================+ + | iteration_count | The KDF algorithm is repeated several times to| + | | slow down brute force attacks on passwords. | + | | The default value is 1 000. | + +------------------+-----------------------------------------------+ + | salt_size | Salt is used to thwart dictionary and rainbow | + | | attacks on passwords. The default value is 8 | + | | bytes. | + +------------------+-----------------------------------------------+ + + randfunc : callable + Random number generation function; it should accept + a single integer N and return a string of random data, + N bytes long. If not specified, a new RNG will be + instantiated from ``Crypto.Random``. + + :Returns: + The encrypted data, as a binary string. + """ + + if prot_params is None: + prot_params = {} + + if randfunc is None: + randfunc = Random.new().read + + if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC': + key_size = 24 + module = DES3 + protection = DES3.MODE_CBC + enc_oid = "1.2.840.113549.3.7" + elif protection == 'PBKDF2WithHMAC-SHA1AndAES128-CBC': + key_size = 16 + module = AES + protection = AES.MODE_CBC + enc_oid = "2.16.840.1.101.3.4.1.2" + elif protection == 'PBKDF2WithHMAC-SHA1AndAES192-CBC': + key_size = 24 + module = AES + protection = AES.MODE_CBC + enc_oid = "2.16.840.1.101.3.4.1.22" + elif protection == 'PBKDF2WithHMAC-SHA1AndAES256-CBC': + key_size = 32 + module = AES + protection = AES.MODE_CBC + enc_oid = "2.16.840.1.101.3.4.1.42" + else: + raise ValueError("Unknown mode") + + # Get random data + iv = randfunc(module.block_size) + salt = randfunc(prot_params.get("salt_size", 8)) + + # Derive key from password + count = prot_params.get("iteration_count", 1000) + key = PBKDF2(passphrase, salt, key_size, count) + key_derivation_func = newDerSequence( + DerObjectId("1.2.840.113549.1.5.12"), # PBKDF2 + newDerSequence( + DerOctetString(salt), + DerInteger(count) + ) + ) + + # Create cipher and use it + cipher = module.new(key, protection, iv) + encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) + encryption_scheme = newDerSequence( + DerObjectId(enc_oid), + DerOctetString(iv) + ) + + # Result + encrypted_private_key_info = newDerSequence( + # encryptionAlgorithm + newDerSequence( + DerObjectId("1.2.840.113549.1.5.13"), # PBES2 + newDerSequence( + key_derivation_func, + encryption_scheme + ), + ), + DerOctetString(encrypted_data) + ) + return encrypted_private_key_info.encode() + encrypt = staticmethod(encrypt) + + def decrypt(data, passphrase): + """Decrypt a piece of data using a passphrase and *PBES2*. + + The algorithm to use is automatically detected. + + :Parameters: + data : byte string + The piece of data to decrypt. + passphrase : byte string + The passphrase to use for decrypting the data. + :Returns: + The decrypted data, as a binary string. + """ + + encrypted_private_key_info = decode_der(DerSequence, data) + encryption_algorithm = decode_der( + DerSequence, + encrypted_private_key_info[0] + ) + encrypted_data = decode_der( + DerOctetString, + encrypted_private_key_info[1] + ).payload + + pbe_oid = decode_der(DerObjectId, encryption_algorithm[0]).value + if pbe_oid != "1.2.840.113549.1.5.13": + raise ValueError("Not a PBES2 object") + + pbes2_params = decode_der(DerSequence, encryption_algorithm[1]) + + ### Key Derivation Function selection + key_derivation_func = decode_der(DerSequence, pbes2_params[0]) + key_derivation_oid = decode_der( + DerObjectId, + key_derivation_func[0] + ).value + + # For now, we only support PBKDF2 + if key_derivation_oid != "1.2.840.113549.1.5.12": + raise ValueError("Unknown KDF") + + pbkdf2_params = decode_der(DerSequence, key_derivation_func[1]) + salt = decode_der(DerOctetString, pbkdf2_params[0]).payload + iteration_count = pbkdf2_params[1] + if len(pbkdf2_params) > 2: + pbkdf2_key_length = pbkdf2_params[2] + else: + pbkdf2_key_length = None + if len(pbkdf2_params) > 3: + raise ValueError("Unsupported PRF for PBKDF2") + + ### Cipher selection + encryption_scheme = decode_der(DerSequence, pbes2_params[1]) + encryption_oid = decode_der( + DerObjectId, + encryption_scheme[0] + ).value + + if encryption_oid == "1.2.840.113549.3.7": + # DES_EDE3_CBC + ciphermod = DES3 + key_size = 24 + elif encryption_oid == "2.16.840.1.101.3.4.1.2": + # AES128_CBC + ciphermod = AES + key_size = 16 + elif encryption_oid == "2.16.840.1.101.3.4.1.22": + # AES192_CBC + ciphermod = AES + key_size = 24 + elif encryption_oid == "2.16.840.1.101.3.4.1.42": + # AES256_CBC + ciphermod = AES + key_size = 32 + else: + raise ValueError("Unsupported cipher") + + if pbkdf2_key_length and pbkdf2_key_length != key_size: + raise ValueError("Mismatch between PBKDF2 parameters" + " and selected cipher") + + IV = decode_der(DerOctetString, encryption_scheme[1]).payload + + # Create cipher + key = PBKDF2(passphrase, salt, key_size, iteration_count) + cipher = ciphermod.new(key, ciphermod.MODE_CBC, IV) + + # Decrypt data + pt = cipher.decrypt(encrypted_data) + return unpad(pt, cipher.block_size) + decrypt = staticmethod(decrypt) diff --git a/lib/Crypto/IO/__init__.py b/lib/Crypto/IO/__init__.py new file mode 100644 index 0000000..86776c4 --- /dev/null +++ b/lib/Crypto/IO/__init__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +""" +Modules for reading and writing cryptographic data. + +======================== ============================================= +Module Description +======================== ============================================= +Crypto.Util.PEM Set of functions for encapsulating data according to the PEM format. +Crypto.Util.PKCS8 Set of functions for wrapping/unwrapping private keys. +======================== ============================================= +""" + +__all__ = ['PEM', 'PKCS8'] diff --git a/lib/Crypto/Protocol/AllOrNothing.py b/lib/Crypto/Protocol/AllOrNothing.py new file mode 100644 index 0000000..acc92d5 --- /dev/null +++ b/lib/Crypto/Protocol/AllOrNothing.py @@ -0,0 +1,319 @@ +# +# AllOrNothing.py : all-or-nothing package transformations +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew M. Kuchling and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""This file implements all-or-nothing package transformations. + +An all-or-nothing package transformation is one in which some text is +transformed into message blocks, such that all blocks must be obtained before +the reverse transformation can be applied. Thus, if any blocks are corrupted +or lost, the original message cannot be reproduced. + +An all-or-nothing package transformation is not encryption, although a block +cipher algorithm is used. The encryption key is randomly generated and is +extractable from the message blocks. + +This class implements the All-Or-Nothing package transformation algorithm +described in: + +Ronald L. Rivest. "All-Or-Nothing Encryption and The Package Transform" +http://theory.lcs.mit.edu/~rivest/fusion.pdf + +""" + +__revision__ = "$Id$" + +import operator +import sys +from Crypto.Util.number import bytes_to_long, long_to_bytes +from Crypto.Util.py3compat import * + +def isInt(x): + test = 0 + try: + test += x + except TypeError: + return 0 + return 1 + +class AllOrNothing: + """Class implementing the All-or-Nothing package transform. + + Methods for subclassing: + + _inventkey(key_size): + Returns a randomly generated key. Subclasses can use this to + implement better random key generating algorithms. The default + algorithm is probably not very cryptographically secure. + + """ + + def __init__(self, ciphermodule, mode=None, IV=None): + """AllOrNothing(ciphermodule, mode=None, IV=None) + + ciphermodule is a module implementing the cipher algorithm to + use. It must provide the PEP272 interface. + + Note that the encryption key is randomly generated + automatically when needed. Optional arguments mode and IV are + passed directly through to the ciphermodule.new() method; they + are the feedback mode and initialization vector to use. All + three arguments must be the same for the object used to create + the digest, and to undigest'ify the message blocks. + """ + + self.__ciphermodule = ciphermodule + self.__mode = mode + self.__IV = IV + self.__key_size = ciphermodule.key_size + if not isInt(self.__key_size) or self.__key_size==0: + self.__key_size = 16 + + __K0digit = bchr(0x69) + + def digest(self, text): + """digest(text:string) : [string] + + Perform the All-or-Nothing package transform on the given + string. Output is a list of message blocks describing the + transformed text, where each block is a string of bit length equal + to the ciphermodule's block_size. + """ + + # generate a random session key and K0, the key used to encrypt the + # hash blocks. Rivest calls this a fixed, publically-known encryption + # key, but says nothing about the security implications of this key or + # how to choose it. + key = self._inventkey(self.__key_size) + K0 = self.__K0digit * self.__key_size + + # we need two cipher objects here, one that is used to encrypt the + # message blocks and one that is used to encrypt the hashes. The + # former uses the randomly generated key, while the latter uses the + # well-known key. + mcipher = self.__newcipher(key) + hcipher = self.__newcipher(K0) + + # Pad the text so that its length is a multiple of the cipher's + # block_size. Pad with trailing spaces, which will be eliminated in + # the undigest() step. + block_size = self.__ciphermodule.block_size + padbytes = block_size - (len(text) % block_size) + text = text + b(' ') * padbytes + + # Run through the algorithm: + # s: number of message blocks (size of text / block_size) + # input sequence: m1, m2, ... ms + # random key K' (`key' in the code) + # Compute output sequence: m'1, m'2, ... m's' for s' = s + 1 + # Let m'i = mi ^ E(K', i) for i = 1, 2, 3, ..., s + # Let m's' = K' ^ h1 ^ h2 ^ ... hs + # where hi = E(K0, m'i ^ i) for i = 1, 2, ... s + # + # The one complication I add is that the last message block is hard + # coded to the number of padbytes added, so that these can be stripped + # during the undigest() step + s = divmod(len(text), block_size)[0] + blocks = [] + hashes = [] + for i in range(1, s+1): + start = (i-1) * block_size + end = start + block_size + mi = text[start:end] + assert len(mi) == block_size + cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) + mticki = bytes_to_long(mi) ^ bytes_to_long(cipherblock) + blocks.append(mticki) + # calculate the hash block for this block + hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size)) + hashes.append(bytes_to_long(hi)) + + # Add the padbytes length as a message block + i = i + 1 + cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) + mticki = padbytes ^ bytes_to_long(cipherblock) + blocks.append(mticki) + + # calculate this block's hash + hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size)) + hashes.append(bytes_to_long(hi)) + + # Now calculate the last message block of the sequence 1..s'. This + # will contain the random session key XOR'd with all the hash blocks, + # so that for undigest(), once all the hash blocks are calculated, the + # session key can be trivially extracted. Calculating all the hash + # blocks requires that all the message blocks be received, thus the + # All-or-Nothing algorithm succeeds. + mtick_stick = bytes_to_long(key) ^ reduce(operator.xor, hashes) + blocks.append(mtick_stick) + + # we convert the blocks to strings since in Python, byte sequences are + # always represented as strings. This is more consistent with the + # model that encryption and hash algorithms always operate on strings. + return [long_to_bytes(i,self.__ciphermodule.block_size) for i in blocks] + + + def undigest(self, blocks): + """undigest(blocks : [string]) : string + + Perform the reverse package transformation on a list of message + blocks. Note that the ciphermodule used for both transformations + must be the same. blocks is a list of strings of bit length + equal to the ciphermodule's block_size. + """ + + # better have at least 2 blocks, for the padbytes package and the hash + # block accumulator + if len(blocks) < 2: + raise ValueError, "List must be at least length 2." + + # blocks is a list of strings. We need to deal with them as long + # integers + blocks = map(bytes_to_long, blocks) + + # Calculate the well-known key, to which the hash blocks are + # encrypted, and create the hash cipher. + K0 = self.__K0digit * self.__key_size + hcipher = self.__newcipher(K0) + block_size = self.__ciphermodule.block_size + + # Since we have all the blocks (or this method would have been called + # prematurely), we can calculate all the hash blocks. + hashes = [] + for i in range(1, len(blocks)): + mticki = blocks[i-1] ^ i + hi = hcipher.encrypt(long_to_bytes(mticki, block_size)) + hashes.append(bytes_to_long(hi)) + + # now we can calculate K' (key). remember the last block contains + # m's' which we don't include here + key = blocks[-1] ^ reduce(operator.xor, hashes) + + # and now we can create the cipher object + mcipher = self.__newcipher(long_to_bytes(key, self.__key_size)) + + # And we can now decode the original message blocks + parts = [] + for i in range(1, len(blocks)): + cipherblock = mcipher.encrypt(long_to_bytes(i, block_size)) + mi = blocks[i-1] ^ bytes_to_long(cipherblock) + parts.append(mi) + + # The last message block contains the number of pad bytes appended to + # the original text string, such that its length was an even multiple + # of the cipher's block_size. This number should be small enough that + # the conversion from long integer to integer should never overflow + padbytes = int(parts[-1]) + text = b('').join(map(long_to_bytes, parts[:-1])) + return text[:-padbytes] + + def _inventkey(self, key_size): + # Return key_size random bytes + from Crypto import Random + return Random.new().read(key_size) + + def __newcipher(self, key): + if self.__mode is None and self.__IV is None: + return self.__ciphermodule.new(key) + elif self.__IV is None: + return self.__ciphermodule.new(key, self.__mode) + else: + return self.__ciphermodule.new(key, self.__mode, self.__IV) + + + +if __name__ == '__main__': + import sys + import getopt + import base64 + + usagemsg = '''\ +Test module usage: %(program)s [-c cipher] [-l] [-h] + +Where: + --cipher module + -c module + Cipher module to use. Default: %(ciphermodule)s + + --aslong + -l + Print the encoded message blocks as long integers instead of base64 + encoded strings + + --help + -h + Print this help message +''' + + ciphermodule = 'AES' + aslong = 0 + + def usage(code, msg=None): + if msg: + print msg + print usagemsg % {'program': sys.argv[0], + 'ciphermodule': ciphermodule} + sys.exit(code) + + try: + opts, args = getopt.getopt(sys.argv[1:], + 'c:l', ['cipher=', 'aslong']) + except getopt.error, msg: + usage(1, msg) + + if args: + usage(1, 'Too many arguments') + + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-c', '--cipher'): + ciphermodule = arg + elif opt in ('-l', '--aslong'): + aslong = 1 + + # ugly hack to force __import__ to give us the end-path module + module = __import__('Crypto.Cipher.'+ciphermodule, None, None, ['new']) + + x = AllOrNothing(module) + print 'Original text:\n==========' + print __doc__ + print '==========' + msgblocks = x.digest(b(__doc__)) + print 'message blocks:' + for i, blk in zip(range(len(msgblocks)), msgblocks): + # base64 adds a trailing newline + print ' %3d' % i, + if aslong: + print bytes_to_long(blk) + else: + print base64.encodestring(blk)[:-1] + # + # get a new undigest-only object so there's no leakage + y = AllOrNothing(module) + text = y.undigest(msgblocks) + if text == b(__doc__): + print 'They match!' + else: + print 'They differ!' diff --git a/lib/Crypto/Protocol/Chaffing.py b/lib/Crypto/Protocol/Chaffing.py new file mode 100644 index 0000000..c19e037 --- /dev/null +++ b/lib/Crypto/Protocol/Chaffing.py @@ -0,0 +1,245 @@ +# +# Chaffing.py : chaffing & winnowing support +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew M. Kuchling, Barry A. Warsaw, and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +# +"""This file implements the chaffing algorithm. + +Winnowing and chaffing is a technique for enhancing privacy without requiring +strong encryption. In short, the technique takes a set of authenticated +message blocks (the wheat) and adds a number of chaff blocks which have +randomly chosen data and MAC fields. This means that to an adversary, the +chaff blocks look as valid as the wheat blocks, and so the authentication +would have to be performed on every block. By tailoring the number of chaff +blocks added to the message, the sender can make breaking the message +computationally infeasible. There are many other interesting properties of +the winnow/chaff technique. + +For example, say Alice is sending a message to Bob. She packetizes the +message and performs an all-or-nothing transformation on the packets. Then +she authenticates each packet with a message authentication code (MAC). The +MAC is a hash of the data packet, and there is a secret key which she must +share with Bob (key distribution is an exercise left to the reader). She then +adds a serial number to each packet, and sends the packets to Bob. + +Bob receives the packets, and using the shared secret authentication key, +authenticates the MACs for each packet. Those packets that have bad MACs are +simply discarded. The remainder are sorted by serial number, and passed +through the reverse all-or-nothing transform. The transform means that an +eavesdropper (say Eve) must acquire all the packets before any of the data can +be read. If even one packet is missing, the data is useless. + +There's one twist: by adding chaff packets, Alice and Bob can make Eve's job +much harder, since Eve now has to break the shared secret key, or try every +combination of wheat and chaff packet to read any of the message. The cool +thing is that Bob doesn't need to add any additional code; the chaff packets +are already filtered out because their MACs don't match (in all likelihood -- +since the data and MACs for the chaff packets are randomly chosen it is +possible, but very unlikely that a chaff MAC will match the chaff data). And +Alice need not even be the party adding the chaff! She could be completely +unaware that a third party, say Charles, is adding chaff packets to her +messages as they are transmitted. + +For more information on winnowing and chaffing see this paper: + +Ronald L. Rivest, "Chaffing and Winnowing: Confidentiality without Encryption" +http://theory.lcs.mit.edu/~rivest/chaffing.txt + +""" + +__revision__ = "$Id$" + +from Crypto.Util.number import bytes_to_long + +class Chaff: + """Class implementing the chaff adding algorithm. + + Methods for subclasses: + + _randnum(size): + Returns a randomly generated number with a byte-length equal + to size. Subclasses can use this to implement better random + data and MAC generating algorithms. The default algorithm is + probably not very cryptographically secure. It is most + important that the chaff data does not contain any patterns + that can be used to discern it from wheat data without running + the MAC. + + """ + + def __init__(self, factor=1.0, blocksper=1): + """Chaff(factor:float, blocksper:int) + + factor is the number of message blocks to add chaff to, + expressed as a percentage between 0.0 and 1.0. blocksper is + the number of chaff blocks to include for each block being + chaffed. Thus the defaults add one chaff block to every + message block. By changing the defaults, you can adjust how + computationally difficult it could be for an adversary to + brute-force crack the message. The difficulty is expressed + as: + + pow(blocksper, int(factor * number-of-blocks)) + + For ease of implementation, when factor < 1.0, only the first + int(factor*number-of-blocks) message blocks are chaffed. + """ + + if not (0.0<=factor<=1.0): + raise ValueError, "'factor' must be between 0.0 and 1.0" + if blocksper < 0: + raise ValueError, "'blocksper' must be zero or more" + + self.__factor = factor + self.__blocksper = blocksper + + + def chaff(self, blocks): + """chaff( [(serial-number:int, data:string, MAC:string)] ) + : [(int, string, string)] + + Add chaff to message blocks. blocks is a list of 3-tuples of the + form (serial-number, data, MAC). + + Chaff is created by choosing a random number of the same + byte-length as data, and another random number of the same + byte-length as MAC. The message block's serial number is + placed on the chaff block and all the packet's chaff blocks + are randomly interspersed with the single wheat block. This + method then returns a list of 3-tuples of the same form. + Chaffed blocks will contain multiple instances of 3-tuples + with the same serial number, but the only way to figure out + which blocks are wheat and which are chaff is to perform the + MAC hash and compare values. + """ + + chaffedblocks = [] + + # count is the number of blocks to add chaff to. blocksper is the + # number of chaff blocks to add per message block that is being + # chaffed. + count = len(blocks) * self.__factor + blocksper = range(self.__blocksper) + for i, wheat in zip(range(len(blocks)), blocks): + # it shouldn't matter which of the n blocks we add chaff to, so for + # ease of implementation, we'll just add them to the first count + # blocks + if i < count: + serial, data, mac = wheat + datasize = len(data) + macsize = len(mac) + addwheat = 1 + # add chaff to this block + for j in blocksper: + import sys + chaffdata = self._randnum(datasize) + chaffmac = self._randnum(macsize) + chaff = (serial, chaffdata, chaffmac) + # mix up the order, if the 5th bit is on then put the + # wheat on the list + if addwheat and bytes_to_long(self._randnum(16)) & 0x40: + chaffedblocks.append(wheat) + addwheat = 0 + chaffedblocks.append(chaff) + if addwheat: + chaffedblocks.append(wheat) + else: + # just add the wheat + chaffedblocks.append(wheat) + return chaffedblocks + + def _randnum(self, size): + from Crypto import Random + return Random.new().read(size) + + +if __name__ == '__main__': + text = """\ +We hold these truths to be self-evident, that all men are created equal, that +they are endowed by their Creator with certain unalienable Rights, that among +these are Life, Liberty, and the pursuit of Happiness. That to secure these +rights, Governments are instituted among Men, deriving their just powers from +the consent of the governed. That whenever any Form of Government becomes +destructive of these ends, it is the Right of the People to alter or to +abolish it, and to institute new Government, laying its foundation on such +principles and organizing its powers in such form, as to them shall seem most +likely to effect their Safety and Happiness. +""" + print 'Original text:\n==========' + print text + print '==========' + + # first transform the text into packets + blocks = [] ; size = 40 + for i in range(0, len(text), size): + blocks.append( text[i:i+size] ) + + # now get MACs for all the text blocks. The key is obvious... + print 'Calculating MACs...' + from Crypto.Hash import HMAC, SHA + key = 'Jefferson' + macs = [HMAC.new(key, block, digestmod=SHA).digest() + for block in blocks] + + assert len(blocks) == len(macs) + + # put these into a form acceptable as input to the chaffing procedure + source = [] + m = zip(range(len(blocks)), blocks, macs) + print m + for i, data, mac in m: + source.append((i, data, mac)) + + # now chaff these + print 'Adding chaff...' + c = Chaff(factor=0.5, blocksper=2) + chaffed = c.chaff(source) + + from base64 import encodestring + + # print the chaffed message blocks. meanwhile, separate the wheat from + # the chaff + + wheat = [] + print 'chaffed message blocks:' + for i, data, mac in chaffed: + # do the authentication + h = HMAC.new(key, data, digestmod=SHA) + pmac = h.digest() + if pmac == mac: + tag = '-->' + wheat.append(data) + else: + tag = ' ' + # base64 adds a trailing newline + print tag, '%3d' % i, \ + repr(data), encodestring(mac)[:-1] + + # now decode the message packets and check it against the original text + print 'Undigesting wheat...' + # PY3K: This is meant to be text, do not change to bytes (data) + newtext = "".join(wheat) + if newtext == text: + print 'They match!' + else: + print 'They differ!' diff --git a/lib/Crypto/Protocol/KDF.py b/lib/Crypto/Protocol/KDF.py new file mode 100644 index 0000000..c5967e4 --- /dev/null +++ b/lib/Crypto/Protocol/KDF.py @@ -0,0 +1,209 @@ +# +# KDF.py : a collection of Key Derivation Functions +# +# Part of the Python Cryptography Toolkit +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""This file contains a collection of standard key derivation functions. + +A key derivation function derives one or more secondary secret keys from +one primary secret (a master key or a pass phrase). + +This is typically done to insulate the secondary keys from each other, +to avoid that leakage of a secondary key compromises the security of the +master key, or to thwart attacks on pass phrases (e.g. via rainbow tables). + +:undocumented: __revision__ +""" + +__revision__ = "$Id$" + +import math +import struct + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from Crypto.Hash import SHA1, HMAC, CMAC +from Crypto.Util.strxor import strxor +from Crypto.Util.number import long_to_bytes, bytes_to_long + +def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None): + """Derive one key from a password (or passphrase). + + This function performs key derivation according an old version of + the PKCS#5 standard (v1.5). + + This algorithm is called ``PBKDF1``. Even though it is still described + in the latest version of the PKCS#5 standard (version 2, or RFC2898), + newer applications should use the more secure and versatile `PBKDF2` instead. + + :Parameters: + password : string + The secret password or pass phrase to generate the key from. + salt : byte string + An 8 byte string to use for better protection from dictionary attacks. + This value does not need to be kept secret, but it should be randomly + chosen for each derivation. + dkLen : integer + The length of the desired key. Default is 16 bytes, suitable for instance for `Crypto.Cipher.AES`. + count : integer + The number of iterations to carry out. It's recommended to use at least 1000. + hashAlgo : module + The hash algorithm to use, as a module or an object from the `Crypto.Hash` package. + The digest length must be no shorter than ``dkLen``. + The default algorithm is `SHA1`. + + :Return: A byte string of length `dkLen` that can be used as key. + """ + if not hashAlgo: + hashAlgo = SHA1 + password = tobytes(password) + pHash = hashAlgo.new(password+salt) + digest = pHash.digest_size + if dkLen>digest: + raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest) + if len(salt)!=8: + raise ValueError("Salt is not 8 bytes long.") + for i in xrange(count-1): + pHash = pHash.new(pHash.digest()) + return pHash.digest()[:dkLen] + +def PBKDF2(password, salt, dkLen=16, count=1000, prf=None): + """Derive one or more keys from a password (or passphrase). + + This performs key derivation according to the PKCS#5 standard (v2.0), + by means of the ``PBKDF2`` algorithm. + + :Parameters: + password : string + The secret password or pass phrase to generate the key from. + salt : string + A string to use for better protection from dictionary attacks. + This value does not need to be kept secret, but it should be randomly + chosen for each derivation. It is recommended to be at least 8 bytes long. + dkLen : integer + The cumulative length of the desired keys. Default is 16 bytes, suitable for instance for `Crypto.Cipher.AES`. + count : integer + The number of iterations to carry out. It's recommended to use at least 1000. + prf : callable + A pseudorandom function. It must be a function that returns a pseudorandom string + from two parameters: a secret and a salt. If not specified, HMAC-SHA1 is used. + + :Return: A byte string of length `dkLen` that can be used as key material. + If you wanted multiple keys, just break up this string into segments of the desired length. +""" + password = tobytes(password) + if prf is None: + prf = lambda p,s: HMAC.new(p,s,SHA1).digest() + key = b('') + i = 1 + while len(key)<dkLen: + U = previousU = prf(password,salt+struct.pack(">I", i)) + for j in xrange(count-1): + previousU = t = prf(password,previousU) + U = strxor(U,t) + key += U + i = i + 1 + return key[:dkLen] + +class _S2V(object): + """String-to-vector PRF as defined in `RFC5297`_. + + This class implements a pseudorandom function family + based on CMAC that takes as input a vector of strings. + + .. _RFC5297: http://tools.ietf.org/html/rfc5297 + """ + + def __init__(self, key, ciphermod): + """Initialize the S2V PRF. + + :Parameters: + key : byte string + A secret that can be used as key for CMACs + based on ciphers from ``ciphermod``. + ciphermod : module + A block cipher module from `Crypto.Cipher`. + """ + + self._key = key + self._ciphermod = ciphermod + self._last_string = self._cache = bchr(0)*ciphermod.block_size + self._n_updates = ciphermod.block_size*8-1 + + def new(key, ciphermod): + """Create a new S2V PRF. + + :Parameters: + key : byte string + A secret that can be used as key for CMACs + based on ciphers from ``ciphermod``. + ciphermod : module + A block cipher module from `Crypto.Cipher`. + """ + return _S2V(key, ciphermod) + new = staticmethod(new) + + def _double(self, bs): + doubled = bytes_to_long(bs)<<1 + if bord(bs[0]) & 0x80: + doubled ^= 0x87 + return long_to_bytes(doubled, len(bs))[-len(bs):] + + def update(self, item): + """Pass the next component of the vector. + + The maximum number of components you can pass is equal to the block + length of the cipher (in bits) minus 1. + + :Parameters: + item : byte string + The next component of the vector. + :Raise TypeError: when the limit on the number of components has been reached. + :Raise ValueError: when the component is empty + """ + + if not item: + raise ValueError("A component cannot be empty") + + if self._n_updates==0: + raise TypeError("Too many components passed to S2V") + self._n_updates -= 1 + + mac = CMAC.new(self._key, msg=self._last_string, ciphermod=self._ciphermod) + self._cache = strxor(self._double(self._cache), mac.digest()) + self._last_string = item + + def derive(self): + """"Derive a secret from the vector of components. + + :Return: a byte string, as long as the block length of the cipher. + """ + + if len(self._last_string)>=16: + final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) + else: + padded = (self._last_string + bchr(0x80)+ bchr(0)*15)[:16] + final = strxor(padded, self._double(self._cache)) + mac = CMAC.new(self._key, msg=final, ciphermod=self._ciphermod) + return mac.digest() diff --git a/lib/Crypto/Protocol/__init__.py b/lib/Crypto/Protocol/__init__.py new file mode 100644 index 0000000..cacc685 --- /dev/null +++ b/lib/Crypto/Protocol/__init__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Cryptographic protocols + +Implements various cryptographic protocols. (Don't expect to find +network protocols here.) + +Crypto.Protocol.AllOrNothing + Transforms a message into a set of message blocks, such that the blocks + can be recombined to get the message back. + +Crypto.Protocol.Chaffing + Takes a set of authenticated message blocks (the wheat) and adds a number + of randomly generated blocks (the chaff). + +Crypto.Protocol.KDF + A collection of standard key derivation functions. + +:undocumented: __revision__ +""" + +__all__ = ['AllOrNothing', 'Chaffing', 'KDF'] +__revision__ = "$Id$" diff --git a/lib/Crypto/PublicKey/DSA.py b/lib/Crypto/PublicKey/DSA.py new file mode 100644 index 0000000..1818def --- /dev/null +++ b/lib/Crypto/PublicKey/DSA.py @@ -0,0 +1,682 @@ +# -*- coding: utf-8 -*- +# +# PublicKey/DSA.py : DSA signature primitive +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""DSA public-key signature algorithm. + +DSA_ is a widespread public-key signature algorithm. Its security is +based on the discrete logarithm problem (DLP_). Given a cyclic +group, a generator *g*, and an element *h*, it is hard +to find an integer *x* such that *g^x = h*. The problem is believed +to be difficult, and it has been proved such (and therefore secure) for +more than 30 years. + +The group is actually a sub-group over the integers modulo *p*, with *p* prime. +The sub-group order is *q*, which is prime too; it always holds that *(p-1)* is a multiple of *q*. +The cryptographic strength is linked to the magnitude of *p* and *q*. +The signer holds a value *x* (*0<x<q-1*) as private key, and its public +key (*y* where *y=g^x mod p*) is distributed. + +In 2012, a sufficient size is deemed to be 2048 bits for *p* and 256 bits for *q*. +For more information, see the most recent ECRYPT_ report. + +DSA is reasonably secure for new designs. + +The algorithm can only be used for authentication (digital signature). +DSA cannot be used for confidentiality (encryption). + +The values *(p,q,g)* are called *domain parameters*; +they are not sensitive but must be shared by both parties (the signer and the verifier). +Different signers can share the same domain parameters with no security +concerns. + +The DSA signature is twice as big as the size of *q* (64 bytes if *q* is 256 bit +long). + +This module provides facilities for generating new DSA keys and for constructing +them from known components. DSA keys allows you to perform basic signing and +verification. + + >>> from Crypto.Random import random + >>> from Crypto.PublicKey import DSA + >>> from Crypto.Hash import SHA256 + >>> + >>> message = "Hello" + >>> key = DSA.generate(2048) + >>> f = open("public_key.pem", "w") + >>> f.write(key.publickey().exportKey(key)) + >>> h = SHA256.new(message).digest() + >>> k = random.StrongRandom().randint(1,key.q-1) + >>> sig = key.sign(h,k) + >>> ... + >>> ... + >>> f = open("public_key.pem", "r") + >>> h = SHA256.new(message).digest() + >>> key = DSA.importKey(f.read()) + >>> if key.verify(h,sig): + >>> print "OK" + >>> else: + >>> print "Incorrect signature" + +.. _DSA: http://en.wikipedia.org/wiki/Digital_Signature_Algorithm +.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf +.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf +""" + +__revision__ = "$Id$" + +__all__ = ['generate', 'construct', 'error', 'DSAImplementation', + '_DSAobj', 'importKey'] + +import binascii +import struct + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from Crypto import Random +from Crypto.IO import PKCS8, PEM +from Crypto.Util.number import bytes_to_long, long_to_bytes +from Crypto.PublicKey import _DSA, _slowmath, pubkey, KeyFormatError +from Crypto.Util.asn1 import DerObject, DerSequence,\ + DerInteger, DerObjectId, DerBitString, newDerSequence, newDerBitString + +try: + from Crypto.PublicKey import _fastmath +except ImportError: + _fastmath = None + +def decode_der(obj_class, binstr): + """Instantiate a DER object class, decode a DER binary string in it, + and return the object.""" + der = obj_class() + der.decode(binstr) + return der + +# ; The following ASN.1 types are relevant for DSA +# +# SubjectPublicKeyInfo ::= SEQUENCE { +# algorithm AlgorithmIdentifier, +# subjectPublicKey BIT STRING +# } +# +# id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } +# +# ; See RFC3279 +# Dss-Parms ::= SEQUENCE { +# p INTEGER, +# q INTEGER, +# g INTEGER +# } +# +# DSAPublicKey ::= INTEGER +# +# DSSPrivatKey_OpenSSL ::= SEQUENCE +# version INTEGER, +# p INTEGER, +# q INTEGER, +# g INTEGER, +# y INTEGER, +# x INTEGER +# } +# + +class _DSAobj(pubkey.pubkey): + """Class defining an actual DSA key. + + :undocumented: __getstate__, __setstate__, __repr__, __getattr__ + """ + #: Dictionary of DSA parameters. + #: + #: A public key will only have the following entries: + #: + #: - **y**, the public key. + #: - **g**, the generator. + #: - **p**, the modulus. + #: - **q**, the order of the sub-group. + #: + #: A private key will also have: + #: + #: - **x**, the private key. + keydata = ['y', 'g', 'p', 'q', 'x'] + + def __init__(self, implementation, key, randfunc=None): + self.implementation = implementation + self.key = key + if randfunc is None: + randfunc = Random.new().read + self._randfunc = randfunc + + def __getattr__(self, attrname): + if attrname in self.keydata: + # For backward compatibility, allow the user to get (not set) the + # DSA key parameters directly from this object. + return getattr(self.key, attrname) + else: + raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,)) + + def sign(self, M, K): + """Sign a piece of data with DSA. + + :Parameter M: The piece of data to sign with DSA. It may + not be longer in bit size than the sub-group order (*q*). + :Type M: byte string or long + + :Parameter K: A secret number, chosen randomly in the closed + range *[1,q-1]*. + :Type K: long (recommended) or byte string (not recommended) + + :attention: selection of *K* is crucial for security. Generating a + random number larger than *q* and taking the modulus by *q* is + **not** secure, since smaller values will occur more frequently. + Generating a random number systematically smaller than *q-1* + (e.g. *floor((q-1)/8)* random bytes) is also **not** secure. In general, + it shall not be possible for an attacker to know the value of `any + bit of K`__. + + :attention: The number *K* shall not be reused for any other + operation and shall be discarded immediately. + + :attention: M must be a digest cryptographic hash, otherwise + an attacker may mount an existential forgery attack. + + :Return: A tuple with 2 longs. + + .. __: http://www.di.ens.fr/~pnguyen/pub_NgSh00.htm + """ + return pubkey.pubkey.sign(self, M, K) + + def verify(self, M, signature): + """Verify the validity of a DSA signature. + + :Parameter M: The expected message. + :Type M: byte string or long + + :Parameter signature: The DSA signature to verify. + :Type signature: A tuple with 2 longs as return by `sign` + + :Return: True if the signature is correct, False otherwise. + """ + return pubkey.pubkey.verify(self, M, signature) + + def _encrypt(self, c, K): + raise TypeError("DSA cannot encrypt") + + def _decrypt(self, c): + raise TypeError("DSA cannot decrypt") + + def _blind(self, m, r): + raise TypeError("DSA cannot blind") + + def _unblind(self, m, r): + raise TypeError("DSA cannot unblind") + + def _sign(self, m, k): + return self.key._sign(m, k) + + def _verify(self, m, sig): + (r, s) = sig + return self.key._verify(m, r, s) + + def has_private(self): + return self.key.has_private() + + def size(self): + return self.key.size() + + def can_blind(self): + return False + + def can_encrypt(self): + return False + + def can_sign(self): + return True + + def publickey(self): + return self.implementation.construct((self.key.y, self.key.g, self.key.p, self.key.q)) + + def __getstate__(self): + d = {} + for k in self.keydata: + try: + d[k] = getattr(self.key, k) + except AttributeError: + pass + return d + + def __setstate__(self, d): + if not hasattr(self, 'implementation'): + self.implementation = DSAImplementation() + if not hasattr(self, '_randfunc'): + self._randfunc = Random.new().read + t = [] + for k in self.keydata: + if not d.has_key(k): + break + t.append(d[k]) + self.key = self.implementation._math.dsa_construct(*tuple(t)) + + def __repr__(self): + attrs = [] + for k in self.keydata: + if k == 'p': + attrs.append("p(%d)" % (self.size()+1,)) + elif hasattr(self.key, k): + attrs.append(k) + if self.has_private(): + attrs.append("private") + # PY3K: This is meant to be text, do not change to bytes (data) + return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) + + def exportKey(self, format='PEM', pkcs8=None, passphrase=None, + protection=None): + """Export this DSA key. + + :Parameters: + format : string + The format to use for wrapping the key: + + - *'DER'*. Binary encoding. + - *'PEM'*. Textual encoding, done according to `RFC1421`_/ + `RFC1423`_ (default). + - *'OpenSSH'*. Textual encoding, one line of text, see `RFC4253`_. + Only suitable for public keys, not private keys. + + passphrase : string + For private keys only. The pass phrase to use for deriving + the encryption key. + + pkcs8 : boolean + For private keys only. If ``True`` (default), the key is arranged + according to `PKCS#8`_ and if `False`, according to the custom + OpenSSL/OpenSSH encoding. + + protection : string + The encryption scheme to use for protecting the private key. + It is only meaningful when a pass phrase is present too. + + If ``pkcs8`` takes value ``True``, ``protection`` is the PKCS#8 + algorithm to use for deriving the secret and encrypting + the private DSA key. + For a complete list of algorithms, see `Crypto.IO.PKCS8`. + The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. + + If ``pkcs8`` is ``False``, the obsolete PEM encryption scheme is + used. It is based on MD5 for key derivation, and Triple DES for + encryption. Parameter ``protection`` is ignored. + + The combination ``format='DER'`` and ``pkcs8=False`` is not allowed + if a passphrase is present. + + :Return: A byte string with the encoded public or private half + of the key. + :Raise ValueError: + When the format is unknown or when you try to encrypt a private + key with *DER* format and OpenSSL/OpenSSH. + :attention: + If you don't provide a pass phrase, the private key will be + exported in the clear! + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + if passphrase is not None: + passphrase = tobytes(passphrase) + if format == 'OpenSSH': + tup1 = [long_to_bytes(x) for x in (self.p, self.q, self.g, self.y)] + + def func(x): + if (bord(x[0]) & 0x80): + return bchr(0) + x + else: + return x + + tup2 = map(func, tup1) + keyparts = [b('ssh-dss')] + tup2 + keystring = b('').join( + [struct.pack(">I", len(kp)) + kp for kp in keyparts] + ) + return b('ssh-dss ') + binascii.b2a_base64(keystring)[:-1] + + # DER format is always used, even in case of PEM, which simply + # encodes it into BASE64. + params = newDerSequence(self.p, self.q, self.g) + if self.has_private(): + if pkcs8 is None: + pkcs8 = True + if pkcs8: + if not protection: + protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' + private_key = DerInteger(self.x).encode() + binary_key = PKCS8.wrap( + private_key, oid, passphrase, + protection, key_params=params, + randfunc=self._randfunc + ) + if passphrase: + key_type = 'ENCRYPTED PRIVATE' + else: + key_type = 'PRIVATE' + passphrase = None + else: + if format != 'PEM' and passphrase: + raise ValueError("DSA private key cannot be encrypted") + ints = [0, self.p, self.q, self.g, self.y, self.x] + binary_key = newDerSequence(*ints).encode() + key_type = "DSA PRIVATE" + else: + if pkcs8: + raise ValueError("PKCS#8 is only meaningful for private keys") + binary_key = newDerSequence( + newDerSequence(DerObjectId(oid), params), + newDerBitString(DerInteger(self.y)) + ).encode() + key_type = "DSA PUBLIC" + + if format == 'DER': + return binary_key + if format == 'PEM': + pem_str = PEM.encode( + binary_key, key_type + " KEY", + passphrase, self._randfunc + ) + return tobytes(pem_str) + raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format) + + +class DSAImplementation(object): + """ + A DSA key factory. + + This class is only internally used to implement the methods of the + `Crypto.PublicKey.DSA` module. + """ + + def __init__(self, **kwargs): + """Create a new DSA key factory. + + :Keywords: + use_fast_math : bool + Specify which mathematic library to use: + + - *None* (default). Use fastest math available. + - *True* . Use fast math. + - *False* . Use slow math. + default_randfunc : callable + Specify how to collect random data: + + - *None* (default). Use Random.new().read(). + - not *None* . Use the specified function directly. + :Raise RuntimeError: + When **use_fast_math** =True but fast math is not available. + """ + use_fast_math = kwargs.get('use_fast_math', None) + if use_fast_math is None: # Automatic + if _fastmath is not None: + self._math = _fastmath + else: + self._math = _slowmath + + elif use_fast_math: # Explicitly select fast math + if _fastmath is not None: + self._math = _fastmath + else: + raise RuntimeError("fast math module not available") + + else: # Explicitly select slow math + self._math = _slowmath + + self.error = self._math.error + + # 'default_randfunc' parameter: + # None (default) - use Random.new().read + # not None - use the specified function + self._default_randfunc = kwargs.get('default_randfunc', None) + self._current_randfunc = None + + def _get_randfunc(self, randfunc): + if randfunc is not None: + return randfunc + elif self._current_randfunc is None: + self._current_randfunc = Random.new().read + return self._current_randfunc + + def generate(self, bits, randfunc=None, progress_func=None): + """Randomly generate a fresh, new DSA key. + + :Parameters: + bits : int + Key length, or size (in bits) of the DSA modulus + *p*. + It must be a multiple of 64, in the closed + interval [512,1024]. + randfunc : callable + Random number generation function; it should accept + a single integer N and return a string of random data + N bytes long. + If not specified, a new one will be instantiated + from ``Crypto.Random``. + progress_func : callable + Optional function that will be called with a short string + containing the key parameter currently being generated; + it's useful for interactive applications where a user is + waiting for a key to be generated. + + :attention: You should always use a cryptographically secure random number generator, + such as the one defined in the ``Crypto.Random`` module; **don't** just use the + current time and the ``random`` module. + + :Return: A DSA key object (`_DSAobj`). + + :Raise ValueError: + When **bits** is too little, too big, or not a multiple of 64. + """ + + # Check against FIPS 186-2, which says that the size of the prime p + # must be a multiple of 64 bits between 512 and 1024 + for i in (0, 1, 2, 3, 4, 5, 6, 7, 8): + if bits == 512 + 64*i: + return self._generate(bits, randfunc, progress_func) + + # The March 2006 draft of FIPS 186-3 also allows 2048 and 3072-bit + # primes, but only with longer q values. Since the current DSA + # implementation only supports a 160-bit q, we don't support larger + # values. + raise ValueError("Number of bits in p must be a multiple of 64 between 512 and 1024, not %d bits" % (bits,)) + + def _generate(self, bits, randfunc=None, progress_func=None): + rf = self._get_randfunc(randfunc) + obj = _DSA.generate_py(bits, rf, progress_func) # TODO: Don't use legacy _DSA module + key = self._math.dsa_construct(obj.y, obj.g, obj.p, obj.q, obj.x) + return _DSAobj(self, key) + + def construct(self, tup): + """Construct a DSA key from a tuple of valid DSA components. + + The modulus *p* must be a prime. + + The following equations must apply: + + - p-1 = 0 mod q + - g^x = y mod p + - 0 < x < q + - 1 < g < p + + :Parameters: + tup : tuple + A tuple of long integers, with 4 or 5 items + in the following order: + + 1. Public key (*y*). + 2. Sub-group generator (*g*). + 3. Modulus, finite field order (*p*). + 4. Sub-group order (*q*). + 5. Private key (*x*). Optional. + + :Return: A DSA key object (`_DSAobj`). + """ + key = self._math.dsa_construct(*tup) + return _DSAobj(self, key) + + def _importKeyDER(self, key_data, passphrase=None, params=None): + """Import a DSA key (public or private half), encoded in DER form.""" + + try: + # + # Dss-Parms ::= SEQUENCE { + # p OCTET STRING, + # q OCTET STRING, + # g OCTET STRING + # } + # + + # Try a simple private key first + if params: + x = decode_der(DerInteger, key_data).value + params = decode_der(DerSequence, params) # Dss-Parms + p, q, g = list(params) + y = pow(g, x, p) + tup = (y, g, p, q, x) + return self.construct(tup) + + der = decode_der(DerSequence, key_data) + + # Try OpenSSL format for private keys + if len(der) == 6 and der.hasOnlyInts() and der[0] == 0: + tup = [der[comp] for comp in (4, 3, 1, 2, 5)] + return self.construct(tup) + + # Try SubjectPublicKeyInfo + if len(der) == 2: + try: + algo = decode_der(DerSequence, der[0]) + algo_oid = decode_der(DerObjectId, algo[0]).value + params = decode_der(DerSequence, algo[1]) # Dss-Parms + + if algo_oid == oid and len(params) == 3 and\ + params.hasOnlyInts(): + bitmap = decode_der(DerBitString, der[1]) + pub_key = decode_der(DerInteger, bitmap.value) + tup = [pub_key.value] + tup += [params[comp] for comp in (2, 0, 1)] + return self.construct(tup) + except (ValueError, EOFError): + pass + + # Try unencrypted PKCS#8 + p8_pair = PKCS8.unwrap(key_data, passphrase) + if p8_pair[0] == oid: + return self._importKeyDER(p8_pair[1], passphrase, p8_pair[2]) + + except (ValueError, EOFError): + pass + + raise KeyFormatError("DSA key format is not supported") + + def importKey(self, extern_key, passphrase=None): + """Import a DSA key (public or private). + + :Parameters: + extern_key : (byte) string + The DSA key to import. + + An DSA *public* key can be in any of the following formats: + + - X.509 ``subjectPublicKeyInfo`` (binary or PEM) + - OpenSSH (one line of text, see `RFC4253`_) + + A DSA *private* key can be in any of the following formats: + + - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` + DER SEQUENCE (binary or PEM encoding) + - OpenSSL/OpenSSH (binary or PEM) + + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + + The private key may be encrypted by means of a certain pass phrase + either at the PEM level or at the PKCS#8 level. + + passphrase : string + In case of an encrypted private key, this is the pass phrase + from which the decryption key is derived. + + :Return: A DSA key object (`_DSAobj`). + :Raise KeyFormatError: + When the given key cannot be parsed (possibly because + the pass phrase is wrong). + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt + .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt + """ + + extern_key = tobytes(extern_key) + if passphrase is not None: + passphrase = tobytes(passphrase) + + if extern_key.startswith(b('-----')): + # This is probably a PEM encoded key + (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) + if enc_flag: + passphrase = None + return self._importKeyDER(der, passphrase) + + if extern_key.startswith(b('ssh-dss ')): + # This is probably a public OpenSSH key + keystring = binascii.a2b_base64(extern_key.split(b(' '))[1]) + keyparts = [] + while len(keystring) > 4: + length = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4:4 + length]) + keystring = keystring[4 + length:] + if keyparts[0] == b("ssh-dss"): + tup = [bytes_to_long(keyparts[x]) for x in (4, 3, 1, 2)] + return self.construct(tup) + + if bord(extern_key[0]) == 0x30: + # This is probably a DER encoded key + return self._importKeyDER(extern_key, passphrase) + + raise KeyFormatError("DSA key format is not supported") + +#: `Object ID`_ for a DSA key. +#: +#: id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } +#: +#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.10040.4.1.html +oid = "1.2.840.10040.4.1" + +_impl = DSAImplementation() +generate = _impl.generate +construct = _impl.construct +importKey = _impl.importKey +error = _impl.error + +# vim:set ts=4 sw=4 sts=4 expandtab: + diff --git a/lib/Crypto/PublicKey/ElGamal.py b/lib/Crypto/PublicKey/ElGamal.py new file mode 100644 index 0000000..0ab07fc --- /dev/null +++ b/lib/Crypto/PublicKey/ElGamal.py @@ -0,0 +1,382 @@ +# +# ElGamal.py : ElGamal encryption/decryption and signatures +# +# Part of the Python Cryptography Toolkit +# +# Originally written by: A.M. Kuchling +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""ElGamal public-key algorithm (randomized encryption and signature). + +Signature algorithm +------------------- +The security of the ElGamal signature scheme is based (like DSA) on the discrete +logarithm problem (DLP_). Given a cyclic group, a generator *g*, +and an element *h*, it is hard to find an integer *x* such that *g^x = h*. + +The group is the largest multiplicative sub-group of the integers modulo *p*, +with *p* prime. +The signer holds a value *x* (*0<x<p-1*) as private key, and its public +key (*y* where *y=g^x mod p*) is distributed. + +The ElGamal signature is twice as big as *p*. + +Encryption algorithm +-------------------- +The security of the ElGamal encryption scheme is based on the computational +Diffie-Hellman problem (CDH_). Given a cyclic group, a generator *g*, +and two integers *a* and *b*, it is difficult to find +the element *g^{ab}* when only *g^a* and *g^b* are known, and not *a* and *b*. + +As before, the group is the largest multiplicative sub-group of the integers +modulo *p*, with *p* prime. +The receiver holds a value *a* (*0<a<p-1*) as private key, and its public key +(*b* where *b*=g^a*) is given to the sender. + +The ElGamal ciphertext is twice as big as *p*. + +Domain parameters +----------------- +For both signature and encryption schemes, the values *(p,g)* are called +*domain parameters*. +They are not sensitive but must be distributed to all parties (senders and +receivers). +Different signers can share the same domain parameters, as can +different recipients of encrypted messages. + +Security +-------- +Both DLP and CDH problem are believed to be difficult, and they have been proved +such (and therefore secure) for more than 30 years. + +The cryptographic strength is linked to the magnitude of *p*. +In 2012, a sufficient size for *p* is deemed to be 2048 bits. +For more information, see the most recent ECRYPT_ report. + +Even though ElGamal algorithms are in theory reasonably secure for new designs, +in practice there are no real good reasons for using them. +The signature is four times larger than the equivalent DSA, and the ciphertext +is two times larger than the equivalent RSA. + +Functionality +------------- +This module provides facilities for generating new ElGamal keys and for constructing +them from known components. ElGamal keys allows you to perform basic signing, +verification, encryption, and decryption. + + >>> from Crypto import Random + >>> from Crypto.Random import random + >>> from Crypto.PublicKey import ElGamal + >>> from Crypto.Util.number import GCD + >>> from Crypto.Hash import SHA + >>> + >>> message = "Hello" + >>> key = ElGamal.generate(1024, Random.new().read) + >>> h = SHA.new(message).digest() + >>> while 1: + >>> k = random.StrongRandom().randint(1,key.p-1) + >>> if GCD(k,key.p-1)==1: break + >>> sig = key.sign(h,k) + >>> ... + >>> if key.verify(h,sig): + >>> print "OK" + >>> else: + >>> print "Incorrect signature" + +.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf +.. _CDH: http://en.wikipedia.org/wiki/Computational_Diffie%E2%80%93Hellman_assumption +.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf +""" + +__revision__ = "$Id$" + +__all__ = ['generate', 'construct', 'error', 'ElGamalobj'] + +from Crypto.PublicKey.pubkey import * +from Crypto.Util import number +from Crypto import Random + +class error (Exception): + pass + +# Generate an ElGamal key with N bits +def generate(bits, randfunc, progress_func=None): + """Randomly generate a fresh, new ElGamal key. + + The key will be safe for use for both encryption and signature + (although it should be used for **only one** purpose). + + :Parameters: + bits : int + Key length, or size (in bits) of the modulus *p*. + Recommended value is 2048. + randfunc : callable + Random number generation function; it should accept + a single integer N and return a string of random data + N bytes long. + progress_func : callable + Optional function that will be called with a short string + containing the key parameter currently being generated; + it's useful for interactive applications where a user is + waiting for a key to be generated. + + :attention: You should always use a cryptographically secure random number generator, + such as the one defined in the ``Crypto.Random`` module; **don't** just use the + current time and the ``random`` module. + + :Return: An ElGamal key object (`ElGamalobj`). + """ + obj=ElGamalobj() + # Generate a safe prime p + # See Algorithm 4.86 in Handbook of Applied Cryptography + if progress_func: + progress_func('p\n') + while 1: + q = bignum(getPrime(bits-1, randfunc)) + obj.p = 2*q+1 + if number.isPrime(obj.p, randfunc=randfunc): + break + # Generate generator g + # See Algorithm 4.80 in Handbook of Applied Cryptography + # Note that the order of the group is n=p-1=2q, where q is prime + if progress_func: + progress_func('g\n') + while 1: + # We must avoid g=2 because of Bleichenbacher's attack described + # in "Generating ElGamal signatures without knowning the secret key", + # 1996 + # + obj.g = number.getRandomRange(3, obj.p, randfunc) + safe = 1 + if pow(obj.g, 2, obj.p)==1: + safe=0 + if safe and pow(obj.g, q, obj.p)==1: + safe=0 + # Discard g if it divides p-1 because of the attack described + # in Note 11.67 (iii) in HAC + if safe and divmod(obj.p-1, obj.g)[1]==0: + safe=0 + # g^{-1} must not divide p-1 because of Khadir's attack + # described in "Conditions of the generator for forging ElGamal + # signature", 2011 + ginv = number.inverse(obj.g, obj.p) + if safe and divmod(obj.p-1, ginv)[1]==0: + safe=0 + if safe: + break + # Generate private key x + if progress_func: + progress_func('x\n') + obj.x=number.getRandomRange(2, obj.p-1, randfunc) + # Generate public key y + if progress_func: + progress_func('y\n') + obj.y = pow(obj.g, obj.x, obj.p) + return obj + +def construct(tup): + """Construct an ElGamal key from a tuple of valid ElGamal components. + + The modulus *p* must be a prime. + + The following conditions must apply: + + - 1 < g < p-1 + - g^{p-1} = 1 mod p + - 1 < x < p-1 + - g^x = y mod p + + :Parameters: + tup : tuple + A tuple of long integers, with 3 or 4 items + in the following order: + + 1. Modulus (*p*). + 2. Generator (*g*). + 3. Public key (*y*). + 4. Private key (*x*). Optional. + + :Return: An ElGamal key object (`ElGamalobj`). + """ + + obj=ElGamalobj() + if len(tup) not in [3,4]: + raise ValueError('argument for construct() wrong length') + for i in range(len(tup)): + field = obj.keydata[i] + setattr(obj, field, tup[i]) + return obj + +class ElGamalobj(pubkey): + """Class defining an ElGamal key. + + :undocumented: __getstate__, __setstate__, __repr__, __getattr__ + """ + + #: Dictionary of ElGamal parameters. + #: + #: A public key will only have the following entries: + #: + #: - **y**, the public key. + #: - **g**, the generator. + #: - **p**, the modulus. + #: + #: A private key will also have: + #: + #: - **x**, the private key. + keydata=['p', 'g', 'y', 'x'] + + def __init__(self, randfunc=None): + if randfunc is None: + randfunc = Random.new().read + self._randfunc = randfunc + + def encrypt(self, plaintext, K): + """Encrypt a piece of data with ElGamal. + + :Parameter plaintext: The piece of data to encrypt with ElGamal. + It must be numerically smaller than the module (*p*). + :Type plaintext: byte string or long + + :Parameter K: A secret number, chosen randomly in the closed + range *[1,p-2]*. + :Type K: long (recommended) or byte string (not recommended) + + :Return: A tuple with two items. Each item is of the same type as the + plaintext (string or long). + + :attention: selection of *K* is crucial for security. Generating a + random number larger than *p-1* and taking the modulus by *p-1* is + **not** secure, since smaller values will occur more frequently. + Generating a random number systematically smaller than *p-1* + (e.g. *floor((p-1)/8)* random bytes) is also **not** secure. + In general, it shall not be possible for an attacker to know + the value of any bit of K. + + :attention: The number *K* shall not be reused for any other + operation and shall be discarded immediately. + """ + return pubkey.encrypt(self, plaintext, K) + + def decrypt(self, ciphertext): + """Decrypt a piece of data with ElGamal. + + :Parameter ciphertext: The piece of data to decrypt with ElGamal. + :Type ciphertext: byte string, long or a 2-item tuple as returned + by `encrypt` + + :Return: A byte string if ciphertext was a byte string or a tuple + of byte strings. A long otherwise. + """ + return pubkey.decrypt(self, ciphertext) + + def sign(self, M, K): + """Sign a piece of data with ElGamal. + + :Parameter M: The piece of data to sign with ElGamal. It may + not be longer in bit size than *p-1*. + :Type M: byte string or long + + :Parameter K: A secret number, chosen randomly in the closed + range *[1,p-2]* and such that *gcd(k,p-1)=1*. + :Type K: long (recommended) or byte string (not recommended) + + :attention: selection of *K* is crucial for security. Generating a + random number larger than *p-1* and taking the modulus by *p-1* is + **not** secure, since smaller values will occur more frequently. + Generating a random number systematically smaller than *p-1* + (e.g. *floor((p-1)/8)* random bytes) is also **not** secure. + In general, it shall not be possible for an attacker to know + the value of any bit of K. + + :attention: The number *K* shall not be reused for any other + operation and shall be discarded immediately. + + :attention: M must be be a cryptographic hash, otherwise an + attacker may mount an existential forgery attack. + + :Return: A tuple with 2 longs. + """ + return pubkey.sign(self, M, K) + + def verify(self, M, signature): + """Verify the validity of an ElGamal signature. + + :Parameter M: The expected message. + :Type M: byte string or long + + :Parameter signature: The ElGamal signature to verify. + :Type signature: A tuple with 2 longs as return by `sign` + + :Return: True if the signature is correct, False otherwise. + """ + return pubkey.verify(self, M, signature) + + def _encrypt(self, M, K): + a=pow(self.g, K, self.p) + b=( M*pow(self.y, K, self.p) ) % self.p + return ( a,b ) + + def _decrypt(self, M): + if (not hasattr(self, 'x')): + raise TypeError('Private key not available in this object') + r = number.getRandomRange(2, self.p-1, self._randfunc) + a_blind = (M[0] * pow(self.g, r, self.p)) % self.p + ax=pow(a_blind, self.x, self.p) + plaintext_blind = (M[1] * inverse(ax, self.p ) ) % self.p + plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p + return plaintext + + def _sign(self, M, K): + if (not hasattr(self, 'x')): + raise TypeError('Private key not available in this object') + p1=self.p-1 + if (GCD(K, p1)!=1): + raise ValueError('Bad K value: GCD(K,p-1)!=1') + a=pow(self.g, K, self.p) + t=(M-self.x*a) % p1 + while t<0: t=t+p1 + b=(t*inverse(K, p1)) % p1 + return (a, b) + + def _verify(self, M, sig): + if sig[0]<1 or sig[0]>self.p-1: + return 0 + v1=pow(self.y, sig[0], self.p) + v1=(v1*pow(sig[0], sig[1], self.p)) % self.p + v2=pow(self.g, M, self.p) + if v1==v2: + return 1 + return 0 + + def size(self): + return number.size(self.p) - 1 + + def has_private(self): + if hasattr(self, 'x'): + return 1 + else: + return 0 + + def publickey(self): + return construct((self.p, self.g, self.y)) + + +object=ElGamalobj diff --git a/lib/Crypto/PublicKey/RSA.py b/lib/Crypto/PublicKey/RSA.py new file mode 100644 index 0000000..a5afeb9 --- /dev/null +++ b/lib/Crypto/PublicKey/RSA.py @@ -0,0 +1,732 @@ +# -*- coding: utf-8 -*- +# +# PublicKey/RSA.py : RSA public key primitive +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""RSA public-key cryptography algorithm (signature and encryption). + +RSA_ is the most widespread and used public key algorithm. Its security is +based on the difficulty of factoring large integers. The algorithm has +withstood attacks for 30 years, and it is therefore considered reasonably +secure for new designs. + +The algorithm can be used for both confidentiality (encryption) and +authentication (digital signature). It is worth noting that signing and +decryption are significantly slower than verification and encryption. +The cryptograhic strength is primarily linked to the length of the modulus *n*. +In 2012, a sufficient length is deemed to be 2048 bits. For more information, +see the most recent ECRYPT_ report. + +Both RSA ciphertext and RSA signature are as big as the modulus *n* (256 +bytes if *n* is 2048 bit long). + +This module provides facilities for generating fresh, new RSA keys, constructing +them from known components, exporting them, and importing them. + + >>> from Crypto.PublicKey import RSA + >>> + >>> key = RSA.generate(2048) + >>> f = open('mykey.pem','w') + >>> f.write(key.exportKey('PEM')) + >>> f.close() + ... + >>> f = open('mykey.pem','r') + >>> key = RSA.importKey(f.read()) + +Even though you may choose to directly use the methods of an RSA key object +to perform the primitive cryptographic operations (e.g. `_RSAobj.encrypt`), +it is recommended to use one of the standardized schemes instead (like +`Crypto.Cipher.PKCS1_v1_5` or `Crypto.Signature.PKCS1_v1_5`). + +.. _RSA: http://en.wikipedia.org/wiki/RSA_%28algorithm%29 +.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf + +:sort: generate,construct,importKey,error +""" + +__revision__ = "$Id$" + +__all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', + '_RSAobj', 'oid' , 'algorithmIdentifier' ] + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes + +from Crypto.PublicKey import _RSA, _slowmath, pubkey +from Crypto.IO import PKCS8, PEM +from Crypto import Random + +from Crypto.Util.asn1 import * + +import binascii +import struct + +from Crypto.Util.number import inverse + +try: + from Crypto.PublicKey import _fastmath +except ImportError: + _fastmath = None + +def decode_der(obj_class, binstr): + """Instantiate a DER object class, decode a DER binary string in it, and + return the object.""" + der = obj_class() + der.decode(binstr) + return der + +class _RSAobj(pubkey.pubkey): + """Class defining an actual RSA key. + + :undocumented: __getstate__, __setstate__, __repr__, __getattr__ + """ + #: Dictionary of RSA parameters. + #: + #: A public key will only have the following entries: + #: + #: - **n**, the modulus. + #: - **e**, the public exponent. + #: + #: A private key will also have: + #: + #: - **d**, the private exponent. + #: - **p**, the first factor of n. + #: - **q**, the second factor of n. + #: - **u**, the CRT coefficient (1/p) mod q. + keydata = ['n', 'e', 'd', 'p', 'q', 'u'] + + def __init__(self, implementation, key, randfunc=None): + self.implementation = implementation + self.key = key + if randfunc is None: + randfunc = Random.new().read + self._randfunc = randfunc + + def __getattr__(self, attrname): + if attrname in self.keydata: + # For backward compatibility, allow the user to get (not set) the + # RSA key parameters directly from this object. + return getattr(self.key, attrname) + else: + raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,)) + + def encrypt(self, plaintext, K): + """Encrypt a piece of data with RSA. + + :Parameter plaintext: The piece of data to encrypt with RSA. It may not + be numerically larger than the RSA module (**n**). + :Type plaintext: byte string or long + + :Parameter K: A random parameter (*for compatibility only. This + value will be ignored*) + :Type K: byte string or long + + :attention: this function performs the plain, primitive RSA encryption + (*textbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly encrypt data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead. + + :Return: A tuple with two items. The first item is the ciphertext + of the same type as the plaintext (string or long). The second item + is always None. + """ + return pubkey.pubkey.encrypt(self, plaintext, K) + + def decrypt(self, ciphertext): + """Decrypt a piece of data with RSA. + + Decryption always takes place with blinding. + + :attention: this function performs the plain, primitive RSA decryption + (*textbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly decrypt data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead. + + :Parameter ciphertext: The piece of data to decrypt with RSA. It may + not be numerically larger than the RSA module (**n**). If a tuple, + the first item is the actual ciphertext; the second item is ignored. + + :Type ciphertext: byte string, long or a 2-item tuple as returned by + `encrypt` + + :Return: A byte string if ciphertext was a byte string or a tuple + of byte strings. A long otherwise. + """ + return pubkey.pubkey.decrypt(self, ciphertext) + + def sign(self, M, K): + """Sign a piece of data with RSA. + + Signing always takes place with blinding. + + :attention: this function performs the plain, primitive RSA decryption + (*textbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly sign data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead. + + :Parameter M: The piece of data to sign with RSA. It may + not be numerically larger than the RSA module (**n**). + :Type M: byte string or long + + :Parameter K: A random parameter (*for compatibility only. This + value will be ignored*) + :Type K: byte string or long + + :Return: A 2-item tuple. The first item is the actual signature (a + long). The second item is always None. + """ + return pubkey.pubkey.sign(self, M, K) + + def verify(self, M, signature): + """Verify the validity of an RSA signature. + + :attention: this function performs the plain, primitive RSA encryption + (*textbook*). In real applications, you always need to use proper + cryptographic padding, and you should not directly verify data with + this method. Failure to do so may lead to security vulnerabilities. + It is recommended to use modules + `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead. + + :Parameter M: The expected message. + :Type M: byte string or long + + :Parameter signature: The RSA signature to verify. The first item of + the tuple is the actual signature (a long not larger than the modulus + **n**), whereas the second item is always ignored. + :Type signature: A 2-item tuple as return by `sign` + + :Return: True if the signature is correct, False otherwise. + """ + return pubkey.pubkey.verify(self, M, signature) + + def _encrypt(self, c, K): + return (self.key._encrypt(c),) + + def _decrypt(self, c): + #(ciphertext,) = c + (ciphertext,) = c[:1] # HACK - We should use the previous line + # instead, but this is more compatible and we're + # going to replace the Crypto.PublicKey API soon + # anyway. + + # Blinded RSA decryption (to prevent timing attacks): + # Step 1: Generate random secret blinding factor r, such that 0 < r < n-1 + r = getRandomRange(1, self.key.n-1, randfunc=self._randfunc) + # Step 2: Compute c' = c * r**e mod n + cp = self.key._blind(ciphertext, r) + # Step 3: Compute m' = c'**d mod n (ordinary RSA decryption) + mp = self.key._decrypt(cp) + # Step 4: Compute m = m**(r-1) mod n + return self.key._unblind(mp, r) + + def _blind(self, m, r): + return self.key._blind(m, r) + + def _unblind(self, m, r): + return self.key._unblind(m, r) + + def _sign(self, m, K=None): + return (self.key._sign(m),) + + def _verify(self, m, sig): + #(s,) = sig + (s,) = sig[:1] # HACK - We should use the previous line instead, but + # this is more compatible and we're going to replace + # the Crypto.PublicKey API soon anyway. + return self.key._verify(m, s) + + def has_private(self): + return self.key.has_private() + + def size(self): + return self.key.size() + + def can_blind(self): + return True + + def can_encrypt(self): + return True + + def can_sign(self): + return True + + def publickey(self): + return self.implementation.construct((self.key.n, self.key.e)) + + def __getstate__(self): + d = {} + for k in self.keydata: + try: + d[k] = getattr(self.key, k) + except AttributeError: + pass + return d + + def __setstate__(self, d): + if not hasattr(self, 'implementation'): + self.implementation = RSAImplementation() + if not hasattr(self, '_randfunc'): + self._randfunc = Random.new().read + t = [] + for k in self.keydata: + if not d.has_key(k): + break + t.append(d[k]) + self.key = self.implementation._math.rsa_construct(*tuple(t)) + + def __repr__(self): + attrs = [] + for k in self.keydata: + if k == 'n': + attrs.append("n(%d)" % (self.size()+1,)) + elif hasattr(self.key, k): + attrs.append(k) + if self.has_private(): + attrs.append("private") + # PY3K: This is meant to be text, do not change to bytes (data) + return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) + + def exportKey(self, format='PEM', passphrase=None, pkcs=1, protection=None): + """Export this RSA key. + + :Parameters: + format : string + The format to use for wrapping the key: + + - *'DER'*. Binary encoding. + - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_. + - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification. + Only suitable for public keys (not private keys). + + passphrase : string + For private keys only. The pass phrase used for deriving the encryption + key. + + pkcs : integer + For *DER* and *PEM* format only. + The PKCS standard to follow for assembling the components of the key. + You have two choices: + + - **1** (default): the public key is embedded into + an X.509 ``SubjectPublicKeyInfo`` DER SEQUENCE. + The private key is embedded into a `PKCS#1`_ + ``RSAPrivateKey`` DER SEQUENCE. + - **8**: the private key is embedded into a `PKCS#8`_ + ``PrivateKeyInfo`` DER SEQUENCE. This value cannot be used + for public keys. + + protection : string + The encryption scheme to use for protecting the private key. + + If ``None`` (default), the behavior depends on ``format``: + + - For *DER*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC* + scheme is used. The following operations are performed: + + 1. A 16 byte Triple DES key is derived from the passphrase + using `Crypto.Protocol.KDF.PBKDF2` with 8 bytes salt, + and 1 000 iterations of `Crypto.Hash.HMAC`. + 2. The private key is encrypted using CBC. + 3. The encrypted key is encoded according to PKCS#8. + + - For *PEM*, the obsolete PEM encryption scheme is used. + It is based on MD5 for key derivation, and Triple DES for encryption. + + Specifying a value for ``protection`` is only meaningful for PKCS#8 + (that is, ``pkcs=8``) and only if a pass phrase is present too. + + The supported schemes for PKCS#8 are listed in the + `Crypto.IO.PKCS8` module (see ``wrap_algo`` parameter). + + :Return: A byte string with the encoded public or private half + of the key. + :Raise ValueError: + When the format is unknown or when you try to encrypt a private + key with *DER* format and PKCS#1. + :attention: + If you don't provide a pass phrase, the private key will be + exported in the clear! + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + if passphrase is not None: + passphrase = tobytes(passphrase) + if format=='OpenSSH': + eb = long_to_bytes(self.e) + nb = long_to_bytes(self.n) + if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb + if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb + keyparts = [ b('ssh-rsa'), eb, nb ] + keystring = b('').join([ struct.pack(">I",len(kp))+kp for kp in keyparts]) + return b('ssh-rsa ')+binascii.b2a_base64(keystring)[:-1] + + # DER format is always used, even in case of PEM, which simply + # encodes it into BASE64. + if self.has_private(): + binary_key = newDerSequence( + 0, + self.n, + self.e, + self.d, + self.p, + self.q, + self.d % (self.p-1), + self.d % (self.q-1), + inverse(self.q, self.p) + ).encode() + if pkcs==1: + keyType = 'RSA PRIVATE' + if format=='DER' and passphrase: + raise ValueError("PKCS#1 private key cannot be encrypted") + else: # PKCS#8 + if format=='PEM' and protection is None: + keyType = 'PRIVATE' + binary_key = PKCS8.wrap(binary_key, oid, None) + else: + keyType = 'ENCRYPTED PRIVATE' + if not protection: + protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' + binary_key = PKCS8.wrap(binary_key, oid, passphrase, protection) + passphrase = None + else: + keyType = "RSA PUBLIC" + binary_key = newDerSequence( + algorithmIdentifier, + newDerBitString( + newDerSequence( self.n, self.e ) + ) + ).encode() + if format=='DER': + return binary_key + if format=='PEM': + pem_str = PEM.encode(binary_key, keyType+" KEY", passphrase, self._randfunc) + return tobytes(pem_str) + raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format) + +class RSAImplementation(object): + """ + An RSA key factory. + + This class is only internally used to implement the methods of the `Crypto.PublicKey.RSA` module. + + :sort: __init__,generate,construct,importKey + :undocumented: _g*, _i* + """ + + def __init__(self, **kwargs): + """Create a new RSA key factory. + + :Keywords: + use_fast_math : bool + Specify which mathematic library to use: + + - *None* (default). Use fastest math available. + - *True* . Use fast math. + - *False* . Use slow math. + default_randfunc : callable + Specify how to collect random data: + + - *None* (default). Use Random.new().read(). + - not *None* . Use the specified function directly. + :Raise RuntimeError: + When **use_fast_math** =True but fast math is not available. + """ + use_fast_math = kwargs.get('use_fast_math', None) + if use_fast_math is None: # Automatic + if _fastmath is not None: + self._math = _fastmath + else: + self._math = _slowmath + + elif use_fast_math: # Explicitly select fast math + if _fastmath is not None: + self._math = _fastmath + else: + raise RuntimeError("fast math module not available") + + else: # Explicitly select slow math + self._math = _slowmath + + self.error = self._math.error + + self._default_randfunc = kwargs.get('default_randfunc', None) + self._current_randfunc = None + + def _get_randfunc(self, randfunc): + if randfunc is not None: + return randfunc + elif self._current_randfunc is None: + self._current_randfunc = Random.new().read + return self._current_randfunc + + def generate(self, bits, randfunc=None, progress_func=None, e=65537): + """Randomly generate a fresh, new RSA key. + + :Parameters: + bits : int + Key length, or size (in bits) of the RSA modulus. + It must be a multiple of 256, and no smaller than 1024. + + randfunc : callable + Random number generation function; it should accept + a single integer N and return a string of random data + N bytes long. + If not specified, a new one will be instantiated + from ``Crypto.Random``. + + progress_func : callable + Optional function that will be called with a short string + containing the key parameter currently being generated; + it's useful for interactive applications where a user is + waiting for a key to be generated. + + e : int + Public RSA exponent. It must be an odd positive integer. + It is typically a small number with very few ones in its + binary representation. + The default value 65537 (= ``0b10000000000000001`` ) is a safe + choice: other common values are 5, 7, 17, and 257. + + :attention: You should always use a cryptographically secure random number generator, + such as the one defined in the ``Crypto.Random`` module; **don't** just use the + current time and the ``random`` module. + + :attention: Exponent 3 is also widely used, but it requires very special care when padding + the message. + + :Return: An RSA key object (`_RSAobj`). + + :Raise ValueError: + When **bits** is too little or not a multiple of 256, or when + **e** is not odd or smaller than 2. + """ + if bits < 1024 or (bits & 0xff) != 0: + # pubkey.getStrongPrime doesn't like anything that's not a multiple of 256 and >= 1024 + raise ValueError("RSA modulus length must be a multiple of 256 and >= 1024") + if e%2==0 or e<3: + raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.") + rf = self._get_randfunc(randfunc) + obj = _RSA.generate_py(bits, rf, progress_func, e) # TODO: Don't use legacy _RSA module + key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u) + return _RSAobj(self, key) + + def construct(self, tup): + """Construct an RSA key from a tuple of valid RSA components. + + The modulus **n** must be the product of two primes. + The public exponent **e** must be odd and larger than 1. + + In case of a private key, the following equations must apply: + + - e != 1 + - p*q = n + - e*d = 1 mod (p-1)(q-1) + - p*u = 1 mod q + + :Parameters: + tup : tuple + A tuple of long integers, with at least 2 and no + more than 6 items. The items come in the following order: + + 1. RSA modulus (n). + 2. Public exponent (e). + 3. Private exponent (d). Only required if the key is private. + 4. First factor of n (p). Optional. + 5. Second factor of n (q). Optional. + 6. CRT coefficient, (1/p) mod q (u). Optional. + + :Return: An RSA key object (`_RSAobj`). + """ + key = self._math.rsa_construct(*tup) + return _RSAobj(self, key) + + def _importKeyDER(self, extern_key, passphrase=None): + """Import an RSA key (public or private half), encoded in DER form.""" + + try: + + der = decode_der(DerSequence, extern_key) + + # Try PKCS#1 first, for a private key + if len(der) == 9 and der.hasOnlyInts() and der[0] == 0: + # ASN.1 RSAPrivateKey element + del der[6:] # Remove d mod (p-1), + # d mod (q-1), and + # q^{-1} mod p + der.append(inverse(der[4], der[5])) # Add p^{-1} mod q + del der[0] # Remove version + return self.construct(der[:]) + + # Keep on trying PKCS#1, but now for a public key + if len(der) == 2: + try: + # The DER object is an RSAPublicKey SEQUENCE with + # two elements + if der.hasOnlyInts(): + return self.construct(der[:]) + # The DER object is a SubjectPublicKeyInfo SEQUENCE + # with two elements: an 'algorithmIdentifier' and a + # 'subjectPublicKey'BIT STRING. + # 'algorithmIdentifier' takes the value given at the + # module level. + # 'subjectPublicKey' encapsulates the actual ASN.1 + # RSAPublicKey element. + if der[0] == algorithmIdentifier: + bitmap = decode_der(DerBitString, der[1]) + rsaPub = decode_der(DerSequence, bitmap.value) + if len(rsaPub) == 2 and rsaPub.hasOnlyInts(): + return self.construct(rsaPub[:]) + except (ValueError, EOFError): + pass + + # Try PKCS#8 (possibly encrypted) + k = PKCS8.unwrap(extern_key, passphrase) + if k[0] == oid: + return self._importKeyDER(k[1], passphrase) + + except (ValueError, EOFError): + pass + + raise ValueError("RSA key format is not supported") + + def importKey(self, extern_key, passphrase=None): + """Import an RSA key (public or private half), encoded in standard + form. + + :Parameter extern_key: + The RSA key to import, encoded as a string. + + An RSA public key can be in any of the following formats: + + - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM + encoding) + - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding) + - OpenSSH (textual public key only) + + An RSA private key can be in any of the following formats: + + - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding) + - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` + DER SEQUENCE (binary or PEM encoding) + - OpenSSH (textual public key only) + + For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. + + The private key may be encrypted by means of a certain pass phrase + either at the PEM level or at the PKCS#8 level. + :Type extern_key: string + + :Parameter passphrase: + In case of an encrypted private key, this is the pass phrase from + which the decryption key is derived. + :Type passphrase: string + + :Return: An RSA key object (`_RSAobj`). + + :Raise ValueError/IndexError/TypeError: + When the given key cannot be parsed (possibly because the pass + phrase is wrong). + + .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt + .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt + .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt + .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt + """ + extern_key = tobytes(extern_key) + if passphrase is not None: + passphrase = tobytes(passphrase) + + if extern_key.startswith(b('-----')): + # This is probably a PEM encoded key. + (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) + if enc_flag: + passphrase = None + return self._importKeyDER(der, passphrase) + + if extern_key.startswith(b('ssh-rsa ')): + # This is probably an OpenSSH key + keystring = binascii.a2b_base64(extern_key.split(b(' '))[1]) + keyparts = [] + while len(keystring) > 4: + l = struct.unpack(">I", keystring[:4])[0] + keyparts.append(keystring[4:4 + l]) + keystring = keystring[4 + l:] + e = bytes_to_long(keyparts[1]) + n = bytes_to_long(keyparts[2]) + return self.construct([n, e]) + + if bord(extern_key[0]) == 0x30: + # This is probably a DER encoded key + return self._importKeyDER(extern_key, passphrase) + + raise ValueError("RSA key format is not supported") + +#: `Object ID`_ for the RSA encryption algorithm. This OID often indicates +#: a generic RSA key, even when such key will be actually used for digital +#: signatures. +#: +#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html +oid = "1.2.840.113549.1.1.1" + +#: This is the standard DER object that qualifies a cryptographic algorithm +#: in ASN.1-based data structures (e.g. X.509 certificates). +algorithmIdentifier = DerSequence( + [DerObjectId(oid).encode(), # algorithm field + DerNull().encode()] # parameters field + ).encode() + +_impl = RSAImplementation() +#: +#: Randomly generate a fresh, new RSA key object. +#: +#: See `RSAImplementation.generate`. +#: +generate = _impl.generate +#: +#: Construct an RSA key object from a tuple of valid RSA components. +#: +#: See `RSAImplementation.construct`. +#: +construct = _impl.construct +#: +#: Import an RSA key (public or private half), encoded in standard form. +#: +#: See `RSAImplementation.importKey`. +#: +importKey = _impl.importKey +error = _impl.error + +# vim:set ts=4 sw=4 sts=4 expandtab: + diff --git a/lib/Crypto/PublicKey/_DSA.py b/lib/Crypto/PublicKey/_DSA.py new file mode 100644 index 0000000..f027d92 --- /dev/null +++ b/lib/Crypto/PublicKey/_DSA.py @@ -0,0 +1,115 @@ + +# +# DSA.py : Digital Signature Algorithm +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew Kuchling, Paul Swartz, and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +# + +__revision__ = "$Id$" + +from Crypto.PublicKey.pubkey import * +from Crypto.Util import number +from Crypto.Util.number import bytes_to_long, long_to_bytes +from Crypto.Hash import SHA1 +from Crypto.Util.py3compat import * + +class error (Exception): + pass + +def generateQ(randfunc): + S=randfunc(20) + hash1=SHA1.new(S).digest() + hash2=SHA1.new(long_to_bytes(bytes_to_long(S)+1)).digest() + q = bignum(0) + for i in range(0,20): + c=bord(hash1[i])^bord(hash2[i]) + if i==0: + c=c | 128 + if i==19: + c= c | 1 + q=q*256+c + while (not isPrime(q)): + q=q+2 + if pow(2,159L) < q < pow(2,160L): + return S, q + raise RuntimeError('Bad q value generated') + +def generate_py(bits, randfunc, progress_func=None): + """generate(bits:int, randfunc:callable, progress_func:callable) + + Generate a DSA key of length 'bits', using 'randfunc' to get + random data and 'progress_func', if present, to display + the progress of the key generation. + """ + + if bits<160: + raise ValueError('Key length < 160 bits') + obj=DSAobj() + # Generate string S and prime q + if progress_func: + progress_func('p,q\n') + while (1): + S, obj.q = generateQ(randfunc) + n=divmod(bits-1, 160)[0] + C, N, V = 0, 2, {} + b=(obj.q >> 5) & 15 + powb=pow(bignum(2), b) + powL1=pow(bignum(2), bits-1) + while C<4096: + for k in range(0, n+1): + V[k]=bytes_to_long(SHA1.new(S+bstr(N)+bstr(k)).digest()) + W=V[n] % powb + for k in range(n-1, -1, -1): + W=(W<<160L)+V[k] + X=W+powL1 + p=X-(X%(2*obj.q)-1) + if powL1<=p and isPrime(p): + break + C, N = C+1, N+n+1 + if C<4096: + break + if progress_func: + progress_func('4096 multiples failed\n') + + obj.p = p + power=divmod(p-1, obj.q)[0] + if progress_func: + progress_func('h,g\n') + while (1): + h=bytes_to_long(randfunc(bits)) % (p-1) + g=pow(h, power, p) + if 1<h<p-1 and g>1: + break + obj.g=g + if progress_func: + progress_func('x,y\n') + while (1): + x=bytes_to_long(randfunc(20)) + if 0 < x < obj.q: + break + obj.x, obj.y = x, pow(g, x, p) + return obj + +class DSAobj: + pass + diff --git a/lib/Crypto/PublicKey/_RSA.py b/lib/Crypto/PublicKey/_RSA.py new file mode 100644 index 0000000..9366d19 --- /dev/null +++ b/lib/Crypto/PublicKey/_RSA.py @@ -0,0 +1,81 @@ +# +# RSA.py : RSA encryption/decryption +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew Kuchling, Paul Swartz, and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +# + +__revision__ = "$Id$" + +from Crypto.PublicKey import pubkey +from Crypto.Util import number + +def generate_py(bits, randfunc, progress_func=None, e=65537): + """generate(bits:int, randfunc:callable, progress_func:callable, e:int) + + Generate an RSA key of length 'bits', public exponent 'e'(which must be + odd), using 'randfunc' to get random data and 'progress_func', + if present, to display the progress of the key generation. + """ + obj=RSAobj() + obj.e = long(e) + + # Generate the prime factors of n + if progress_func: + progress_func('p,q\n') + p = q = 1L + while number.size(p*q) < bits: + # Note that q might be one bit longer than p if somebody specifies an odd + # number of bits for the key. (Why would anyone do that? You don't get + # more security.) + p = pubkey.getStrongPrime(bits>>1, obj.e, 1e-12, randfunc) + q = pubkey.getStrongPrime(bits - (bits>>1), obj.e, 1e-12, randfunc) + + # It's OK for p to be larger than q, but let's be + # kind to the function that will invert it for + # th calculation of u. + if p > q: + (p, q)=(q, p) + obj.p = p + obj.q = q + + if progress_func: + progress_func('u\n') + obj.u = pubkey.inverse(obj.p, obj.q) + obj.n = obj.p*obj.q + + if progress_func: + progress_func('d\n') + obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1)) + + assert bits <= 1+obj.size(), "Generated key is too small" + + return obj + +class RSAobj(pubkey.pubkey): + + def size(self): + """size() : int + Return the maximum number of bits that can be handled by this key. + """ + return number.size(self.n) - 1 + diff --git a/lib/Crypto/PublicKey/__init__.py b/lib/Crypto/PublicKey/__init__.py new file mode 100644 index 0000000..df60c25 --- /dev/null +++ b/lib/Crypto/PublicKey/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Public-key encryption and signature algorithms. + +Public-key encryption uses two different keys, one for encryption and +one for decryption. The encryption key can be made public, and the +decryption key is kept private. Many public-key algorithms can also +be used to sign messages, and some can *only* be used for signatures. + +======================== ============================================= +Module Description +======================== ============================================= +Crypto.PublicKey.DSA Digital Signature Algorithm (Signature only) +Crypto.PublicKey.ElGamal (Signing and encryption) +Crypto.PublicKey.RSA (Signing, encryption, and blinding) +======================== ============================================= + +:undocumented: _DSA, _RSA, _fastmath, _slowmath, pubkey +""" + +class KeyFormatError(ValueError): + pass + +__all__ = ['RSA', 'DSA', 'ElGamal'] +__revision__ = "$Id$" + diff --git a/lib/Crypto/PublicKey/_slowmath.py b/lib/Crypto/PublicKey/_slowmath.py new file mode 100644 index 0000000..d926596 --- /dev/null +++ b/lib/Crypto/PublicKey/_slowmath.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# +# PubKey/RSA/_slowmath.py : Pure Python implementation of the RSA portions of _fastmath +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Pure Python implementation of the RSA-related portions of Crypto.PublicKey._fastmath.""" + +__revision__ = "$Id$" + +__all__ = ['rsa_construct'] + +import sys + +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.number import size, inverse, GCD + +class error(Exception): + pass + +class _RSAKey(object): + def _blind(self, m, r): + # compute r**e * m (mod n) + return m * pow(r, self.e, self.n) + + def _unblind(self, m, r): + # compute m / r (mod n) + return inverse(r, self.n) * m % self.n + + def _decrypt(self, c): + # compute c**d (mod n) + if not self.has_private(): + raise TypeError("No private key") + if (hasattr(self,'p') and hasattr(self,'q') and hasattr(self,'u')): + m1 = pow(c, self.d % (self.p-1), self.p) + m2 = pow(c, self.d % (self.q-1), self.q) + h = m2 - m1 + if (h<0): + h = h + self.q + h = h*self.u % self.q + return h*self.p+m1 + return pow(c, self.d, self.n) + + def _encrypt(self, m): + # compute m**d (mod n) + return pow(m, self.e, self.n) + + def _sign(self, m): # alias for _decrypt + if not self.has_private(): + raise TypeError("No private key") + return self._decrypt(m) + + def _verify(self, m, sig): + return self._encrypt(sig) == m + + def has_private(self): + return hasattr(self, 'd') + + def size(self): + """Return the maximum number of bits that can be encrypted""" + return size(self.n) - 1 + +def rsa_construct(n, e, d=None, p=None, q=None, u=None): + """Construct an RSAKey object""" + assert isinstance(n, long) + assert isinstance(e, long) + assert isinstance(d, (long, type(None))) + assert isinstance(p, (long, type(None))) + assert isinstance(q, (long, type(None))) + assert isinstance(u, (long, type(None))) + obj = _RSAKey() + obj.n = n + obj.e = e + if d is None: + return obj + obj.d = d + if p is not None and q is not None: + obj.p = p + obj.q = q + else: + # Compute factors p and q from the private exponent d. + # We assume that n has no more than two factors. + # See 8.2.2(i) in Handbook of Applied Cryptography. + ktot = d*e-1 + # The quantity d*e-1 is a multiple of phi(n), even, + # and can be represented as t*2^s. + t = ktot + while t%2==0: + t=divmod(t,2)[0] + # Cycle through all multiplicative inverses in Zn. + # The algorithm is non-deterministic, but there is a 50% chance + # any candidate a leads to successful factoring. + # See "Digitalized Signatures and Public Key Functions as Intractable + # as Factorization", M. Rabin, 1979 + spotted = 0 + a = 2 + while not spotted and a<100: + k = t + # Cycle through all values a^{t*2^i}=a^k + while k<ktot: + cand = pow(a,k,n) + # Check if a^k is a non-trivial root of unity (mod n) + if cand!=1 and cand!=(n-1) and pow(cand,2,n)==1: + # We have found a number such that (cand-1)(cand+1)=0 (mod n). + # Either of the terms divides n. + obj.p = GCD(cand+1,n) + spotted = 1 + break + k = k*2 + # This value was not any good... let's try another! + a = a+2 + if not spotted: + raise ValueError("Unable to compute factors p and q from exponent d.") + # Found ! + assert ((n % obj.p)==0) + obj.q = divmod(n,obj.p)[0] + if u is not None: + obj.u = u + else: + obj.u = inverse(obj.p, obj.q) + return obj + +class _DSAKey(object): + def size(self): + """Return the maximum number of bits that can be encrypted""" + return size(self.p) - 1 + + def has_private(self): + return hasattr(self, 'x') + + def _sign(self, m, k): # alias for _decrypt + # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API. + if not self.has_private(): + raise TypeError("No private key") + if not (1L < k < self.q): + raise ValueError("k is not between 2 and q-1") + inv_k = inverse(k, self.q) # Compute k**-1 mod q + r = pow(self.g, k, self.p) % self.q # r = (g**k mod p) mod q + s = (inv_k * (m + self.x * r)) % self.q + return (r, s) + + def _verify(self, m, r, s): + # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API. + if not (0 < r < self.q) or not (0 < s < self.q): + return False + w = inverse(s, self.q) + u1 = (m*w) % self.q + u2 = (r*w) % self.q + v = (pow(self.g, u1, self.p) * pow(self.y, u2, self.p) % self.p) % self.q + return v == r + +def dsa_construct(y, g, p, q, x=None): + assert isinstance(y, long) + assert isinstance(g, long) + assert isinstance(p, long) + assert isinstance(q, long) + assert isinstance(x, (long, type(None))) + obj = _DSAKey() + obj.y = y + obj.g = g + obj.p = p + obj.q = q + if x is not None: obj.x = x + return obj + + +# vim:set ts=4 sw=4 sts=4 expandtab: + diff --git a/lib/Crypto/PublicKey/pubkey.py b/lib/Crypto/PublicKey/pubkey.py new file mode 100644 index 0000000..e44de8f --- /dev/null +++ b/lib/Crypto/PublicKey/pubkey.py @@ -0,0 +1,240 @@ +# +# pubkey.py : Internal functions for public key operations +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew Kuchling, Paul Swartz, and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +# + +__revision__ = "$Id$" + +import types, warnings +from Crypto.Util.number import * + +# Basic public key class +class pubkey: + """An abstract class for a public key object. + + :undocumented: __getstate__, __setstate__, __eq__, __ne__, validate + """ + def __init__(self): + pass + + def __getstate__(self): + """To keep key objects platform-independent, the key data is + converted to standard Python long integers before being + written out. It will then be reconverted as necessary on + restoration.""" + d=self.__dict__ + for key in self.keydata: + if d.has_key(key): d[key]=long(d[key]) + return d + + def __setstate__(self, d): + """On unpickling a key object, the key data is converted to the big +number representation being used, whether that is Python long +integers, MPZ objects, or whatever.""" + for key in self.keydata: + if d.has_key(key): self.__dict__[key]=bignum(d[key]) + + def encrypt(self, plaintext, K): + """Encrypt a piece of data. + + :Parameter plaintext: The piece of data to encrypt. + :Type plaintext: byte string or long + + :Parameter K: A random parameter required by some algorithms + :Type K: byte string or long + + :Return: A tuple with two items. Each item is of the same type as the + plaintext (string or long). + """ + wasString=0 + if isinstance(plaintext, types.StringType): + plaintext=bytes_to_long(plaintext) ; wasString=1 + if isinstance(K, types.StringType): + K=bytes_to_long(K) + ciphertext=self._encrypt(plaintext, K) + if wasString: return tuple(map(long_to_bytes, ciphertext)) + else: return ciphertext + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :Parameter ciphertext: The piece of data to decrypt. + :Type ciphertext: byte string, long or a 2-item tuple as returned by `encrypt` + + :Return: A byte string if ciphertext was a byte string or a tuple + of byte strings. A long otherwise. + """ + wasString=0 + if not isinstance(ciphertext, types.TupleType): + ciphertext=(ciphertext,) + if isinstance(ciphertext[0], types.StringType): + ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1 + plaintext=self._decrypt(ciphertext) + if wasString: return long_to_bytes(plaintext) + else: return plaintext + + def sign(self, M, K): + """Sign a piece of data. + + :Parameter M: The piece of data to encrypt. + :Type M: byte string or long + + :Parameter K: A random parameter required by some algorithms + :Type K: byte string or long + + :Return: A tuple with two items. + """ + if (not self.has_private()): + raise TypeError('Private key not available in this object') + if isinstance(M, types.StringType): M=bytes_to_long(M) + if isinstance(K, types.StringType): K=bytes_to_long(K) + return self._sign(M, K) + + def verify (self, M, signature): + """Verify the validity of a signature. + + :Parameter M: The expected message. + :Type M: byte string or long + + :Parameter signature: The signature to verify. + :Type signature: tuple with two items, as return by `sign` + + :Return: True if the signature is correct, False otherwise. + """ + if isinstance(M, types.StringType): M=bytes_to_long(M) + return self._verify(M, signature) + + # alias to compensate for the old validate() name + def validate (self, M, signature): + warnings.warn("validate() method name is obsolete; use verify()", + DeprecationWarning) + + def blind(self, M, B): + """Blind a message to prevent certain side-channel attacks. + + :Parameter M: The message to blind. + :Type M: byte string or long + + :Parameter B: Blinding factor. + :Type B: byte string or long + + :Return: A byte string if M was so. A long otherwise. + """ + wasString=0 + if isinstance(M, types.StringType): + M=bytes_to_long(M) ; wasString=1 + if isinstance(B, types.StringType): B=bytes_to_long(B) + blindedmessage=self._blind(M, B) + if wasString: return long_to_bytes(blindedmessage) + else: return blindedmessage + + def unblind(self, M, B): + """Unblind a message after cryptographic processing. + + :Parameter M: The encoded message to unblind. + :Type M: byte string or long + + :Parameter B: Blinding factor. + :Type B: byte string or long + """ + wasString=0 + if isinstance(M, types.StringType): + M=bytes_to_long(M) ; wasString=1 + if isinstance(B, types.StringType): B=bytes_to_long(B) + unblindedmessage=self._unblind(M, B) + if wasString: return long_to_bytes(unblindedmessage) + else: return unblindedmessage + + + # The following methods will usually be left alone, except for + # signature-only algorithms. They both return Boolean values + # recording whether this key's algorithm can sign and encrypt. + def can_sign (self): + """Tell if the algorithm can deal with cryptographic signatures. + + This property concerns the *algorithm*, not the key itself. + It may happen that this particular key object hasn't got + the private information required to generate a signature. + + :Return: boolean + """ + return 1 + + def can_encrypt (self): + """Tell if the algorithm can deal with data encryption. + + This property concerns the *algorithm*, not the key itself. + It may happen that this particular key object hasn't got + the private information required to decrypt data. + + :Return: boolean + """ + return 1 + + def can_blind (self): + """Tell if the algorithm can deal with data blinding. + + This property concerns the *algorithm*, not the key itself. + It may happen that this particular key object hasn't got + the private information required carry out blinding. + + :Return: boolean + """ + return 0 + + # The following methods will certainly be overridden by + # subclasses. + + def size (self): + """Tell the maximum number of bits that can be handled by this key. + + :Return: int + """ + return 0 + + def has_private (self): + """Tell if the key object contains private components. + + :Return: bool + """ + return 0 + + def publickey (self): + """Construct a new key carrying only the public information. + + :Return: A new `pubkey` object. + """ + return self + + def __eq__ (self, other): + """__eq__(other): 0, 1 + Compare us to other for equality. + """ + return self.__getstate__() == other.__getstate__() + + def __ne__ (self, other): + """__ne__(other): 0, 1 + Compare us to other for inequality. + """ + return not self.__eq__(other) diff --git a/lib/Crypto/Random/Fortuna/FortunaAccumulator.py b/lib/Crypto/Random/Fortuna/FortunaAccumulator.py new file mode 100644 index 0000000..5ffe825 --- /dev/null +++ b/lib/Crypto/Random/Fortuna/FortunaAccumulator.py @@ -0,0 +1,174 @@ +# -*- coding: ascii -*- +# +# FortunaAccumulator.py : Fortuna's internal accumulator +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from binascii import b2a_hex +import time +import warnings + +from Crypto.pct_warnings import ClockRewindWarning +import SHAd256 + +# If the system has monotonic time, we'll use it. +from Crypto.Util._time import maybe_monotonic_time + +import FortunaGenerator + +class FortunaPool(object): + """Fortuna pool type + + This object acts like a hash object, with the following differences: + + - It keeps a count (the .length attribute) of the number of bytes that + have been added to the pool + - It supports a .reset() method for in-place reinitialization + - The method to add bytes to the pool is .append(), not .update(). + """ + + digest_size = SHAd256.digest_size + + def __init__(self): + self.reset() + + def append(self, data): + self._h.update(data) + self.length += len(data) + + def digest(self): + return self._h.digest() + + def hexdigest(self): + if sys.version_info[0] == 2: + return b2a_hex(self.digest()) + else: + return b2a_hex(self.digest()).decode() + + def reset(self): + self._h = SHAd256.new() + self.length = 0 + +def which_pools(r): + """Return a list of pools indexes (in range(32)) that are to be included during reseed number r. + + According to _Practical Cryptography_, chapter 10.5.2 "Pools": + + "Pool P_i is included if 2**i is a divisor of r. Thus P_0 is used + every reseed, P_1 every other reseed, P_2 every fourth reseed, etc." + """ + # This is a separate function so that it can be unit-tested. + assert r >= 1 + retval = [] + mask = 0 + for i in range(32): + # "Pool P_i is included if 2**i is a divisor of [reseed_count]" + if (r & mask) == 0: + retval.append(i) + else: + break # optimization. once this fails, it always fails + mask = (mask << 1) | 1L + return retval + +class FortunaAccumulator(object): + + # An estimate of how many bytes we must append to pool 0 before it will + # contain 128 bits of entropy (with respect to an attack). We reseed the + # generator only after pool 0 contains `min_pool_size` bytes. Note that + # unlike with some other PRNGs, Fortuna's security does not rely on the + # accuracy of this estimate---we can accord to be optimistic here. + min_pool_size = 64 # size in bytes + + # If an attacker can predict some (but not all) of our entropy sources, the + # `min_pool_size` check may not be sufficient to prevent a successful state + # compromise extension attack. To resist this attack, Fortuna spreads the + # input across 32 pools, which are then consumed (to reseed the output + # generator) with exponentially decreasing frequency. + # + # In order to prevent an attacker from gaining knowledge of all 32 pools + # before we have a chance to fill them with enough information that the + # attacker cannot predict, we impose a rate limit of 10 reseeds/second (one + # per 100 ms). This ensures that a hypothetical 33rd pool would only be + # needed after a minimum of 13 years of sustained attack. + reseed_interval = 0.100 # time in seconds + + def __init__(self): + self.reseed_count = 0 + self.generator = FortunaGenerator.AESGenerator() + self.last_reseed = None + + # Initialize 32 FortunaPool instances. + # NB: This is _not_ equivalent to [FortunaPool()]*32, which would give + # us 32 references to the _same_ FortunaPool instance (and cause the + # assertion below to fail). + self.pools = [FortunaPool() for i in range(32)] # 32 pools + assert(self.pools[0] is not self.pools[1]) + + def _forget_last_reseed(self): + # This is not part of the standard Fortuna definition, and using this + # function frequently can weaken Fortuna's ability to resist a state + # compromise extension attack, but we need this in order to properly + # implement Crypto.Random.atfork(). Otherwise, forked child processes + # might continue to use their parent's PRNG state for up to 100ms in + # some cases. (e.g. CVE-2013-1445) + self.last_reseed = None + + def random_data(self, bytes): + current_time = maybe_monotonic_time() + if (self.last_reseed is not None and self.last_reseed > current_time): # Avoid float comparison to None to make Py3k happy + warnings.warn("Clock rewind detected. Resetting last_reseed.", ClockRewindWarning) + self.last_reseed = None + if (self.pools[0].length >= self.min_pool_size and + (self.last_reseed is None or + current_time > self.last_reseed + self.reseed_interval)): + self._reseed(current_time) + # The following should fail if we haven't seeded the pool yet. + return self.generator.pseudo_random_data(bytes) + + def _reseed(self, current_time=None): + if current_time is None: + current_time = maybe_monotonic_time() + seed = [] + self.reseed_count += 1 + self.last_reseed = current_time + for i in which_pools(self.reseed_count): + seed.append(self.pools[i].digest()) + self.pools[i].reset() + + seed = b("").join(seed) + self.generator.reseed(seed) + + def add_random_event(self, source_number, pool_number, data): + assert 1 <= len(data) <= 32 + assert 0 <= source_number <= 255 + assert 0 <= pool_number <= 31 + self.pools[pool_number].append(bchr(source_number)) + self.pools[pool_number].append(bchr(len(data))) + self.pools[pool_number].append(data) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/Fortuna/FortunaGenerator.py b/lib/Crypto/Random/Fortuna/FortunaGenerator.py new file mode 100644 index 0000000..09351fc --- /dev/null +++ b/lib/Crypto/Random/Fortuna/FortunaGenerator.py @@ -0,0 +1,132 @@ +# -*- coding: ascii -*- +# +# FortunaGenerator.py : Fortuna's internal PRNG +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +import struct + +from Crypto.Util.number import ceil_shift, exact_log2, exact_div +from Crypto.Util import Counter +from Crypto.Cipher import AES + +import SHAd256 + +class AESGenerator(object): + """The Fortuna "generator" + + This is used internally by the Fortuna PRNG to generate arbitrary amounts + of pseudorandom data from a smaller amount of seed data. + + The output is generated by running AES-256 in counter mode and re-keying + after every mebibyte (2**16 blocks) of output. + """ + + block_size = AES.block_size # output block size in octets (128 bits) + key_size = 32 # key size in octets (256 bits) + + # Because of the birthday paradox, we expect to find approximately one + # collision for every 2**64 blocks of output from a real random source. + # However, this code generates pseudorandom data by running AES in + # counter mode, so there will be no collisions until the counter + # (theoretically) wraps around at 2**128 blocks. Thus, in order to prevent + # Fortuna's pseudorandom output from deviating perceptibly from a true + # random source, Ferguson and Schneier specify a limit of 2**16 blocks + # without rekeying. + max_blocks_per_request = 2**16 # Allow no more than this number of blocks per _pseudo_random_data request + + _four_kiblocks_of_zeros = b("\0") * block_size * 4096 + + def __init__(self): + self.counter = Counter.new(nbits=self.block_size*8, initial_value=0, little_endian=True) + self.key = None + + # Set some helper constants + self.block_size_shift = exact_log2(self.block_size) + assert (1 << self.block_size_shift) == self.block_size + + self.blocks_per_key = exact_div(self.key_size, self.block_size) + assert self.key_size == self.blocks_per_key * self.block_size + + self.max_bytes_per_request = self.max_blocks_per_request * self.block_size + + def reseed(self, seed): + if self.key is None: + self.key = b("\0") * self.key_size + + self._set_key(SHAd256.new(self.key + seed).digest()) + self.counter() # increment counter + assert len(self.key) == self.key_size + + def pseudo_random_data(self, bytes): + assert bytes >= 0 + + num_full_blocks = bytes >> 20 + remainder = bytes & ((1<<20)-1) + + retval = [] + for i in xrange(num_full_blocks): + retval.append(self._pseudo_random_data(1<<20)) + retval.append(self._pseudo_random_data(remainder)) + + return b("").join(retval) + + def _set_key(self, key): + self.key = key + self._cipher = AES.new(key, AES.MODE_CTR, counter=self.counter) + + def _pseudo_random_data(self, bytes): + if not (0 <= bytes <= self.max_bytes_per_request): + raise AssertionError("You cannot ask for more than 1 MiB of data per request") + + num_blocks = ceil_shift(bytes, self.block_size_shift) # num_blocks = ceil(bytes / self.block_size) + + # Compute the output + retval = self._generate_blocks(num_blocks)[:bytes] + + # Switch to a new key to avoid later compromises of this output (i.e. + # state compromise extension attacks) + self._set_key(self._generate_blocks(self.blocks_per_key)) + + assert len(retval) == bytes + assert len(self.key) == self.key_size + + return retval + + def _generate_blocks(self, num_blocks): + if self.key is None: + raise AssertionError("generator must be seeded before use") + assert 0 <= num_blocks <= self.max_blocks_per_request + retval = [] + for i in xrange(num_blocks >> 12): # xrange(num_blocks / 4096) + retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros)) + remaining_bytes = (num_blocks & 4095) << self.block_size_shift # (num_blocks % 4095) * self.block_size + retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros[:remaining_bytes])) + return b("").join(retval) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/Fortuna/SHAd256.py b/lib/Crypto/Random/Fortuna/SHAd256.py new file mode 100644 index 0000000..2e135c9 --- /dev/null +++ b/lib/Crypto/Random/Fortuna/SHAd256.py @@ -0,0 +1,98 @@ +# -*- coding: ascii -*- +# +# Random/Fortuna/SHAd256.py : SHA_d-256 hash function implementation +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""\ +SHA_d-256 hash function implementation. + +This module should comply with PEP 247. +""" + +__revision__ = "$Id$" +__all__ = ['new', 'digest_size'] + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from binascii import b2a_hex + +from Crypto.Hash import SHA256 + +assert SHA256.digest_size == 32 + +class _SHAd256(object): + """SHA-256, doubled. + + Returns SHA-256(SHA-256(data)). + """ + + digest_size = SHA256.digest_size + + _internal = object() + + def __init__(self, internal_api_check, sha256_hash_obj): + if internal_api_check is not self._internal: + raise AssertionError("Do not instantiate this class directly. Use %s.new()" % (__name__,)) + self._h = sha256_hash_obj + + # PEP 247 "copy" method + def copy(self): + """Return a copy of this hashing object""" + return _SHAd256(SHAd256._internal, self._h.copy()) + + # PEP 247 "digest" method + def digest(self): + """Return the hash value of this object as a binary string""" + retval = SHA256.new(self._h.digest()).digest() + assert len(retval) == 32 + return retval + + # PEP 247 "hexdigest" method + def hexdigest(self): + """Return the hash value of this object as a (lowercase) hexadecimal string""" + retval = b2a_hex(self.digest()) + assert len(retval) == 64 + if sys.version_info[0] == 2: + return retval + else: + return retval.decode() + + # PEP 247 "update" method + def update(self, data): + self._h.update(data) + +# PEP 247 module-level "digest_size" variable +digest_size = _SHAd256.digest_size + +# PEP 247 module-level "new" function +def new(data=None): + """Return a new SHAd256 hashing object""" + if not data: + data=b("") + sha = _SHAd256(_SHAd256._internal, SHA256.new(data)) + sha.new = globals()['new'] + return sha + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/Fortuna/__init__.py b/lib/Crypto/Random/Fortuna/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/Crypto/Random/Fortuna/__init__.py diff --git a/lib/Crypto/Random/OSRNG/__init__.py b/lib/Crypto/Random/OSRNG/__init__.py new file mode 100644 index 0000000..2fbbecb --- /dev/null +++ b/lib/Crypto/Random/OSRNG/__init__.py @@ -0,0 +1,40 @@ +# +# Random/OSRNG/__init__.py : Platform-independent OS RNG API +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Provides a platform-independent interface to the random number generators +supplied by various operating systems.""" + +__revision__ = "$Id$" + +import os + +if os.name == 'posix': + from Crypto.Random.OSRNG.posix import new +elif os.name == 'nt': + from Crypto.Random.OSRNG.nt import new +elif hasattr(os, 'urandom'): + from Crypto.Random.OSRNG.fallback import new +else: + raise ImportError("Not implemented") + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/OSRNG/fallback.py b/lib/Crypto/Random/OSRNG/fallback.py new file mode 100644 index 0000000..5bb6126 --- /dev/null +++ b/lib/Crypto/Random/OSRNG/fallback.py @@ -0,0 +1,46 @@ +# +# Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + + +__revision__ = "$Id$" +__all__ = ['PythonOSURandomRNG'] + +import os + +from rng_base import BaseRNG + +class PythonOSURandomRNG(BaseRNG): + + name = "<os.urandom>" + + def __init__(self): + self._read = os.urandom + BaseRNG.__init__(self) + + def _close(self): + self._read = None + +def new(*args, **kwargs): + return PythonOSURandomRNG(*args, **kwargs) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/OSRNG/nt.py b/lib/Crypto/Random/OSRNG/nt.py new file mode 100644 index 0000000..40aa495 --- /dev/null +++ b/lib/Crypto/Random/OSRNG/nt.py @@ -0,0 +1,74 @@ +# +# Random/OSRNG/nt.py : OS entropy source for MS Windows +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + + +__revision__ = "$Id$" +__all__ = ['WindowsRNG'] + +from Crypto.Random.OSRNG import winrandom +from rng_base import BaseRNG + +class WindowsRNG(BaseRNG): + + name = "<CryptGenRandom>" + + def __init__(self): + self.__winrand = winrandom.new() + BaseRNG.__init__(self) + + def flush(self): + """Work around weakness in Windows RNG. + + The CryptGenRandom mechanism in some versions of Windows allows an + attacker to learn 128 KiB of past and future output. As a workaround, + this function reads 128 KiB of 'random' data from Windows and discards + it. + + For more information about the weaknesses in CryptGenRandom, see + _Cryptanalysis of the Random Number Generator of the Windows Operating + System_, by Leo Dorrendorf and Zvi Gutterman and Benny Pinkas + http://eprint.iacr.org/2007/419 + """ + if self.closed: + raise ValueError("I/O operation on closed file") + data = self.__winrand.get_bytes(128*1024) + assert (len(data) == 128*1024) + BaseRNG.flush(self) + + def _close(self): + self.__winrand = None + + def _read(self, N): + # Unfortunately, research shows that CryptGenRandom doesn't provide + # forward secrecy and fails the next-bit test unless we apply a + # workaround, which we do here. See http://eprint.iacr.org/2007/419 + # for information on the vulnerability. + self.flush() + data = self.__winrand.get_bytes(N) + self.flush() + return data + +def new(*args, **kwargs): + return WindowsRNG(*args, **kwargs) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/OSRNG/posix.py b/lib/Crypto/Random/OSRNG/posix.py new file mode 100644 index 0000000..ca6ac05 --- /dev/null +++ b/lib/Crypto/Random/OSRNG/posix.py @@ -0,0 +1,86 @@ +# +# Random/OSRNG/posix.py : OS entropy source for POSIX systems +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + + +__revision__ = "$Id$" +__all__ = ['DevURandomRNG'] + +import errno +import os +import stat + +from rng_base import BaseRNG +from Crypto.Util.py3compat import b + +class DevURandomRNG(BaseRNG): + + def __init__(self, devname=None): + if devname is None: + self.name = "/dev/urandom" + else: + self.name = devname + + # Test that /dev/urandom is a character special device + f = open(self.name, "rb", 0) + fmode = os.fstat(f.fileno())[stat.ST_MODE] + if not stat.S_ISCHR(fmode): + f.close() + raise TypeError("%r is not a character special device" % (self.name,)) + + self.__file = f + + BaseRNG.__init__(self) + + def _close(self): + self.__file.close() + + def _read(self, N): + # Starting with Python 3 open with buffering=0 returns a FileIO object. + # FileIO.read behaves like read(2) and not like fread(3) and thus we + # have to handle the case that read returns less data as requested here + # more carefully. + data = b("") + while len(data) < N: + try: + d = self.__file.read(N - len(data)) + except IOError, e: + # read(2) has been interrupted by a signal; redo the read + if e.errno == errno.EINTR: + continue + raise + + if d is None: + # __file is in non-blocking mode and no data is available + return data + if len(d) == 0: + # __file is in blocking mode and arrived at EOF + return data + + data += d + return data + +def new(*args, **kwargs): + return DevURandomRNG(*args, **kwargs) + + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/OSRNG/rng_base.py b/lib/Crypto/Random/OSRNG/rng_base.py new file mode 100644 index 0000000..54c3aa0 --- /dev/null +++ b/lib/Crypto/Random/OSRNG/rng_base.py @@ -0,0 +1,88 @@ +# +# Random/OSRNG/rng_base.py : Base class for OSRNG +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +class BaseRNG(object): + + def __init__(self): + self.closed = False + self._selftest() + + def __del__(self): + self.close() + + def _selftest(self): + # Test that urandom can return data + data = self.read(16) + if len(data) != 16: + raise AssertionError("read truncated") + + # Test that we get different data every time (if we don't, the RNG is + # probably malfunctioning) + data2 = self.read(16) + if data == data2: + raise AssertionError("OS RNG returned duplicate data") + + # PEP 343: Support for the "with" statement + def __enter__(self): + pass + def __exit__(self): + """PEP 343 support""" + self.close() + + def close(self): + if not self.closed: + self._close() + self.closed = True + + def flush(self): + pass + + def read(self, N=-1): + """Return N bytes from the RNG.""" + if self.closed: + raise ValueError("I/O operation on closed file") + if not isinstance(N, (long, int)): + raise TypeError("an integer is required") + if N < 0: + raise ValueError("cannot read to end of infinite stream") + elif N == 0: + return "" + data = self._read(N) + if len(data) != N: + raise AssertionError("%s produced truncated output (requested %d, got %d)" % (self.name, N, len(data))) + return data + + def _close(self): + raise NotImplementedError("child class must implement this") + + def _read(self, N): + raise NotImplementedError("child class must implement this") + + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/_UserFriendlyRNG.py b/lib/Crypto/Random/_UserFriendlyRNG.py new file mode 100644 index 0000000..957e006 --- /dev/null +++ b/lib/Crypto/Random/_UserFriendlyRNG.py @@ -0,0 +1,230 @@ +# -*- coding: utf-8 -*- +# +# Random/_UserFriendlyRNG.py : A user-friendly random number generator +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +import os +import threading +import struct +import time +from math import floor + +from Crypto.Random import OSRNG +from Crypto.Random.Fortuna import FortunaAccumulator + +class _EntropySource(object): + def __init__(self, accumulator, src_num): + self._fortuna = accumulator + self._src_num = src_num + self._pool_num = 0 + + def feed(self, data): + self._fortuna.add_random_event(self._src_num, self._pool_num, data) + self._pool_num = (self._pool_num + 1) & 31 + +class _EntropyCollector(object): + + def __init__(self, accumulator): + self._osrng = OSRNG.new() + self._osrng_es = _EntropySource(accumulator, 255) + self._time_es = _EntropySource(accumulator, 254) + self._clock_es = _EntropySource(accumulator, 253) + + def reinit(self): + # Add 256 bits to each of the 32 pools, twice. (For a total of 16384 + # bits collected from the operating system.) + for i in range(2): + block = self._osrng.read(32*32) + for p in range(32): + self._osrng_es.feed(block[p*32:(p+1)*32]) + block = None + self._osrng.flush() + + def collect(self): + # Collect 64 bits of entropy from the operating system and feed it to Fortuna. + self._osrng_es.feed(self._osrng.read(8)) + + # Add the fractional part of time.time() + t = time.time() + self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t))))) + + # Add the fractional part of time.clock() + t = time.clock() + self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t))))) + + +class _UserFriendlyRNG(object): + + def __init__(self): + self.closed = False + self._fa = FortunaAccumulator.FortunaAccumulator() + self._ec = _EntropyCollector(self._fa) + self.reinit() + + def reinit(self): + """Initialize the random number generator and seed it with entropy from + the operating system. + """ + + # Save the pid (helps ensure that Crypto.Random.atfork() gets called) + self._pid = os.getpid() + + # Collect entropy from the operating system and feed it to + # FortunaAccumulator + self._ec.reinit() + + # Override FortunaAccumulator's 100ms minimum re-seed interval. This + # is necessary to avoid a race condition between this function and + # self.read(), which that can otherwise cause forked child processes to + # produce identical output. (e.g. CVE-2013-1445) + # + # Note that if this function can be called frequently by an attacker, + # (and if the bits from OSRNG are insufficiently random) it will weaken + # Fortuna's ability to resist a state compromise extension attack. + self._fa._forget_last_reseed() + + def close(self): + self.closed = True + self._osrng = None + self._fa = None + + def flush(self): + pass + + def read(self, N): + """Return N bytes from the RNG.""" + if self.closed: + raise ValueError("I/O operation on closed file") + if not isinstance(N, (long, int)): + raise TypeError("an integer is required") + if N < 0: + raise ValueError("cannot read to end of infinite stream") + + # Collect some entropy and feed it to Fortuna + self._ec.collect() + + # Ask Fortuna to generate some bytes + retval = self._fa.random_data(N) + + # Check that we haven't forked in the meantime. (If we have, we don't + # want to use the data, because it might have been duplicated in the + # parent process. + self._check_pid() + + # Return the random data. + return retval + + def _check_pid(self): + # Lame fork detection to remind developers to invoke Random.atfork() + # after every call to os.fork(). Note that this check is not reliable, + # since process IDs can be reused on most operating systems. + # + # You need to do Random.atfork() in the child process after every call + # to os.fork() to avoid reusing PRNG state. If you want to avoid + # leaking PRNG state to child processes (for example, if you are using + # os.setuid()) then you should also invoke Random.atfork() in the + # *parent* process. + if os.getpid() != self._pid: + raise AssertionError("PID check failed. RNG must be re-initialized after fork(). Hint: Try Random.atfork()") + + +class _LockingUserFriendlyRNG(_UserFriendlyRNG): + def __init__(self): + self._lock = threading.Lock() + _UserFriendlyRNG.__init__(self) + + def close(self): + self._lock.acquire() + try: + return _UserFriendlyRNG.close(self) + finally: + self._lock.release() + + def reinit(self): + self._lock.acquire() + try: + return _UserFriendlyRNG.reinit(self) + finally: + self._lock.release() + + def read(self, bytes): + self._lock.acquire() + try: + return _UserFriendlyRNG.read(self, bytes) + finally: + self._lock.release() + +class RNGFile(object): + def __init__(self, singleton): + self.closed = False + self._singleton = singleton + + # PEP 343: Support for the "with" statement + def __enter__(self): + """PEP 343 support""" + def __exit__(self): + """PEP 343 support""" + self.close() + + def close(self): + # Don't actually close the singleton, just close this RNGFile instance. + self.closed = True + self._singleton = None + + def read(self, bytes): + if self.closed: + raise ValueError("I/O operation on closed file") + return self._singleton.read(bytes) + + def flush(self): + if self.closed: + raise ValueError("I/O operation on closed file") + +_singleton_lock = threading.Lock() +_singleton = None +def _get_singleton(): + global _singleton + _singleton_lock.acquire() + try: + if _singleton is None: + _singleton = _LockingUserFriendlyRNG() + return _singleton + finally: + _singleton_lock.release() + +def new(): + return RNGFile(_get_singleton()) + +def reinit(): + _get_singleton().reinit() + +def get_random_bytes(n): + """Return the specified number of cryptographically-strong random bytes.""" + return _get_singleton().read(n) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/__init__.py b/lib/Crypto/Random/__init__.py new file mode 100644 index 0000000..659ffee --- /dev/null +++ b/lib/Crypto/Random/__init__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# +# Random/__init__.py : PyCrypto random number generation +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" +__all__ = ['new'] + +from Crypto.Random import OSRNG +from Crypto.Random import _UserFriendlyRNG + +def new(*args, **kwargs): + """Return a file-like object that outputs cryptographically random bytes.""" + return _UserFriendlyRNG.new(*args, **kwargs) + +def atfork(): + """Call this whenever you call os.fork()""" + _UserFriendlyRNG.reinit() + +def get_random_bytes(n): + """Return the specified number of cryptographically-strong random bytes.""" + return _UserFriendlyRNG.get_random_bytes(n) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Random/random.py b/lib/Crypto/Random/random.py new file mode 100644 index 0000000..6b1c57a --- /dev/null +++ b/lib/Crypto/Random/random.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +# +# Random/random.py : Strong alternative for the standard 'random' module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""A cryptographically strong version of Python's standard "random" module.""" + +__revision__ = "$Id$" +__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] + +from Crypto import Random +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +class StrongRandom(object): + def __init__(self, rng=None, randfunc=None): + if randfunc is None and rng is None: + self._randfunc = None + elif randfunc is not None and rng is None: + self._randfunc = randfunc + elif randfunc is None and rng is not None: + self._randfunc = rng.read + else: + raise ValueError("Cannot specify both 'rng' and 'randfunc'") + + def getrandbits(self, k): + """Return a python long integer with k random bits.""" + if self._randfunc is None: + self._randfunc = Random.new().read + mask = (1L << k) - 1 + return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) + + def randrange(self, *args): + """randrange([start,] stop[, step]): + Return a randomly-selected element from range(start, stop, step).""" + if len(args) == 3: + (start, stop, step) = args + elif len(args) == 2: + (start, stop) = args + step = 1 + elif len(args) == 1: + (stop,) = args + start = 0 + step = 1 + else: + raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) + if (not isinstance(start, (int, long)) + or not isinstance(stop, (int, long)) + or not isinstance(step, (int, long))): + raise TypeError("randrange requires integer arguments") + if step == 0: + raise ValueError("randrange step argument must not be zero") + + num_choices = ceil_div(stop - start, step) + if num_choices < 0: + num_choices = 0 + if num_choices < 1: + raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step)) + + # Pick a random number in the range of possible numbers + r = num_choices + while r >= num_choices: + r = self.getrandbits(size(num_choices)) + + return start + (step * r) + + def randint(self, a, b): + """Return a random integer N such that a <= N <= b.""" + if not isinstance(a, (int, long)) or not isinstance(b, (int, long)): + raise TypeError("randint requires integer arguments") + N = self.randrange(a, b+1) + assert a <= N <= b + return N + + def choice(self, seq): + """Return a random element from a (non-empty) sequence. + + If the seqence is empty, raises IndexError. + """ + if len(seq) == 0: + raise IndexError("empty sequence") + return seq[self.randrange(len(seq))] + + def shuffle(self, x): + """Shuffle the sequence in place.""" + # Fisher-Yates shuffle. O(n) + # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + # Working backwards from the end of the array, we choose a random item + # from the remaining items until all items have been chosen. + for i in xrange(len(x)-1, 0, -1): # iterate from len(x)-1 downto 1 + j = self.randrange(0, i+1) # choose random j such that 0 <= j <= i + x[i], x[j] = x[j], x[i] # exchange x[i] and x[j] + + def sample(self, population, k): + """Return a k-length list of unique elements chosen from the population sequence.""" + + num_choices = len(population) + if k > num_choices: + raise ValueError("sample larger than population") + + retval = [] + selected = {} # we emulate a set using a dict here + for i in xrange(k): + r = None + while r is None or selected.has_key(r): + r = self.randrange(num_choices) + retval.append(population[r]) + selected[r] = 1 + return retval + +_r = StrongRandom() +getrandbits = _r.getrandbits +randrange = _r.randrange +randint = _r.randint +choice = _r.choice +shuffle = _r.shuffle +sample = _r.sample + +# These are at the bottom to avoid problems with recursive imports +from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes, size + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/__init__.py b/lib/Crypto/SelfTest/Cipher/__init__.py new file mode 100644 index 0000000..63e9c57 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/__init__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/__init__.py: Self-test for cipher modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for cipher modules""" + +__revision__ = "$Id$" + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.Cipher import test_AES; tests += test_AES.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_ARC2; tests += test_ARC2.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_ARC4; tests += test_ARC4.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_Blowfish; tests += test_Blowfish.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_CAST; tests += test_CAST.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_DES3; tests += test_DES3.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_DES; tests += test_DES.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_XOR; tests += test_XOR.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config) + from Crypto.SelfTest.Cipher import test_pkcs1_oaep; tests += test_pkcs1_oaep.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/common.py b/lib/Crypto/SelfTest/Cipher/common.py new file mode 100644 index 0000000..a5f8a88 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/common.py @@ -0,0 +1,811 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-testing for PyCrypto hash modules""" + +from __future__ import nested_scopes + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +import unittest +from binascii import a2b_hex, b2a_hex, hexlify + +from Crypto.Util.py3compat import * +from Crypto.Util.strxor import strxor_c + +# For compatibility with Python 2.1 and Python 2.2 +if sys.hexversion < 0x02030000: + # Python 2.1 doesn't have a dict() function + # Python 2.2 dict() function raises TypeError if you do dict(MD5='blah') + def dict(**kwargs): + return kwargs.copy() +else: + dict = dict + +class _NoDefault: pass # sentinel object +def _extract(d, k, default=_NoDefault): + """Get an item from a dictionary, and remove it from the dictionary.""" + try: + retval = d[k] + except KeyError: + if default is _NoDefault: + raise + return default + del d[k] + return retval + +# Generic cipher test case +class CipherSelfTest(unittest.TestCase): + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + + # Extract the parameters + params = params.copy() + self.description = _extract(params, 'description') + self.key = b(_extract(params, 'key')) + self.plaintext = b(_extract(params, 'plaintext')) + self.ciphertext = b(_extract(params, 'ciphertext')) + self.module_name = _extract(params, 'module_name', None) + self.assoc_data = _extract(params, 'assoc_data', None) + self.mac = _extract(params, 'mac', None) + if self.assoc_data: + self.mac = b(self.mac) + + mode = _extract(params, 'mode', None) + self.mode_name = str(mode) + if mode is not None: + # Block cipher + self.mode = getattr(self.module, "MODE_" + mode) + + self.iv = _extract(params, 'iv', None) + if self.iv is None: + self.iv = _extract(params, 'nonce', None) + if self.iv is not None: + self.iv = b(self.iv) + + # Only relevant for OPENPGP mode + self.encrypted_iv = _extract(params, 'encrypted_iv', None) + if self.encrypted_iv is not None: + self.encrypted_iv = b(self.encrypted_iv) + else: + # Stream cipher + self.mode = None + self.iv = None + + self.extra_params = params + + def shortDescription(self): + return self.description + + def _new(self, do_decryption=0): + params = self.extra_params.copy() + + # Handle CTR mode parameters. By default, we use Counter.new(self.module.block_size) + if hasattr(self.module, "MODE_CTR") and self.mode == self.module.MODE_CTR: + from Crypto.Util import Counter + ctr_class = _extract(params, 'ctr_class', Counter.new) + ctr_params = _extract(params, 'ctr_params', {}).copy() + if ctr_params.has_key('prefix'): ctr_params['prefix'] = a2b_hex(b(ctr_params['prefix'])) + if ctr_params.has_key('suffix'): ctr_params['suffix'] = a2b_hex(b(ctr_params['suffix'])) + if not ctr_params.has_key('nbits'): + ctr_params['nbits'] = 8*(self.module.block_size - len(ctr_params.get('prefix', '')) - len(ctr_params.get('suffix', ''))) + params['counter'] = ctr_class(**ctr_params) + + if self.mode is None: + # Stream cipher + return self.module.new(a2b_hex(self.key), **params) + elif self.iv is None: + # Block cipher without iv + return self.module.new(a2b_hex(self.key), self.mode, **params) + else: + # Block cipher with iv + if do_decryption and self.mode == self.module.MODE_OPENPGP: + # In PGP mode, the IV to feed for decryption is the *encrypted* one + return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.encrypted_iv), **params) + else: + return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.iv), **params) + + def isMode(self, name): + if not hasattr(self.module, "MODE_"+name): + return False + return self.mode == getattr(self.module, "MODE_"+name) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + assoc_data = [] + if self.assoc_data: + assoc_data = [ a2b_hex(b(x)) for x in self.assoc_data] + + ct = None + pt = None + + # + # Repeat the same encryption or decryption twice and verify + # that the result is always the same + # + for i in xrange(2): + cipher = self._new() + decipher = self._new(1) + + # Only AEAD modes + for comp in assoc_data: + cipher.update(comp) + decipher.update(comp) + + ctX = b2a_hex(cipher.encrypt(plaintext)) + if self.isMode("SIV"): + ptX = b2a_hex(decipher.decrypt_and_verify(ciphertext, a2b_hex(self.mac))) + else: + ptX = b2a_hex(decipher.decrypt(ciphertext)) + + if ct: + self.assertEqual(ct, ctX) + self.assertEqual(pt, ptX) + ct, pt = ctX, ptX + + if self.isMode("OPENPGP"): + # In PGP mode, data returned by the first encrypt() + # is prefixed with the encrypted IV. + # Here we check it and then remove it from the ciphertexts. + eilen = len(self.encrypted_iv) + self.assertEqual(self.encrypted_iv, ct[:eilen]) + ct = ct[eilen:] + + self.assertEqual(self.ciphertext, ct) # encrypt + self.assertEqual(self.plaintext, pt) # decrypt + + if self.mac: + mac = b2a_hex(cipher.digest()) + self.assertEqual(self.mac, mac) + decipher.verify(a2b_hex(self.mac)) + +class CipherStreamingSelfTest(CipherSelfTest): + + def shortDescription(self): + desc = self.module_name + if self.mode is not None: + desc += " in %s mode" % (self.mode_name,) + return "%s should behave like a stream cipher" % (desc,) + + def runTest(self): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + + # The cipher should work like a stream cipher + + # Test counter mode encryption, 3 bytes at a time + ct3 = [] + cipher = self._new() + for i in range(0, len(plaintext), 3): + ct3.append(cipher.encrypt(plaintext[i:i+3])) + ct3 = b2a_hex(b("").join(ct3)) + self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time) + + # Test counter mode decryption, 3 bytes at a time + pt3 = [] + cipher = self._new() + for i in range(0, len(ciphertext), 3): + pt3.append(cipher.encrypt(ciphertext[i:i+3])) + # PY3K: This is meant to be text, do not change to bytes (data) + pt3 = b2a_hex(b("").join(pt3)) + self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time) + +class CTRSegfaultTest(unittest.TestCase): + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params['key']) + self.module_name = params.get('module_name', None) + + def shortDescription(self): + return """Regression test: %s.new(key, %s.MODE_CTR) should raise TypeError, not segfault""" % (self.module_name, self.module_name) + + def runTest(self): + self.assertRaises(TypeError, self.module.new, a2b_hex(self.key), self.module.MODE_CTR) + +class CTRWraparoundTest(unittest.TestCase): + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params['key']) + self.module_name = params.get('module_name', None) + + def shortDescription(self): + return """Regression test: %s with MODE_CTR raising OverflowError on wraparound""" % (self.module_name,) + + def runTest(self): + from Crypto.Util import Counter + + def pythonCounter(): + state = [0] + def ctr(): + # First block succeeds; Second and subsequent blocks raise OverflowError + if state[0] == 0: + state[0] = 1 + return b("\xff") * self.module.block_size + else: + raise OverflowError + return ctr + + for little_endian in (0, 1): # (False, True) Test both endiannesses + block = b("\x00") * self.module.block_size + + # Test PyObject_CallObject code path: if the counter raises OverflowError + cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=pythonCounter()) + cipher.encrypt(block) + self.assertRaises(OverflowError, cipher.encrypt, block) + self.assertRaises(OverflowError, cipher.encrypt, block) + + # Test PyObject_CallObject code path: counter object should raise OverflowError + ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian) + ctr() + self.assertRaises(OverflowError, ctr) + self.assertRaises(OverflowError, ctr) + + # Test the CTR-mode shortcut + ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian) + cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr) + cipher.encrypt(block) + self.assertRaises(OverflowError, cipher.encrypt, block) + self.assertRaises(OverflowError, cipher.encrypt, block) + +class CFBSegmentSizeTest(unittest.TestCase): + + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params['key']) + self.description = params['description'] + + def shortDescription(self): + return self.description + + def runTest(self): + """Regression test: m.new(key, m.MODE_CFB, segment_size=N) should require segment_size to be a multiple of 8 bits""" + for i in range(1, 8): + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), self.module.MODE_CFB, segment_size=i) + self.module.new(a2b_hex(self.key), self.module.MODE_CFB, "\0"*self.module.block_size, segment_size=8) # should succeed + +class CCMMACLengthTest(unittest.TestCase): + """CCM specific tests about MAC""" + + def __init__(self, module): + unittest.TestCase.__init__(self) + self.module = module + self.key = b('\xFF')*16 + self.iv = b('\x00')*10 + + def shortDescription(self): + return self.description + + def runTest(self): + """Verify that MAC can only be 4,6,8,..,16 bytes long.""" + for i in range(3,16,2): + self.description = "CCM MAC length check (%d bytes)" % i + self.assertRaises(ValueError, self.module.new, self.key, + self.module.MODE_CCM, self.iv, msg_len=10, mac_len=i) + + """Verify that default MAC length is 16.""" + self.description = "CCM default MAC length check" + cipher = self.module.new(self.key, self.module.MODE_CCM, + self.iv, msg_len=4) + cipher.encrypt(b('z')*4) + self.assertEqual(len(cipher.digest()), 16) + +class CCMSplitEncryptionTest(unittest.TestCase): + """CCM specific tests to validate how encrypt() + decrypt() can be called multiple times on the + same object.""" + + def __init__(self, module): + unittest.TestCase.__init__(self) + self.module = module + self.key = b('\xFF')*16 + self.iv = b('\x00')*10 + self.description = "CCM Split Encryption Test" + + def shortDescription(self): + return self.description + + def runTest(self): + """Verify that CCM update()/encrypt() can be called multiple times, + provided that lengths are declared beforehand""" + + data = b("AUTH DATA") + pt1 = b("PLAINTEXT1") # Short + pt2 = b("PLAINTEXT2") # Long + pt_ref = pt1+pt2 + + # REFERENCE: Run with 1 update() and 1 encrypt() + cipher = self.module.new(self.key, self.module.MODE_CCM, + self.iv) + cipher.update(data) + ct_ref = cipher.encrypt(pt_ref) + mac_ref = cipher.digest() + + # Verify that calling CCM encrypt()/decrypt() twice is not + # possible without the 'msg_len' parameter and regardless + # of the 'assoc_len' parameter + for ad_len in None, len(data): + cipher = self.module.new(self.key, self.module.MODE_CCM, + self.iv, assoc_len=ad_len) + cipher.update(data) + cipher.encrypt(pt1) + self.assertRaises(TypeError, cipher.encrypt, pt2) + + cipher = self.module.new(self.key, self.module.MODE_CCM, + self.iv, assoc_len=ad_len) + cipher.update(data) + cipher.decrypt(ct_ref[:len(pt1)]) + self.assertRaises(TypeError, cipher.decrypt, ct_ref[len(pt1):]) + + # Run with 2 encrypt()/decrypt(). Results must be the same + # regardless of the 'assoc_len' parameter + for ad_len in None, len(data): + cipher = self.module.new(self.key, self.module.MODE_CCM, + self.iv, assoc_len=ad_len, msg_len=len(pt_ref)) + cipher.update(data) + ct = cipher.encrypt(pt1) + ct += cipher.encrypt(pt2) + mac = cipher.digest() + self.assertEqual(ct_ref, ct) + self.assertEqual(mac_ref, mac) + + cipher = self.module.new(self.key, self.module.MODE_CCM, + self.iv, msg_len=len(pt1+pt2)) + cipher.update(data) + pt = cipher.decrypt(ct[:len(pt1)]) + pt += cipher.decrypt(ct[len(pt1):]) + mac = cipher.verify(mac_ref) + self.assertEqual(pt_ref, pt) + +class AEADTests(unittest.TestCase): + """Tests generic to all AEAD modes""" + + def __init__(self, module, mode_name, key_size): + unittest.TestCase.__init__(self) + self.module = module + self.mode_name = mode_name + self.mode = getattr(module, mode_name) + if not self.isMode("SIV"): + self.key = b('\xFF')*key_size + else: + self.key = b('\xFF')*key_size*2 + self.iv = b('\x00')*10 + self.description = "AEAD Test" + + def isMode(self, name): + if not hasattr(self.module, "MODE_"+name): + return False + return self.mode == getattr(self.module, "MODE_"+name) + + def right_mac_test(self): + """Positive tests for MAC""" + + self.description = "Test for right MAC in %s of %s" % \ + (self.mode_name, self.module.__name__) + + ad_ref = b("Reference AD") + pt_ref = b("Reference plaintext") + + # Encrypt and create the reference MAC + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.update(ad_ref) + ct_ref = cipher.encrypt(pt_ref) + mac_ref = cipher.digest() + + # Decrypt and verify that MAC is accepted + decipher = self.module.new(self.key, self.mode, self.iv) + decipher.update(ad_ref) + pt = decipher.decrypt_and_verify(ct_ref, mac_ref) + self.assertEqual(pt, pt_ref) + + # Verify that hexverify work + decipher.hexverify(hexlify(mac_ref)) + + def wrong_mac_test(self): + """Negative tests for MAC""" + + self.description = "Test for wrong MAC in %s of %s" % \ + (self.mode_name, self.module.__name__) + + ad_ref = b("Reference AD") + pt_ref = b("Reference plaintext") + + # Encrypt and create the reference MAC + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.update(ad_ref) + ct_ref = cipher.encrypt(pt_ref) + mac_ref = cipher.digest() + + # Modify the MAC and verify it is NOT ACCEPTED + wrong_mac = strxor_c(mac_ref, 255) + decipher = self.module.new(self.key, self.mode, self.iv) + decipher.update(ad_ref) + self.assertRaises(ValueError, decipher.decrypt_and_verify, + ct_ref, wrong_mac) + + def zero_data(self): + """Verify transition from INITIALIZED to FINISHED""" + + self.description = "Test for zero data in %s of %s" % \ + (self.mode_name, self.module.__name__) + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.digest() + + def multiple_updates(self): + """Verify that update() can be called multiple times""" + + self.description = "Test for multiple updates in %s of %s" % \ + (self.mode_name, self.module.__name__) + + # In all modes other than SIV, the associated data is a single + # component that can be arbitrarilly split and submitted to update(). + # + # In SIV, associated data is instead organized in a vector or multiple + # components. Each component is passed to update() as a whole. + # This test is therefore not meaningful to SIV. + if self.isMode("SIV"): + return + + ad = b("").join([bchr(x) for x in xrange(0,128)]) + + mac1, mac2, mac3 = (None,)*3 + for chunk_length in 1,10,40,80,128: + chunks = [ad[i:i+chunk_length] for i in range(0, len(ad), chunk_length)] + + # No encryption/decryption + cipher = self.module.new(self.key, self.mode, self.iv) + for c in chunks: + cipher.update(c) + if mac1: + cipher.verify(mac1) + else: + mac1 = cipher.digest() + + # Encryption + cipher = self.module.new(self.key, self.mode, self.iv) + for c in chunks: + cipher.update(c) + ct = cipher.encrypt(b("PT")) + mac2 = cipher.digest() + + # Decryption + cipher = self.module.new(self.key, self.mode, self.iv) + for c in chunks: + cipher.update(c) + cipher.decrypt(ct) + cipher.verify(mac2) + + def no_mix_encrypt_decrypt(self): + """Verify that encrypt and decrypt cannot be mixed up""" + + self.description = "Test for mix of encrypt and decrypt in %s of %s" % \ + (self.mode_name, self.module.__name__) + + # Calling decrypt after encrypt raises an exception + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.encrypt(b("PT")*40) + self.assertRaises(TypeError, cipher.decrypt, b("XYZ")*40) + + # Calling encrypt() after decrypt() raises an exception + # (excluded for SIV, since decrypt() is not valid) + if not self.isMode("SIV"): + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.decrypt(b("CT")*40) + self.assertRaises(TypeError, cipher.encrypt, b("XYZ")*40) + + # Calling verify after encrypt raises an exception + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.encrypt(b("PT")*40) + self.assertRaises(TypeError, cipher.verify, b("XYZ")) + self.assertRaises(TypeError, cipher.hexverify, "12") + + # Calling digest() after decrypt() raises an exception + # (excluded for SIV, since decrypt() is not valid) + if not self.isMode("SIV"): + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.decrypt(b("CT")*40) + self.assertRaises(TypeError, cipher.digest) + self.assertRaises(TypeError, cipher.hexdigest) + + def no_late_update(self): + """Verify that update cannot be called after encrypt or decrypt""" + + self.description = "Test for late update in %s of %s" % \ + (self.mode_name, self.module.__name__) + + # Calling update after encrypt raises an exception + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.update(b("XX")) + cipher.encrypt(b("PT")*40) + self.assertRaises(TypeError, cipher.update, b("XYZ")) + + # Calling update() after decrypt() raises an exception + # (excluded for SIV, since decrypt() is not valid) + if not self.isMode("SIV"): + cipher = self.module.new(self.key, self.mode, self.iv) + cipher.update(b("XX")) + cipher.decrypt(b("CT")*40) + self.assertRaises(TypeError, cipher.update, b("XYZ")) + + def loopback(self): + """Verify composition of encrypt_and_digest() and decrypt_and_verify() + is the identity function.""" + + self.description = "Lookback test decrypt_and_verify(encrypt_and_digest)"\ + "for %s in %s" % (self.mode_name, + self.module.__name__) + + enc_cipher = self.module.new(self.key, self.mode, self.iv) + dec_cipher = self.module.new(self.key, self.mode, self.iv) + + enc_cipher.update(b("XXX")) + dec_cipher.update(b("XXX")) + + plaintext = b("Reference") * 10 + ct, mac = enc_cipher.encrypt_and_digest(plaintext) + pt = dec_cipher.decrypt_and_verify(ct, mac) + + self.assertEqual(plaintext, pt) + + def runTest(self): + self.right_mac_test() + self.wrong_mac_test() + self.zero_data() + self.multiple_updates() + self.no_mix_encrypt_decrypt() + self.no_late_update() + self.loopback() + + def shortDescription(self): + return self.description + +class RoundtripTest(unittest.TestCase): + def __init__(self, module, params): + from Crypto import Random + unittest.TestCase.__init__(self) + self.module = module + self.iv = Random.get_random_bytes(module.block_size) + self.key = b(params['key']) + self.plaintext = 100 * b(params['plaintext']) + self.module_name = params.get('module_name', None) + + def shortDescription(self): + return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) + + def runTest(self): + + ## ECB mode + mode = self.module.MODE_ECB + encryption_cipher = self.module.new(a2b_hex(self.key), mode) + ciphertext = encryption_cipher.encrypt(self.plaintext) + decryption_cipher = self.module.new(a2b_hex(self.key), mode) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) + + ## OPENPGP mode + mode = self.module.MODE_OPENPGP + encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) + eiv_ciphertext = encryption_cipher.encrypt(self.plaintext) + eiv = eiv_ciphertext[:self.module.block_size+2] + ciphertext = eiv_ciphertext[self.module.block_size+2:] + decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) + + ## All other non-AEAD modes (but CTR) + for mode in (self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB): + encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) + ciphertext = encryption_cipher.encrypt(self.plaintext) + decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) + + +class PGPTest(unittest.TestCase): + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params['key']) + + def shortDescription(self): + return "MODE_PGP was implemented incorrectly and insecurely. It's completely banished now." + + def runTest(self): + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), + self.module.MODE_PGP) + +class IVLengthTest(unittest.TestCase): + def __init__(self, module, params): + unittest.TestCase.__init__(self) + self.module = module + self.key = b(params['key']) + + def shortDescription(self): + return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length" + + def runTest(self): + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), + self.module.MODE_CBC, "") + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), + self.module.MODE_CFB, "") + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), + self.module.MODE_OFB, "") + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), + self.module.MODE_OPENPGP, "") + if hasattr(self.module, "MODE_CCM"): + for ivlen in (0,6,14): + self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), + self.module.MODE_CCM, bchr(0)*ivlen, msg_len=10) + self.module.new(a2b_hex(self.key), self.module.MODE_ECB, "") + self.module.new(a2b_hex(self.key), self.module.MODE_CTR, "", counter=self._dummy_counter) + + def _dummy_counter(self): + return "\0" * self.module.block_size + +def make_block_tests(module, module_name, test_data, additional_params=dict()): + tests = [] + extra_tests_added = 0 + for i in range(len(test_data)): + row = test_data[i] + + # Build the "params" dictionary + params = {'mode': 'ECB'} + if len(row) == 3: + (params['plaintext'], params['ciphertext'], params['key']) = row + elif len(row) == 4: + (params['plaintext'], params['ciphertext'], params['key'], params['description']) = row + elif len(row) == 5: + (params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row + params.update(extra_params) + else: + raise AssertionError("Unsupported tuple size %d" % (len(row),)) + + # Build the display-name for the test + p2 = params.copy() + p_key = _extract(p2, 'key') + p_plaintext = _extract(p2, 'plaintext') + p_ciphertext = _extract(p2, 'ciphertext') + p_description = _extract(p2, 'description', None) + p_mode = p2.get('mode', 'ECB') + if p_mode == 'ECB': + _extract(p2, 'mode', 'ECB') + + if p_description is not None: + description = p_description + elif p_mode == 'ECB' and not p2: + description = "p=%s, k=%s" % (p_plaintext, p_key) + else: + description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) + name = "%s #%d: %s" % (module_name, i+1, description) + params['description'] = name + params['module_name'] = module_name + params.update(additional_params) + + # Add extra test(s) to the test suite before the current test + if not extra_tests_added: + tests += [ + CTRSegfaultTest(module, params), + CTRWraparoundTest(module, params), + CFBSegmentSizeTest(module, params), + RoundtripTest(module, params), + PGPTest(module, params), + IVLengthTest(module, params), + ] + extra_tests_added = 1 + + # Extract associated data and MAC for AEAD modes + if p_mode in ('CCM', 'EAX', 'SIV', 'GCM'): + assoc_data, params['plaintext'] = params['plaintext'].split('|') + assoc_data2, params['ciphertext'], params['mac'] = params['ciphertext'].split('|') + params['assoc_data'] = assoc_data.split("-") + params['mac_len'] = len(params['mac'])>>1 + + # Add the current test to the test suite + tests.append(CipherSelfTest(module, params)) + + # When using CTR mode, test that the interface behaves like a stream cipher + if p_mode in ('OFB', 'CTR'): + tests.append(CipherStreamingSelfTest(module, params)) + + # When using CTR mode, test the non-shortcut code path. + if p_mode == 'CTR' and not params.has_key('ctr_class'): + params2 = params.copy() + params2['description'] += " (shortcut disabled)" + ctr_params2 = params.get('ctr_params', {}).copy() + params2['ctr_params'] = ctr_params2 + if not params2['ctr_params'].has_key('disable_shortcut'): + params2['ctr_params']['disable_shortcut'] = 1 + tests.append(CipherSelfTest(module, params2)) + + # Add tests that don't use test vectors + if hasattr(module, "MODE_CCM"): + tests += [ + CCMMACLengthTest(module), + CCMSplitEncryptionTest(module), + ] + for aead_mode in ("MODE_CCM","MODE_EAX", "MODE_SIV", "MODE_GCM"): + if hasattr(module, aead_mode): + key_sizes = [] + try: + key_sizes += module.key_size + except TypeError: + key_sizes = [ module.key_size ] + for ks in key_sizes: + tests += [ + AEADTests(module, aead_mode, ks), + ] + + return tests + +def make_stream_tests(module, module_name, test_data): + tests = [] + for i in range(len(test_data)): + row = test_data[i] + + # Build the "params" dictionary + params = {} + if len(row) == 3: + (params['plaintext'], params['ciphertext'], params['key']) = row + elif len(row) == 4: + (params['plaintext'], params['ciphertext'], params['key'], params['description']) = row + elif len(row) == 5: + (params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row + params.update(extra_params) + else: + raise AssertionError("Unsupported tuple size %d" % (len(row),)) + + # Build the display-name for the test + p2 = params.copy() + p_key = _extract(p2, 'key') + p_plaintext = _extract(p2, 'plaintext') + p_ciphertext = _extract(p2, 'ciphertext') + p_description = _extract(p2, 'description', None) + + if p_description is not None: + description = p_description + elif not p2: + description = "p=%s, k=%s" % (p_plaintext, p_key) + else: + description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2) + name = "%s #%d: %s" % (module_name, i+1, description) + params['description'] = name + params['module_name'] = module_name + + # Add the test to the test suite + tests.append(CipherSelfTest(module, params)) + tests.append(CipherStreamingSelfTest(module, params)) + return tests + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_AES.py b/lib/Crypto/SelfTest/Cipher/test_AES.py new file mode 100644 index 0000000..f54f473 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_AES.py @@ -0,0 +1,2013 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/AES.py: Self-test for the AES cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.AES""" + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * +from common import dict # For compatibility with Python 2.1 and 2.2 +from binascii import hexlify + +# This is a list of (plaintext, ciphertext, key[, description[, params]]) tuples. +test_data = [ + # FIPS PUB 197 test vectors + # http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + + ('00112233445566778899aabbccddeeff', '69c4e0d86a7b0430d8cdb78070b4c55a', + '000102030405060708090a0b0c0d0e0f', 'FIPS 197 C.1 (AES-128)'), + + ('00112233445566778899aabbccddeeff', 'dda97ca4864cdfe06eaf70a0ec0d7191', + '000102030405060708090a0b0c0d0e0f1011121314151617', + 'FIPS 197 C.2 (AES-192)'), + + ('00112233445566778899aabbccddeeff', '8ea2b7ca516745bfeafc49904b496089', + '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', + 'FIPS 197 C.3 (AES-256)'), + + # Rijndael128 test vectors + # Downloaded 2008-09-13 from + # http://www.iaik.tugraz.at/Research/krypto/AES/old/~rijmen/rijndael/testvalues.tar.gz + + # ecb_tbl.txt, KEYSIZE=128 + ('506812a45f08c889b97f5980038b8359', 'd8f532538289ef7d06b506a4fd5be9c9', + '00010203050607080a0b0c0d0f101112', + 'ecb-tbl-128: I=1'), + ('5c6d71ca30de8b8b00549984d2ec7d4b', '59ab30f4d4ee6e4ff9907ef65b1fb68c', + '14151617191a1b1c1e1f202123242526', + 'ecb-tbl-128: I=2'), + ('53f3f4c64f8616e4e7c56199f48f21f6', 'bf1ed2fcb2af3fd41443b56d85025cb1', + '28292a2b2d2e2f30323334353738393a', + 'ecb-tbl-128: I=3'), + ('a1eb65a3487165fb0f1c27ff9959f703', '7316632d5c32233edcb0780560eae8b2', + '3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-128: I=4'), + ('3553ecf0b1739558b08e350a98a39bfa', '408c073e3e2538072b72625e68b8364b', + '50515253555657585a5b5c5d5f606162', + 'ecb-tbl-128: I=5'), + ('67429969490b9711ae2b01dc497afde8', 'e1f94dfa776597beaca262f2f6366fea', + '64656667696a6b6c6e6f707173747576', + 'ecb-tbl-128: I=6'), + ('93385c1f2aec8bed192f5a8e161dd508', 'f29e986c6a1c27d7b29ffd7ee92b75f1', + '78797a7b7d7e7f80828384858788898a', + 'ecb-tbl-128: I=7'), + ('b5bf946be19beb8db3983b5f4c6e8ddb', '131c886a57f8c2e713aba6955e2b55b5', + '8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-128: I=8'), + ('41321ee10e21bd907227c4450ff42324', 'd2ab7662df9b8c740210e5eeb61c199d', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', + 'ecb-tbl-128: I=9'), + ('00a82f59c91c8486d12c0a80124f6089', '14c10554b2859c484cab5869bbe7c470', + 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-128: I=10'), + ('7ce0fd076754691b4bbd9faf8a1372fe', 'db4d498f0a49cf55445d502c1f9ab3b5', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', + 'ecb-tbl-128: I=11'), + ('23605a8243d07764541bc5ad355b3129', '6d96fef7d66590a77a77bb2056667f7f', + 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-128: I=12'), + ('12a8cfa23ea764fd876232b4e842bc44', '316fb68edba736c53e78477bf913725c', + 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', + 'ecb-tbl-128: I=13'), + ('bcaf32415e8308b3723e5fdd853ccc80', '6936f2b93af8397fd3a771fc011c8c37', + '04050607090a0b0c0e0f101113141516', + 'ecb-tbl-128: I=14'), + ('89afae685d801ad747ace91fc49adde0', 'f3f92f7a9c59179c1fcc2c2ba0b082cd', + '2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-128: I=15'), + ('f521d07b484357c4a69e76124a634216', '6a95ea659ee3889158e7a9152ff04ebc', + '40414243454647484a4b4c4d4f505152', + 'ecb-tbl-128: I=16'), + ('3e23b3bc065bcc152407e23896d77783', '1959338344e945670678a5d432c90b93', + '54555657595a5b5c5e5f606163646566', + 'ecb-tbl-128: I=17'), + ('79f0fba002be1744670e7e99290d8f52', 'e49bddd2369b83ee66e6c75a1161b394', + '68696a6b6d6e6f70727374757778797a', + 'ecb-tbl-128: I=18'), + ('da23fe9d5bd63e1d72e3dafbe21a6c2a', 'd3388f19057ff704b70784164a74867d', + '7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-128: I=19'), + ('e3f5698ba90b6a022efd7db2c7e6c823', '23aa03e2d5e4cd24f3217e596480d1e1', + 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-128: I=20'), + ('bdc2691d4f1b73d2700679c3bcbf9c6e', 'c84113d68b666ab2a50a8bdb222e91b9', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', + 'ecb-tbl-128: I=21'), + ('ba74e02093217ee1ba1b42bd5624349a', 'ac02403981cd4340b507963db65cb7b6', + '08090a0b0d0e0f10121314151718191a', + 'ecb-tbl-128: I=22'), + ('b5c593b5851c57fbf8b3f57715e8f680', '8d1299236223359474011f6bf5088414', + '6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-128: I=23'), + ('3da9bd9cec072381788f9387c3bbf4ee', '5a1d6ab8605505f7977e55b9a54d9b90', + '80818283858687888a8b8c8d8f909192', + 'ecb-tbl-128: I=24'), + ('4197f3051121702ab65d316b3c637374', '72e9c2d519cf555e4208805aabe3b258', + '94959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-128: I=25'), + ('9f46c62ec4f6ee3f6e8c62554bc48ab7', 'a8f3e81c4a23a39ef4d745dffe026e80', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', + 'ecb-tbl-128: I=26'), + ('0220673fe9e699a4ebc8e0dbeb6979c8', '546f646449d31458f9eb4ef5483aee6c', + 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', + 'ecb-tbl-128: I=27'), + ('b2b99171337ded9bc8c2c23ff6f18867', '4dbe4bc84ac797c0ee4efb7f1a07401c', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', + 'ecb-tbl-128: I=28'), + ('a7facf4e301e984e5efeefd645b23505', '25e10bfb411bbd4d625ac8795c8ca3b3', + 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-128: I=29'), + ('f7c762e4a9819160fd7acfb6c4eedcdd', '315637405054ec803614e43def177579', + 'f8f9fafbfdfefe00020304050708090a', + 'ecb-tbl-128: I=30'), + ('9b64fc21ea08709f4915436faa70f1be', '60c5bc8a1410247295c6386c59e572a8', + '0c0d0e0f11121314161718191b1c1d1e', + 'ecb-tbl-128: I=31'), + ('52af2c3de07ee6777f55a4abfc100b3f', '01366fc8ca52dfe055d6a00a76471ba6', + '20212223252627282a2b2c2d2f303132', + 'ecb-tbl-128: I=32'), + ('2fca001224386c57aa3f968cbe2c816f', 'ecc46595516ec612449c3f581e7d42ff', + '34353637393a3b3c3e3f404143444546', + 'ecb-tbl-128: I=33'), + ('4149c73658a4a9c564342755ee2c132f', '6b7ffe4c602a154b06ee9c7dab5331c9', + '48494a4b4d4e4f50525354555758595a', + 'ecb-tbl-128: I=34'), + ('af60005a00a1772f7c07a48a923c23d2', '7da234c14039a240dd02dd0fbf84eb67', + '5c5d5e5f61626364666768696b6c6d6e', + 'ecb-tbl-128: I=35'), + ('6fccbc28363759914b6f0280afaf20c6', 'c7dc217d9e3604ffe7e91f080ecd5a3a', + '70717273757677787a7b7c7d7f808182', + 'ecb-tbl-128: I=36'), + ('7d82a43ddf4fefa2fc5947499884d386', '37785901863f5c81260ea41e7580cda5', + '84858687898a8b8c8e8f909193949596', + 'ecb-tbl-128: I=37'), + ('5d5a990eaab9093afe4ce254dfa49ef9', 'a07b9338e92ed105e6ad720fccce9fe4', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', + 'ecb-tbl-128: I=38'), + ('4cd1e2fd3f4434b553aae453f0ed1a02', 'ae0fb9722418cc21a7da816bbc61322c', + 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-128: I=39'), + ('5a2c9a9641d4299125fa1b9363104b5e', 'c826a193080ff91ffb21f71d3373c877', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', + 'ecb-tbl-128: I=40'), + ('b517fe34c0fa217d341740bfd4fe8dd4', '1181b11b0e494e8d8b0aa6b1d5ac2c48', + 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-128: I=41'), + ('014baf2278a69d331d5180103643e99a', '6743c3d1519ab4f2cd9a78ab09a511bd', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', + 'ecb-tbl-128: I=42'), + ('b529bd8164f20d0aa443d4932116841c', 'dc55c076d52bacdf2eefd952946a439d', + 'fcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-128: I=43'), + ('2e596dcbb2f33d4216a1176d5bd1e456', '711b17b590ffc72b5c8e342b601e8003', + '10111213151617181a1b1c1d1f202122', + 'ecb-tbl-128: I=44'), + ('7274a1ea2b7ee2424e9a0e4673689143', '19983bb0950783a537e1339f4aa21c75', + '24252627292a2b2c2e2f303133343536', + 'ecb-tbl-128: I=45'), + ('ae20020bd4f13e9d90140bee3b5d26af', '3ba7762e15554169c0f4fa39164c410c', + '38393a3b3d3e3f40424344454748494a', + 'ecb-tbl-128: I=46'), + ('baac065da7ac26e855e79c8849d75a02', 'a0564c41245afca7af8aa2e0e588ea89', + '4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-128: I=47'), + ('7c917d8d1d45fab9e2540e28832540cc', '5e36a42a2e099f54ae85ecd92e2381ed', + '60616263656667686a6b6c6d6f707172', + 'ecb-tbl-128: I=48'), + ('bde6f89e16daadb0e847a2a614566a91', '770036f878cd0f6ca2268172f106f2fe', + '74757677797a7b7c7e7f808183848586', + 'ecb-tbl-128: I=49'), + ('c9de163725f1f5be44ebb1db51d07fbc', '7e4e03908b716116443ccf7c94e7c259', + '88898a8b8d8e8f90929394959798999a', + 'ecb-tbl-128: I=50'), + ('3af57a58f0c07dffa669572b521e2b92', '482735a48c30613a242dd494c7f9185d', + '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-128: I=51'), + ('3d5ebac306dde4604f1b4fbbbfcdae55', 'b4c0f6c9d4d7079addf9369fc081061d', + 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', + 'ecb-tbl-128: I=52'), + ('c2dfa91bceb76a1183c995020ac0b556', 'd5810fe0509ac53edcd74f89962e6270', + 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-128: I=53'), + ('c70f54305885e9a0746d01ec56c8596b', '03f17a16b3f91848269ecdd38ebb2165', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', + 'ecb-tbl-128: I=54'), + ('c4f81b610e98012ce000182050c0c2b2', 'da1248c3180348bad4a93b4d9856c9df', + 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-128: I=55'), + ('eaab86b1d02a95d7404eff67489f97d4', '3d10d7b63f3452c06cdf6cce18be0c2c', + '00010203050607080a0b0c0d0f101112', + 'ecb-tbl-128: I=56'), + ('7c55bdb40b88870b52bec3738de82886', '4ab823e7477dfddc0e6789018fcb6258', + '14151617191a1b1c1e1f202123242526', + 'ecb-tbl-128: I=57'), + ('ba6eaa88371ff0a3bd875e3f2a975ce0', 'e6478ba56a77e70cfdaa5c843abde30e', + '28292a2b2d2e2f30323334353738393a', + 'ecb-tbl-128: I=58'), + ('08059130c4c24bd30cf0575e4e0373dc', '1673064895fbeaf7f09c5429ff75772d', + '3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-128: I=59'), + ('9a8eab004ef53093dfcf96f57e7eda82', '4488033ae9f2efd0ca9383bfca1a94e9', + '50515253555657585a5b5c5d5f606162', + 'ecb-tbl-128: I=60'), + ('0745b589e2400c25f117b1d796c28129', '978f3b8c8f9d6f46626cac3c0bcb9217', + '64656667696a6b6c6e6f707173747576', + 'ecb-tbl-128: I=61'), + ('2f1777781216cec3f044f134b1b92bbe', 'e08c8a7e582e15e5527f1d9e2eecb236', + '78797a7b7d7e7f80828384858788898a', + 'ecb-tbl-128: I=62'), + ('353a779ffc541b3a3805d90ce17580fc', 'cec155b76ac5ffda4cf4f9ca91e49a7a', + '8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-128: I=63'), + ('1a1eae4415cefcf08c4ac1c8f68bea8f', 'd5ac7165763225dd2a38cdc6862c29ad', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', + 'ecb-tbl-128: I=64'), + ('e6e7e4e5b0b3b2b5d4d5aaab16111013', '03680fe19f7ce7275452020be70e8204', + 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-128: I=65'), + ('f8f9fafbfbf8f9e677767170efe0e1e2', '461df740c9781c388e94bb861ceb54f6', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', + 'ecb-tbl-128: I=66'), + ('63626160a1a2a3a445444b4a75727370', '451bd60367f96483042742219786a074', + 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-128: I=67'), + ('717073720605040b2d2c2b2a05fafbf9', 'e4dfa42671a02e57ef173b85c0ea9f2b', + 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', + 'ecb-tbl-128: I=68'), + ('78797a7beae9e8ef3736292891969794', 'ed11b89e76274282227d854700a78b9e', + '04050607090a0b0c0e0f101113141516', + 'ecb-tbl-128: I=69'), + ('838281803231300fdddcdbdaa0afaead', '433946eaa51ea47af33895f2b90b3b75', + '18191a1b1d1e1f20222324252728292a', + 'ecb-tbl-128: I=70'), + ('18191a1bbfbcbdba75747b7a7f78797a', '6bc6d616a5d7d0284a5910ab35022528', + '2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-128: I=71'), + ('848586879b989996a3a2a5a4849b9a99', 'd2a920ecfe919d354b5f49eae9719c98', + '40414243454647484a4b4c4d4f505152', + 'ecb-tbl-128: I=72'), + ('0001020322212027cacbf4f551565754', '3a061b17f6a92885efbd0676985b373d', + '54555657595a5b5c5e5f606163646566', + 'ecb-tbl-128: I=73'), + ('cecfcccdafacadb2515057564a454447', 'fadeec16e33ea2f4688499d157e20d8f', + '68696a6b6d6e6f70727374757778797a', + 'ecb-tbl-128: I=74'), + ('92939091cdcecfc813121d1c80878685', '5cdefede59601aa3c3cda36fa6b1fa13', + '7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-128: I=75'), + ('d2d3d0d16f6c6d6259585f5ed1eeefec', '9574b00039844d92ebba7ee8719265f8', + '90919293959697989a9b9c9d9fa0a1a2', + 'ecb-tbl-128: I=76'), + ('acadaeaf878485820f0e1110d5d2d3d0', '9a9cf33758671787e5006928188643fa', + 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-128: I=77'), + ('9091929364676619e6e7e0e1757a7b78', '2cddd634c846ba66bb46cbfea4a674f9', + 'b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', + 'ecb-tbl-128: I=78'), + ('babbb8b98a89888f74757a7b92959497', 'd28bae029393c3e7e26e9fafbbb4b98f', + 'cccdcecfd1d2d3d4d6d7d8d9dbdcddde', + 'ecb-tbl-128: I=79'), + ('8d8c8f8e6e6d6c633b3a3d3ccad5d4d7', 'ec27529b1bee0a9ab6a0d73ebc82e9b7', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', + 'ecb-tbl-128: I=80'), + ('86878485010203040808f7f767606162', '3cb25c09472aff6ee7e2b47ccd7ccb17', + 'f4f5f6f7f9fafbfcfefe010103040506', + 'ecb-tbl-128: I=81'), + ('8e8f8c8d656667788a8b8c8d010e0f0c', 'dee33103a7283370d725e44ca38f8fe5', + '08090a0b0d0e0f10121314151718191a', + 'ecb-tbl-128: I=82'), + ('c8c9cacb858687807a7b7475e7e0e1e2', '27f9bcd1aac64bffc11e7815702c1a69', + '1c1d1e1f21222324262728292b2c2d2e', + 'ecb-tbl-128: I=83'), + ('6d6c6f6e5053525d8c8d8a8badd2d3d0', '5df534ffad4ed0749a9988e9849d0021', + '30313233353637383a3b3c3d3f404142', + 'ecb-tbl-128: I=84'), + ('28292a2b393a3b3c0607181903040506', 'a48bee75db04fb60ca2b80f752a8421b', + '44454647494a4b4c4e4f505153545556', + 'ecb-tbl-128: I=85'), + ('a5a4a7a6b0b3b28ddbdadddcbdb2b3b0', '024c8cf70bc86ee5ce03678cb7af45f9', + '58595a5b5d5e5f60626364656768696a', + 'ecb-tbl-128: I=86'), + ('323330316467666130313e3f2c2b2a29', '3c19ac0f8a3a3862ce577831301e166b', + '6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-128: I=87'), + ('27262524080b0a05171611100b141516', 'c5e355b796a57421d59ca6be82e73bca', + '80818283858687888a8b8c8d8f909192', + 'ecb-tbl-128: I=88'), + ('040506074142434435340b0aa3a4a5a6', 'd94033276417abfb05a69d15b6e386e2', + '94959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-128: I=89'), + ('242526271112130c61606766bdb2b3b0', '24b36559ea3a9b9b958fe6da3e5b8d85', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', + 'ecb-tbl-128: I=90'), + ('4b4a4948252627209e9f9091cec9c8cb', '20fd4feaa0e8bf0cce7861d74ef4cb72', + 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', + 'ecb-tbl-128: I=91'), + ('68696a6b6665646b9f9e9998d9e6e7e4', '350e20d5174277b9ec314c501570a11d', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', + 'ecb-tbl-128: I=92'), + ('34353637c5c6c7c0f0f1eeef7c7b7a79', '87a29d61b7c604d238fe73045a7efd57', + 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-128: I=93'), + ('32333031c2c1c13f0d0c0b0a050a0b08', '2c3164c1cc7d0064816bdc0faa362c52', + 'f8f9fafbfdfefe00020304050708090a', + 'ecb-tbl-128: I=94'), + ('cdcccfcebebdbcbbabaaa5a4181f1e1d', '195fe5e8a05a2ed594f6e4400eee10b3', + '0c0d0e0f11121314161718191b1c1d1e', + 'ecb-tbl-128: I=95'), + ('212023223635343ba0a1a6a7445b5a59', 'e4663df19b9a21a5a284c2bd7f905025', + '20212223252627282a2b2c2d2f303132', + 'ecb-tbl-128: I=96'), + ('0e0f0c0da8abaaad2f2e515002050407', '21b88714cfb4e2a933bd281a2c4743fd', + '34353637393a3b3c3e3f404143444546', + 'ecb-tbl-128: I=97'), + ('070605042a2928378e8f8889bdb2b3b0', 'cbfc3980d704fd0fc54378ab84e17870', + '48494a4b4d4e4f50525354555758595a', + 'ecb-tbl-128: I=98'), + ('cbcac9c893909196a9a8a7a6a5a2a3a0', 'bc5144baa48bdeb8b63e22e03da418ef', + '5c5d5e5f61626364666768696b6c6d6e', + 'ecb-tbl-128: I=99'), + ('80818283c1c2c3cc9c9d9a9b0cf3f2f1', '5a1dbaef1ee2984b8395da3bdffa3ccc', + '70717273757677787a7b7c7d7f808182', + 'ecb-tbl-128: I=100'), + ('1213101125262720fafbe4e5b1b6b7b4', 'f0b11cd0729dfcc80cec903d97159574', + '84858687898a8b8c8e8f909193949596', + 'ecb-tbl-128: I=101'), + ('7f7e7d7c3033320d97969190222d2c2f', '9f95314acfddc6d1914b7f19a9cc8209', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', + 'ecb-tbl-128: I=102'), + ('4e4f4c4d484b4a4d81808f8e53545556', '595736f6f0f70914a94e9e007f022519', + 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-128: I=103'), + ('dcdddedfb0b3b2bd15141312a1bebfbc', '1f19f57892cae586fcdfb4c694deb183', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', + 'ecb-tbl-128: I=104'), + ('93929190282b2a2dc4c5fafb92959497', '540700ee1f6f3dab0b3eddf6caee1ef5', + 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-128: I=105'), + ('f5f4f7f6c4c7c6d9373631307e717073', '14a342a91019a331687a2254e6626ca2', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', + 'ecb-tbl-128: I=106'), + ('93929190b6b5b4b364656a6b05020300', '7b25f3c3b2eea18d743ef283140f29ff', + 'fcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-128: I=107'), + ('babbb8b90d0e0f00a4a5a2a3043b3a39', '46c2587d66e5e6fa7f7ca6411ad28047', + '10111213151617181a1b1c1d1f202122', + 'ecb-tbl-128: I=108'), + ('d8d9dadb7f7c7d7a10110e0f787f7e7d', '09470e72229d954ed5ee73886dfeeba9', + '24252627292a2b2c2e2f303133343536', + 'ecb-tbl-128: I=109'), + ('fefffcfdefeced923b3a3d3c6768696a', 'd77c03de92d4d0d79ef8d4824ef365eb', + '38393a3b3d3e3f40424344454748494a', + 'ecb-tbl-128: I=110'), + ('d6d7d4d58a89888f96979899a5a2a3a0', '1d190219f290e0f1715d152d41a23593', + '4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-128: I=111'), + ('18191a1ba8abaaa5303136379b848586', 'a2cd332ce3a0818769616292e87f757b', + '60616263656667686a6b6c6d6f707172', + 'ecb-tbl-128: I=112'), + ('6b6a6968a4a7a6a1d6d72829b0b7b6b5', 'd54afa6ce60fbf9341a3690e21385102', + '74757677797a7b7c7e7f808183848586', + 'ecb-tbl-128: I=113'), + ('000102038a89889755545352a6a9a8ab', '06e5c364ded628a3f5e05e613e356f46', + '88898a8b8d8e8f90929394959798999a', + 'ecb-tbl-128: I=114'), + ('2d2c2f2eb3b0b1b6b6b7b8b9f2f5f4f7', 'eae63c0e62556dac85d221099896355a', + '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-128: I=115'), + ('979695943536373856575051e09f9e9d', '1fed060e2c6fc93ee764403a889985a2', + 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', + 'ecb-tbl-128: I=116'), + ('a4a5a6a7989b9a9db1b0afae7a7d7c7f', 'c25235c1a30fdec1c7cb5c5737b2a588', + 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-128: I=117'), + ('c1c0c3c2686b6a55a8a9aeafeae5e4e7', '796dbef95147d4d30873ad8b7b92efc0', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', + 'ecb-tbl-128: I=118'), + ('c1c0c3c2141716118c8d828364636261', 'cbcf0fb34d98d0bd5c22ce37211a46bf', + 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-128: I=119'), + ('93929190cccfcec196979091e0fffefd', '94b44da6466126cafa7c7fd09063fc24', + '00010203050607080a0b0c0d0f101112', + 'ecb-tbl-128: I=120'), + ('b4b5b6b7f9fafbfc25241b1a6e69686b', 'd78c5b5ebf9b4dbda6ae506c5074c8fe', + '14151617191a1b1c1e1f202123242526', + 'ecb-tbl-128: I=121'), + ('868784850704051ac7c6c1c08788898a', '6c27444c27204b043812cf8cf95f9769', + '28292a2b2d2e2f30323334353738393a', + 'ecb-tbl-128: I=122'), + ('f4f5f6f7aaa9a8affdfcf3f277707172', 'be94524ee5a2aa50bba8b75f4c0aebcf', + '3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-128: I=123'), + ('d3d2d1d00605040bc3c2c5c43e010003', 'a0aeaae91ba9f31f51aeb3588cf3a39e', + '50515253555657585a5b5c5d5f606162', + 'ecb-tbl-128: I=124'), + ('73727170424140476a6b74750d0a0b08', '275297779c28266ef9fe4c6a13c08488', + '64656667696a6b6c6e6f707173747576', + 'ecb-tbl-128: I=125'), + ('c2c3c0c10a0908f754555253a1aeafac', '86523d92bb8672cb01cf4a77fd725882', + '78797a7b7d7e7f80828384858788898a', + 'ecb-tbl-128: I=126'), + ('6d6c6f6ef8fbfafd82838c8df8fffefd', '4b8327640e9f33322a04dd96fcbf9a36', + '8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-128: I=127'), + ('f5f4f7f684878689a6a7a0a1d2cdcccf', 'ce52af650d088ca559425223f4d32694', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', + 'ecb-tbl-128: I=128'), + + # ecb_tbl.txt, KEYSIZE=192 + ('2d33eef2c0430a8a9ebf45e809c40bb6', 'dff4945e0336df4c1c56bc700eff837f', + '00010203050607080a0b0c0d0f10111214151617191a1b1c', + 'ecb-tbl-192: I=1'), + ('6aa375d1fa155a61fb72353e0a5a8756', 'b6fddef4752765e347d5d2dc196d1252', + '1e1f20212324252628292a2b2d2e2f30323334353738393a', + 'ecb-tbl-192: I=2'), + ('bc3736518b9490dcb8ed60eb26758ed4', 'd23684e3d963b3afcf1a114aca90cbd6', + '3c3d3e3f41424344464748494b4c4d4e5051525355565758', + 'ecb-tbl-192: I=3'), + ('aa214402b46cffb9f761ec11263a311e', '3a7ac027753e2a18c2ceab9e17c11fd0', + '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-192: I=4'), + ('02aea86e572eeab66b2c3af5e9a46fd6', '8f6786bd007528ba26603c1601cdd0d8', + '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', + 'ecb-tbl-192: I=5'), + ('e2aef6acc33b965c4fa1f91c75ff6f36', 'd17d073b01e71502e28b47ab551168b3', + '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', + 'ecb-tbl-192: I=6'), + ('0659df46427162b9434865dd9499f91d', 'a469da517119fab95876f41d06d40ffa', + 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', + 'ecb-tbl-192: I=7'), + ('49a44239c748feb456f59c276a5658df', '6091aa3b695c11f5c0b6ad26d3d862ff', + 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-192: I=8'), + ('66208f6e9d04525bdedb2733b6a6be37', '70f9e67f9f8df1294131662dc6e69364', + 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', + 'ecb-tbl-192: I=9'), + ('3393f8dfc729c97f5480b950bc9666b0', 'd154dcafad8b207fa5cbc95e9996b559', + '0e0f10111314151618191a1b1d1e1f20222324252728292a', + 'ecb-tbl-192: I=10'), + ('606834c8ce063f3234cf1145325dbd71', '4934d541e8b46fa339c805a7aeb9e5da', + '2c2d2e2f31323334363738393b3c3d3e4041424345464748', + 'ecb-tbl-192: I=11'), + ('fec1c04f529bbd17d8cecfcc4718b17f', '62564c738f3efe186e1a127a0c4d3c61', + '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', + 'ecb-tbl-192: I=12'), + ('32df99b431ed5dc5acf8caf6dc6ce475', '07805aa043986eb23693e23bef8f3438', + '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', + 'ecb-tbl-192: I=13'), + ('7fdc2b746f3f665296943b83710d1f82', 'df0b4931038bade848dee3b4b85aa44b', + '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', + 'ecb-tbl-192: I=14'), + ('8fba1510a3c5b87e2eaa3f7a91455ca2', '592d5fded76582e4143c65099309477c', + 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6b8b9babbbdbebfc0', + 'ecb-tbl-192: I=15'), + ('2c9b468b1c2eed92578d41b0716b223b', 'c9b8d6545580d3dfbcdd09b954ed4e92', + 'c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', + 'ecb-tbl-192: I=16'), + ('0a2bbf0efc6bc0034f8a03433fca1b1a', '5dccd5d6eb7c1b42acb008201df707a0', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfc', + 'ecb-tbl-192: I=17'), + ('25260e1f31f4104d387222e70632504b', 'a2a91682ffeb6ed1d34340946829e6f9', + 'fefe01010304050608090a0b0d0e0f10121314151718191a', + 'ecb-tbl-192: I=18'), + ('c527d25a49f08a5228d338642ae65137', 'e45d185b797000348d9267960a68435d', + '1c1d1e1f21222324262728292b2c2d2e3031323335363738', + 'ecb-tbl-192: I=19'), + ('3b49fc081432f5890d0e3d87e884a69e', '45e060dae5901cda8089e10d4f4c246b', + '3a3b3c3d3f40414244454647494a4b4c4e4f505153545556', + 'ecb-tbl-192: I=20'), + ('d173f9ed1e57597e166931df2754a083', 'f6951afacc0079a369c71fdcff45df50', + '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374', + 'ecb-tbl-192: I=21'), + ('8c2b7cafa5afe7f13562daeae1adede0', '9e95e00f351d5b3ac3d0e22e626ddad6', + '767778797b7c7d7e80818283858687888a8b8c8d8f909192', + 'ecb-tbl-192: I=22'), + ('aaf4ec8c1a815aeb826cab741339532c', '9cb566ff26d92dad083b51fdc18c173c', + '94959697999a9b9c9e9fa0a1a3a4a5a6a8a9aaabadaeafb0', + 'ecb-tbl-192: I=23'), + ('40be8c5d9108e663f38f1a2395279ecf', 'c9c82766176a9b228eb9a974a010b4fb', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebec', + 'ecb-tbl-192: I=24'), + ('0c8ad9bc32d43e04716753aa4cfbe351', 'd8e26aa02945881d5137f1c1e1386e88', + '2a2b2c2d2f30313234353637393a3b3c3e3f404143444546', + 'ecb-tbl-192: I=25'), + ('1407b1d5f87d63357c8dc7ebbaebbfee', 'c0e024ccd68ff5ffa4d139c355a77c55', + '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364', + 'ecb-tbl-192: I=26'), + ('e62734d1ae3378c4549e939e6f123416', '0b18b3d16f491619da338640df391d43', + '84858687898a8b8c8e8f90919394959698999a9b9d9e9fa0', + 'ecb-tbl-192: I=27'), + ('5a752cff2a176db1a1de77f2d2cdee41', 'dbe09ac8f66027bf20cb6e434f252efc', + 'a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-192: I=28'), + ('a9c8c3a4eabedc80c64730ddd018cd88', '6d04e5e43c5b9cbe05feb9606b6480fe', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdc', + 'ecb-tbl-192: I=29'), + ('ee9b3dbbdb86180072130834d305999a', 'dd1d6553b96be526d9fee0fbd7176866', + '1a1b1c1d1f20212224252627292a2b2c2e2f303133343536', + 'ecb-tbl-192: I=30'), + ('a7fa8c3586b8ebde7568ead6f634a879', '0260ca7e3f979fd015b0dd4690e16d2a', + '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354', + 'ecb-tbl-192: I=31'), + ('37e0f4a87f127d45ac936fe7ad88c10a', '9893734de10edcc8a67c3b110b8b8cc6', + '929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-192: I=32'), + ('3f77d8b5d92bac148e4e46f697a535c5', '93b30b750516b2d18808d710c2ee84ef', + '464748494b4c4d4e50515253555657585a5b5c5d5f606162', + 'ecb-tbl-192: I=33'), + ('d25ebb686c40f7e2c4da1014936571ca', '16f65fa47be3cb5e6dfe7c6c37016c0e', + '828384858788898a8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-192: I=34'), + ('4f1c769d1e5b0552c7eca84dea26a549', 'f3847210d5391e2360608e5acb560581', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbc', + 'ecb-tbl-192: I=35'), + ('8548e2f882d7584d0fafc54372b6633a', '8754462cd223366d0753913e6af2643d', + 'bebfc0c1c3c4c5c6c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', + 'ecb-tbl-192: I=36'), + ('87d7a336cb476f177cd2a51af2a62cdf', '1ea20617468d1b806a1fd58145462017', + 'dcdddedfe1e2e3e4e6e7e8e9ebecedeef0f1f2f3f5f6f7f8', + 'ecb-tbl-192: I=37'), + ('03b1feac668c4e485c1065dfc22b44ee', '3b155d927355d737c6be9dda60136e2e', + 'fafbfcfdfe01000204050607090a0b0c0e0f101113141516', + 'ecb-tbl-192: I=38'), + ('bda15e66819fa72d653a6866aa287962', '26144f7b66daa91b6333dbd3850502b3', + '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334', + 'ecb-tbl-192: I=39'), + ('4d0c7a0d2505b80bf8b62ceb12467f0a', 'e4f9a4ab52ced8134c649bf319ebcc90', + '363738393b3c3d3e40414243454647484a4b4c4d4f505152', + 'ecb-tbl-192: I=40'), + ('626d34c9429b37211330986466b94e5f', 'b9ddd29ac6128a6cab121e34a4c62b36', + '54555657595a5b5c5e5f60616364656668696a6b6d6e6f70', + 'ecb-tbl-192: I=41'), + ('333c3e6bf00656b088a17e5ff0e7f60a', '6fcddad898f2ce4eff51294f5eaaf5c9', + '727374757778797a7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-192: I=42'), + ('687ed0cdc0d2a2bc8c466d05ef9d2891', 'c9a6fe2bf4028080bea6f7fc417bd7e3', + '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabac', + 'ecb-tbl-192: I=43'), + ('487830e78cc56c1693e64b2a6660c7b6', '6a2026846d8609d60f298a9c0673127f', + 'aeafb0b1b3b4b5b6b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', + 'ecb-tbl-192: I=44'), + ('7a48d6b7b52b29392aa2072a32b66160', '2cb25c005e26efea44336c4c97a4240b', + 'cccdcecfd1d2d3d4d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8', + 'ecb-tbl-192: I=45'), + ('907320e64c8c5314d10f8d7a11c8618d', '496967ab8680ddd73d09a0e4c7dcc8aa', + 'eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', + 'ecb-tbl-192: I=46'), + ('b561f2ca2d6e65a4a98341f3ed9ff533', 'd5af94de93487d1f3a8c577cb84a66a4', + '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324', + 'ecb-tbl-192: I=47'), + ('df769380d212792d026f049e2e3e48ef', '84bdac569cae2828705f267cc8376e90', + '262728292b2c2d2e30313233353637383a3b3c3d3f404142', + 'ecb-tbl-192: I=48'), + ('79f374bc445bdabf8fccb8843d6054c6', 'f7401dda5ad5ab712b7eb5d10c6f99b6', + '44454647494a4b4c4e4f50515354555658595a5b5d5e5f60', + 'ecb-tbl-192: I=49'), + ('4e02f1242fa56b05c68dbae8fe44c9d6', '1c9d54318539ebd4c3b5b7e37bf119f0', + '626364656768696a6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-192: I=50'), + ('cf73c93cbff57ac635a6f4ad2a4a1545', 'aca572d65fb2764cffd4a6eca090ea0d', + '80818283858687888a8b8c8d8f90919294959697999a9b9c', + 'ecb-tbl-192: I=51'), + ('9923548e2875750725b886566784c625', '36d9c627b8c2a886a10ccb36eae3dfbb', + '9e9fa0a1a3a4a5a6a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', + 'ecb-tbl-192: I=52'), + ('4888336b723a022c9545320f836a4207', '010edbf5981e143a81d646e597a4a568', + 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdced0d1d2d3d5d6d7d8', + 'ecb-tbl-192: I=53'), + ('f84d9a5561b0608b1160dee000c41ba8', '8db44d538dc20cc2f40f3067fd298e60', + 'dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-192: I=54'), + ('c23192a0418e30a19b45ae3e3625bf22', '930eb53bc71e6ac4b82972bdcd5aafb3', + 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314', + 'ecb-tbl-192: I=55'), + ('b84e0690b28b0025381ad82a15e501a7', '6c42a81edcbc9517ccd89c30c95597b4', + '161718191b1c1d1e20212223252627282a2b2c2d2f303132', + 'ecb-tbl-192: I=56'), + ('acef5e5c108876c4f06269f865b8f0b0', 'da389847ad06df19d76ee119c71e1dd3', + '34353637393a3b3c3e3f40414344454648494a4b4d4e4f50', + 'ecb-tbl-192: I=57'), + ('0f1b3603e0f5ddea4548246153a5e064', 'e018fdae13d3118f9a5d1a647a3f0462', + '525354555758595a5c5d5e5f61626364666768696b6c6d6e', + 'ecb-tbl-192: I=58'), + ('fbb63893450d42b58c6d88cd3c1809e3', '2aa65db36264239d3846180fabdfad20', + '70717273757677787a7b7c7d7f80818284858687898a8b8c', + 'ecb-tbl-192: I=59'), + ('4bef736df150259dae0c91354e8a5f92', '1472163e9a4f780f1ceb44b07ecf4fdb', + '8e8f90919394959698999a9b9d9e9fa0a2a3a4a5a7a8a9aa', + 'ecb-tbl-192: I=60'), + ('7d2d46242056ef13d3c3fc93c128f4c7', 'c8273fdc8f3a9f72e91097614b62397c', + 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8', + 'ecb-tbl-192: I=61'), + ('e9c1ba2df415657a256edb33934680fd', '66c8427dcd733aaf7b3470cb7d976e3f', + 'cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-192: I=62'), + ('e23ee277b0aa0a1dfb81f7527c3514f1', '146131cb17f1424d4f8da91e6f80c1d0', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304', + 'ecb-tbl-192: I=63'), + ('3e7445b0b63caaf75e4a911e12106b4c', '2610d0ad83659081ae085266a88770dc', + '060708090b0c0d0e10111213151617181a1b1c1d1f202122', + 'ecb-tbl-192: I=64'), + ('767774752023222544455a5be6e1e0e3', '38a2b5a974b0575c5d733917fb0d4570', + '24252627292a2b2c2e2f30313334353638393a3b3d3e3f40', + 'ecb-tbl-192: I=65'), + ('72737475717e7f7ce9e8ebea696a6b6c', 'e21d401ebc60de20d6c486e4f39a588b', + '424344454748494a4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-192: I=66'), + ('dfdedddc25262728c9c8cfcef1eeefec', 'e51d5f88c670b079c0ca1f0c2c4405a2', + '60616263656667686a6b6c6d6f70717274757677797a7b7c', + 'ecb-tbl-192: I=67'), + ('fffe0100707776755f5e5d5c7675746b', '246a94788a642fb3d1b823c8762380c8', + '7e7f80818384858688898a8b8d8e8f90929394959798999a', + 'ecb-tbl-192: I=68'), + ('e0e1e2e3424140479f9e9190292e2f2c', 'b80c391c5c41a4c3b30c68e0e3d7550f', + '9c9d9e9fa1a2a3a4a6a7a8a9abacadaeb0b1b2b3b5b6b7b8', + 'ecb-tbl-192: I=69'), + ('2120272690efeeed3b3a39384e4d4c4b', 'b77c4754fc64eb9a1154a9af0bb1f21c', + 'babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-192: I=70'), + ('ecedeeef5350516ea1a0a7a6a3acadae', 'fb554de520d159a06bf219fc7f34a02f', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4', + 'ecb-tbl-192: I=71'), + ('32333c3d25222320e9e8ebeacecdccc3', 'a89fba152d76b4927beed160ddb76c57', + 'f6f7f8f9fbfcfdfe00010203050607080a0b0c0d0f101112', + 'ecb-tbl-192: I=72'), + ('40414243626160678a8bb4b511161714', '5676eab4a98d2e8473b3f3d46424247c', + '14151617191a1b1c1e1f20212324252628292a2b2d2e2f30', + 'ecb-tbl-192: I=73'), + ('94959293f5fafbf81f1e1d1c7c7f7e79', '4e8f068bd7ede52a639036ec86c33568', + '323334353738393a3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-192: I=74'), + ('bebfbcbd191a1b14cfcec9c8546b6a69', 'f0193c4d7aff1791ee4c07eb4a1824fc', + '50515253555657585a5b5c5d5f60616264656667696a6b6c', + 'ecb-tbl-192: I=75'), + ('2c2d3233898e8f8cbbbab9b8333031ce', 'ac8686eeca9ba761afe82d67b928c33f', + '6e6f70717374757678797a7b7d7e7f80828384858788898a', + 'ecb-tbl-192: I=76'), + ('84858687bfbcbdba37363938fdfafbf8', '5faf8573e33b145b6a369cd3606ab2c9', + '8c8d8e8f91929394969798999b9c9d9ea0a1a2a3a5a6a7a8', + 'ecb-tbl-192: I=77'), + ('828384857669686b909192930b08090e', '31587e9944ab1c16b844ecad0df2e7da', + 'aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-192: I=78'), + ('bebfbcbd9695948b707176779e919093', 'd017fecd91148aba37f6f3068aa67d8a', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4', + 'ecb-tbl-192: I=79'), + ('8b8a85846067666521202322d0d3d2dd', '788ef2f021a73cba2794b616078a8500', + 'e6e7e8e9ebecedeef0f1f2f3f5f6f7f8fafbfcfdfe010002', + 'ecb-tbl-192: I=80'), + ('76777475f1f2f3f4f8f9e6e777707172', '5d1ef20dced6bcbc12131ac7c54788aa', + '04050607090a0b0c0e0f10111314151618191a1b1d1e1f20', + 'ecb-tbl-192: I=81'), + ('a4a5a2a34f404142b4b5b6b727242522', 'b3c8cf961faf9ea05fdde6d1e4d8f663', + '222324252728292a2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-192: I=82'), + ('94959697e1e2e3ec16171011839c9d9e', '143075c70605861c7fac6526199e459f', + '40414243454647484a4b4c4d4f50515254555657595a5b5c', + 'ecb-tbl-192: I=83'), + ('03023d3c06010003dedfdcddfffcfde2', 'a5ae12eade9a87268d898bfc8fc0252a', + '5e5f60616364656668696a6b6d6e6f70727374757778797a', + 'ecb-tbl-192: I=84'), + ('10111213f1f2f3f4cecfc0c1dbdcddde', '0924f7cf2e877a4819f5244a360dcea9', + '7c7d7e7f81828384868788898b8c8d8e9091929395969798', + 'ecb-tbl-192: I=85'), + ('67666160724d4c4f1d1c1f1e73707176', '3d9e9635afcc3e291cc7ab3f27d1c99a', + '9a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-192: I=86'), + ('e6e7e4e5a8abaad584858283909f9e9d', '9d80feebf87510e2b8fb98bb54fd788c', + 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4', + 'ecb-tbl-192: I=87'), + ('71707f7e565150537d7c7f7e6162636c', '5f9d1a082a1a37985f174002eca01309', + 'd6d7d8d9dbdcdddee0e1e2e3e5e6e7e8eaebecedeff0f1f2', + 'ecb-tbl-192: I=88'), + ('64656667212223245555aaaa03040506', 'a390ebb1d1403930184a44b4876646e4', + 'f4f5f6f7f9fafbfcfefe01010304050608090a0b0d0e0f10', + 'ecb-tbl-192: I=89'), + ('9e9f9899aba4a5a6cfcecdcc2b28292e', '700fe918981c3195bb6c4bcb46b74e29', + '121314151718191a1c1d1e1f21222324262728292b2c2d2e', + 'ecb-tbl-192: I=90'), + ('c7c6c5c4d1d2d3dc626364653a454447', '907984406f7bf2d17fb1eb15b673d747', + '30313233353637383a3b3c3d3f40414244454647494a4b4c', + 'ecb-tbl-192: I=91'), + ('f6f7e8e9e0e7e6e51d1c1f1e5b585966', 'c32a956dcfc875c2ac7c7cc8b8cc26e1', + '4e4f50515354555658595a5b5d5e5f60626364656768696a', + 'ecb-tbl-192: I=92'), + ('bcbdbebf5d5e5f5868696667f4f3f2f1', '02646e2ebfa9b820cf8424e9b9b6eb51', + '6c6d6e6f71727374767778797b7c7d7e8081828385868788', + 'ecb-tbl-192: I=93'), + ('40414647b0afaead9b9a99989b98999e', '621fda3a5bbd54c6d3c685816bd4ead8', + '8a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-192: I=94'), + ('69686b6a0201001f0f0e0908b4bbbab9', 'd4e216040426dfaf18b152469bc5ac2f', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4', + 'ecb-tbl-192: I=95'), + ('c7c6c9c8d8dfdedd5a5b5859bebdbcb3', '9d0635b9d33b6cdbd71f5d246ea17cc8', + 'c6c7c8c9cbcccdced0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', + 'ecb-tbl-192: I=96'), + ('dedfdcdd787b7a7dfffee1e0b2b5b4b7', '10abad1bd9bae5448808765583a2cc1a', + 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6f8f9fafbfdfefe00', + 'ecb-tbl-192: I=97'), + ('4d4c4b4a606f6e6dd0d1d2d3fbf8f9fe', '6891889e16544e355ff65a793c39c9a8', + '020304050708090a0c0d0e0f11121314161718191b1c1d1e', + 'ecb-tbl-192: I=98'), + ('b7b6b5b4d7d4d5dae5e4e3e2e1fefffc', 'cc735582e68072c163cd9ddf46b91279', + '20212223252627282a2b2c2d2f30313234353637393a3b3c', + 'ecb-tbl-192: I=99'), + ('cecfb0b1f7f0f1f2aeafacad3e3d3c23', 'c5c68b9aeeb7f878df578efa562f9574', + '3e3f40414344454648494a4b4d4e4f50525354555758595a', + 'ecb-tbl-192: I=100'), + ('cacbc8c9cdcecfc812131c1d494e4f4c', '5f4764395a667a47d73452955d0d2ce8', + '5c5d5e5f61626364666768696b6c6d6e7071727375767778', + 'ecb-tbl-192: I=101'), + ('9d9c9b9ad22d2c2fb1b0b3b20c0f0e09', '701448331f66106cefddf1eb8267c357', + '7a7b7c7d7f80818284858687898a8b8c8e8f909193949596', + 'ecb-tbl-192: I=102'), + ('7a7b787964676659959493924f404142', 'cb3ee56d2e14b4e1941666f13379d657', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4', + 'ecb-tbl-192: I=103'), + ('aaaba4a5cec9c8cb1f1e1d1caba8a9a6', '9fe16efd18ab6e1981191851fedb0764', + 'b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', + 'ecb-tbl-192: I=104'), + ('93929190282b2a2dc4c5fafb92959497', '3dc9ba24e1b223589b147adceb4c8e48', + 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6e8e9eaebedeeeff0', + 'ecb-tbl-192: I=105'), + ('efeee9e8ded1d0d339383b3a888b8a8d', '1c333032682e7d4de5e5afc05c3e483c', + 'f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-192: I=106'), + ('7f7e7d7ca2a1a0af78797e7f112e2f2c', 'd593cc99a95afef7e92038e05a59d00a', + '10111213151617181a1b1c1d1f20212224252627292a2b2c', + 'ecb-tbl-192: I=107'), + ('84859a9b2b2c2d2e868784852625245b', '51e7f96f53b4353923452c222134e1ec', + '2e2f30313334353638393a3b3d3e3f40424344454748494a', + 'ecb-tbl-192: I=108'), + ('b0b1b2b3070405026869666710171615', '4075b357a1a2b473400c3b25f32f81a4', + '4c4d4e4f51525354565758595b5c5d5e6061626365666768', + 'ecb-tbl-192: I=109'), + ('acadaaabbda2a3a00d0c0f0e595a5b5c', '302e341a3ebcd74f0d55f61714570284', + '6a6b6c6d6f70717274757677797a7b7c7e7f808183848586', + 'ecb-tbl-192: I=110'), + ('121310115655544b5253545569666764', '57abdd8231280da01c5042b78cf76522', + '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4', + 'ecb-tbl-192: I=111'), + ('dedfd0d166616063eaebe8e94142434c', '17f9ea7eea17ac1adf0e190fef799e92', + 'a6a7a8a9abacadaeb0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', + 'ecb-tbl-192: I=112'), + ('dbdad9d81417161166677879e0e7e6e5', '2e1bdd563dd87ee5c338dd6d098d0a7a', + 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6d8d9dadbdddedfe0', + 'ecb-tbl-192: I=113'), + ('6a6b6c6de0efeeed2b2a2928c0c3c2c5', 'eb869996e6f8bfb2bfdd9e0c4504dbb2', + 'e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-192: I=114'), + ('b1b0b3b21714151a1a1b1c1d5649484b', 'c2e01549e9decf317468b3e018c61ba8', + '00010203050607080a0b0c0d0f10111214151617191a1b1c', + 'ecb-tbl-192: I=115'), + ('39380706a3a4a5a6c4c5c6c77271706f', '8da875d033c01dd463b244a1770f4a22', + '1e1f20212324252628292a2b2d2e2f30323334353738393a', + 'ecb-tbl-192: I=116'), + ('5c5d5e5f1013121539383736e2e5e4e7', '8ba0dcf3a186844f026d022f8839d696', + '3c3d3e3f41424344464748494b4c4d4e5051525355565758', + 'ecb-tbl-192: I=117'), + ('43424544ead5d4d72e2f2c2d64676661', 'e9691ff9a6cc6970e51670a0fd5b88c1', + '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-192: I=118'), + ('55545756989b9a65f8f9feff18171615', 'f2baec06faeed30f88ee63ba081a6e5b', + '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', + 'ecb-tbl-192: I=119'), + ('05040b0a525554573c3d3e3f4a494847', '9c39d4c459ae5753394d6094adc21e78', + '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', + 'ecb-tbl-192: I=120'), + ('14151617595a5b5c8584fbfa8e89888b', '6345b532a11904502ea43ba99c6bd2b2', + 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', + 'ecb-tbl-192: I=121'), + ('7c7d7a7bfdf2f3f029282b2a51525354', '5ffae3061a95172e4070cedce1e428c8', + 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-192: I=122'), + ('38393a3b1e1d1c1341404746c23d3c3e', '0a4566be4cdf9adce5dec865b5ab34cd', + 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', + 'ecb-tbl-192: I=123'), + ('8d8c939240474645818083827c7f7e41', 'ca17fcce79b7404f2559b22928f126fb', + '0e0f10111314151618191a1b1d1e1f20222324252728292a', + 'ecb-tbl-192: I=124'), + ('3b3a39381a19181f32333c3d45424340', '97ca39b849ed73a6470a97c821d82f58', + '2c2d2e2f31323334363738393b3c3d3e4041424345464748', + 'ecb-tbl-192: I=125'), + ('f0f1f6f738272625828380817f7c7d7a', '8198cb06bc684c6d3e9b7989428dcf7a', + '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', + 'ecb-tbl-192: I=126'), + ('89888b8a0407061966676061141b1a19', 'f53c464c705ee0f28d9a4c59374928bd', + '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', + 'ecb-tbl-192: I=127'), + ('d3d2dddcaaadacaf9c9d9e9fe8ebeae5', '9adb3d4cca559bb98c3e2ed73dbf1154', + '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', + 'ecb-tbl-192: I=128'), + + # ecb_tbl.txt, KEYSIZE=256 + ('834eadfccac7e1b30664b1aba44815ab', '1946dabf6a03a2a2c3d0b05080aed6fc', + '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', + 'ecb-tbl-256: I=1'), + ('d9dc4dba3021b05d67c0518f72b62bf1', '5ed301d747d3cc715445ebdec62f2fb4', + '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-256: I=2'), + ('a291d86301a4a739f7392173aa3c604c', '6585c8f43d13a6beab6419fc5935b9d0', + '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-256: I=3'), + ('4264b2696498de4df79788a9f83e9390', '2a5b56a596680fcc0e05f5e0f151ecae', + '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-256: I=4'), + ('ee9932b3721804d5a83ef5949245b6f6', 'f5d6ff414fd2c6181494d20c37f2b8c4', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-256: I=5'), + ('e6248f55c5fdcbca9cbbb01c88a2ea77', '85399c01f59fffb5204f19f8482f00b8', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-256: I=6'), + ('b8358e41b9dff65fd461d55a99266247', '92097b4c88a041ddf98144bc8d22e8e7', + 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', + 'ecb-tbl-256: I=7'), + ('f0e2d72260af58e21e015ab3a4c0d906', '89bd5b73b356ab412aef9f76cea2d65c', + '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-256: I=8'), + ('475b8b823ce8893db3c44a9f2a379ff7', '2536969093c55ff9454692f2fac2f530', + '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', + 'ecb-tbl-256: I=9'), + ('688f5281945812862f5f3076cf80412f', '07fc76a872843f3f6e0081ee9396d637', + '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-256: I=10'), + ('08d1d2bc750af553365d35e75afaceaa', 'e38ba8ec2aa741358dcc93e8f141c491', + '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-256: I=11'), + ('8707121f47cc3efceca5f9a8474950a1', 'd028ee23e4a89075d0b03e868d7d3a42', + 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', + 'ecb-tbl-256: I=12'), + ('e51aa0b135dba566939c3b6359a980c5', '8cd9423dfc459e547155c5d1d522e540', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', + 'ecb-tbl-256: I=13'), + ('069a007fc76a459f98baf917fedf9521', '080e9517eb1677719acf728086040ae3', + '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', + 'ecb-tbl-256: I=14'), + ('726165c1723fbcf6c026d7d00b091027', '7c1700211a3991fc0ecded0ab3e576b0', + '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', + 'ecb-tbl-256: I=15'), + ('d7c544de91d55cfcde1f84ca382200ce', 'dabcbcc855839251db51e224fbe87435', + '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-256: I=16'), + ('fed3c9a161b9b5b2bd611b41dc9da357', '68d56fad0406947a4dd27a7448c10f1d', + '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-256: I=17'), + ('4f634cdc6551043409f30b635832cf82', 'da9a11479844d1ffee24bbf3719a9925', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', + 'ecb-tbl-256: I=18'), + ('109ce98db0dfb36734d9f3394711b4e6', '5e4ba572f8d23e738da9b05ba24b8d81', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-256: I=19'), + ('4ea6dfaba2d8a02ffdffa89835987242', 'a115a2065d667e3f0b883837a6e903f8', + '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', + 'ecb-tbl-256: I=20'), + ('5ae094f54af58e6e3cdbf976dac6d9ef', '3e9e90dc33eac2437d86ad30b137e66e', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-256: I=21'), + ('764d8e8e0f29926dbe5122e66354fdbe', '01ce82d8fbcdae824cb3c48e495c3692', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-256: I=22'), + ('3f0418f888cdf29a982bf6b75410d6a9', '0c9cff163ce936faaf083cfd3dea3117', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-256: I=23'), + ('e4a3e7cb12cdd56aa4a75197a9530220', '5131ba9bd48f2bba85560680df504b52', + '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', + 'ecb-tbl-256: I=24'), + ('211677684aac1ec1a160f44c4ebf3f26', '9dc503bbf09823aec8a977a5ad26ccb2', + '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-256: I=25'), + ('d21e439ff749ac8f18d6d4b105e03895', '9a6db0c0862e506a9e397225884041d7', + '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', + 'ecb-tbl-256: I=26'), + ('d9f6ff44646c4725bd4c0103ff5552a7', '430bf9570804185e1ab6365fc6a6860c', + '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-256: I=27'), + ('0b1256c2a00b976250cfc5b0c37ed382', '3525ebc02f4886e6a5a3762813e8ce8a', + 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-256: I=28'), + ('b056447ffc6dc4523a36cc2e972a3a79', '07fa265c763779cce224c7bad671027b', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-256: I=29'), + ('5e25ca78f0de55802524d38da3fe4456', 'e8b72b4e8be243438c9fff1f0e205872', + '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', + 'ecb-tbl-256: I=30'), + ('a5bcf4728fa5eaad8567c0dc24675f83', '109d4f999a0e11ace1f05e6b22cbcb50', + '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-256: I=31'), + ('814e59f97ed84646b78b2ca022e9ca43', '45a5e8d4c3ed58403ff08d68a0cc4029', + '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-256: I=32'), + ('15478beec58f4775c7a7f5d4395514d7', '196865964db3d417b6bd4d586bcb7634', + '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-256: I=33'), + ('253548ffca461c67c8cbc78cd59f4756', '60436ad45ac7d30d99195f815d98d2ae', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-256: I=34'), + ('fd7ad8d73b9b0f8cc41600640f503d65', 'bb07a23f0b61014b197620c185e2cd75', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-256: I=35'), + ('06199de52c6cbf8af954cd65830bcd56', '5bc0b2850129c854423aff0751fe343b', + 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', + 'ecb-tbl-256: I=36'), + ('f17c4ffe48e44c61bd891e257e725794', '7541a78f96738e6417d2a24bd2beca40', + '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-256: I=37'), + ('9a5b4a402a3e8a59be6bf5cd8154f029', 'b0a303054412882e464591f1546c5b9e', + '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', + 'ecb-tbl-256: I=38'), + ('79bd40b91a7e07dc939d441782ae6b17', '778c06d8a355eeee214fcea14b4e0eef', + '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-256: I=39'), + ('d8ceaaf8976e5fbe1012d8c84f323799', '09614206d15cbace63227d06db6beebb', + '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-256: I=40'), + ('3316e2751e2e388b083da23dd6ac3fbe', '41b97fb20e427a9fdbbb358d9262255d', + 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', + 'ecb-tbl-256: I=41'), + ('8b7cfbe37de7dca793521819242c5816', 'c1940f703d845f957652c2d64abd7adf', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', + 'ecb-tbl-256: I=42'), + ('f23f033c0eebf8ec55752662fd58ce68', 'd2d44fcdae5332343366db297efcf21b', + '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', + 'ecb-tbl-256: I=43'), + ('59eb34f6c8bdbacc5fc6ad73a59a1301', 'ea8196b79dbe167b6aa9896e287eed2b', + '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', + 'ecb-tbl-256: I=44'), + ('dcde8b6bd5cf7cc22d9505e3ce81261a', 'd6b0b0c4ba6c7dbe5ed467a1e3f06c2d', + '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-256: I=45'), + ('e33cf7e524fed781e7042ff9f4b35dc7', 'ec51eb295250c22c2fb01816fb72bcae', + '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-256: I=46'), + ('27963c8facdf73062867d164df6d064c', 'aded6630a07ce9c7408a155d3bd0d36f', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', + 'ecb-tbl-256: I=47'), + ('77b1ce386b551b995f2f2a1da994eef8', '697c9245b9937f32f5d1c82319f0363a', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-256: I=48'), + ('f083388b013679efcf0bb9b15d52ae5c', 'aad5ad50c6262aaec30541a1b7b5b19c', + 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', + 'ecb-tbl-256: I=49'), + ('c5009e0dab55db0abdb636f2600290c8', '7d34b893855341ec625bd6875ac18c0d', + '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', + 'ecb-tbl-256: I=50'), + ('7804881e26cd532d8514d3683f00f1b9', '7ef05105440f83862f5d780e88f02b41', + '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', + 'ecb-tbl-256: I=51'), + ('46cddcd73d1eb53e675ca012870a92a3', 'c377c06403382061af2c9c93a8e70df6', + '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', + 'ecb-tbl-256: I=52'), + ('a9fb44062bb07fe130a8e8299eacb1ab', '1dbdb3ffdc052dacc83318853abc6de5', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-256: I=53'), + ('2b6ff8d7a5cc3a28a22d5a6f221af26b', '69a6eab00432517d0bf483c91c0963c7', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-256: I=54'), + ('1a9527c29b8add4b0e3e656dbb2af8b4', '0797f41dc217c80446e1d514bd6ab197', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-256: I=55'), + ('7f99cf2c75244df015eb4b0c1050aeae', '9dfd76575902a637c01343c58e011a03', + '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', + 'ecb-tbl-256: I=56'), + ('e84ff85b0d9454071909c1381646c4ed', 'acf4328ae78f34b9fa9b459747cc2658', + '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-256: I=57'), + ('89afd40f99521280d5399b12404f6db4', 'b0479aea12bac4fe2384cf98995150c6', + '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', + 'ecb-tbl-256: I=58'), + ('a09ef32dbc5119a35ab7fa38656f0329', '9dd52789efe3ffb99f33b3da5030109a', + '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-256: I=59'), + ('61773457f068c376c7829b93e696e716', 'abbb755e4621ef8f1214c19f649fb9fd', + 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-256: I=60'), + ('a34f0cae726cce41dd498747d891b967', 'da27fb8174357bce2bed0e7354f380f9', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-256: I=61'), + ('856f59496c7388ee2d2b1a27b7697847', 'c59a0663f0993838f6e5856593bdc5ef', + '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', + 'ecb-tbl-256: I=62'), + ('cb090c593ef7720bd95908fb93b49df4', 'ed60b264b5213e831607a99c0ce5e57e', + '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-256: I=63'), + ('a0ac75cd2f1923d460fc4d457ad95baf', 'e50548746846f3eb77b8c520640884ed', + '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-256: I=64'), + ('2a2b282974777689e8e9eeef525d5c5f', '28282cc7d21d6a2923641e52d188ef0c', + '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-256: I=65'), + ('909192939390919e0f0e09089788898a', '0dfa5b02abb18e5a815305216d6d4f8e', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-256: I=66'), + ('777675748d8e8f907170777649464744', '7359635c0eecefe31d673395fb46fb99', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-256: I=67'), + ('717073720605040b2d2c2b2a05fafbf9', '73c679f7d5aef2745c9737bb4c47fb36', + 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', + 'ecb-tbl-256: I=68'), + ('64656667fefdfcc31b1a1d1ca5aaaba8', 'b192bd472a4d2eafb786e97458967626', + '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-256: I=69'), + ('dbdad9d86a696867b5b4b3b2c8d7d6d5', '0ec327f6c8a2b147598ca3fde61dc6a4', + '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', + 'ecb-tbl-256: I=70'), + ('5c5d5e5fe3e0e1fe31303736333c3d3e', 'fc418eb3c41b859b38d4b6f646629729', + '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-256: I=71'), + ('545556574b48494673727574546b6a69', '30249e5ac282b1c981ea64b609f3a154', + '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-256: I=72'), + ('ecedeeefc6c5c4bb56575051f5fafbf8', '5e6e08646d12150776bb43c2d78a9703', + 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', + 'ecb-tbl-256: I=73'), + ('464744452724252ac9c8cfced2cdcccf', 'faeb3d5de652cd3447dceb343f30394a', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', + 'ecb-tbl-256: I=74'), + ('e6e7e4e54142435c878681801c131211', 'a8e88706823f6993ef80d05c1c7b2cf0', + '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', + 'ecb-tbl-256: I=75'), + ('72737071cfcccdc2f9f8fffe710e0f0c', '8ced86677e6e00a1a1b15968f2d3cce6', + '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', + 'ecb-tbl-256: I=76'), + ('505152537370714ec3c2c5c4010e0f0c', '9fc7c23858be03bdebb84e90db6786a9', + '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-256: I=77'), + ('a8a9aaab5c5f5e51aeafa8a93d222320', 'b4fbd65b33f70d8cf7f1111ac4649c36', + '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-256: I=78'), + ('dedfdcddf6f5f4eb10111617fef1f0f3', 'c5c32d5ed03c4b53cc8c1bd0ef0dbbf6', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', + 'ecb-tbl-256: I=79'), + ('bdbcbfbe5e5d5c530b0a0d0cfac5c4c7', 'd1a7f03b773e5c212464b63709c6a891', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-256: I=80'), + ('8a8b8889050606f8f4f5f2f3636c6d6e', '6b7161d8745947ac6950438ea138d028', + 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', + 'ecb-tbl-256: I=81'), + ('a6a7a4a54d4e4f40b2b3b4b539262724', 'fd47a9f7e366ee7a09bc508b00460661', + '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', + 'ecb-tbl-256: I=82'), + ('9c9d9e9fe9eaebf40e0f08099b949596', '00d40b003dc3a0d9310b659b98c7e416', + '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', + 'ecb-tbl-256: I=83'), + ('2d2c2f2e1013121dcccdcacbed121310', 'eea4c79dcc8e2bda691f20ac48be0717', + '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', + 'ecb-tbl-256: I=84'), + ('f4f5f6f7edeeefd0eaebecedf7f8f9fa', 'e78f43b11c204403e5751f89d05a2509', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-256: I=85'), + ('3d3c3f3e282b2a2573727574150a0b08', 'd0f0e3d1f1244bb979931e38dd1786ef', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-256: I=86'), + ('b6b7b4b5f8fbfae5b4b5b2b3a0afaead', '042e639dc4e1e4dde7b75b749ea6f765', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-256: I=87'), + ('b7b6b5b4989b9a95878681809ba4a5a6', 'bc032fdd0efe29503a980a7d07ab46a8', + '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', + 'ecb-tbl-256: I=88'), + ('a8a9aaabe5e6e798e9e8efee4748494a', '0c93ac949c0da6446effb86183b6c910', + '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-256: I=89'), + ('ecedeeefd9dadbd4b9b8bfbe657a7b78', 'e0d343e14da75c917b4a5cec4810d7c2', + '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', + 'ecb-tbl-256: I=90'), + ('7f7e7d7c696a6b74cacbcccd929d9c9f', '0eafb821748408279b937b626792e619', + '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-256: I=91'), + ('08090a0b0605040bfffef9f8b9c6c7c4', 'fa1ac6e02d23b106a1fef18b274a553f', + 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-256: I=92'), + ('08090a0bf1f2f3ccfcfdfafb68676665', '0dadfe019cd12368075507df33c1a1e9', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-256: I=93'), + ('cacbc8c93a393837050403020d121310', '3a0879b414465d9ffbaf86b33a63a1b9', + '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', + 'ecb-tbl-256: I=94'), + ('e9e8ebea8281809f8f8e8988343b3a39', '62199fadc76d0be1805d3ba0b7d914bf', + '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-256: I=95'), + ('515053524645444bd0d1d6d7340b0a09', '1b06d6c5d333e742730130cf78e719b4', + '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-256: I=96'), + ('42434041ecefee1193929594c6c9c8cb', 'f1f848824c32e9dcdcbf21580f069329', + '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', + 'ecb-tbl-256: I=97'), + ('efeeedecc2c1c0cf76777071455a5b58', '1a09050cbd684f784d8e965e0782f28a', + 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', + 'ecb-tbl-256: I=98'), + ('5f5e5d5c3f3c3d221d1c1b1a19161714', '79c2969e7ded2ba7d088f3f320692360', + 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', + 'ecb-tbl-256: I=99'), + ('000102034142434c1c1d1a1b8d727371', '091a658a2f7444c16accb669450c7b63', + 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', + 'ecb-tbl-256: I=100'), + ('8e8f8c8db1b2b38c56575051050a0b08', '97c1e3a72cca65fa977d5ed0e8a7bbfc', + '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', + 'ecb-tbl-256: I=101'), + ('a7a6a5a4e8ebeae57f7e7978cad5d4d7', '70c430c6db9a17828937305a2df91a2a', + '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', + 'ecb-tbl-256: I=102'), + ('8a8b888994979689454443429f909192', '629553457fbe2479098571c7c903fde8', + '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', + 'ecb-tbl-256: I=103'), + ('8c8d8e8fe0e3e2ed45444342f1cecfcc', 'a25b25a61f612669e7d91265c7d476ba', + '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', + 'ecb-tbl-256: I=104'), + ('fffefdfc4c4f4e31d8d9dedfb6b9b8bb', 'eb7e4e49b8ae0f024570dda293254fed', + 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', + 'ecb-tbl-256: I=105'), + ('fdfcfffecccfcec12f2e29286679787b', '38fe15d61cca84516e924adce5014f67', + 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', + 'ecb-tbl-256: I=106'), + ('67666564bab9b8a77071767719161714', '3ad208492249108c9f3ebeb167ad0583', + '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', + 'ecb-tbl-256: I=107'), + ('9a9b98992d2e2f2084858283245b5a59', '299ba9f9bf5ab05c3580fc26edd1ed12', + '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', + 'ecb-tbl-256: I=108'), + ('a4a5a6a70b0809365c5d5a5b2c232221', '19dc705b857a60fb07717b2ea5717781', + '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', + 'ecb-tbl-256: I=109'), + ('464744455754555af3f2f5f4afb0b1b2', 'ffc8aeb885b5efcad06b6dbebf92e76b', + '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', + 'ecb-tbl-256: I=110'), + ('323330317675746b7273747549464744', 'f58900c5e0b385253ff2546250a0142b', + 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', + 'ecb-tbl-256: I=111'), + ('a8a9aaab181b1a15808186872b141516', '2ee67b56280bc462429cee6e3370cbc1', + 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', + 'ecb-tbl-256: I=112'), + ('e7e6e5e4202323ddaaabacad343b3a39', '20db650a9c8e9a84ab4d25f7edc8f03f', + 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', + 'ecb-tbl-256: I=113'), + ('a8a9aaab2221202fedecebea1e010003', '3c36da169525cf818843805f25b78ae5', + '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', + 'ecb-tbl-256: I=114'), + ('f9f8fbfa5f5c5d42424344450e010003', '9a781d960db9e45e37779042fea51922', + '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', + 'ecb-tbl-256: I=115'), + ('57565554f5f6f7f89697909120dfdedd', '6560395ec269c672a3c288226efdba77', + '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', + 'ecb-tbl-256: I=116'), + ('f8f9fafbcccfcef1dddcdbda0e010003', '8c772b7a189ac544453d5916ebb27b9a', + '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', + 'ecb-tbl-256: I=117'), + ('d9d8dbda7073727d80818687c2dddcdf', '77ca5468cc48e843d05f78eed9d6578f', + 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', + 'ecb-tbl-256: I=118'), + ('c5c4c7c6080b0a1588898e8f68676665', '72cdcc71dc82c60d4429c9e2d8195baa', + 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', + 'ecb-tbl-256: I=119'), + ('83828180dcdfded186878081f0cfcecd', '8080d68ce60e94b40b5b8b69eeb35afa', + '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', + 'ecb-tbl-256: I=120'), + ('98999a9bdddedfa079787f7e0a050407', '44222d3cde299c04369d58ac0eba1e8e', + '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', + 'ecb-tbl-256: I=121'), + ('cecfcccd4f4c4d429f9e9998dfc0c1c2', '9b8721b0a8dfc691c5bc5885dbfcb27a', + '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', + 'ecb-tbl-256: I=122'), + ('404142436665647b29282f2eaba4a5a6', '0dc015ce9a3a3414b5e62ec643384183', + '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', + 'ecb-tbl-256: I=123'), + ('33323130e6e5e4eb23222524dea1a0a3', '705715448a8da412025ce38345c2a148', + 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', + 'ecb-tbl-256: I=124'), + ('cfcecdccf6f5f4cbe6e7e0e199969794', 'c32b5b0b6fbae165266c569f4b6ecf0b', + 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', + 'ecb-tbl-256: I=125'), + ('babbb8b97271707fdcdddadb29363734', '4dca6c75192a01ddca9476af2a521e87', + '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', + 'ecb-tbl-256: I=126'), + ('c9c8cbca4447465926272021545b5a59', '058691e627ecbc36ac07b6db423bd698', + '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', + 'ecb-tbl-256: I=127'), + ('050407067477767956575051221d1c1f', '7444527095838fe080fc2bcdd30847eb', + '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', + 'ecb-tbl-256: I=128'), + + # FIPS PUB 800-38A test vectors, 2001 edition. Annex F. + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '3ad77bb40d7a3660a89ecaf32466ef97'+'f5d3d58503b9699de785895a96fdbaaf'+ + '43b1cd7f598ece23881b00e3ed030688'+'7b0c785e27e8ad3f8223207104725dd4', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.1.1, ECB and AES-128'), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'bd334f1d6e45f25ff712a214571fa5cc'+'974104846d0ad3ad7734ecb3ecee4eef'+ + 'ef7afd2270e2e60adce0ba2face6444e'+'9a4b41ba738d6c72fb16691603c18e0e', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.1.3, ECB and AES-192'), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'f3eed1bdb5d2a03c064b5a7e3db181f8'+'591ccb10d410ed26dc5ba74a31362870'+ + 'b6ed21b99ca6f4f9f153e7b1beafed1d'+'23304b7a39f9f3ff067d8d8f9e24ecc7', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.1.3, ECB and AES-256'), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '7649abac8119b246cee98e9b12e9197d'+'5086cb9b507219ee95db113a917678b2'+ + '73bed6b8e3c1743b7116e69e22229516'+'3ff1caa1681fac09120eca307586e1a7', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.2.1, CBC and AES-128', + dict(mode='CBC', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '4f021db243bc633d7178183a9fa071e8'+'b4d9ada9ad7dedf4e5e738763f69145a'+ + '571b242012fb7ae07fa9baac3df102e0'+'08b0e27988598881d920a9e64f5615cd', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.2.1, CBC and AES-192', + dict(mode='CBC', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'f58c4c04d6e5f1ba779eabfb5f7bfbd6'+'9cfc4e967edb808d679f777bc6702c7d'+ + '39f23369a9d9bacfa530e26304231461'+'b2eb05e2c39be9fcda6c19078c6a9d1b', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.2.1, CBC and AES-256', + dict(mode='CBC', iv='000102030405060708090a0b0c0d0e0f')), + + # Skip CFB-1 since it is not supported by PyCrypto + + ('6bc1bee22e409f96e93d7e117393172aae2d','3b79424c9c0dd436bace9e0ed4586a4f32b9', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.3.7, CFB-8 and AES-128', + dict(mode='CFB', iv='000102030405060708090a0b0c0d0e0f', segment_size=8)), + + ('6bc1bee22e409f96e93d7e117393172aae2d','cda2521ef0a905ca44cd057cbf0d47a0678a', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.3.9, CFB-8 and AES-192', + dict(mode='CFB', iv='000102030405060708090a0b0c0d0e0f', segment_size=8)), + + ('6bc1bee22e409f96e93d7e117393172aae2d','dc1f1a8520a64db55fcc8ac554844e889700', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.3.11, CFB-8 and AES-256', + dict(mode='CFB', iv='000102030405060708090a0b0c0d0e0f', segment_size=8)), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '3b3fd92eb72dad20333449f8e83cfb4a'+'c8a64537a0b3a93fcde3cdad9f1ce58b'+ + '26751f67a3cbb140b1808cf187a4f4df'+'c04b05357c5d1c0eeac4c66f9ff7f2e6', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.3.13, CFB-128 and AES-128', + dict(mode='CFB', iv='000102030405060708090a0b0c0d0e0f', segment_size=128)), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'cdc80d6fddf18cab34c25909c99a4174'+'67ce7f7f81173621961a2b70171d3d7a'+ + '2e1e8a1dd59b88b1c8e60fed1efac4c9'+'c05f9f9ca9834fa042ae8fba584b09ff', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.3.15, CFB-128 and AES-192', + dict(mode='CFB', iv='000102030405060708090a0b0c0d0e0f', segment_size=128)), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'dc7e84bfda79164b7ecd8486985d3860'+'39ffed143b28b1c832113c6331e5407b'+ + 'df10132415e54b92a13ed0a8267ae2f9'+'75a385741ab9cef82031623d55b1e471', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.3.17, CFB-128 and AES-256', + dict(mode='CFB', iv='000102030405060708090a0b0c0d0e0f', segment_size=128)), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '3b3fd92eb72dad20333449f8e83cfb4a'+'7789508d16918f03f53c52dac54ed825'+ + '9740051e9c5fecf64344f7a82260edcc'+'304c6528f659c77866a510d9c1d6ae5e', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.4.1, OFB and AES-128', + dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'cdc80d6fddf18cab34c25909c99a4174'+'fcc28b8d4c63837c09e81700c1100401'+ + '8d9a9aeac0f6596f559c6d4daf59a5f2'+'6d9f200857ca6c3e9cac524bd9acc92a', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.4.3, OFB and AES-192', + dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + 'dc7e84bfda79164b7ecd8486985d3860'+'4febdc6740d20b3ac88f6ad82a4fb08d'+ + '71ab47a086e86eedf39d1c5bba97c408'+'0126141d67f37be8538f5a8be740e484', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.4.5, OFB and AES-256', + dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17', + '3b3fd92eb72dad20333449f8e83cfb4a'+'7789508d16918f03f53c52dac54ed825'+ + '9740051e9c5fecf64344f7a82260edcc'+'304c6528f659c778', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.4.1, OFB and AES-128 (partial last block)', + dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17', + 'cdc80d6fddf18cab34c25909c99a4174'+'fcc28b8d4c63837c09e81700c1100401'+ + '8d9a9aeac0f6596f559c6d4daf59a5f2'+'6d9f200857ca6c3e', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.4.3, OFB and AES-192 (partial last block)', + dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17', + 'dc7e84bfda79164b7ecd8486985d3860'+'4febdc6740d20b3ac88f6ad82a4fb08d'+ + '71ab47a086e86eedf39d1c5bba97c408'+'0126141d67f37be8', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.4.5, OFB and AES-256 (partial last block)', + dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '874d6191b620e3261bef6864990db6ce'+'9806f66b7970fdff8617187bb9fffdff'+ + '5ae4df3edbd5d35e5b4f09020db03eab'+'1e031dda2fbe03d1792170a0f3009cee', + '2b7e151628aed2a6abf7158809cf4f3c', + 'NIST 800-38A, F.5.1, CTR and AES-128', + dict(mode='CTR', ctr_params=dict(nbits=16, prefix='f0f1f2f3f4f5f6f7f8f9fafbfcfd', initial_value=0xfeff))), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '1abc932417521ca24f2b0459fe7e6e0b'+'090339ec0aa6faefd5ccc2c6f4ce8e94'+ + '1e36b26bd1ebc670d1bd1d665620abf7'+'4f78a7f6d29809585a97daec58c6b050', + '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', + 'NIST 800-38A, F.5.3, CTR and AES-192', + dict(mode='CTR', ctr_params=dict(nbits=16, prefix='f0f1f2f3f4f5f6f7f8f9fafbfcfd', initial_value=0xfeff))), + + ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', + '601ec313775789a5b7a7f504bbf3d228'+'f443e3ca4d62b59aca84e990cacaf5c5'+ + '2b0930daa23de94ce87017ba2d84988d'+'dfc9c58db67aada613c2dd08457941a6', + '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', + 'NIST 800-38A, F.5.5, CTR and AES-256', + dict(mode='CTR', ctr_params=dict(nbits=16, prefix='f0f1f2f3f4f5f6f7f8f9fafbfcfd', initial_value=0xfeff))), + + # RFC 3686 test vectors + # This is a list of (plaintext, ciphertext, key[, description[, params]]) tuples. + ('53696e676c6520626c6f636b206d7367', 'e4095d4fb7a7b3792d6175a3261311b8', + 'ae6852f8121067cc4bf7a5765577f39e', + 'RFC 3686 Test Vector #1: Encrypting 16 octets using AES-CTR with 128-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='00000030'+'0000000000000000'))), + ('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', + '5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28', + '7e24067817fae0d743d6ce1f32539163', + 'RFC 3686 Test Vector #2: Encrypting 32 octets using AES-CTR with 128-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='006cb6db'+'c0543b59da48d90b'))), + ('000102030405060708090a0b0c0d0e0f'+'101112131415161718191a1b1c1d1e1f'+'20212223', + 'c1cf48a89f2ffdd9cf4652e9efdb72d7'+'4540a42bde6d7836d59a5ceaaef31053'+'25b2072f', + '7691be035e5020a8ac6e618529f9a0dc', + 'RFC 3686 Test Vector #3: Encrypting 36 octets using AES-CTR with 128-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='00e0017b'+'27777f3f4a1786f0'))), + ('53696e676c6520626c6f636b206d7367', + '4b55384fe259c9c84e7935a003cbe928', + '16af5b145fc9f579c175f93e3bfb0eed'+'863d06ccfdb78515', + 'RFC 3686 Test Vector #4: Encrypting 16 octets using AES-CTR with 192-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='00000048'+'36733c147d6d93cb'))), + ('000102030405060708090a0b0c0d0e0f'+'101112131415161718191a1b1c1d1e1f', + '453243fc609b23327edfaafa7131cd9f'+'8490701c5ad4a79cfc1fe0ff42f4fb00', + '7c5cb2401b3dc33c19e7340819e0f69c'+'678c3db8e6f6a91a', + 'RFC 3686 Test Vector #5: Encrypting 32 octets using AES-CTR with 192-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='0096b03b'+'020c6eadc2cb500d'))), + ('000102030405060708090a0b0c0d0e0f'+'101112131415161718191a1b1c1d1e1f'+'20212223', + '96893fc55e5c722f540b7dd1ddf7e758'+'d288bc95c69165884536c811662f2188'+'abee0935', + '02bf391ee8ecb159b959617b0965279b'+'f59b60a786d3e0fe', + 'RFC 3686 Test Vector #6: Encrypting 36 octets using AES-CTR with 192-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='0007bdfd'+'5cbd60278dcc0912'))), + ('53696e676c6520626c6f636b206d7367', + '145ad01dbf824ec7560863dc71e3e0c0', + '776beff2851db06f4c8a0542c8696f6c'+'6a81af1eec96b4d37fc1d689e6c1c104', + 'RFC 3686 Test Vector #7: Encrypting 16 octets using AES-CTR with 256-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='00000060'+'db5672c97aa8f0b2'))), + ('000102030405060708090a0b0c0d0e0f'+'101112131415161718191a1b1c1d1e1f', + 'f05e231b3894612c49ee000b804eb2a9'+'b8306b508f839d6a5530831d9344af1c', + 'f6d66d6bd52d59bb0796365879eff886'+'c66dd51a5b6a99744b50590c87a23884', + 'RFC 3686 Test Vector #8: Encrypting 32 octets using AES-CTR with 256-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='00faac24'+'c1585ef15a43d875'))), + ('000102030405060708090a0b0c0d0e0f'+'101112131415161718191a1b1c1d1e1f'+'20212223', + 'eb6c52821d0bbbf7ce7594462aca4faa'+'b407df866569fd07f48cc0b583d6071f'+'1ec0e6b8', + 'ff7a617ce69148e4f1726e2f43581de2'+'aa62d9f805532edff1eed687fb54153d', + 'RFC 3686 Test Vector #9: Encrypting 36 octets using AES-CTR with 256-bit key', + dict(mode='CTR', ctr_params=dict(nbits=32, prefix='001cc5b7'+'51a51d70a1c11148'))), + + # The following test vectors have been generated with gpg v1.4.0. + # The command line used was: + # + # gpg -c -z 0 --cipher-algo AES --passphrase secret_passphrase \ + # --disable-mdc --s2k-mode 0 --output ct pt + # + # As result, the content of the file 'pt' is encrypted with a key derived + # from 'secret_passphrase' and written to file 'ct'. + # Test vectors must be extracted from 'ct', which is a collection of + # TLVs (see RFC4880 for all details): + # - the encrypted data (with the encrypted IV as prefix) is the payload + # of the TLV with tag 9 (Symmetrical Encrypted Data Packet). + # This is the ciphertext in the test vector. + # - inside the encrypted part, there is a further layer of TLVs. One must + # look for tag 11 (Literal Data Packet); in its payload, after a short + # but time dependent header, there is the content of file 'pt'. + # In the test vector, the plaintext is the complete set of TLVs that gets + # encrypted. It is not just the content of 'pt'. + # - the key is the leftmost 16 bytes of the SHA1 digest of the password. + # The test vector contains such shortened digest. + # + # Note that encryption uses a clear IV, and decryption an encrypted IV + ( 'ac18620270744fb4f647426c61636b4361745768697465436174', # Plaintext, 'BlackCatWhiteCat' + 'dc6b9e1f095de609765c59983db5956ae4f63aea7405389d2ebb', # Ciphertext + '5baa61e4c9b93f3f0682250b6cf8331b', # Key (hash of 'password') + 'GPG Test Vector #1', + dict(mode='OPENPGP', iv='3d7d3e62282add7eb203eeba5c800733', encrypted_iv='fd934601ef49cb58b6d9aebca6056bdb96ef' ) ), + + # NIST SP 800-38C test vectors for CCM + # This is a list of tuples with 5 items: + # + # 1. Associated data + '|' + plaintext + # 2. Associated data + '|' + ciphertext + '|' + MAC + # 3. AES-128 key + # 4. Description + # 5. Dictionary of parameters to be passed to AES.new(). + # It must include the nonce. + # + ( '0001020304050607|20212223', + '0001020304050607|7162015b|4dac255d', + '404142434445464748494a4b4c4d4e4f', + 'NIST SP 800-38C Appex C.1', + dict(mode='CCM', nonce='10111213141516') + ), + ( '000102030405060708090a0b0c0d0e0f|202122232425262728292a2b2c2d2e2f', + '000102030405060708090a0b0c0d0e0f|d2a1f0e051ea5f62081a7792073d593d|1fc64fbfaccd', + '404142434445464748494a4b4c4d4e4f', + 'NIST SP 800-38C Appex C.2', + dict(mode='CCM', nonce='1011121314151617') + ), + ( '000102030405060708090a0b0c0d0e0f10111213|'+ + '202122232425262728292a2b2c2d2e2f3031323334353637', + '000102030405060708090a0b0c0d0e0f10111213|'+ + 'e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5|484392fbc1b09951', + '404142434445464748494a4b4c4d4e4f', + 'NIST SP 800-38C Appex C.3', + dict(mode='CCM', nonce='101112131415161718191a1b') + ), + ( + (''.join(["%02X" % (x*16+y) for x in xrange(0,16) for y in xrange(0,16)]))*256+'|'+ + '202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f', + (''.join(["%02X" % (x*16+y) for x in xrange(0,16) for y in xrange(0,16)]))*256+'|'+ + '69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72|'+ + 'b4ac6bec93e8598e7f0dadbcea5b', + '404142434445464748494a4b4c4d4e4f', + 'NIST SP 800-38C Appex C.4', + dict(mode='CCM', nonce='101112131415161718191a1b1c') + ), + # RFC3610 test vectors + ( + '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', + '0001020304050607|588c979a61c663d2f066d0c2c0f989806d5f6b61dac384|'+ + '17e8d12cfdf926e0', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #1', + dict(mode='CCM', nonce='00000003020100a0a1a2a3a4a5') + ), + ( + '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', + '0001020304050607|72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b|'+ + 'a091d56e10400916', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #2', + dict(mode='CCM', nonce='00000004030201a0a1a2a3a4a5') + ), + ( + '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', + '0001020304050607|51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657|'+ + '4adaa76fbd9fb0c5', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #3', + dict(mode='CCM', nonce='00000005040302A0A1A2A3A4A5') + ), + ( + '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e', + '000102030405060708090a0b|a28c6865939a9a79faaa5c4c2a9d4a91cdac8c|'+ + '96c861b9c9e61ef1', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #4', + dict(mode='CCM', nonce='00000006050403a0a1a2a3a4a5') + ), + ( + '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f', + '000102030405060708090a0b|dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e|'+ + '51e83f077d9c2d93', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #5', + dict(mode='CCM', nonce='00000007060504a0a1a2a3a4a5') + ), + ( + '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f20', + '000102030405060708090a0b|6fc1b011f006568b5171a42d953d469b2570a4bd87|'+ + '405a0443ac91cb94', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #6', + dict(mode='CCM', nonce='00000008070605a0a1a2a3a4a5') + ), + ( + '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', + '0001020304050607|0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c|'+ + '048c56602c97acbb7490', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #7', + dict(mode='CCM', nonce='00000009080706a0a1a2a3a4a5') + ), + ( + '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', + '0001020304050607|7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24|'+ + 'c17b4433f434963f34b4', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #8', + dict(mode='CCM', nonce='0000000a090807a0a1a2a3a4a5') + ), + ( + '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', + '0001020304050607|82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197|'+ + 'ea9c07e56b5eb17e5f4e', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #9', + dict(mode='CCM', nonce='0000000b0a0908a0a1a2a3a4a5') + ), + ( + '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e', + '000102030405060708090a0b|07342594157785152b074098330abb141b947b|'+ + '566aa9406b4d999988dd', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #10', + dict(mode='CCM', nonce='0000000c0b0a09a0a1a2a3a4a5') + ), + ( + '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f', + '000102030405060708090a0b|676bb20380b0e301e8ab79590a396da78b834934|'+ + 'f53aa2e9107a8b6c022c', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #11', + dict(mode='CCM', nonce='0000000d0c0b0aa0a1a2a3a4a5') + ), + ( + '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f20', + '000102030405060708090a0b|c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43|'+ + 'cd1aa31662e7ad65d6db', + 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', + 'RFC3610 Packet Vector #12', + dict(mode='CCM', nonce='0000000e0d0c0ba0a1a2a3a4a5') + ), + ( + '0be1a88bace018b1|08e8cf97d820ea258460e96ad9cf5289054d895ceac47c', + '0be1a88bace018b1|4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8|'+ + 'e78cf7cb0cddd7b3', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #13', + dict(mode='CCM', nonce='00412b4ea9cdbe3c9696766cfa') + ), + ( + '63018f76dc8a1bcb|9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec', + '63018f76dc8a1bcb|4ccb1e7ca981befaa0726c55d378061298c85c92814abc33|'+ + 'c52ee81d7d77c08a', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #14', + dict(mode='CCM', nonce='0033568ef7b2633c9696766cfa') + ), + ( + 'aa6cfa36cae86b40|b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e', + 'aa6cfa36cae86b40|b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708|'+ + 'a776796edb723506', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #15', + dict(mode='CCM', nonce='00103fe41336713c9696766cfa') + ), + ( + 'd0d0735c531e1becf049c244|12daac5630efa5396f770ce1a66b21f7b2101c', + 'd0d0735c531e1becf049c244|14d253c3967b70609b7cbb7c49916028324526|'+ + '9a6f49975bcadeaf', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #16', + dict(mode='CCM', nonce='00764c63b8058e3c9696766cfa') + ), + ( + '77b60f011c03e1525899bcae|e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d', + '77b60f011c03e1525899bcae|5545ff1a085ee2efbf52b2e04bee1e2336c73e3f|'+ + '762c0c7744fe7e3c', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #17', + dict(mode='CCM', nonce='00f8b678094e3b3c9696766cfa') + ), + ( + 'cd9044d2b71fdb8120ea60c0|6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f', + 'cd9044d2b71fdb8120ea60c0|009769ecabdf48625594c59251e6035722675e04c8|'+ + '47099e5ae0704551', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #18', + dict(mode='CCM', nonce='00d560912d3f703c9696766cfa') + ), + ( + 'd85bc7e69f944fb8|8a19b950bcf71a018e5e6701c91787659809d67dbedd18', + 'd85bc7e69f944fb8|bc218daa947427b6db386a99ac1aef23ade0b52939cb6a|'+ + '637cf9bec2408897c6ba', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #19', + dict(mode='CCM', nonce='0042fff8f1951c3c9696766cfa') + ), + ( + '74a0ebc9069f5b37|1761433c37c5a35fc1f39f406302eb907c6163be38c98437', + '74a0ebc9069f5b37|5810e6fd25874022e80361a478e3e9cf484ab04f447efff6|'+ + 'f0a477cc2fc9bf548944', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #20', + dict(mode='CCM', nonce='00920f40e56cdc3c9696766cfa') + ), + ( + '44a3aa3aae6475ca|a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa', + '44a3aa3aae6475ca|f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154|'+ + '4d4151a4ed3a8b87b9ce', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #21', + dict(mode='CCM', nonce='0027ca0c7120bc3c9696766cfa') + ), + ( + 'ec46bb63b02520c33c49fd70|b96b49e21d621741632875db7f6c9243d2d7c2', + 'ec46bb63b02520c33c49fd70|31d750a09da3ed7fddd49a2032aabf17ec8ebf|'+ + '7d22c8088c666be5c197', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #22', + dict(mode='CCM', nonce='005b8ccbcd9af83c9696766cfa') + ), + ( + '47a65ac78b3d594227e85e71|e2fcfbb880442c731bf95167c8ffd7895e337076', + '47a65ac78b3d594227e85e71|e882f1dbd38ce3eda7c23f04dd65071eb41342ac|'+ + 'df7e00dccec7ae52987d', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #23', + dict(mode='CCM', nonce='003ebe94044b9a3c9696766cfa') + ), + ( + '6e37a6ef546d955d34ab6059|abf21c0b02feb88f856df4a37381bce3cc128517d4', + '6e37a6ef546d955d34ab6059|f32905b88a641b04b9c9ffb58cc390900f3da12ab1|'+ + '6dce9e82efa16da62059', + 'd7828d13b2b0bdc325a76236df93cc6b', + 'RFC3610 Packet Vector #24', + dict(mode='CCM', nonce='008d493b30ae8b3c9696766cfa') + ), + + # Test vectors for EAX taken from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf + # This is a list of tuples with 5 items: + # + # 1. Header + '|' + plaintext + # 2. Header + '|' + ciphertext + '|' + MAC + # 3. AES-128 key + # 4. Description + # 5. Dictionary of parameters to be passed to AES.new(). It must + # include the nonce. + # + ( '6bfb914fd07eae6b|', + '6bfb914fd07eae6b||e037830e8389f27b025a2d6527e79d01', + '233952dee4d5ed5f9b9c6d6ff80ff478', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='62EC67F9C3A4A407FCB2A8C49031A8B3') + ), + + ( 'fa3bfd4806eb53fa|f7fb', + 'fa3bfd4806eb53fa|19dd|5c4c9331049d0bdab0277408f67967e5', + '91945d3f4dcbee0bf45ef52255f095a4', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='BECAF043B0A23D843194BA972C66DEBD') + ), + + ( '234a3463c1264ac6|1a47cb4933', + '234a3463c1264ac6|d851d5bae0|3a59f238a23e39199dc9266626c40f80', + '01f74ad64077f2e704c0f60ada3dd523', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='70C3DB4F0D26368400A10ED05D2BFF5E') + ), + + ( '33cce2eabff5a79d|481c9e39b1', + '33cce2eabff5a79d|632a9d131a|d4c168a4225d8e1ff755939974a7bede', + 'd07cf6cbb7f313bdde66b727afd3c5e8', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='8408DFFF3C1A2B1292DC199E46B7D617') + ), + + ( 'aeb96eaebe2970e9|40d0c07da5e4', + 'aeb96eaebe2970e9|071dfe16c675|cb0677e536f73afe6a14b74ee49844dd', + '35b6d0580005bbc12b0587124557d2c2', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='FDB6B06676EEDC5C61D74276E1F8E816') + ), + + ( 'd4482d1ca78dce0f|4de3b35c3fc039245bd1fb7d', + 'd4482d1ca78dce0f|835bb4f15d743e350e728414|abb8644fd6ccb86947c5e10590210a4f', + 'bd8e6e11475e60b268784c38c62feb22', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='6EAC5C93072D8E8513F750935E46DA1B') + ), + + ( '65d2017990d62528|8b0a79306c9ce7ed99dae4f87f8dd61636', + '65d2017990d62528|02083e3979da014812f59f11d52630da30|137327d10649b0aa6e1c181db617d7f2', + '7c77d6e813bed5ac98baa417477a2e7d', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='1A8C98DCD73D38393B2BF1569DEEFC19') + ), + + ( '54b9f04e6a09189a|1bda122bce8a8dbaf1877d962b8592dd2d56', + '54b9f04e6a09189a|2ec47b2c4954a489afc7ba4897edcdae8cc3|3b60450599bd02c96382902aef7f832a', + '5fff20cafab119ca2fc73549e20f5b0d', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='DDE59B97D722156D4D9AFF2BC7559826') + ), + + ( '899a175897561d7e|6cf36720872b8513f6eab1a8a44438d5ef11', + '899a175897561d7e|0de18fd0fdd91e7af19f1d8ee8733938b1e8|e7f6d2231618102fdb7fe55ff1991700', + 'a4a4782bcffd3ec5e7ef6d8c34a56123', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='B781FCF2F75FA5A8DE97A9CA48E522EC') + ), + + ( '126735fcc320d25a|ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7', + '126735fcc320d25a|cb8920f87a6c75cff39627b56e3ed197c552d295a7|cfc46afc253b4652b1af3795b124ab6e', + '8395fcf1e95bebd697bd010bc766aac3', + 'EAX spec Appendix G', + dict(mode='EAX', nonce='22E7ADD93CFC6393C57EC0B3C17D6B44') + ), + + # Test vectors for SIV taken from RFC5297 + # This is a list of tuples with 5 items: + # + # 1. Header + '|' + plaintext + # 2. Header + '|' + ciphertext + '|' + MAC + # 3. AES-128 key + # 4. Description + # 5. Dictionary of parameters to be passed to AES.new(). + # It must include the nonce. + # + # A "Header" is a dash ('-') separated sequece of components. + # + ( '101112131415161718191a1b1c1d1e1f2021222324252627|112233445566778899aabbccddee', + '101112131415161718191a1b1c1d1e1f2021222324252627|40c02b9690c4dc04daef7f6afe5c|' + + '85632d07c6e8f37f950acd320a2ecc93', + 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', + 'RFC5297 A.1', + dict(mode='SIV', nonce=None) + ), + + ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' + + '7766554433221100-102030405060708090a0|' + + '7468697320697320736f6d6520706c61696e7465787420746f20656e63727970' + + '74207573696e67205349562d414553', + + '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' + + '7766554433221100-102030405060708090a0|' + + 'cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829' + + 'ea64ad544a272e9c485b62a3fd5c0d|' + + '7bdb6e3b432667eb06f4d14bff2fbd0f', + + '7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f', + 'RFC5297 A.2', + dict(mode='SIV', nonce='09f911029d74e35bd84156c5635688c0') + ), + + # Test vectors for GCM taken from + # http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + # This is a list of tuples with 5 items: + # + # 1. Header + '|' + plaintext + # 2. Header + '|' + ciphertext + '|' + MAC + # 3. AES-128 key + # 4. Description + # 5. Dictionary of parameters to be passed to AES.new(). + # It must include the nonce. + # + ( '|', + '||58e2fccefa7e3061367f1d57a4e7455a', + '00000000000000000000000000000000', + 'GCM Test Case 1', + dict(mode='GCM', nonce='000000000000000000000000') + ), + + ( '|00000000000000000000000000000000', + '|0388dace60b6a392f328c2b971b2fe78|ab6e47d42cec13bdf53a67b21257bddf', + '00000000000000000000000000000000', + 'GCM Test Case 2', + dict(mode='GCM', nonce='000000000000000000000000') + ), + + ( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', + '|42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + + '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985|' + + '4d5c2af327cd64a62cf35abd2ba6fab4', + 'feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 3', + dict(mode='GCM', nonce='cafebabefacedbaddecaf888') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + + '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091|' + + '5bc94fbc3221a5db94fae95ae7121a47', + 'feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 4', + dict(mode='GCM', nonce='cafebabefacedbaddecaf888') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423' + + '73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598|' + + '3612d2e79e3b0785561be14aaca2fccb', + 'feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 5', + dict(mode='GCM', nonce='cafebabefacedbad') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7' + + '01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5|' + + '619cc5aefffe0bfa462af43c1699d050', + 'feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 6', + dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+ + '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+ + '16aedbf5a0de6a57a637b39b' ) + ), + + ( '|', + '||cd33b28ac773f74ba00ed1f312572435', + '000000000000000000000000000000000000000000000000', + 'GCM Test Case 7', + dict(mode='GCM', nonce='000000000000000000000000') + ), + + ( '|00000000000000000000000000000000', + '|98e7247c07f0fe411c267e4384b0f600|2ff58d80033927ab8ef4d4587514f0fb', + '000000000000000000000000000000000000000000000000', + 'GCM Test Case 8', + dict(mode='GCM', nonce='000000000000000000000000') + ), + + ( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', + '|3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + + '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256|' + + '9924a7c8587336bfb118024db8674a14', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c', + 'GCM Test Case 9', + dict(mode='GCM', nonce='cafebabefacedbaddecaf888') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + + '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710|' + + '2519498e80f1478f37ba55bd6d27618c', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c', + 'GCM Test Case 10', + dict(mode='GCM', nonce='cafebabefacedbaddecaf888') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057' + + 'fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7|' + + '65dcc57fcf623a24094fcca40d3533f8', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c', + 'GCM Test Case 11', + dict(mode='GCM', nonce='cafebabefacedbad') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45' + + '81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b|' + + 'dcf566ff291c25bbb8568fc3d376a6d9', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c', + 'GCM Test Case 12', + dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+ + '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+ + '16aedbf5a0de6a57a637b39b' ) + ), + + ( '|', + '||530f8afbc74536b9a963b4f1c4cb738b', + '0000000000000000000000000000000000000000000000000000000000000000', + 'GCM Test Case 13', + dict(mode='GCM', nonce='000000000000000000000000') + ), + + ( '|00000000000000000000000000000000', + '|cea7403d4d606b6e074ec5d3baf39d18|d0d1c8a799996bf0265b98b5d48ab919', + '0000000000000000000000000000000000000000000000000000000000000000', + 'GCM Test Case 14', + dict(mode='GCM', nonce='000000000000000000000000') + ), + + ( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', + '|522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + + '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad|' + + 'b094dac5d93471bdec1a502270e3cc6c', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 15', + dict(mode='GCM', nonce='cafebabefacedbaddecaf888') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + + '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662|' + + '76fc6ece0f4e1768cddf8853bb2d551b', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 16', + dict(mode='GCM', nonce='cafebabefacedbaddecaf888') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0' + + 'feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f|' + + '3a337dbf46a792c45e454913fe2ea8f2', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 17', + dict(mode='GCM', nonce='cafebabefacedbad') + ), + + ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + + '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', + 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + + '5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4' + + '0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f|' + + 'a44a8266ee1c8eb0c8b5d4cf5ae9f19a', + 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', + 'GCM Test Case 18', + dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+ + '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+ + '16aedbf5a0de6a57a637b39b' ) + ), +] + +def get_tests(config={}): + from Crypto.Cipher import AES + from Crypto.Util import cpuid + from common import make_block_tests + + tests = make_block_tests(AES, "AES", test_data, {'use_aesni': False}) + if cpuid.have_aes_ni(): + # Run tests with AES-NI instructions if they are available. + tests += make_block_tests(AES, "AESNI", test_data, {'use_aesni': True}) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_ARC2.py b/lib/Crypto/SelfTest/Cipher/test_ARC2.py new file mode 100644 index 0000000..b6bc519 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_ARC2.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/ARC2.py: Self-test for the Alleged-RC2 cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.ARC2""" + +__revision__ = "$Id$" + +from common import dict # For compatibility with Python 2.1 and 2.2 + +import unittest +from Crypto.Util.py3compat import * + +# This is a list of (plaintext, ciphertext, key[, description[, extra_params]]) tuples. +test_data = [ + # Test vectors from RFC 2268 + + # 63-bit effective key length + ('0000000000000000', 'ebb773f993278eff', '0000000000000000', + 'RFC2268-1', dict(effective_keylen=63)), + + # 64-bit effective key length + ('ffffffffffffffff', '278b27e42e2f0d49', 'ffffffffffffffff', + 'RFC2268-2', dict(effective_keylen=64)), + ('1000000000000001', '30649edf9be7d2c2', '3000000000000000', + 'RFC2268-3', dict(effective_keylen=64)), + ('0000000000000000', '61a8a244adacccf0', '88', + 'RFC2268-4', dict(effective_keylen=64)), + ('0000000000000000', '6ccf4308974c267f', '88bca90e90875a', + 'RFC2268-5', dict(effective_keylen=64)), + ('0000000000000000', '1a807d272bbe5db1', '88bca90e90875a7f0f79c384627bafb2', + 'RFC2268-6', dict(effective_keylen=64)), + + # 128-bit effective key length + ('0000000000000000', '2269552ab0f85ca6', '88bca90e90875a7f0f79c384627bafb2', + "RFC2268-7", dict(effective_keylen=128)), + ('0000000000000000', '5b78d3a43dfff1f1', + '88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', + "RFC2268-8", dict(effective_keylen=129)), + + # Test vectors from PyCrypto 2.0.1's testdata.py + # 1024-bit effective key length + ('0000000000000000', '624fb3e887419e48', '5068696c6970476c617373', + 'PCTv201-0'), + ('ffffffffffffffff', '79cadef44c4a5a85', '5068696c6970476c617373', + 'PCTv201-1'), + ('0001020304050607', '90411525b34e4c2c', '5068696c6970476c617373', + 'PCTv201-2'), + ('0011223344556677', '078656aaba61cbfb', '5068696c6970476c617373', + 'PCTv201-3'), + ('0000000000000000', 'd7bcc5dbb4d6e56a', 'ffffffffffffffff', + 'PCTv201-4'), + ('ffffffffffffffff', '7259018ec557b357', 'ffffffffffffffff', + 'PCTv201-5'), + ('0001020304050607', '93d20a497f2ccb62', 'ffffffffffffffff', + 'PCTv201-6'), + ('0011223344556677', 'cb15a7f819c0014d', 'ffffffffffffffff', + 'PCTv201-7'), + ('0000000000000000', '63ac98cdf3843a7a', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', + 'PCTv201-8'), + ('ffffffffffffffff', '3fb49e2fa12371dd', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', + 'PCTv201-9'), + ('0001020304050607', '46414781ab387d5f', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', + 'PCTv201-10'), + ('0011223344556677', 'be09dc81feaca271', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553', + 'PCTv201-11'), + ('0000000000000000', 'e64221e608be30ab', '53e5ffe553', + 'PCTv201-12'), + ('ffffffffffffffff', '862bc60fdcd4d9a9', '53e5ffe553', + 'PCTv201-13'), + ('0001020304050607', '6a34da50fa5e47de', '53e5ffe553', + 'PCTv201-14'), + ('0011223344556677', '584644c34503122c', '53e5ffe553', + 'PCTv201-15'), +] + +class BufferOverflowTest(unittest.TestCase): + # Test a buffer overflow found in older versions of PyCrypto + + def setUp(self): + global ARC2 + from Crypto.Cipher import ARC2 + + def runTest(self): + """ARC2 with keylength > 128""" + key = "x" * 16384 + mode = ARC2.MODE_ECB + self.assertRaises(ValueError, ARC2.new, key, mode) + +def get_tests(config={}): + from Crypto.Cipher import ARC2 + from common import make_block_tests + + tests = make_block_tests(ARC2, "ARC2", test_data) + tests.append(BufferOverflowTest()) + + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_ARC4.py b/lib/Crypto/SelfTest/Cipher/test_ARC4.py new file mode 100644 index 0000000..801d2cb --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_ARC4.py @@ -0,0 +1,457 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/ARC4.py: Self-test for the Alleged-RC4 cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.ARC4""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * +from Crypto.SelfTest.st_common import * +from binascii import unhexlify + +from Crypto.Cipher import ARC4 + +# This is a list of (plaintext, ciphertext, key[, description]) tuples. +test_data = [ + # Test vectors from Eric Rescorla's message with the subject + # "RC4 compatibility testing", sent to the cipherpunks mailing list on + # September 13, 1994. + # http://cypherpunks.venona.com/date/1994/09/msg00420.html + + ('0123456789abcdef', '75b7878099e0c596', '0123456789abcdef', + 'Test vector 0'), + + ('0000000000000000', '7494c2e7104b0879', '0123456789abcdef', + 'Test vector 1'), + + ('0000000000000000', 'de188941a3375d3a', '0000000000000000', + 'Test vector 2'), + + ('00000000000000000000', 'd6a141a7ec3c38dfbd61', 'ef012345', + 'Test vector 3'), + + ('01' * 512, + '7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8' + + 'c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8' + + '47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd' + + 'cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43' + + '03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747' + + 'b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f' + + '5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421' + + 'd43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5' + + '585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729' + + '12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c' + + '91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1' + + 'eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320' + + 'c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f' + + '7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1' + + 'b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f' + + '12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0', + '0123456789abcdef', + "Test vector 4"), +] + +class RFC6229_Tests(unittest.TestCase): + # Test vectors from RFC 6229. Each test vector is a tuple with two items: + # the ARC4 key and a dictionary. The dictionary has keystream offsets as keys + # and the 16-byte keystream starting at the relevant offset as value. + rfc6229_data = [ + # Page 3 + ( + '0102030405', + { + 0: 'b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8', + 16: '69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19', + 240: '28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae', + 256: '1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93', + 496: '42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41', + 512: '64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6', + 752: 'ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22', + 768: 'eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b', + 1008:'45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5', + 1024:'30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df', + 1520:'32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea', + 1536:'d8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30', + 2032:'1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b', + 2048:'cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7', + 3056:'f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c', + 3072:'ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81', + 4080:'06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50', + 4096:'ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75' + } + ), + # Page 4 + ( + '01020304050607', + { + 0: '29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b', + 16: 'e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1', + 240: '91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c', + 256: 'd0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5', + 496: '75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54', + 512: '0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4', + 752: 'c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66', + 768: '32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2', + 1008:'f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1', + 1024:'8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f', + 1520:'d2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f', + 1536:'78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3', + 2032:'f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49', + 2048:'05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23', + 3056:'ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09', + 3072:'ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5', + 4080:'f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c', + 4096:'e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8' + } + ), + ( + '0102030405060708', + { + 0: '97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8', + 16: '82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09', + 240: '96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18', + 256: 'd0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a', + 496: '73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63', + 512: '16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f', + 752: '49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66', + 768: '44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0', + 1008:'27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4', + 1024:'c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d', + 1520:'1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3', + 1536:'83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb', + 2032:'0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f', + 2048:'c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c', + 3056:'26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3', + 3072:'bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b', + 4080:'d5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b', + 4096:'3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62' + } + ), + # Page 5 + ( + '0102030405060708090a', + { + 0: 'ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02', + 16: '03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11', + 240: '3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d', + 256: '48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad', + 496: '3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86', + 512: 'e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe', + 752: '5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15', + 768: 'e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb', + 1008:'a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08', + 1024:'f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16', + 1520:'bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99', + 1536:'8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a', + 2032:'b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a', + 2048:'d9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39', + 3056:'55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc', + 3072:'7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8', + 4080:'1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c', + 4096:'08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53' + } + ), + ( + '0102030405060708090a0b0c0d0e0f10', + { + 0: '9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97', + 16: '52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c', + 240: '06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b', + 256: 'd3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f', + 496: 'b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11', + 512: 'c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89', + 752: 'c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59', + 768: 'ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d', + 1008:'e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65', + 1024:'bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16', + 1520:'b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97', + 1536:'ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81', + 2032:'d0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd', + 2048:'8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5', + 3056:'fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3', + 3072:'c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23', + 4080:'ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8', + 4096:'a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc' + } + ), + # Page 6 + ( + '0102030405060708090a0b0c0d0e0f101112131415161718', + { + 0: '05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11', + 16: 'df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26', + 240: 'b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05', + 256: '6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff', + 496: 'e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22', + 512: '9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22', + 752: '04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82', + 768: '59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac', + 1008:'27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02', + 1024:'93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0', + 1520:'96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a', + 1536:'0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19', + 2032:'bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20', + 2048:'88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10', + 3056:'68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40', + 3072:'32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5', + 4080:'29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8', + 4096:'3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68' + } + ), + ( + '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', + { + 0: 'ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91', + 16: 'cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80', + 240: '11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8', + 256: '02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6', + 496: '91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b', + 512: '49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd', + 752: '87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74', + 768: 'e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35', + 1008:'c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90', + 1024:'7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58', + 1520:'40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15', + 1536:'3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73', + 2032:'f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec', + 2048:'18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34', + 3056:'8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9', + 3072:'62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18', + 4080:'a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9', + 4096:'f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48' + } + ), + # Page 7 + ( + '833222772a', + { + 0: '80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da', + 16: '20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0', + 240: 'fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9', + 256: 'f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a', + 496: '1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8', + 512: '3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12', + 752: 'e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97', + 768: '75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9', + 1008:'6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3', + 1024:'78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb', + 1520:'ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c', + 1536:'62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00', + 2032:'e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2', + 2048:'78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab', + 3056:'af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82', + 3072:'db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0', + 4080:'63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc', + 4096:'bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15' + } + ), + ( + '1910833222772a', + { + 0: 'bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b', + 16: '7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3', + 240: '3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64', + 256: 'be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81', + 496: '74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe', + 512: '9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8', + 752: 'ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40', + 768: '8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a', + 1008:'62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49', + 1024:'42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82', + 1520:'cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9', + 1536:'f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d', + 2032:'2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1', + 2048:'86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9', + 3056:'55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8', + 3072:'1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1', + 4080:'ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9', + 4096:'02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61' + } + ), + # Page 8 + ( + '641910833222772a', + { + 0: 'bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26', + 16: '46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9', + 240: 'cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0', + 256: '34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7', + 496: '78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3', + 512: '8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32', + 752: '94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72', + 768: 'b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7', + 1008:'02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4', + 1024:'bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e', + 1520:'bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73', + 1536:'d0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49', + 2032:'97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0', + 2048:'e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1', + 3056:'c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f', + 3072:'5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0', + 4080:'6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9', + 4096:'81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9' + } + ), + ( + '8b37641910833222772a', + { + 0: 'ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c', + 16: 'bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30', + 240: 'b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05', + 256: '3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c', + 496: '12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b', + 512: '28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d', + 752: 'bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04', + 768: '67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32', + 1008:'8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41', + 1024:'31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2', + 1520:'56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5', + 1536:'3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4', + 2032:'f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd', + 2048:'02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7', + 3056:'72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f', + 3072:'4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4', + 4080:'43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68', + 4096:'5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8' + } + ), + # Page 9 + ( + 'ebb46227c6cc8b37641910833222772a', + { + 0: '72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30', + 16: 'c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b', + 240: 'b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f', + 256: '48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f', + 496: '08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95', + 512: '97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61', + 752: '3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac', + 768: 'ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe', + 1008:'b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44', + 1024:'b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e', + 1520:'3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95', + 1536:'11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70', + 2032:'00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e', + 2048:'58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de', + 3056:'34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6', + 3072:'84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25', + 4080:'a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a', + 4096:'5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b' + } + ), + ( + 'c109163908ebe51debb46227c6cc8b37641910833222772a', + { + 0: '54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7', + 16: 'c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce', + 240: 'cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01', + 256: '83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f', + 496: '17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94', + 512: '4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9', + 752: '80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c', + 768: 'd1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2', + 1008:'34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa', + 1024:'f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3', + 1520:'53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c', + 1536:'ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90', + 2032:'e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07', + 2048:'4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23', + 3056:'36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb', + 3072:'1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e', + 4080:'63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc', + 4096:'e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91' + } + ), + # Page 10 + ( + '1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a', + { + 0: 'dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3', + 16: 'c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb', + 240: 'af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98', + 256: 'f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e', + 496: '25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab', + 512: '9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c', + 752: 'a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2', + 768: '85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65', + 1008:'5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31', + 1024:'34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc', + 1520:'ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95', + 1536:'8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46', + 2032:'13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16', + 2048:'dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e', + 3056:'f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59', + 3072:'9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70', + 4080:'d5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d', + 4096:'37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8' + } + ) + ] + + def test_keystream(self): + for tv in self.rfc6229_data: + key = unhexlify(b((tv[0]))) + cipher = ARC4.new(key) + count = 0 + for offset in range(0,4096+1,16): + ct = cipher.encrypt(b('\x00')*16) + expected = tv[1].get(offset) + if expected: + expected = unhexlify(b(expected.replace(" ",''))) + self.assertEquals(ct, expected) + count += 1 + self.assertEqual(count, len(tv[1])) + +class Drop_Tests(unittest.TestCase): + key = b('\xAA')*16 + data = b('\x00')*5000 + + def setUp(self): + self.cipher = ARC4.new(self.key) + + def test_drop256_encrypt(self): + cipher_drop = ARC4.new(self.key, 256) + ct_drop = cipher_drop.encrypt(self.data[:16]) + ct = self.cipher.encrypt(self.data)[256:256+16] + self.assertEquals(ct_drop, ct) + + def test_drop256_decrypt(self): + cipher_drop = ARC4.new(self.key, 256) + pt_drop = cipher_drop.decrypt(self.data[:16]) + pt = self.cipher.decrypt(self.data)[256:256+16] + self.assertEquals(pt_drop, pt) + +def get_tests(config={}): + from common import make_stream_tests + tests = make_stream_tests(ARC4, "ARC4", test_data) + tests += list_test_cases(RFC6229_Tests) + tests += list_test_cases(Drop_Tests) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_Blowfish.py b/lib/Crypto/SelfTest/Cipher/test_Blowfish.py new file mode 100644 index 0000000..e8f73a6 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_Blowfish.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/test_Blowfish.py: Self-test for the Blowfish cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.Blowfish""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (plaintext, ciphertext, key) tuples. +test_data = [ + # Test vectors from http://www.schneier.com/code/vectors.txt + ('0000000000000000', '4ef997456198dd78', '0000000000000000'), + ('ffffffffffffffff', '51866fd5b85ecb8a', 'ffffffffffffffff'), + ('1000000000000001', '7d856f9a613063f2', '3000000000000000'), + ('1111111111111111', '2466dd878b963c9d', '1111111111111111'), + ('1111111111111111', '61f9c3802281b096', '0123456789abcdef'), + ('0123456789abcdef', '7d0cc630afda1ec7', '1111111111111111'), + ('0000000000000000', '4ef997456198dd78', '0000000000000000'), + ('0123456789abcdef', '0aceab0fc6a0a28d', 'fedcba9876543210'), + ('01a1d6d039776742', '59c68245eb05282b', '7ca110454a1a6e57'), + ('5cd54ca83def57da', 'b1b8cc0b250f09a0', '0131d9619dc1376e'), + ('0248d43806f67172', '1730e5778bea1da4', '07a1133e4a0b2686'), + ('51454b582ddf440a', 'a25e7856cf2651eb', '3849674c2602319e'), + ('42fd443059577fa2', '353882b109ce8f1a', '04b915ba43feb5b6'), + ('059b5e0851cf143a', '48f4d0884c379918', '0113b970fd34f2ce'), + ('0756d8e0774761d2', '432193b78951fc98', '0170f175468fb5e6'), + ('762514b829bf486a', '13f04154d69d1ae5', '43297fad38e373fe'), + ('3bdd119049372802', '2eedda93ffd39c79', '07a7137045da2a16'), + ('26955f6835af609a', 'd887e0393c2da6e3', '04689104c2fd3b2f'), + ('164d5e404f275232', '5f99d04f5b163969', '37d06bb516cb7546'), + ('6b056e18759f5cca', '4a057a3b24d3977b', '1f08260d1ac2465e'), + ('004bd6ef09176062', '452031c1e4fada8e', '584023641aba6176'), + ('480d39006ee762f2', '7555ae39f59b87bd', '025816164629b007'), + ('437540c8698f3cfa', '53c55f9cb49fc019', '49793ebc79b3258f'), + ('072d43a077075292', '7a8e7bfa937e89a3', '4fb05e1515ab73a7'), + ('02fe55778117f12a', 'cf9c5d7a4986adb5', '49e95d6d4ca229bf'), + ('1d9d5c5018f728c2', 'd1abb290658bc778', '018310dc409b26d6'), + ('305532286d6f295a', '55cb3774d13ef201', '1c587f1c13924fef'), + ('0123456789abcdef', 'fa34ec4847b268b2', '0101010101010101'), + ('0123456789abcdef', 'a790795108ea3cae', '1f1f1f1f0e0e0e0e'), + ('0123456789abcdef', 'c39e072d9fac631d', 'e0fee0fef1fef1fe'), + ('ffffffffffffffff', '014933e0cdaff6e4', '0000000000000000'), + ('0000000000000000', 'f21e9a77b71c49bc', 'ffffffffffffffff'), + ('0000000000000000', '245946885754369a', '0123456789abcdef'), + ('ffffffffffffffff', '6b5c5a9c5d9e0a5a', 'fedcba9876543210'), + ('fedcba9876543210', 'f9ad597c49db005e', 'f0'), + ('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'), + ('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'), + ('fedcba9876543210', 'be1e639408640f05', 'f0e1d2c3'), + ('fedcba9876543210', 'b39e44481bdb1e6e', 'f0e1d2c3b4'), + ('fedcba9876543210', '9457aa83b1928c0d', 'f0e1d2c3b4a5'), + ('fedcba9876543210', '8bb77032f960629d', 'f0e1d2c3b4a596'), + ('fedcba9876543210', 'e87a244e2cc85e82', 'f0e1d2c3b4a59687'), + ('fedcba9876543210', '15750e7a4f4ec577', 'f0e1d2c3b4a5968778'), + ('fedcba9876543210', '122ba70b3ab64ae0', 'f0e1d2c3b4a596877869'), + ('fedcba9876543210', '3a833c9affc537f6', 'f0e1d2c3b4a5968778695a'), + ('fedcba9876543210', '9409da87a90f6bf2', 'f0e1d2c3b4a5968778695a4b'), + ('fedcba9876543210', '884f80625060b8b4', 'f0e1d2c3b4a5968778695a4b3c'), + ('fedcba9876543210', '1f85031c19e11968', 'f0e1d2c3b4a5968778695a4b3c2d'), + ('fedcba9876543210', '79d9373a714ca34f', 'f0e1d2c3b4a5968778695a4b3c2d1e'), + ('fedcba9876543210', '93142887ee3be15c', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f'), + ('fedcba9876543210', '03429e838ce2d14b', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f00'), + ('fedcba9876543210', 'a4299e27469ff67b', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011'), + ('fedcba9876543210', 'afd5aed1c1bc96a8', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f001122'), + ('fedcba9876543210', '10851c0e3858da9f', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233'), + ('fedcba9876543210', 'e6f51ed79b9db21f', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344'), + ('fedcba9876543210', '64a6e14afd36b46f', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455'), + ('fedcba9876543210', '80c7d7d45a5479ad', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566'), + ('fedcba9876543210', '05044b62fa52d080', + 'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677'), +] + +def get_tests(config={}): + from Crypto.Cipher import Blowfish + from common import make_block_tests + return make_block_tests(Blowfish, "Blowfish", test_data) + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_CAST.py b/lib/Crypto/SelfTest/Cipher/test_CAST.py new file mode 100644 index 0000000..1cfcec0 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_CAST.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/CAST.py: Self-test for the CAST-128 (CAST5) cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.CAST""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (plaintext, ciphertext, key) tuples. +test_data = [ + # Test vectors from RFC 2144, B.1 + ('0123456789abcdef', '238b4fe5847e44b2', + '0123456712345678234567893456789a', + '128-bit key'), + + ('0123456789abcdef', 'eb6a711a2c02271b', + '01234567123456782345', + '80-bit key'), + + ('0123456789abcdef', '7ac816d16e9b302e', + '0123456712', + '40-bit key'), +] + +def get_tests(config={}): + from Crypto.Cipher import CAST + from common import make_block_tests + return make_block_tests(CAST, "CAST", test_data) + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_DES.py b/lib/Crypto/SelfTest/Cipher/test_DES.py new file mode 100644 index 0000000..c5d114b --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_DES.py @@ -0,0 +1,339 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/DES.py: Self-test for the (Single) DES cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.DES""" + +__revision__ = "$Id$" + +from common import dict # For compatibility with Python 2.1 and 2.2 +from Crypto.Util.py3compat import * +import unittest + +# This is a list of (plaintext, ciphertext, key, description) tuples. +SP800_17_B1_KEY = '01' * 8 +SP800_17_B2_PT = '00' * 8 +test_data = [ + # Test vectors from Appendix A of NIST SP 800-17 + # "Modes of Operation Validation System (MOVS): Requirements and Procedures" + # http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf + + # Appendix A - "Sample Round Outputs for the DES" + ('0000000000000000', '82dcbafbdeab6602', '10316e028c8f3b4a', + "NIST SP800-17 A"), + + # Table B.1 - Variable Plaintext Known Answer Test + ('8000000000000000', '95f8a5e5dd31d900', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #0'), + ('4000000000000000', 'dd7f121ca5015619', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #1'), + ('2000000000000000', '2e8653104f3834ea', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #2'), + ('1000000000000000', '4bd388ff6cd81d4f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #3'), + ('0800000000000000', '20b9e767b2fb1456', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #4'), + ('0400000000000000', '55579380d77138ef', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #5'), + ('0200000000000000', '6cc5defaaf04512f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #6'), + ('0100000000000000', '0d9f279ba5d87260', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #7'), + ('0080000000000000', 'd9031b0271bd5a0a', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #8'), + ('0040000000000000', '424250b37c3dd951', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #9'), + ('0020000000000000', 'b8061b7ecd9a21e5', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #10'), + ('0010000000000000', 'f15d0f286b65bd28', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #11'), + ('0008000000000000', 'add0cc8d6e5deba1', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #12'), + ('0004000000000000', 'e6d5f82752ad63d1', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #13'), + ('0002000000000000', 'ecbfe3bd3f591a5e', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #14'), + ('0001000000000000', 'f356834379d165cd', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #15'), + ('0000800000000000', '2b9f982f20037fa9', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #16'), + ('0000400000000000', '889de068a16f0be6', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #17'), + ('0000200000000000', 'e19e275d846a1298', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #18'), + ('0000100000000000', '329a8ed523d71aec', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #19'), + ('0000080000000000', 'e7fce22557d23c97', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #20'), + ('0000040000000000', '12a9f5817ff2d65d', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #21'), + ('0000020000000000', 'a484c3ad38dc9c19', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #22'), + ('0000010000000000', 'fbe00a8a1ef8ad72', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #23'), + ('0000008000000000', '750d079407521363', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #24'), + ('0000004000000000', '64feed9c724c2faf', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #25'), + ('0000002000000000', 'f02b263b328e2b60', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #26'), + ('0000001000000000', '9d64555a9a10b852', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #27'), + ('0000000800000000', 'd106ff0bed5255d7', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #28'), + ('0000000400000000', 'e1652c6b138c64a5', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #29'), + ('0000000200000000', 'e428581186ec8f46', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #30'), + ('0000000100000000', 'aeb5f5ede22d1a36', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #31'), + ('0000000080000000', 'e943d7568aec0c5c', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #32'), + ('0000000040000000', 'df98c8276f54b04b', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #33'), + ('0000000020000000', 'b160e4680f6c696f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #34'), + ('0000000010000000', 'fa0752b07d9c4ab8', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #35'), + ('0000000008000000', 'ca3a2b036dbc8502', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #36'), + ('0000000004000000', '5e0905517bb59bcf', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #37'), + ('0000000002000000', '814eeb3b91d90726', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #38'), + ('0000000001000000', '4d49db1532919c9f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #39'), + ('0000000000800000', '25eb5fc3f8cf0621', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #40'), + ('0000000000400000', 'ab6a20c0620d1c6f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #41'), + ('0000000000200000', '79e90dbc98f92cca', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #42'), + ('0000000000100000', '866ecedd8072bb0e', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #43'), + ('0000000000080000', '8b54536f2f3e64a8', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #44'), + ('0000000000040000', 'ea51d3975595b86b', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #45'), + ('0000000000020000', 'caffc6ac4542de31', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #46'), + ('0000000000010000', '8dd45a2ddf90796c', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #47'), + ('0000000000008000', '1029d55e880ec2d0', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #48'), + ('0000000000004000', '5d86cb23639dbea9', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #49'), + ('0000000000002000', '1d1ca853ae7c0c5f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #50'), + ('0000000000001000', 'ce332329248f3228', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #51'), + ('0000000000000800', '8405d1abe24fb942', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #52'), + ('0000000000000400', 'e643d78090ca4207', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #53'), + ('0000000000000200', '48221b9937748a23', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #54'), + ('0000000000000100', 'dd7c0bbd61fafd54', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #55'), + ('0000000000000080', '2fbc291a570db5c4', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #56'), + ('0000000000000040', 'e07c30d7e4e26e12', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #57'), + ('0000000000000020', '0953e2258e8e90a1', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #58'), + ('0000000000000010', '5b711bc4ceebf2ee', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #59'), + ('0000000000000008', 'cc083f1e6d9e85f6', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #60'), + ('0000000000000004', 'd2fd8867d50d2dfe', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #61'), + ('0000000000000002', '06e7ea22ce92708f', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #62'), + ('0000000000000001', '166b40b44aba4bd6', SP800_17_B1_KEY, + 'NIST SP800-17 B.1 #63'), + + # Table B.2 - Variable Key Known Answer Test + (SP800_17_B2_PT, '95a8d72813daa94d', '8001010101010101', + 'NIST SP800-17 B.2 #0'), + (SP800_17_B2_PT, '0eec1487dd8c26d5', '4001010101010101', + 'NIST SP800-17 B.2 #1'), + (SP800_17_B2_PT, '7ad16ffb79c45926', '2001010101010101', + 'NIST SP800-17 B.2 #2'), + (SP800_17_B2_PT, 'd3746294ca6a6cf3', '1001010101010101', + 'NIST SP800-17 B.2 #3'), + (SP800_17_B2_PT, '809f5f873c1fd761', '0801010101010101', + 'NIST SP800-17 B.2 #4'), + (SP800_17_B2_PT, 'c02faffec989d1fc', '0401010101010101', + 'NIST SP800-17 B.2 #5'), + (SP800_17_B2_PT, '4615aa1d33e72f10', '0201010101010101', + 'NIST SP800-17 B.2 #6'), + (SP800_17_B2_PT, '2055123350c00858', '0180010101010101', + 'NIST SP800-17 B.2 #7'), + (SP800_17_B2_PT, 'df3b99d6577397c8', '0140010101010101', + 'NIST SP800-17 B.2 #8'), + (SP800_17_B2_PT, '31fe17369b5288c9', '0120010101010101', + 'NIST SP800-17 B.2 #9'), + (SP800_17_B2_PT, 'dfdd3cc64dae1642', '0110010101010101', + 'NIST SP800-17 B.2 #10'), + (SP800_17_B2_PT, '178c83ce2b399d94', '0108010101010101', + 'NIST SP800-17 B.2 #11'), + (SP800_17_B2_PT, '50f636324a9b7f80', '0104010101010101', + 'NIST SP800-17 B.2 #12'), + (SP800_17_B2_PT, 'a8468ee3bc18f06d', '0102010101010101', + 'NIST SP800-17 B.2 #13'), + (SP800_17_B2_PT, 'a2dc9e92fd3cde92', '0101800101010101', + 'NIST SP800-17 B.2 #14'), + (SP800_17_B2_PT, 'cac09f797d031287', '0101400101010101', + 'NIST SP800-17 B.2 #15'), + (SP800_17_B2_PT, '90ba680b22aeb525', '0101200101010101', + 'NIST SP800-17 B.2 #16'), + (SP800_17_B2_PT, 'ce7a24f350e280b6', '0101100101010101', + 'NIST SP800-17 B.2 #17'), + (SP800_17_B2_PT, '882bff0aa01a0b87', '0101080101010101', + 'NIST SP800-17 B.2 #18'), + (SP800_17_B2_PT, '25610288924511c2', '0101040101010101', + 'NIST SP800-17 B.2 #19'), + (SP800_17_B2_PT, 'c71516c29c75d170', '0101020101010101', + 'NIST SP800-17 B.2 #20'), + (SP800_17_B2_PT, '5199c29a52c9f059', '0101018001010101', + 'NIST SP800-17 B.2 #21'), + (SP800_17_B2_PT, 'c22f0a294a71f29f', '0101014001010101', + 'NIST SP800-17 B.2 #22'), + (SP800_17_B2_PT, 'ee371483714c02ea', '0101012001010101', + 'NIST SP800-17 B.2 #23'), + (SP800_17_B2_PT, 'a81fbd448f9e522f', '0101011001010101', + 'NIST SP800-17 B.2 #24'), + (SP800_17_B2_PT, '4f644c92e192dfed', '0101010801010101', + 'NIST SP800-17 B.2 #25'), + (SP800_17_B2_PT, '1afa9a66a6df92ae', '0101010401010101', + 'NIST SP800-17 B.2 #26'), + (SP800_17_B2_PT, 'b3c1cc715cb879d8', '0101010201010101', + 'NIST SP800-17 B.2 #27'), + (SP800_17_B2_PT, '19d032e64ab0bd8b', '0101010180010101', + 'NIST SP800-17 B.2 #28'), + (SP800_17_B2_PT, '3cfaa7a7dc8720dc', '0101010140010101', + 'NIST SP800-17 B.2 #29'), + (SP800_17_B2_PT, 'b7265f7f447ac6f3', '0101010120010101', + 'NIST SP800-17 B.2 #30'), + (SP800_17_B2_PT, '9db73b3c0d163f54', '0101010110010101', + 'NIST SP800-17 B.2 #31'), + (SP800_17_B2_PT, '8181b65babf4a975', '0101010108010101', + 'NIST SP800-17 B.2 #32'), + (SP800_17_B2_PT, '93c9b64042eaa240', '0101010104010101', + 'NIST SP800-17 B.2 #33'), + (SP800_17_B2_PT, '5570530829705592', '0101010102010101', + 'NIST SP800-17 B.2 #34'), + (SP800_17_B2_PT, '8638809e878787a0', '0101010101800101', + 'NIST SP800-17 B.2 #35'), + (SP800_17_B2_PT, '41b9a79af79ac208', '0101010101400101', + 'NIST SP800-17 B.2 #36'), + (SP800_17_B2_PT, '7a9be42f2009a892', '0101010101200101', + 'NIST SP800-17 B.2 #37'), + (SP800_17_B2_PT, '29038d56ba6d2745', '0101010101100101', + 'NIST SP800-17 B.2 #38'), + (SP800_17_B2_PT, '5495c6abf1e5df51', '0101010101080101', + 'NIST SP800-17 B.2 #39'), + (SP800_17_B2_PT, 'ae13dbd561488933', '0101010101040101', + 'NIST SP800-17 B.2 #40'), + (SP800_17_B2_PT, '024d1ffa8904e389', '0101010101020101', + 'NIST SP800-17 B.2 #41'), + (SP800_17_B2_PT, 'd1399712f99bf02e', '0101010101018001', + 'NIST SP800-17 B.2 #42'), + (SP800_17_B2_PT, '14c1d7c1cffec79e', '0101010101014001', + 'NIST SP800-17 B.2 #43'), + (SP800_17_B2_PT, '1de5279dae3bed6f', '0101010101012001', + 'NIST SP800-17 B.2 #44'), + (SP800_17_B2_PT, 'e941a33f85501303', '0101010101011001', + 'NIST SP800-17 B.2 #45'), + (SP800_17_B2_PT, 'da99dbbc9a03f379', '0101010101010801', + 'NIST SP800-17 B.2 #46'), + (SP800_17_B2_PT, 'b7fc92f91d8e92e9', '0101010101010401', + 'NIST SP800-17 B.2 #47'), + (SP800_17_B2_PT, 'ae8e5caa3ca04e85', '0101010101010201', + 'NIST SP800-17 B.2 #48'), + (SP800_17_B2_PT, '9cc62df43b6eed74', '0101010101010180', + 'NIST SP800-17 B.2 #49'), + (SP800_17_B2_PT, 'd863dbb5c59a91a0', '0101010101010140', + 'NIST SP800-17 B.2 #50'), + (SP800_17_B2_PT, 'a1ab2190545b91d7', '0101010101010120', + 'NIST SP800-17 B.2 #51'), + (SP800_17_B2_PT, '0875041e64c570f7', '0101010101010110', + 'NIST SP800-17 B.2 #52'), + (SP800_17_B2_PT, '5a594528bebef1cc', '0101010101010108', + 'NIST SP800-17 B.2 #53'), + (SP800_17_B2_PT, 'fcdb3291de21f0c0', '0101010101010104', + 'NIST SP800-17 B.2 #54'), + (SP800_17_B2_PT, '869efd7f9f265a09', '0101010101010102', + 'NIST SP800-17 B.2 #55'), +] + +class RonRivestTest(unittest.TestCase): + """ Ronald L. Rivest's DES test, see + http://people.csail.mit.edu/rivest/Destest.txt + ABSTRACT + -------- + + We present a simple way to test the correctness of a DES implementation: + Use the recurrence relation: + + X0 = 9474B8E8C73BCA7D (hexadecimal) + + X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi) + + to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here + E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes + the DES decryption of X using key K. If you obtain + + X16 = 1B1A2DDB4C642438 + + your implementation does not have any of the 36,568 possible single-fault + errors described herein. + """ + def runTest(self): + from Crypto.Cipher import DES + from binascii import b2a_hex + + X = [] + X[0:] = [b('\x94\x74\xB8\xE8\xC7\x3B\xCA\x7D')] + + for i in range(16): + c = DES.new(X[i],DES.MODE_ECB) + if not (i&1): # (num&1) returns 1 for odd numbers + X[i+1:] = [c.encrypt(X[i])] # even + else: + X[i+1:] = [c.decrypt(X[i])] # odd + + self.assertEqual(b2a_hex(X[16]), + b2a_hex(b('\x1B\x1A\x2D\xDB\x4C\x64\x24\x38'))) + +def get_tests(config={}): + from Crypto.Cipher import DES + from common import make_block_tests + return make_block_tests(DES, "DES", test_data) + [RonRivestTest()] + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_DES3.py b/lib/Crypto/SelfTest/Cipher/test_DES3.py new file mode 100644 index 0000000..50e969b --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_DES3.py @@ -0,0 +1,333 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/DES3.py: Self-test for the Triple-DES cipher +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.DES3""" + +__revision__ = "$Id$" + +from common import dict # For compatibility with Python 2.1 and 2.2 +from Crypto.Util.py3compat import * +from binascii import hexlify + +# This is a list of (plaintext, ciphertext, key, description) tuples. +SP800_20_A1_KEY = '01' * 24 +SP800_20_A2_PT = '00' * 8 +test_data = [ + # Test vector from Appendix B of NIST SP 800-67 + # "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block + # Cipher" + # http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf + ('54686520717566636b2062726f776e20666f78206a756d70', + 'a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900', + '0123456789abcdef23456789abcdef01456789abcdef0123', + 'NIST SP800-67 B.1'), + + # Test vectors "The Multi-block Message Test (MMT) for DES and TDES" + # http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf + ('326a494cd33fe756', 'b22b8d66de970692', + '627f460e08104a1043cd265d5840eaf1313edf97df2a8a8c', + 'DESMMT #1', dict(mode='CBC', iv='8e29f75ea77e5475')), + + ('84401f78fe6c10876d8ea23094ea5309', '7b1f7c7e3b1c948ebd04a75ffba7d2f5', + '37ae5ebf46dff2dc0754b94f31cbb3855e7fd36dc870bfae', + 'DESMMT #2', dict(mode='CBC', iv='3d1de3cc132e3b65')), + + # Test vectors from Appendix A of NIST SP 800-20 + # "Modes of Operation Validation System for the Triple Data Encryption + # Algorithm (TMOVS): Requirements and Procedures" + # http://csrc.nist.gov/publications/nistpubs/800-20/800-20.pdf + + # Table A.1 - Variable Plaintext Known Answer Test + ('8000000000000000', '95f8a5e5dd31d900', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #0'), + ('4000000000000000', 'dd7f121ca5015619', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #1'), + ('2000000000000000', '2e8653104f3834ea', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #2'), + ('1000000000000000', '4bd388ff6cd81d4f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #3'), + ('0800000000000000', '20b9e767b2fb1456', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #4'), + ('0400000000000000', '55579380d77138ef', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #5'), + ('0200000000000000', '6cc5defaaf04512f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #6'), + ('0100000000000000', '0d9f279ba5d87260', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #7'), + ('0080000000000000', 'd9031b0271bd5a0a', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #8'), + ('0040000000000000', '424250b37c3dd951', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #9'), + ('0020000000000000', 'b8061b7ecd9a21e5', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #10'), + ('0010000000000000', 'f15d0f286b65bd28', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #11'), + ('0008000000000000', 'add0cc8d6e5deba1', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #12'), + ('0004000000000000', 'e6d5f82752ad63d1', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #13'), + ('0002000000000000', 'ecbfe3bd3f591a5e', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #14'), + ('0001000000000000', 'f356834379d165cd', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #15'), + ('0000800000000000', '2b9f982f20037fa9', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #16'), + ('0000400000000000', '889de068a16f0be6', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #17'), + ('0000200000000000', 'e19e275d846a1298', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #18'), + ('0000100000000000', '329a8ed523d71aec', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #19'), + ('0000080000000000', 'e7fce22557d23c97', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #20'), + ('0000040000000000', '12a9f5817ff2d65d', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #21'), + ('0000020000000000', 'a484c3ad38dc9c19', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #22'), + ('0000010000000000', 'fbe00a8a1ef8ad72', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #23'), + ('0000008000000000', '750d079407521363', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #24'), + ('0000004000000000', '64feed9c724c2faf', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #25'), + ('0000002000000000', 'f02b263b328e2b60', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #26'), + ('0000001000000000', '9d64555a9a10b852', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #27'), + ('0000000800000000', 'd106ff0bed5255d7', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #28'), + ('0000000400000000', 'e1652c6b138c64a5', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #29'), + ('0000000200000000', 'e428581186ec8f46', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #30'), + ('0000000100000000', 'aeb5f5ede22d1a36', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #31'), + ('0000000080000000', 'e943d7568aec0c5c', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #32'), + ('0000000040000000', 'df98c8276f54b04b', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #33'), + ('0000000020000000', 'b160e4680f6c696f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #34'), + ('0000000010000000', 'fa0752b07d9c4ab8', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #35'), + ('0000000008000000', 'ca3a2b036dbc8502', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #36'), + ('0000000004000000', '5e0905517bb59bcf', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #37'), + ('0000000002000000', '814eeb3b91d90726', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #38'), + ('0000000001000000', '4d49db1532919c9f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #39'), + ('0000000000800000', '25eb5fc3f8cf0621', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #40'), + ('0000000000400000', 'ab6a20c0620d1c6f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #41'), + ('0000000000200000', '79e90dbc98f92cca', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #42'), + ('0000000000100000', '866ecedd8072bb0e', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #43'), + ('0000000000080000', '8b54536f2f3e64a8', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #44'), + ('0000000000040000', 'ea51d3975595b86b', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #45'), + ('0000000000020000', 'caffc6ac4542de31', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #46'), + ('0000000000010000', '8dd45a2ddf90796c', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #47'), + ('0000000000008000', '1029d55e880ec2d0', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #48'), + ('0000000000004000', '5d86cb23639dbea9', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #49'), + ('0000000000002000', '1d1ca853ae7c0c5f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #50'), + ('0000000000001000', 'ce332329248f3228', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #51'), + ('0000000000000800', '8405d1abe24fb942', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #52'), + ('0000000000000400', 'e643d78090ca4207', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #53'), + ('0000000000000200', '48221b9937748a23', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #54'), + ('0000000000000100', 'dd7c0bbd61fafd54', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #55'), + ('0000000000000080', '2fbc291a570db5c4', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #56'), + ('0000000000000040', 'e07c30d7e4e26e12', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #57'), + ('0000000000000020', '0953e2258e8e90a1', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #58'), + ('0000000000000010', '5b711bc4ceebf2ee', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #59'), + ('0000000000000008', 'cc083f1e6d9e85f6', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #60'), + ('0000000000000004', 'd2fd8867d50d2dfe', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #61'), + ('0000000000000002', '06e7ea22ce92708f', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #62'), + ('0000000000000001', '166b40b44aba4bd6', SP800_20_A1_KEY, + 'NIST SP800-20 A.1 #63'), + + # Table A.2 - Variable Key Known Answer Test + (SP800_20_A2_PT, '95a8d72813daa94d', '8001010101010101'*3, + 'NIST SP800-20 A.2 #0'), + (SP800_20_A2_PT, '0eec1487dd8c26d5', '4001010101010101'*3, + 'NIST SP800-20 A.2 #1'), + (SP800_20_A2_PT, '7ad16ffb79c45926', '2001010101010101'*3, + 'NIST SP800-20 A.2 #2'), + (SP800_20_A2_PT, 'd3746294ca6a6cf3', '1001010101010101'*3, + 'NIST SP800-20 A.2 #3'), + (SP800_20_A2_PT, '809f5f873c1fd761', '0801010101010101'*3, + 'NIST SP800-20 A.2 #4'), + (SP800_20_A2_PT, 'c02faffec989d1fc', '0401010101010101'*3, + 'NIST SP800-20 A.2 #5'), + (SP800_20_A2_PT, '4615aa1d33e72f10', '0201010101010101'*3, + 'NIST SP800-20 A.2 #6'), + (SP800_20_A2_PT, '2055123350c00858', '0180010101010101'*3, + 'NIST SP800-20 A.2 #7'), + (SP800_20_A2_PT, 'df3b99d6577397c8', '0140010101010101'*3, + 'NIST SP800-20 A.2 #8'), + (SP800_20_A2_PT, '31fe17369b5288c9', '0120010101010101'*3, + 'NIST SP800-20 A.2 #9'), + (SP800_20_A2_PT, 'dfdd3cc64dae1642', '0110010101010101'*3, + 'NIST SP800-20 A.2 #10'), + (SP800_20_A2_PT, '178c83ce2b399d94', '0108010101010101'*3, + 'NIST SP800-20 A.2 #11'), + (SP800_20_A2_PT, '50f636324a9b7f80', '0104010101010101'*3, + 'NIST SP800-20 A.2 #12'), + (SP800_20_A2_PT, 'a8468ee3bc18f06d', '0102010101010101'*3, + 'NIST SP800-20 A.2 #13'), + (SP800_20_A2_PT, 'a2dc9e92fd3cde92', '0101800101010101'*3, + 'NIST SP800-20 A.2 #14'), + (SP800_20_A2_PT, 'cac09f797d031287', '0101400101010101'*3, + 'NIST SP800-20 A.2 #15'), + (SP800_20_A2_PT, '90ba680b22aeb525', '0101200101010101'*3, + 'NIST SP800-20 A.2 #16'), + (SP800_20_A2_PT, 'ce7a24f350e280b6', '0101100101010101'*3, + 'NIST SP800-20 A.2 #17'), + (SP800_20_A2_PT, '882bff0aa01a0b87', '0101080101010101'*3, + 'NIST SP800-20 A.2 #18'), + (SP800_20_A2_PT, '25610288924511c2', '0101040101010101'*3, + 'NIST SP800-20 A.2 #19'), + (SP800_20_A2_PT, 'c71516c29c75d170', '0101020101010101'*3, + 'NIST SP800-20 A.2 #20'), + (SP800_20_A2_PT, '5199c29a52c9f059', '0101018001010101'*3, + 'NIST SP800-20 A.2 #21'), + (SP800_20_A2_PT, 'c22f0a294a71f29f', '0101014001010101'*3, + 'NIST SP800-20 A.2 #22'), + (SP800_20_A2_PT, 'ee371483714c02ea', '0101012001010101'*3, + 'NIST SP800-20 A.2 #23'), + (SP800_20_A2_PT, 'a81fbd448f9e522f', '0101011001010101'*3, + 'NIST SP800-20 A.2 #24'), + (SP800_20_A2_PT, '4f644c92e192dfed', '0101010801010101'*3, + 'NIST SP800-20 A.2 #25'), + (SP800_20_A2_PT, '1afa9a66a6df92ae', '0101010401010101'*3, + 'NIST SP800-20 A.2 #26'), + (SP800_20_A2_PT, 'b3c1cc715cb879d8', '0101010201010101'*3, + 'NIST SP800-20 A.2 #27'), + (SP800_20_A2_PT, '19d032e64ab0bd8b', '0101010180010101'*3, + 'NIST SP800-20 A.2 #28'), + (SP800_20_A2_PT, '3cfaa7a7dc8720dc', '0101010140010101'*3, + 'NIST SP800-20 A.2 #29'), + (SP800_20_A2_PT, 'b7265f7f447ac6f3', '0101010120010101'*3, + 'NIST SP800-20 A.2 #30'), + (SP800_20_A2_PT, '9db73b3c0d163f54', '0101010110010101'*3, + 'NIST SP800-20 A.2 #31'), + (SP800_20_A2_PT, '8181b65babf4a975', '0101010108010101'*3, + 'NIST SP800-20 A.2 #32'), + (SP800_20_A2_PT, '93c9b64042eaa240', '0101010104010101'*3, + 'NIST SP800-20 A.2 #33'), + (SP800_20_A2_PT, '5570530829705592', '0101010102010101'*3, + 'NIST SP800-20 A.2 #34'), + (SP800_20_A2_PT, '8638809e878787a0', '0101010101800101'*3, + 'NIST SP800-20 A.2 #35'), + (SP800_20_A2_PT, '41b9a79af79ac208', '0101010101400101'*3, + 'NIST SP800-20 A.2 #36'), + (SP800_20_A2_PT, '7a9be42f2009a892', '0101010101200101'*3, + 'NIST SP800-20 A.2 #37'), + (SP800_20_A2_PT, '29038d56ba6d2745', '0101010101100101'*3, + 'NIST SP800-20 A.2 #38'), + (SP800_20_A2_PT, '5495c6abf1e5df51', '0101010101080101'*3, + 'NIST SP800-20 A.2 #39'), + (SP800_20_A2_PT, 'ae13dbd561488933', '0101010101040101'*3, + 'NIST SP800-20 A.2 #40'), + (SP800_20_A2_PT, '024d1ffa8904e389', '0101010101020101'*3, + 'NIST SP800-20 A.2 #41'), + (SP800_20_A2_PT, 'd1399712f99bf02e', '0101010101018001'*3, + 'NIST SP800-20 A.2 #42'), + (SP800_20_A2_PT, '14c1d7c1cffec79e', '0101010101014001'*3, + 'NIST SP800-20 A.2 #43'), + (SP800_20_A2_PT, '1de5279dae3bed6f', '0101010101012001'*3, + 'NIST SP800-20 A.2 #44'), + (SP800_20_A2_PT, 'e941a33f85501303', '0101010101011001'*3, + 'NIST SP800-20 A.2 #45'), + (SP800_20_A2_PT, 'da99dbbc9a03f379', '0101010101010801'*3, + 'NIST SP800-20 A.2 #46'), + (SP800_20_A2_PT, 'b7fc92f91d8e92e9', '0101010101010401'*3, + 'NIST SP800-20 A.2 #47'), + (SP800_20_A2_PT, 'ae8e5caa3ca04e85', '0101010101010201'*3, + 'NIST SP800-20 A.2 #48'), + (SP800_20_A2_PT, '9cc62df43b6eed74', '0101010101010180'*3, + 'NIST SP800-20 A.2 #49'), + (SP800_20_A2_PT, 'd863dbb5c59a91a0', '0101010101010140'*3, + 'NIST SP800-20 A.2 #50'), + (SP800_20_A2_PT, 'a1ab2190545b91d7', '0101010101010120'*3, + 'NIST SP800-20 A.2 #51'), + (SP800_20_A2_PT, '0875041e64c570f7', '0101010101010110'*3, + 'NIST SP800-20 A.2 #52'), + (SP800_20_A2_PT, '5a594528bebef1cc', '0101010101010108'*3, + 'NIST SP800-20 A.2 #53'), + (SP800_20_A2_PT, 'fcdb3291de21f0c0', '0101010101010104'*3, + 'NIST SP800-20 A.2 #54'), + (SP800_20_A2_PT, '869efd7f9f265a09', '0101010101010102'*3, + 'NIST SP800-20 A.2 #55'), + + # "Two-key 3DES". Test vector generated using PyCrypto 2.0.1. + # This test is designed to test the DES3 API, not the correctness of the + # output. + ('21e81b7ade88a259', '5c577d4d9b20c0f8', + '9b397ebf81b1181e282f4bb8adbadc6b', 'Two-key 3DES'), + + # The following test vectors have been generated with gpg v1.4.0. + # The command line used was: + # gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \ + # --disable-mdc --s2k-mode 0 --output ct pt + # For an explanation, see test_AES.py . + ( 'ac1762037074324fb53ba3596f73656d69746556616c6c6579', # Plaintext, 'YosemiteValley' + '9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d', # Ciphertext + '7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2', # Key (hash of 'BearsAhead') + 'GPG Test Vector #1', + dict(mode='OPENPGP', iv='cd47e2afb8b7e4b0', encrypted_iv='6a7eef0b58050e8b904a' ) ), +] + +def get_tests(config={}): + from Crypto.Cipher import DES3 + from common import make_block_tests + return make_block_tests(DES3, "DES3", test_data) + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_XOR.py b/lib/Crypto/SelfTest/Cipher/test_XOR.py new file mode 100644 index 0000000..a4d542a --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_XOR.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/XOR.py: Self-test for the XOR "cipher" +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Cipher.XOR""" + +import unittest + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (plaintext, ciphertext, key) tuples. +test_data = [ + # Test vectors written from scratch. (Nobody posts XOR test vectors on the web? How disappointing.) + ('01', '01', + '00', + 'zero key'), + + ('0102040810204080', '0003050911214181', + '01', + '1-byte key'), + + ('0102040810204080', 'cda8c8a2dc8a8c2a', + 'ccaa', + '2-byte key'), + + ('ff'*64, 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0'*2, + '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', + '32-byte key'), +] + +class TruncationSelfTest(unittest.TestCase): + + def runTest(self): + """33-byte key (should raise ValueError under current implementation)""" + # Crypto.Cipher.XOR previously truncated its inputs at 32 bytes. Now + # it should raise a ValueError if the length is too long. + self.assertRaises(ValueError, XOR.new, "x"*33) + +def get_tests(config={}): + global XOR + from Crypto.Cipher import XOR + from common import make_stream_tests + return make_stream_tests(XOR, "XOR", test_data) + [TruncationSelfTest()] + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_pkcs1_15.py b/lib/Crypto/SelfTest/Cipher/test_pkcs1_15.py new file mode 100644 index 0000000..7aa1703 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_pkcs1_15.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/test_pkcs1_15.py: Self-test for PKCS#1 v1.5 encryption +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import unittest +import sys + +from Crypto.PublicKey import RSA +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex +from Crypto import Random +from Crypto.Cipher import PKCS1_v1_5 as PKCS +from Crypto.Util.py3compat import * + +def rws(t): + """Remove white spaces, tabs, and new lines from a string""" + for c in ['\n', '\t', ' ']: + t = t.replace(c,'') + return t + +def t2b(t): + """Convert a text string with bytes in hex form to a byte string""" + clean = b(rws(t)) + if len(clean)%2 == 1: + print clean + raise ValueError("Even number of characters expected") + return a2b_hex(clean) + +class PKCS1_15_Tests(unittest.TestCase): + + def setUp(self): + self.rng = Random.new().read + self.key1024 = RSA.generate(1024, self.rng) + + # List of tuples with test data for PKCS#1 v1.5. + # Each tuple is made up by: + # Item #0: dictionary with RSA key component, or key to import + # Item #1: plaintext + # Item #2: ciphertext + # Item #3: random data + + _testData = ( + + # + # Generated with openssl 0.9.8o + # + ( + # Private key + '''-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDAiAnvIAOvqVwJTaYzsKnefZftgtXGE2hPJppGsWl78yz9jeXY +W/FxX/gTPURArNhdnhP6n3p2ZaDIBrO2zizbgIXs0IsljTTcr4vnI8fMXzyNUOjA +zP3nzMqZDZK6757XQAobOssMkBFqRWwilT/3DsBhRpl3iMUhF+wvpTSHewIDAQAB +AoGAC4HV/inOrpgTvSab8Wj0riyZgQOZ3U3ZpSlsfR8ra9Ib9Uee3jCYnKscu6Gk +y6zI/cdt8EPJ4PuwAWSNJzbpbVaDvUq25OD+CX8/uRT08yBS4J8TzBitZJTD4lS7 +atdTnKT0Wmwk+u8tDbhvMKwnUHdJLcuIsycts9rwJVapUtkCQQDvDpx2JMun0YKG +uUttjmL8oJ3U0m3ZvMdVwBecA0eebZb1l2J5PvI3EJD97eKe91Nsw8T3lwpoN40k +IocSVDklAkEAzi1HLHE6EzVPOe5+Y0kGvrIYRRhncOb72vCvBZvD6wLZpQgqo6c4 +d3XHFBBQWA6xcvQb5w+VVEJZzw64y25sHwJBAMYReRl6SzL0qA0wIYrYWrOt8JeQ +8mthulcWHXmqTgC6FEXP9Es5GD7/fuKl4wqLKZgIbH4nqvvGay7xXLCXD/ECQH9a +1JYNMtRen5unSAbIOxRcKkWz92F0LKpm9ZW/S9vFHO+mBcClMGoKJHiuQxLBsLbT +NtEZfSJZAeS2sUtn3/0CQDb2M2zNBTF8LlM0nxmh0k9VGm5TVIyBEMcipmvOgqIs +HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5LzuvwU= +-----END RSA PRIVATE KEY-----''', + # Plaintext + '''THIS IS PLAINTEXT\x0A''', + # Ciphertext + '''3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36 + 8f 8f d9 e3 13 1c 7f c8 b3 f9 c1 08 e4 eb 79 9c + 91 89 1f 96 3b 94 77 61 99 a4 b1 ee 5d e6 17 c9 + 5d 0a b5 63 52 0a eb 00 45 38 2a fb b0 71 3d 11 + f7 a1 9e a7 69 b3 af 61 c0 bb 04 5b 5d 4b 27 44 + 1f 5b 97 89 ba 6a 08 95 ee 4f a2 eb 56 64 e5 0f + da 7c f9 9a 61 61 06 62 ed a0 bc 5f aa 6c 31 78 + 70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75''', + # Random data + '''eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d + 61 6c af 67 b8 4e 17 56 80 66 36 04 64 34 26 8a + 47 dd 44 b3 1a b2 17 60 f4 91 2e e2 b5 95 64 cc + f9 da c8 70 94 54 86 4c ef 5b 08 7d 18 c4 ab 8d + 04 06 33 8f ca 15 5f 52 60 8a a1 0c f5 08 b5 4c + bb 99 b8 94 25 04 9c e6 01 75 e6 f9 63 7a 65 61 + 13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5''' + ), + ) + + def testEncrypt1(self): + for test in self._testData: + # Build the key + key = RSA.importKey(test[0]) + # RNG that takes its random numbers from a pool given + # at initialization + class randGen: + def __init__(self, data): + self.data = data + self.idx = 0 + def __call__(self, N): + r = self.data[self.idx:N] + self.idx += N + return r + # The real test + key._randfunc = randGen(t2b(test[3])) + cipher = PKCS.new(key) + ct = cipher.encrypt(b(test[1])) + self.assertEqual(ct, t2b(test[2])) + + def testEncrypt2(self): + # Verify that encryption fail if plaintext is too long + pt = '\x00'*(128-11+1) + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.encrypt, pt) + + def testVerify1(self): + for test in self._testData: + # Build the key + key = RSA.importKey(test[0]) + # The real test + cipher = PKCS.new(key) + pt = cipher.decrypt(t2b(test[2]), "---") + self.assertEqual(pt, b(test[1])) + + def testVerify2(self): + # Verify that decryption fails if ciphertext is not as long as + # RSA modulus + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---") + self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---") + + # Verify that decryption fails if there are less then 8 non-zero padding + # bytes + pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118) + ct = self.key1024.encrypt(pt, 0)[0] + ct = b('\x00'*(128-len(ct))) + ct + self.assertEqual("---", cipher.decrypt(ct, "---")) + + def testEncryptVerify1(self): + # Encrypt/Verify messages of length [0..RSAlen-11] + # and therefore padding [8..117] + for pt_len in xrange(0,128-11+1): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + pt2 = cipher.decrypt(ct, "---") + self.assertEqual(pt,pt2) + + +def get_tests(config={}): + tests = [] + tests += list_test_cases(PKCS1_15_Tests) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py b/lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py new file mode 100644 index 0000000..86c38a3 --- /dev/null +++ b/lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py @@ -0,0 +1,373 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Cipher/test_pkcs1_oaep.py: Self-test for PKCS#1 OAEP encryption +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +from __future__ import nested_scopes + +__revision__ = "$Id$" + +import unittest + +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex + +from Crypto.Util.py3compat import * +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_OAEP as PKCS +from Crypto.Hash import MD2,MD5,SHA1,SHA256,RIPEMD160 +from Crypto import Random + +def rws(t): + """Remove white spaces, tabs, and new lines from a string""" + for c in ['\n', '\t', ' ']: + t = t.replace(c,'') + return t + +def t2b(t): + """Convert a text string with bytes in hex form to a byte string""" + clean = rws(t) + if len(clean)%2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) + +class PKCS1_OAEP_Tests(unittest.TestCase): + + def setUp(self): + self.rng = Random.new().read + self.key1024 = RSA.generate(1024, self.rng) + + # List of tuples with test data for PKCS#1 OAEP + # Each tuple is made up by: + # Item #0: dictionary with RSA key component + # Item #1: plaintext + # Item #2: ciphertext + # Item #3: random data (=seed) + # Item #4: hash object + + _testData = ( + + # + # From in oaep-int.txt to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 + 36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f + b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 + 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f + af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 + ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e + e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f + e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb''', + # Public key + 'e':'11', + # In the test vector, only p and q were given... + # d is computed offline as e^{-1} mod (p-1)(q-1) + 'd':'''a5dafc5341faf289c4b988db30c1cdf83f31251e0 + 668b42784813801579641b29410b3c7998d6bc465745e5c3 + 92669d6870da2c082a939e37fdcb82ec93edac97ff3ad595 + 0accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef + 5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b + 8883fe4463a4bc85b1cb3c1''' + } + , + # Plaintext + '''d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49''', + # Ciphertext + '''12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 + 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 + 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 + 53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb + 6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 + 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 + da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d + 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55''', + # Random + '''aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 + f0 6c b5 8f''', + # Hash + SHA1, + ), + + # + # From in oaep-vect.txt to be found in Example 1.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 + 91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab + c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 + 12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 + f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 + c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 + 8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 + 76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb''', + 'e':'''01 00 01''', + 'd':'''53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c + 55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd + 8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b + 15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 + fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 + 2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf + b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de + f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 ''' + } + , + # Plaintext + '''66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 + 97 d5 0d ba 79 b9 87 00 4a fe fe 34''', + # Ciphertext + '''35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f + 7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb + 21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 + 03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f + a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 + d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 + d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c + 40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a''', + # Random + '''18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 + dd a0 a5 ef''', + SHA1 + ), + + # + # From in oaep-vect.txt to be found in Example 2.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 + e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e + 49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba + 7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d + 0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d + de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05 + 5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66 + 32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f + 45''', + 'e':'''01 00 01''', + 'd':'''08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa + 4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93 + c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47 + 39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc + d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0 + 8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59 + 41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25 + 25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39''' + }, + # Plaintext + '''8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 + 52 b5 8c f1 d9 2f ec 57 0b ee e7''', + # Ciphertext + '''01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 + 2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a + 5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a + ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34 + 56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d + 56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a + bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f + ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72 + 0e''', + # Random + '''8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 + e7 1b 17 82''', + SHA1 + ), + + # + # From in oaep-vect.txt to be found in Example 10.1 + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d + db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8 + df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4 + 02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5 + 40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d + 4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f + a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1 + 2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0 + 33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a + 53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00 + c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8 + 4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef + a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76 + 57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88 + d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc + 36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb''', + 'e':'''01 00 01''', + 'd':'''05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 + 25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59 + 6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0 + d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d + 19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80 + 4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be + be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19 + 34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10 + 2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2 + 4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64 + fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1 + 3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43 + 0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87 + 6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01 + 84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e + 97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79''' + }, + # Plaintext + '''8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 + b0 89 53 b0 6b 4e b2 05 bc 16 94 ee''', + # Ciphertext + '''53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 + 52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19 + ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee + e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14 + 4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a + 8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc + c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb + ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87 + 74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec + 6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1 + fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62 + 93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05 + ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55 + ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64 + 73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54 + bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc''', + # Random + '''47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 + aa 63 bd 33''', + SHA1 + ), + ) + + def testEncrypt1(self): + # Verify encryption using all test vectors + for test in self._testData: + # Build the key + comps = [ long(rws(test[0][x]),16) for x in ('n','e') ] + key = RSA.construct(comps) + # RNG that takes its random numbers from a pool given + # at initialization + class randGen: + def __init__(self, data): + self.data = data + self.idx = 0 + def __call__(self, N): + r = self.data[self.idx:N] + self.idx += N + return r + # The real test + key._randfunc = randGen(t2b(test[3])) + cipher = PKCS.new(key, test[4]) + ct = cipher.encrypt(t2b(test[1])) + self.assertEqual(ct, t2b(test[2])) + + def testEncrypt2(self): + # Verify that encryption fails if plaintext is too long + pt = '\x00'*(128-2*20-2+1) + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.encrypt, pt) + + def testDecrypt1(self): + # Verify decryption using all test vectors + for test in self._testData: + # Build the key + comps = [ long(rws(test[0][x]),16) for x in ('n','e','d') ] + key = RSA.construct(comps) + # The real test + cipher = PKCS.new(key, test[4]) + pt = cipher.decrypt(t2b(test[2])) + self.assertEqual(pt, t2b(test[1])) + + def testDecrypt2(self): + # Simplest possible negative tests + for ct_size in (127,128,129): + cipher = PKCS.new(self.key1024) + self.assertRaises(ValueError, cipher.decrypt, bchr(0x00)*ct_size) + + def testEncryptDecrypt1(self): + # Encrypt/Decrypt messages of length [0..128-2*20-2] + for pt_len in xrange(0,128-2*20-2): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) + pt2 = cipher.decrypt(ct) + self.assertEqual(pt,pt2) + + def testEncryptDecrypt2(self): + # Helper function to monitor what's requested from RNG + global asked + def localRng(N): + global asked + asked += N + return self.rng(N) + # Verify that OAEP is friendly to all hashes + for hashmod in (MD2,MD5,SHA1,SHA256,RIPEMD160): + # Verify that encrypt() asks for as many random bytes + # as the hash output size + asked = 0 + pt = self.rng(40) + self.key1024._randfunc = localRng + cipher = PKCS.new(self.key1024, hashmod) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) + self.failUnless(asked > hashmod.digest_size) + + def testEncryptDecrypt3(self): + # Verify that OAEP supports labels + pt = self.rng(35) + xlabel = self.rng(22) + cipher = PKCS.new(self.key1024, label=xlabel) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) + + def testEncryptDecrypt4(self): + # Verify that encrypt() uses the custom MGF + global mgfcalls + # Helper function to monitor what's requested from MGF + def newMGF(seed,maskLen): + global mgfcalls + mgfcalls += 1 + return bchr(0x00)*maskLen + mgfcalls = 0 + pt = self.rng(32) + cipher = PKCS.new(self.key1024, mgfunc=newMGF) + ct = cipher.encrypt(pt) + self.assertEqual(mgfcalls, 2) + self.assertEqual(cipher.decrypt(ct), pt) + +def get_tests(config={}): + tests = [] + tests += list_test_cases(PKCS1_OAEP_Tests) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/__init__.py b/lib/Crypto/SelfTest/Hash/__init__.py new file mode 100644 index 0000000..e2d9cd8 --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/__init__.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/__init__.py: Self-test for hash modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for hash modules""" + +__revision__ = "$Id$" + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config) + from Crypto.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config) + from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config) + from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config) + from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config) + from Crypto.SelfTest.Hash import test_RIPEMD160; tests += test_RIPEMD160.get_tests(config=config) + from Crypto.SelfTest.Hash import test_SHA1; tests += test_SHA1.get_tests(config=config) + from Crypto.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config) + try: + from Crypto.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config) + from Crypto.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config) + from Crypto.SelfTest.Hash import test_SHA512; tests += test_SHA512.get_tests(config=config) + except ImportError: + import sys + sys.stderr.write("SelfTest: warning: not testing SHA224/SHA384/SHA512 modules (not available)\n") + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/common.py b/lib/Crypto/SelfTest/Hash/common.py new file mode 100644 index 0000000..7bf0cdc --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/common.py @@ -0,0 +1,261 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-testing for PyCrypto hash modules""" + +__revision__ = "$Id$" + +import sys +import unittest +import binascii +import Crypto.Hash +from Crypto.Util.py3compat import * +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +# For compatibility with Python 2.1 and Python 2.2 +if sys.hexversion < 0x02030000: + # Python 2.1 doesn't have a dict() function + # Python 2.2 dict() function raises TypeError if you do dict(MD5='blah') + def dict(**kwargs): + return kwargs.copy() +else: + dict = dict + +from Crypto.SelfTest.st_common import docstrings_disabled +from Crypto.Util.strxor import strxor_c + +class HashDigestSizeSelfTest(unittest.TestCase): + + def __init__(self, hashmod, description, expected): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.expected = expected + self.description = description + + def shortDescription(self): + return self.description + + def runTest(self): + self.failUnless(hasattr(self.hashmod, "digest_size")) + self.assertEquals(self.hashmod.digest_size, self.expected) + h = self.hashmod.new() + self.failUnless(hasattr(h, "digest_size")) + self.assertEquals(h.digest_size, self.expected) + + +class HashSelfTest(unittest.TestCase): + + def __init__(self, hashmod, description, expected, input): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.expected = expected + self.input = input + self.description = description + + def shortDescription(self): + return self.description + + def runTest(self): + h = self.hashmod.new() + h.update(self.input) + + out1 = binascii.b2a_hex(h.digest()) + out2 = h.hexdigest() + + h = self.hashmod.new(self.input) + + out3 = h.hexdigest() + out4 = binascii.b2a_hex(h.digest()) + + # PY3K: hexdigest() should return str(), and digest() bytes + self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest() + if sys.version_info[0] == 2: + self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest() + self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest() + else: + self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest() + self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest() + self.assertEqual(self.expected, out4) # h = .new(data); h.digest() + + # Verify that the .new() method produces a fresh hash object, except + # for MD5 and SHA1, which are hashlib objects. (But test any .new() + # method that does exist.) + if self.hashmod.__name__ not in ('Crypto.Hash.MD5', 'Crypto.Hash.SHA1') or hasattr(h, 'new'): + h2 = h.new() + h2.update(self.input) + out5 = binascii.b2a_hex(h2.digest()) + self.assertEqual(self.expected, out5) + + # Verify that Crypto.Hash.new(h) produces a fresh hash object + h3 = Crypto.Hash.new(h) + h3.update(self.input) + out6 = binascii.b2a_hex(h3.digest()) + self.assertEqual(self.expected, out6) + + if hasattr(h, 'name'): + # Verify that Crypto.Hash.new(h.name) produces a fresh hash object + h4 = Crypto.Hash.new(h.name) + h4.update(self.input) + out7 = binascii.b2a_hex(h4.digest()) + self.assertEqual(self.expected, out7) + +class HashTestOID(unittest.TestCase): + def __init__(self, hashmod, oid): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + self.oid = oid + + def runTest(self): + from Crypto.Signature import PKCS1_v1_5 + h = self.hashmod.new() + self.assertEqual(PKCS1_v1_5._HASH_OIDS[h.name], self.oid) + +class HashDocStringTest(unittest.TestCase): + def __init__(self, hashmod): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + + def runTest(self): + docstring = self.hashmod.__doc__ + self.assert_(hasattr(self.hashmod, '__doc__')) + if not docstrings_disabled(): # -OO makes docstrings disappear globally + self.assert_(isinstance(self.hashmod.__doc__, str)) + +class GenericHashConstructorTest(unittest.TestCase): + def __init__(self, hashmod): + unittest.TestCase.__init__(self) + self.hashmod = hashmod + + def runTest(self): + obj1 = self.hashmod.new("foo") + obj2 = self.hashmod.new() + obj3 = Crypto.Hash.new(obj1.name, "foo") + obj4 = Crypto.Hash.new(obj1.name) + obj5 = Crypto.Hash.new(obj1, "foo") + obj6 = Crypto.Hash.new(obj1) + self.assert_(isinstance(self.hashmod, obj1)) + self.assert_(isinstance(self.hashmod, obj2)) + self.assert_(isinstance(self.hashmod, obj3)) + self.assert_(isinstance(self.hashmod, obj4)) + self.assert_(isinstance(self.hashmod, obj5)) + self.assert_(isinstance(self.hashmod, obj6)) + +class MACSelfTest(unittest.TestCase): + + def __init__(self, module, description, result, input, key, params): + unittest.TestCase.__init__(self) + self.module = module + self.result = result + self.input = input + self.key = key + self.params = params + self.description = description + + def shortDescription(self): + return self.description + + def runTest(self): + key = binascii.a2b_hex(b(self.key)) + data = binascii.a2b_hex(b(self.input)) + + # Strip whitespace from the expected string (which should be in lowercase-hex) + expected = b("".join(self.result.split())) + + h = self.module.new(key, **self.params) + h.update(data) + out1_bin = h.digest() + out1 = binascii.b2a_hex(h.digest()) + out2 = h.hexdigest() + + # Verify that correct MAC does not raise any exception + h.hexverify(out1) + h.verify(out1_bin) + + # Verify that incorrect MAC does raise ValueError exception + wrong_mac = strxor_c(out1_bin, 255) + self.assertRaises(ValueError, h.verify, wrong_mac) + self.assertRaises(ValueError, h.hexverify, "4556") + + h = self.module.new(key, data, **self.params) + + out3 = h.hexdigest() + out4 = binascii.b2a_hex(h.digest()) + + # Test .copy() + h2 = h.copy() + h.update(b("blah blah blah")) # Corrupt the original hash object + out5 = binascii.b2a_hex(h2.digest()) # The copied hash object should return the correct result + + # PY3K: Check that hexdigest() returns str and digest() returns bytes + if sys.version_info[0] > 2: + self.assertTrue(isinstance(h.digest(), type(b("")))) + self.assertTrue(isinstance(h.hexdigest(), type(""))) + + # PY3K: Check that .hexverify() accepts bytes or str + if sys.version_info[0] > 2: + h.hexverify(h.hexdigest()) + h.hexverify(h.hexdigest().encode('ascii')) + + # PY3K: hexdigest() should return str, and digest() should return bytes + self.assertEqual(expected, out1) + if sys.version_info[0] == 2: + self.assertEqual(expected, out2) + self.assertEqual(expected, out3) + else: + self.assertEqual(expected.decode(), out2) + self.assertEqual(expected.decode(), out3) + self.assertEqual(expected, out4) + self.assertEqual(expected, out5) + +def make_hash_tests(module, module_name, test_data, digest_size, oid=None): + tests = [] + for i in range(len(test_data)): + row = test_data[i] + (expected, input) = map(b,row[0:2]) + if len(row) < 3: + description = repr(input) + else: + description = row[2] + name = "%s #%d: %s" % (module_name, i+1, description) + tests.append(HashSelfTest(module, name, expected, input)) + name = "%s #%d: digest_size" % (module_name, i+1) + tests.append(HashDigestSizeSelfTest(module, name, digest_size)) + if oid is not None: + tests.append(HashTestOID(module, oid)) + tests.append(HashDocStringTest(module)) + if getattr(module, 'name', None) is not None: + tests.append(GenericHashConstructorTest(module)) + return tests + +def make_mac_tests(module, module_name, test_data): + tests = [] + for i in range(len(test_data)): + row = test_data[i] + (key, data, results, description, params) = row + name = "%s #%d: %s" % (module_name, i+1, description) + tests.append(MACSelfTest(module, name, results, data, key, params)) + return tests + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_CMAC.py b/lib/Crypto/SelfTest/Hash/test_CMAC.py new file mode 100644 index 0000000..f16d89f --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_CMAC.py @@ -0,0 +1,249 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/CMAC.py: Self-test for the CMAC module +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.CMAC""" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from common import dict + +from Crypto.Hash import CMAC +from Crypto.Cipher import AES, DES3 + +# This is a list of (key, data, result, description, module) tuples. +test_data = [ + + ## Test vectors from RFC 4493 ## + ## The are also in NIST SP 800 38B D.2 ## + ( '2b7e151628aed2a6abf7158809cf4f3c', + '', + 'bb1d6929e95937287fa37d129b756746', + 'RFC 4493 #1', + AES + ), + + ( '2b7e151628aed2a6abf7158809cf4f3c', + '6bc1bee22e409f96e93d7e117393172a', + '070a16b46b4d4144f79bdd9dd04a287c', + 'RFC 4493 #2', + AES + ), + + ( '2b7e151628aed2a6abf7158809cf4f3c', + '6bc1bee22e409f96e93d7e117393172a'+ + 'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411', + 'dfa66747de9ae63030ca32611497c827', + 'RFC 4493 #3', + AES + ), + + ( '2b7e151628aed2a6abf7158809cf4f3c', + '6bc1bee22e409f96e93d7e117393172a'+ + 'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+ + 'f69f2445df4f9b17ad2b417be66c3710', + '51f0bebf7e3b9d92fc49741779363cfe', + 'RFC 4493 #4', + AES + ), + + ## The rest of Appendix D of NIST SP 800 38B + ## was not totally correct. + ## Values in Examples 14, 15, 18, and 19 were wrong. + ## The updated test values are published in: + ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf + + ( '8e73b0f7da0e6452c810f32b809079e5'+ + '62f8ead2522c6b7b', + '', + 'd17ddf46adaacde531cac483de7a9367', + 'NIST SP 800 38B D.2 Example 5', + AES + ), + + ( '8e73b0f7da0e6452c810f32b809079e5'+ + '62f8ead2522c6b7b', + '6bc1bee22e409f96e93d7e117393172a', + '9e99a7bf31e710900662f65e617c5184', + 'NIST SP 800 38B D.2 Example 6', + AES + ), + + ( '8e73b0f7da0e6452c810f32b809079e5'+ + '62f8ead2522c6b7b', + '6bc1bee22e409f96e93d7e117393172a'+ + 'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411', + '8a1de5be2eb31aad089a82e6ee908b0e', + 'NIST SP 800 38B D.2 Example 7', + AES + ), + + ( '8e73b0f7da0e6452c810f32b809079e5'+ + '62f8ead2522c6b7b', + '6bc1bee22e409f96e93d7e117393172a'+ + 'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+ + 'f69f2445df4f9b17ad2b417be66c3710', + 'a1d5df0eed790f794d77589659f39a11', + 'NIST SP 800 38B D.2 Example 8', + AES + ), + + ( '603deb1015ca71be2b73aef0857d7781'+ + '1f352c073b6108d72d9810a30914dff4', + '', + '028962f61b7bf89efc6b551f4667d983', + 'NIST SP 800 38B D.3 Example 9', + AES + ), + + ( '603deb1015ca71be2b73aef0857d7781'+ + '1f352c073b6108d72d9810a30914dff4', + '6bc1bee22e409f96e93d7e117393172a', + '28a7023f452e8f82bd4bf28d8c37c35c', + 'NIST SP 800 38B D.3 Example 10', + AES + ), + + ( '603deb1015ca71be2b73aef0857d7781'+ + '1f352c073b6108d72d9810a30914dff4', + '6bc1bee22e409f96e93d7e117393172a'+ + 'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411', + 'aaf3d8f1de5640c232f5b169b9c911e6', + 'NIST SP 800 38B D.3 Example 11', + AES + ), + + ( '603deb1015ca71be2b73aef0857d7781'+ + '1f352c073b6108d72d9810a30914dff4', + '6bc1bee22e409f96e93d7e117393172a'+ + 'ae2d8a571e03ac9c9eb76fac45af8e51'+ + '30c81c46a35ce411e5fbc1191a0a52ef'+ + 'f69f2445df4f9b17ad2b417be66c3710', + 'e1992190549f6ed5696a2c056c315410', + 'NIST SP 800 38B D.3 Example 12', + AES + ), + + ( '8aa83bf8cbda1062'+ + '0bc1bf19fbb6cd58'+ + 'bc313d4a371ca8b5', + '', + 'b7a688e122ffaf95', + 'NIST SP 800 38B D.4 Example 13', + DES3 + ), + + ( '8aa83bf8cbda1062'+ + '0bc1bf19fbb6cd58'+ + 'bc313d4a371ca8b5', + '6bc1bee22e409f96', + '8e8f293136283797', + 'NIST SP 800 38B D.4 Example 14', + DES3 + ), + + ( '8aa83bf8cbda1062'+ + '0bc1bf19fbb6cd58'+ + 'bc313d4a371ca8b5', + '6bc1bee22e409f96'+ + 'e93d7e117393172a'+ + 'ae2d8a57', + '743ddbe0ce2dc2ed', + 'NIST SP 800 38B D.4 Example 15', + DES3 + ), + + ( '8aa83bf8cbda1062'+ + '0bc1bf19fbb6cd58'+ + 'bc313d4a371ca8b5', + '6bc1bee22e409f96'+ + 'e93d7e117393172a'+ + 'ae2d8a571e03ac9c'+ + '9eb76fac45af8e51', + '33e6b1092400eae5', + 'NIST SP 800 38B D.4 Example 16', + DES3 + ), + + ( '4cf15134a2850dd5'+ + '8a3d10ba80570d38', + '', + 'bd2ebf9a3ba00361', + 'NIST SP 800 38B D.7 Example 17', + DES3 + ), + + ( '4cf15134a2850dd5'+ + '8a3d10ba80570d38', + '6bc1bee22e409f96', + '4ff2ab813c53ce83', + 'NIST SP 800 38B D.7 Example 18', + DES3 + ), + + ( '4cf15134a2850dd5'+ + '8a3d10ba80570d38', + '6bc1bee22e409f96'+ + 'e93d7e117393172a'+ + 'ae2d8a57', + '62dd1b471902bd4e', + 'NIST SP 800 38B D.7 Example 19', + DES3 + ), + + ( '4cf15134a2850dd5'+ + '8a3d10ba80570d38', + '6bc1bee22e409f96'+ + 'e93d7e117393172a'+ + 'ae2d8a571e03ac9c'+ + '9eb76fac45af8e51', + '31b1e431dabc4eb8', + 'NIST SP 800 38B D.7 Example 20', + DES3 + ), + +] + +def get_tests(config={}): + global test_data + from common import make_mac_tests + + # Add new() parameters to the back of each test vector + params_test_data = [] + for row in test_data: + t = list(row) + t[4] = dict(ciphermod=t[4]) + params_test_data.append(t) + + return make_mac_tests(CMAC, "CMAC", params_test_data) + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') diff --git a/lib/Crypto/SelfTest/Hash/test_HMAC.py b/lib/Crypto/SelfTest/Hash/test_HMAC.py new file mode 100644 index 0000000..baaea5e --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_HMAC.py @@ -0,0 +1,233 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/HMAC.py: Self-test for the HMAC module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.HMAC""" + +__revision__ = "$Id$" + +from common import dict # For compatibility with Python 2.1 and 2.2 +from Crypto.Util.py3compat import * + +from Crypto.Hash import MD5, SHA1, SHA224, SHA256, SHA384, SHA512, HMAC + +default_hash = None + +# This is a list of (key, data, results, description) tuples. +test_data = [ + ## Test vectors from RFC 2202 ## + # Test that the default hashmod is MD5 + ('0b' * 16, + '4869205468657265', + dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'), + 'default-is-MD5'), + + # Test case 1 (MD5) + ('0b' * 16, + '4869205468657265', + dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'), + 'RFC 2202 #1-MD5 (HMAC-MD5)'), + + # Test case 1 (SHA1) + ('0b' * 20, + '4869205468657265', + dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'), + 'RFC 2202 #1-SHA1 (HMAC-SHA1)'), + + # Test case 2 + ('4a656665', + '7768617420646f2079612077616e7420666f72206e6f7468696e673f', + dict(MD5='750c783e6ab0b503eaa86e310a5db738', + SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'), + 'RFC 2202 #2 (HMAC-MD5/SHA1)'), + + # Test case 3 (MD5) + ('aa' * 16, + 'dd' * 50, + dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'), + 'RFC 2202 #3-MD5 (HMAC-MD5)'), + + # Test case 3 (SHA1) + ('aa' * 20, + 'dd' * 50, + dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'), + 'RFC 2202 #3-SHA1 (HMAC-SHA1)'), + + # Test case 4 + ('0102030405060708090a0b0c0d0e0f10111213141516171819', + 'cd' * 50, + dict(MD5='697eaf0aca3a3aea3a75164746ffaa79', + SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'), + 'RFC 2202 #4 (HMAC-MD5/SHA1)'), + + # Test case 5 (MD5) + ('0c' * 16, + '546573742057697468205472756e636174696f6e', + dict(MD5='56461ef2342edc00f9bab995690efd4c'), + 'RFC 2202 #5-MD5 (HMAC-MD5)'), + + # Test case 5 (SHA1) + # NB: We do not implement hash truncation, so we only test the full hash here. + ('0c' * 20, + '546573742057697468205472756e636174696f6e', + dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'), + 'RFC 2202 #5-SHA1 (HMAC-SHA1)'), + + # Test case 6 + ('aa' * 80, + '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' + + '65204b6579202d2048617368204b6579204669727374', + dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd', + SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'), + 'RFC 2202 #6 (HMAC-MD5/SHA1)'), + + # Test case 7 + ('aa' * 80, + '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' + + '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d' + + '53697a652044617461', + dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e', + SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'), + 'RFC 2202 #7 (HMAC-MD5/SHA1)'), + + ## Test vectors from RFC 4231 ## + # 4.2. Test Case 1 + ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', + '4869205468657265', + dict(SHA256=''' + b0344c61d8db38535ca8afceaf0bf12b + 881dc200c9833da726e9376c2e32cff7 + '''), + 'RFC 4231 #1 (HMAC-SHA256)'), + + # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC + # output. + ('4a656665', + '7768617420646f2079612077616e7420666f72206e6f7468696e673f', + dict(SHA256=''' + 5bdcc146bf60754e6a042426089575c7 + 5a003f089d2739839dec58b964ec3843 + '''), + 'RFC 4231 #2 (HMAC-SHA256)'), + + # 4.4. Test Case 3 - Test with a combined length of key and data that is + # larger than 64 bytes (= block-size of SHA-224 and SHA-256). + ('aa' * 20, + 'dd' * 50, + dict(SHA256=''' + 773ea91e36800e46854db8ebd09181a7 + 2959098b3ef8c122d9635514ced565fe + '''), + 'RFC 4231 #3 (HMAC-SHA256)'), + + # 4.5. Test Case 4 - Test with a combined length of key and data that is + # larger than 64 bytes (= block-size of SHA-224 and SHA-256). + ('0102030405060708090a0b0c0d0e0f10111213141516171819', + 'cd' * 50, + dict(SHA256=''' + 82558a389a443c0ea4cc819899f2083a + 85f0faa3e578f8077a2e3ff46729665b + '''), + 'RFC 4231 #4 (HMAC-SHA256)'), + + # 4.6. Test Case 5 - Test with a truncation of output to 128 bits. + # + # Not included because we do not implement hash truncation. + # + + # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of + # SHA-384 and SHA-512). + ('aa' * 131, + '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' + + '65204b6579202d2048617368204b6579204669727374', + dict(SHA256=''' + 60e431591ee0b67f0d8a26aacbf5b77f + 8e0bc6213728c5140546040f0ee37f54 + '''), + 'RFC 4231 #6 (HMAC-SHA256)'), + + # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes + # (= block-size of SHA-384 and SHA-512). + ('aa' * 131, + '5468697320697320612074657374207573696e672061206c6172676572207468' + + '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074' + + '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565' + + '647320746f20626520686173686564206265666f7265206265696e6720757365' + + '642062792074686520484d414320616c676f726974686d2e', + dict(SHA256=''' + 9b09ffa71b942fcb27635fbcd5b0e944 + bfdc63644f0713938a7f51535c3a35e2 + '''), + 'RFC 4231 #7 (HMAC-SHA256)'), + + # Test case 8 (SHA224) + ('4a656665', + '7768617420646f2079612077616e74' + + '20666f72206e6f7468696e673f', + dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'), + 'RFC 4634 8.4 SHA224 (HMAC-SHA224)'), + + # Test case 9 (SHA384) + ('4a656665', + '7768617420646f2079612077616e74' + + '20666f72206e6f7468696e673f', + dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'), + 'RFC 4634 8.4 SHA384 (HMAC-SHA384)'), + + # Test case 10 (SHA512) + ('4a656665', + '7768617420646f2079612077616e74' + + '20666f72206e6f7468696e673f', + dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'), + 'RFC 4634 8.4 SHA512 (HMAC-SHA512)'), + +] + +def get_tests(config={}): + global test_data + from common import make_mac_tests + + # A test vector contains multiple results, each one for a + # different hash algorithm. + # Here we expand each test vector into multiple ones, + # and add the relevant parameters that will be passed to new() + exp_test_data = [] + for row in test_data: + for modname in row[2].keys(): + t = list(row) + t[2] = row[2][modname] + try: + t.append(dict(digestmod=globals()[modname])) + exp_test_data.append(t) + except AttributeError: + import sys + sys.stderr.write("SelfTest: warning: not testing HMAC-%s (not available)\n" % modname) + + return make_mac_tests(HMAC, "HMAC", exp_test_data) + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_MD2.py b/lib/Crypto/SelfTest/Hash/test_MD2.py new file mode 100644 index 0000000..fd03e78 --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_MD2.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/MD2.py: Self-test for the MD2 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.MD2""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + # Test vectors from RFC 1319 + ('8350e5a3e24c153df2275c9f80692773', '', "'' (empty string)"), + ('32ec01ec4a6dac72c0ab96fb34c0b5d1', 'a'), + ('da853b0d3f88d99b30283a69e6ded6bb', 'abc'), + ('ab4f496bfb2a530b219ff33031fe06b0', 'message digest'), + + ('4e8ddff3650292ab5a4108c3aa47940b', 'abcdefghijklmnopqrstuvwxyz', + 'a-z'), + + ('da33def2a42df13975352846c30338cd', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + 'A-Z, a-z, 0-9'), + + ('d5976f79d83d3a0dc9806c3c66f3efd8', + '1234567890123456789012345678901234567890123456' + + '7890123456789012345678901234567890', + "'1234567890' * 8"), +] + +def get_tests(config={}): + from Crypto.Hash import MD2 + from common import make_hash_tests + return make_hash_tests(MD2, "MD2", test_data, + digest_size=16, + oid="1.2.840.113549.2.2") + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_MD4.py b/lib/Crypto/SelfTest/Hash/test_MD4.py new file mode 100644 index 0000000..7dbf49f --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_MD4.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/MD4.py: Self-test for the MD4 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.MD4""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + # Test vectors from RFC 1320 + ('31d6cfe0d16ae931b73c59d7e0c089c0', '', "'' (empty string)"), + ('bde52cb31de33e46245e05fbdbd6fb24', 'a'), + ('a448017aaf21d8525fc10ae87aa6729d', 'abc'), + ('d9130a8164549fe818874806e1c7014b', 'message digest'), + + ('d79e1c308aa5bbcdeea8ed63df412da9', 'abcdefghijklmnopqrstuvwxyz', + 'a-z'), + + ('043f8582f241db351ce627e153e7f0e4', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + 'A-Z, a-z, 0-9'), + + ('e33b4ddc9c38f2199c3e7b164fcc0536', + '1234567890123456789012345678901234567890123456' + + '7890123456789012345678901234567890', + "'1234567890' * 8"), +] + +def get_tests(config={}): + from Crypto.Hash import MD4 + from common import make_hash_tests + return make_hash_tests(MD4, "MD4", test_data, + digest_size=16, + oid="1.2.840.113549.2.4") + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_MD5.py b/lib/Crypto/SelfTest/Hash/test_MD5.py new file mode 100644 index 0000000..0683113 --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_MD5.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/MD5.py: Self-test for the MD5 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.MD5""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + # Test vectors from RFC 1321 + ('d41d8cd98f00b204e9800998ecf8427e', '', "'' (empty string)"), + ('0cc175b9c0f1b6a831c399e269772661', 'a'), + ('900150983cd24fb0d6963f7d28e17f72', 'abc'), + ('f96b697d7cb7938d525a2f31aaf161d0', 'message digest'), + + ('c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz', + 'a-z'), + + ('d174ab98d277d9f5a5611c2c9f419d9f', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + 'A-Z, a-z, 0-9'), + + ('57edf4a22be3c955ac49da2e2107b67a', + '1234567890123456789012345678901234567890123456' + + '7890123456789012345678901234567890', + "'1234567890' * 8"), +] + +def get_tests(config={}): + from Crypto.Hash import MD5 + from common import make_hash_tests + return make_hash_tests(MD5, "MD5", test_data, + digest_size=16, + oid="1.2.840.113549.2.5") + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_RIPEMD160.py b/lib/Crypto/SelfTest/Hash/test_RIPEMD160.py new file mode 100644 index 0000000..b0d6980 --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_RIPEMD160.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/test_RIPEMD160.py: Self-test for the RIPEMD-160 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +#"""Self-test suite for Crypto.Hash.RIPEMD160""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + # Test vectors downloaded 2008-09-12 from + # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + ('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"), + ('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'), + ('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'), + ('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'), + + ('f71c27109c692c1b56bbdceb5b9d2865b3708dbc', + 'abcdefghijklmnopqrstuvwxyz', + 'a-z'), + + ('12a053384a9c0c88e405a06c27dcf49ada62eb2b', + 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', + 'abcdbcd...pnopq'), + + ('b0e20b6e3116640286ed3a87a5713079b21f5189', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + 'A-Z, a-z, 0-9'), + + ('9b752e45573d4b39f4dbd3323cab82bf63326bfb', + '1234567890' * 8, + "'1234567890' * 8"), + + ('52783243c1697bdbe16d37f97f68f08325dc1528', + 'a' * 10**6, + '"a" * 10**6'), +] + +def get_tests(config={}): + from Crypto.Hash import RIPEMD160 + from common import make_hash_tests + return make_hash_tests(RIPEMD160, "RIPEMD160", test_data, + digest_size=20, + oid="1.3.36.3.2.1") + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_SHA1.py b/lib/Crypto/SelfTest/Hash/test_SHA1.py new file mode 100644 index 0000000..436f7de --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_SHA1.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/SHA1.py: Self-test for the SHA-1 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.SHA""" + +__revision__ = "$Id$" + +from Crypto.Util.py3compat import * + +# Test vectors from various sources +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + # FIPS PUB 180-2, A.1 - "One-Block Message" + ('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'), + + # FIPS PUB 180-2, A.2 - "Multi-Block Message" + ('84983e441c3bd26ebaae4aa1f95129e5e54670f1', + 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), + + # FIPS PUB 180-2, A.3 - "Long Message" +# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f', +# 'a' * 10**6, +# '"a" * 10**6'), + + # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits) + ('dea356a2cddd90c7a7ecedc5ebb563934f460452', + '01234567' * 80, + '"01234567" * 80'), +] + +def get_tests(config={}): + from Crypto.Hash import SHA1 + from common import make_hash_tests + return make_hash_tests(SHA1, "SHA1", test_data, + digest_size=20, + oid="1.3.14.3.2.26") + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_SHA224.py b/lib/Crypto/SelfTest/Hash/test_SHA224.py new file mode 100644 index 0000000..eb28ebc --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_SHA224.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/test_SHA224.py: Self-test for the SHA-224 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.SHA224""" + +__revision__ = "$Id$" + +# Test vectors from various sources +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + + # RFC 3874: Section 3.1, "Test Vector #1 + ('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', 'abc'), + + # RFC 3874: Section 3.2, "Test Vector #2 + ('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), + + # RFC 3874: Section 3.3, "Test Vector #3 + ('20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67', 'a' * 10**6, "'a' * 10**6"), + + # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f', ''), + + ('49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b', + 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + + ('58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1', + 'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern'), + +] + +def get_tests(config={}): + from Crypto.Hash import SHA224 + from common import make_hash_tests + return make_hash_tests(SHA224, "SHA224", test_data, + digest_size=28, + oid='2.16.840.1.101.3.4.2.4') + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_SHA256.py b/lib/Crypto/SelfTest/Hash/test_SHA256.py new file mode 100644 index 0000000..50bdba8 --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_SHA256.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/test_SHA256.py: Self-test for the SHA-256 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.SHA256""" + +__revision__ = "$Id$" + +import unittest +from Crypto.Util.py3compat import * + +class LargeSHA256Test(unittest.TestCase): + def runTest(self): + """SHA256: 512/520 MiB test""" + from Crypto.Hash import SHA256 + zeros = bchr(0x00) * (1024*1024) + + h = SHA256.new(zeros) + for i in xrange(511): + h.update(zeros) + + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB + + for i in xrange(8): + h.update(zeros) + + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual('abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e', h.hexdigest()) # 520 MiB + +def get_tests(config={}): + # Test vectors from FIPS PUB 180-2 + # This is a list of (expected_result, input[, description]) tuples. + test_data = [ + # FIPS PUB 180-2, B.1 - "One-Block Message" + ('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', + 'abc'), + + # FIPS PUB 180-2, B.2 - "Multi-Block Message" + ('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', + 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), + + # FIPS PUB 180-2, B.3 - "Long Message" + ('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0', + 'a' * 10**6, + '"a" * 10**6'), + + # Test for an old PyCrypto bug. + ('f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103', + 'This message is precisely 55 bytes long, to test a bug.', + 'Length = 55 (mod 64)'), + + # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ''), + + ('d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8', + 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + ] + + from Crypto.Hash import SHA256 + from common import make_hash_tests + tests = make_hash_tests(SHA256, "SHA256", test_data, + digest_size=32, + oid="2.16.840.1.101.3.4.2.1") + + if config.get('slow_tests'): + tests += [LargeSHA256Test()] + + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_SHA384.py b/lib/Crypto/SelfTest/Hash/test_SHA384.py new file mode 100644 index 0000000..27d16b3 --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_SHA384.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/test_SHA.py: Self-test for the SHA-384 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.SHA384""" + +__revision__ = "$Id$" + +# Test vectors from various sources +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + + # RFC 4634: Section Page 8.4, "Test 1" + ('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', 'abc'), + + # RFC 4634: Section Page 8.4, "Test 2.2" + ('09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), + + # RFC 4634: Section Page 8.4, "Test 3" + ('9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985', 'a' * 10**6, "'a' * 10**6"), + + # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ('38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ''), + + # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ('71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677', + 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), + +] + +def get_tests(config={}): + from Crypto.Hash import SHA384 + from common import make_hash_tests + return make_hash_tests(SHA384, "SHA384", test_data, + digest_size=48, + oid='2.16.840.1.101.3.4.2.2') + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Hash/test_SHA512.py b/lib/Crypto/SelfTest/Hash/test_SHA512.py new file mode 100644 index 0000000..04a505e --- /dev/null +++ b/lib/Crypto/SelfTest/Hash/test_SHA512.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Hash/test_SHA512.py: Self-test for the SHA-512 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Hash.SHA512""" + +__revision__ = "$Id$" + +# Test vectors from various sources +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + + # RFC 4634: Section Page 8.4, "Test 1" + ('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc'), + + # RFC 4634: Section Page 8.4, "Test 2.1" + ('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), + + # RFC 4634: Section Page 8.4, "Test 3" + ('e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b', 'a' * 10**6, "'a' * 10**6"), + + # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm + ('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', ''), + + ('af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c', 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), +] + +def get_tests(config={}): + from Crypto.Hash import SHA512 + from common import make_hash_tests + return make_hash_tests(SHA512, "SHA512", test_data, + digest_size=64, + oid="2.16.840.1.101.3.4.2.3") + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/IO/__init__.py b/lib/Crypto/SelfTest/IO/__init__.py new file mode 100644 index 0000000..084904e --- /dev/null +++ b/lib/Crypto/SelfTest/IO/__init__.py @@ -0,0 +1,34 @@ +# +# SelfTest/IO/__init__.py: Self-test for input/output module +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for I/O""" + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.IO import test_PKCS8; tests += test_PKCS8.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + + diff --git a/lib/Crypto/SelfTest/IO/test_PKCS8.py b/lib/Crypto/SelfTest/IO/test_PKCS8.py new file mode 100644 index 0000000..6902ab4 --- /dev/null +++ b/lib/Crypto/SelfTest/IO/test_PKCS8.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/test_PKCS8.py: Self-test for the PKCS8 module +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-tests for Crypto.PublicKey.PKCS8 module""" + +__revision__ = "$Id$" + +import unittest +import sys +from binascii import unhexlify + +from Crypto.Util.py3compat import * +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +from Crypto.IO import PKCS8 + +oid_key = '1.2.840.113549.1.1.1' + +# Original RSA key (in DER format) +# hexdump -v -e '32/1 "%02x" "\n"' key.der +clear_key=""" +308201ab020100025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf16 +0c951a870b71783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f0 +6fe20faeebb0c356e79cdec6db4dd427e82d8ae4a5b90996227b8ba54ccfc4d2 +5c08050203010001025a00afa09c70d528299b7552fe766b5d20f9a221d66938 +c3b68371d48515359863ff96f0978d700e08cd6fd3d8a3f97066fc2e0d5f78eb +3a50b8e17ba297b24d1b8e9cdfd18d608668198d724ad15863ef0329195dee89 +3f039395022d0ebe0518df702a8b25954301ec60a97efdcec8eaa4f2e76ca7e8 +8dfbc3f7e0bb83f9a0e8dc47c0f8c746e9df6b022d0c9195de13f09b7be1fdd7 +1f56ae7d973e08bd9fd2c3dfd8936bb05be9cc67bd32d663c7f00d70932a0be3 +c24f022d0ac334eb6cabf1933633db007b763227b0d9971a9ea36aca8b669ec9 +4fcf16352f6b3dcae28e4bd6137db4ddd3022d0400a09f15ee7b351a2481cb03 +09920905c236d09c87afd3022f3afc2a19e3b746672b635238956ee7e6dd62d5 +022d0cd88ed14fcfbda5bbf0257f700147137bbab9c797af7df866704b889aa3 +7e2e93df3ff1a0fd3490111dcdbc4c +""" + +# Same key as above, wrapped in PKCS#8 but w/o password +# +# openssl pkcs8 -topk8 -inform DER -nocrypt -in key.der -outform DER -out keyp8.der +# hexdump -v -e '32/1 "%02x" "\n"' keyp8.der +wrapped_clear_key=""" +308201c5020100300d06092a864886f70d0101010500048201af308201ab0201 +00025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf160c951a870b71 +783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f06fe20faeebb0 +c356e79cdec6db4dd427e82d8ae4a5b90996227b8ba54ccfc4d25c0805020301 +0001025a00afa09c70d528299b7552fe766b5d20f9a221d66938c3b68371d485 +15359863ff96f0978d700e08cd6fd3d8a3f97066fc2e0d5f78eb3a50b8e17ba2 +97b24d1b8e9cdfd18d608668198d724ad15863ef0329195dee893f039395022d +0ebe0518df702a8b25954301ec60a97efdcec8eaa4f2e76ca7e88dfbc3f7e0bb +83f9a0e8dc47c0f8c746e9df6b022d0c9195de13f09b7be1fdd71f56ae7d973e +08bd9fd2c3dfd8936bb05be9cc67bd32d663c7f00d70932a0be3c24f022d0ac3 +34eb6cabf1933633db007b763227b0d9971a9ea36aca8b669ec94fcf16352f6b +3dcae28e4bd6137db4ddd3022d0400a09f15ee7b351a2481cb0309920905c236 +d09c87afd3022f3afc2a19e3b746672b635238956ee7e6dd62d5022d0cd88ed1 +4fcfbda5bbf0257f700147137bbab9c797af7df866704b889aa37e2e93df3ff1 +a0fd3490111dcdbc4c +""" + +### +# +# The key above will now be encrypted with different algorithms. +# The password is always 'TestTest'. +# +# Each item in the wrapped_enc_keys list contains: +# * wrap algorithm +# * iteration count +# * Salt +# * IV +# * Expected result +### +wrapped_enc_keys = [] + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der -v2 des3 +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC', +2048, +"47EA7227D8B22E2F", # IV +"E3F7A838AB911A4D", # Salt +""" +30820216304006092a864886f70d01050d3033301b06092a864886f70d01050c +300e0408e3f7a838ab911a4d02020800301406082a864886f70d0307040847ea +7227d8b22e2f048201d0ea388b374d2d0e4ceb7a5139f850fdff274884a6e6c0 +64326e09d00dbba9018834edb5a51a6ae3d1806e6e91eebf33788ce71fee0637 +a2ebf58859dd32afc644110c390274a6128b50c39b8d907823810ec471bada86 +6f5b75d8ea04ad310fad2e73621696db8e426cd511ee93ec1714a1a7db45e036 +4bf20d178d1f16bbb250b32c2d200093169d588de65f7d99aad9ddd0104b44f1 +326962e1520dfac3c2a800e8a14f678dff2b3d0bb23f69da635bf2a643ac934e +219a447d2f4460b67149e860e54f365da130763deefa649c72b0dcd48966a2d3 +4a477444782e3e66df5a582b07bbb19778a79bd355074ce331f4a82eb966b0c4 +52a09eab6116f2722064d314ae433b3d6e81d2436e93fdf446112663cde93b87 +9c8be44beb45f18e2c78fee9b016033f01ecda51b9b142091fa69f65ab784d2c +5ad8d34be6f7f1464adfc1e0ef3f7848f40d3bdea4412758f2fcb655c93d8f4d +f6fa48fc5aa4b75dd1c017ab79ac9d737233a6d668f5364ccf47786debd37334 +9c10c9e6efbe78430a61f71c89948aa32cdc3cc7338cf994147819ce7ab23450 +c8f7d9b94c3bb377d17a3fa204b601526317824b142ff6bc843fa7815ece89c0 +839573f234dac8d80cc571a045353d61db904a4398d8ef3df5ac +""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +-1, # pbeWithMD5AndDES-CBC, only decoding is supported +-1, +"", +"", +""" +308201f1301b06092a864886f70d010503300e0408f9b990c89af1d41b020208 +00048201d0c6267fe8592903891933d559e71a7ca68b2e39150f19daca0f7921 +52f97e249d72f670d5140e9150433310ed7c7ee51927693fd39884cb9551cea5 +a7b746f7edf199f8787d4787a35dad930d7db057b2118851211b645ac8b90fa6 +b0e7d49ac8567cbd5fff226e87aa9129a0f52c45e9307752e8575c3b0ff756b7 +31fda6942d15ecb6b27ea19370ccc79773f47891e80d22b440d81259c4c28eac +e0ca839524116bcf52d8c566e49a95ddb0e5493437279a770a39fd333f3fca91 +55884fad0ba5aaf273121f893059d37dd417da7dcfd0d6fa7494968f13b2cc95 +65633f2c891340193e5ec00e4ee0b0e90b3b93da362a4906360845771ade1754 +9df79140be5993f3424c012598eadd3e7c7c0b4db2c72cf103d7943a5cf61420 +93370b9702386c3dd4eb0a47f34b579624a46a108b2d13921fa1b367495fe345 +6aa128aa70f8ca80ae13eb301e96c380724ce67c54380bbea2316c1faf4d058e +b4ca2e23442047606b9bc4b3bf65b432cb271bea4eb35dd3eb360d3be8612a87 +a50e96a2264490aeabdc07c6e78e5dbf4fe3388726d0e2a228346bf3c2907d68 +2a6276b22ae883fb30fa611f4e4193e7a08480fcd7db48308bacbd72bf4807aa +11fd394859f97d22982f7fe890b2e2a0f7e7ffb693 +""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der +# -outform DER -out keyenc.der -v1 PBE-SHA1-RC2-64 +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +-1, # pbeWithSHA1AndRC2-CBC, only decoding is supported +-1, +"", +"", +""" +308201f1301b06092a864886f70d01050b300e04083ee943bdae185008020208 +00048201d0e4614d9371d3ff10ceabc2f6a7a13a0f449f9a714144e46518ea55 +e3e6f0cde24031d01ef1f37ec40081449ef01914faf45983dde0d2bc496712de +8dd15a5527dff4721d9016c13f34fb93e3ce68577e30146266d71b539f854e56 +753a192cf126ed4812734d86f81884374f1100772f78d0646e9946407637c565 +d070acab413c55952f7237437f2e48cae7fa0ff8d370de2bf446dd08049a3663 +d9c813ac197468c02e2b687e7ca994cf7f03f01b6eca87dbfed94502c2094157 +ea39f73fe4e591df1a68b04d19d9adab90bb9898467c1464ad20bf2b8fb9a5ff +d3ec91847d1c67fd768a4b9cfb46572eccc83806601372b6fad0243f58f623b7 +1c5809dea0feb8278fe27e5560eed8448dc93f5612f546e5dd7c5f6404365eb2 +5bf3396814367ae8b15c5c432b57eaed1f882c05c7f6517ee9e42b87b7b8d071 +9d6125d1b52f7b2cca1f6bd5f584334bf90bce1a7d938274cafe27b68e629698 +b16e27ae528db28593af9adcfccbebb3b9e1f2af5cd5531b51968389caa6c091 +e7de1f1b96f0d258e54e540d961a7c0ef51fda45d6da5fddd33e9bbfd3a5f8d7 +d7ab2e971de495cddbc86d38444fee9f0ac097b00adaf7802dabe0cff5b43b45 +4f26b7b547016f89be52676866189911c53e2f2477""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der +# -outform DER -out keyenc.der -v1 PBE-MD5-RC2-64 +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +-1, # pbeWithMD5AndRC2-CBC, only decoding is supported +-1, +"", +"", +""" +308201f1301b06092a864886f70d010506300e0408f5cd2fee56d9b4b8020208 +00048201d086454942d6166a19d6b108465bd111e7080911f573d54b1369c676 +df28600e84936bfec04f91023ff16499e2e07178c340904f12ffa6886ab66228 +32bf43c2bff5a0ed14e765918cf5fc543ad49566246f7eb3fc044fa5a9c25f40 +8fc8c8296b91658d3bb1067c0aba008c4fefd9e2bcdbbbd63fdc8085482bccf4 +f150cec9a084259ad441a017e5d81a1034ef2484696a7a50863836d0eeda45cd +8cee8ecabfed703f8d9d4bbdf3a767d32a0ccdc38550ee2928d7fe3fa27eda5b +5c7899e75ad55d076d2c2d3c37d6da3d95236081f9671dab9a99afdb1cbc890e +332d1a91105d9a8ce08b6027aa07367bd1daec3059cb51f5d896124da16971e4 +0ca4bcadb06c854bdf39f42dd24174011414e51626d198775eff3449a982df7b +ace874e77e045eb6d7c3faef0750792b29a068a6291f7275df1123fac5789c51 +27ace42836d81633faf9daf38f6787fff0394ea484bbcd465b57d4dbee3cf8df +b77d1db287b3a6264c466805be5a4fe85cfbca180699859280f2dd8e2c2c10b5 +7a7d2ac670c6039d41952fbb0e4f99b560ebe1d020e1b96d02403283819c00cc +529c51f0b0101555e4c58002ba3c6e3c12e3fde1aec94382792e96d9666a2b33 +3dc397b22ecab67ee38a552fec29a1d4ff8719c748""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der +# -outform DER -out keyenc.der -v1 PBE-SHA1-DES +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +-1, # pbeWithSHA1AndDES-CBC, only decoding is supported +-1, +"", +"", +""" +308201f1301b06092a864886f70d01050a300e04089bacc9cf1e8f734e020208 +00048201d03e502f3ceafe8fd19ab2939576bfdded26d719b2441db1459688f5 +9673218b41ec1f739edf1e460bd927bc28470c87b2d4fc8ea02ba17b47a63c49 +c5c1bee40529dadfd3ef8b4472c730bc136678c78abfb34670ec9d7dcd17ee3f +892f93f2629e6e0f4b24ecb9f954069bf722f466dece3913bb6abbd2c471d9a5 +c5eea89b14aaccda43d30b0dd0f6eb6e9850d9747aa8aa8414c383ad01c374ee +26d3552abec9ba22669cc9622ccf2921e3d0c8ecd1a70e861956de0bec6104b5 +b649ac994970c83f8a9e84b14a7dff7843d4ca3dd4af87cea43b5657e15ae0b5 +a940ce5047f006ab3596506600724764f23757205fe374fee04911336d655acc +03e159ec27789191d1517c4f3f9122f5242d44d25eab8f0658cafb928566ca0e +8f6589aa0c0ab13ca7a618008ae3eafd4671ee8fe0b562e70b3623b0e2a16eee +97fd388087d2e03530c9fe7db6e52eccc7c48fd701ede35e08922861a9508d12 +bc8bbf24f0c6bee6e63dbcb489b603d4c4a78ce45bf2eab1d5d10456c42a65a8 +3a606f4e4b9b46eb13b57f2624b651859d3d2d5192b45dbd5a2ead14ff20ca76 +48f321309aa56d8c0c4a192b580821cc6c70c75e6f19d1c5414da898ec4dd39d +b0eb93d6ba387a80702dfd2db610757ba340f63230 +""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der +# -outform DER -out keyenc.der -v2 aes128 +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +'PBKDF2WithHMAC-SHA1AndAES128-CBC', +2048, +"4F66EE5D3BCD531FE6EBF4B4E73016B8", # IV +"479F25156176C53A", # Salt +""" +3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c +300e0408479f25156176c53a02020800301d060960864801650304010204104f +66ee5d3bcd531fe6ebf4b4e73016b8048201d0e33cfa560423f589d097d21533 +3b880a5ebac5b2ac58b4e73b0d787aee7764f034fe34ca1d1bd845c0a7c3316f +afbfb2129e03dcaf5a5031394206492828dacef1e04639bee5935e0f46114202 +10bc6c37182f4889be11c5d0486c398f4be952e5740f65de9d8edeb275e2b406 +e19bc29ad5ebb97fa536344fc3d84c7e755696f12b810898de4e6f069b8a81c8 +0aab0d45d7d062303aaa4a10c2ce84fdb5a03114039cfe138e38bb15b2ced717 +93549cdad85e730b14d9e2198b663dfdc8d04a4349eb3de59b076ad40b116d4a +25ed917c576bc7c883c95ef0f1180e28fc9981bea069594c309f1aa1b253ceab +a2f0313bb1372bcb51a745056be93d77a1f235a762a45e8856512d436b2ca0f7 +dd60fbed394ba28978d2a2b984b028529d0a58d93aba46c6bbd4ac1e4013cbaa +63b00988bc5f11ccc40141c346762d2b28f64435d4be98ec17c1884985e3807e +e550db606600993efccf6de0dfc2d2d70b5336a3b018fa415d6bdd59f5777118 +16806b7bc17c4c7e20ad7176ebfa5a1aa3f6bc10f04b77afd443944642ac9cca +d740e082b4a3bbb8bafdd34a0b3c5f2f3c2aceccccdccd092b78994b845bfa61 +706c3b9df5165ed1dbcbf1244fe41fc9bf993f52f7658e2f87e1baaeacb0f562 +9d905c +""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der +# -outform DER -out keyenc.der -v2 aes192 +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +'PBKDF2WithHMAC-SHA1AndAES192-CBC', +2048, +"5CFC2A4FF7B63201A4A8A5B021148186", # IV +"D718541C264944CE", # Salt +""" +3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c +300e0408d718541c264944ce02020800301d060960864801650304011604105c +fc2a4ff7b63201a4a8a5b021148186048201d08e74aaa21b8bcfb15b9790fe95 +b0e09ddb0f189b6fb1682fdb9f122b804650ddec3c67a1df093a828b3e5fbcc6 +286abbcc5354c482fd796d972e919ca8a5eba1eaa2293af1d648013ddad72106 +75622264dfba55dafdda39e338f058f1bdb9846041ffff803797d3fdf3693135 +8a192729ea8346a7e5e58e925a2e2e4af0818581859e8215d87370eb4194a5ff +bae900857d4c591dbc651a241865a817eaede9987c9f9ae4f95c0bf930eea88c +4d7596e535ffb7ca369988aba75027a96b9d0bc9c8b0b75f359067fd145a378b +02aaa15e9db7a23176224da48a83249005460cc6e429168657f2efa8b1af7537 +d7d7042f2d683e8271b21d591090963eeb57aea6172f88da139e1614d6a7d1a2 +1002d5a7a93d6d21156e2b4777f6fc069287a85a1538c46b7722ccde591ab55c +630e1ceeb1ac42d1b41f3f654e9da86b5efced43775ea68b2594e50e4005e052 +0fe753c0898120c2c07265367ff157f6538a1e4080d6f9d1ca9eb51939c9574e +f2e4e1e87c1434affd5808563cddd376776dbbf790c6a40028f311a8b58dafa2 +0970ed34acd6e3e89d063987893b2b9570ddb8cc032b05a723bba9444933ebf3 +c624204be72f4190e0245197d0cb772bec933fd8442445f9a28bd042d5a3a1e9 +9a8a07 +""" +)) + +# +# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der +# -outform DER -out keyenc.der -v2 aes192 +# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der +# +wrapped_enc_keys.append(( +'PBKDF2WithHMAC-SHA1AndAES256-CBC', +2048, +"323351F94462AC563E053A056252C2C4", # IV +"02A6CD0D12E727B5", # Salt +""" +3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c +300e040802a6cd0d12e727b502020800301d060960864801650304012a041032 +3351f94462ac563e053a056252c2c4048201d07f4ef1c7be21aae738a20c5632 +b8bdbbb9083b6e7f68822267b1f481fd27fdafd61a90660de6e4058790e4c912 +bf3f319a7c37e6eb3d956daaa143865020d554bf6215e8d7492359aaeef45d6e +d85a686ed26c0bf7c18d071d827a86f0b73e1db0c0e7f3d42201544093302a90 +551ad530692468c47ac15c69500b8ca67d4a17b64d15cecc035ae50b768a36cf +07c395afa091e9e6f86f665455fbdc1b21ad79c0908b73da5de75a9b43508d5d +44dc97a870cd3cd9f01ca24452e9b11c1b4982946702cfcbfda5b2fcc0203fb5 +0b52a115760bd635c94d4c95ac2c640ee9a04ffaf6ccff5a8d953dd5d88ca478 +c377811c521f2191639c643d657a9e364af88bb7c14a356c2b0b4870a23c2f54 +d41f8157afff731471dccc6058b15e1151bcf84b39b5e622a3a1d65859c912a5 +591b85e034a1f6af664f030a6bfc8c3d20c70f32b54bcf4da9c2da83cef49cf8 +e9a74f0e5d358fe50b88acdce6a9db9a7ad61536212fc5f877ebfc7957b8bda4 +b1582a0f10d515a20ee06cf768db9c977aa6fbdca7540d611ff953012d009dac +e8abd059f8e8ffea637c9c7721f817aaf0bb23403e26a0ef0ff0e2037da67d41 +af728481f53443551a9bff4cea023164e9622b5441a309e1f4bff98e5bf76677 +8d7cd9 +""" +)) + +def txt2bin(inputs): + s = b('').join([b(x) for x in inputs if not (x in '\n\r\t ')]) + return unhexlify(s) + +class Rng: + def __init__(self, output): + self.output=output + self.idx=0 + def __call__(self, n): + output = self.output[self.idx:self.idx+n] + self.idx += n + return output + +class PKCS8_Decrypt(unittest.TestCase): + + def setUp(self): + self.oid_key = oid_key + self.clear_key = txt2bin(clear_key) + self.wrapped_clear_key = txt2bin(wrapped_clear_key) + self.wrapped_enc_keys = [] + for t in wrapped_enc_keys: + self.wrapped_enc_keys.append(( + t[0], + t[1], + txt2bin(t[2]), + txt2bin(t[3]), + txt2bin(t[4]) + )) + + ### NO ENCRYTION + + def test1(self): + """Verify unwrapping w/o encryption""" + res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + def test2(self): + """Verify wrapping w/o encryption""" + wrapped = PKCS8.wrap(self.clear_key, self.oid_key) + res1, res2, res3 = PKCS8.unwrap(wrapped) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + ## ENCRYPTION + + def test3(self): + """Verify unwrapping with encryption""" + + for t in self.wrapped_enc_keys: + res1, res2, res3 = PKCS8.unwrap(t[4], b("TestTest")) + self.assertEqual(res1, self.oid_key) + self.assertEqual(res2, self.clear_key) + + def test4(self): + """Verify wrapping with encryption""" + + for t in self.wrapped_enc_keys: + if t[0]==-1: + continue + rng = Rng(t[2]+t[3]) + params = { 'iteration_count':t[1] } + wrapped = PKCS8.wrap( + self.clear_key, + self.oid_key, + b("TestTest"), + protection=t[0], + prot_params=params, + key_params=None, + randfunc=rng) + self.assertEqual(wrapped, t[4]) + +def get_tests(config={}): + from Crypto.SelfTest.st_common import list_test_cases + listTests = [] + listTests += list_test_cases(PKCS8_Decrypt) + return listTests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + diff --git a/lib/Crypto/SelfTest/Protocol/__init__.py b/lib/Crypto/SelfTest/Protocol/__init__.py new file mode 100644 index 0000000..33ff581 --- /dev/null +++ b/lib/Crypto/SelfTest/Protocol/__init__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Protocol/__init__.py: Self-tests for Crypto.Protocol +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for Crypto.Protocol""" + +__revision__ = "$Id$" + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.Protocol import test_chaffing; tests += test_chaffing.get_tests(config=config) + from Crypto.SelfTest.Protocol import test_rfc1751; tests += test_rfc1751.get_tests(config=config) + from Crypto.SelfTest.Protocol import test_AllOrNothing; tests += test_AllOrNothing.get_tests(config=config) + from Crypto.SelfTest.Protocol import test_KDF; tests += test_KDF.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Protocol/test_AllOrNothing.py b/lib/Crypto/SelfTest/Protocol/test_AllOrNothing.py new file mode 100644 index 0000000..a211eab --- /dev/null +++ b/lib/Crypto/SelfTest/Protocol/test_AllOrNothing.py @@ -0,0 +1,76 @@ +# +# Test script for Crypto.Protocol.AllOrNothing +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew Kuchling and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import unittest +from Crypto.Protocol import AllOrNothing +from Crypto.Util.py3compat import * + +text = b("""\ +When in the Course of human events, it becomes necessary for one people to +dissolve the political bands which have connected them with another, and to +assume among the powers of the earth, the separate and equal station to which +the Laws of Nature and of Nature's God entitle them, a decent respect to the +opinions of mankind requires that they should declare the causes which impel +them to the separation. + +We hold these truths to be self-evident, that all men are created equal, that +they are endowed by their Creator with certain unalienable Rights, that among +these are Life, Liberty, and the pursuit of Happiness. That to secure these +rights, Governments are instituted among Men, deriving their just powers from +the consent of the governed. That whenever any Form of Government becomes +destructive of these ends, it is the Right of the People to alter or to +abolish it, and to institute new Government, laying its foundation on such +principles and organizing its powers in such form, as to them shall seem most +likely to effect their Safety and Happiness. +""") + +class AllOrNothingTest (unittest.TestCase): + + def runTest(self): + "Simple test of AllOrNothing" + + from Crypto.Cipher import AES + import base64 + + # The current AllOrNothing will fail + # every so often. Repeat the test + # several times to force this. + for i in range(50): + x = AllOrNothing.AllOrNothing(AES) + + msgblocks = x.digest(text) + + # get a new undigest-only object so there's no leakage + y = AllOrNothing.AllOrNothing(AES) + text2 = y.undigest(msgblocks) + self.assertEqual(text, text2) + +def get_tests(config={}): + return [AllOrNothingTest()] + +if __name__ == "__main__": + unittest.main() diff --git a/lib/Crypto/SelfTest/Protocol/test_KDF.py b/lib/Crypto/SelfTest/Protocol/test_KDF.py new file mode 100644 index 0000000..de09b41 --- /dev/null +++ b/lib/Crypto/SelfTest/Protocol/test_KDF.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Protocol/test_KDF.py: Self-test for key derivation functions +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import unittest +from binascii import unhexlify + +from Crypto.Util.py3compat import * + +from Crypto.SelfTest.st_common import list_test_cases +from Crypto.Hash import SHA1, HMAC +from Crypto.Cipher import AES, DES3 + +from Crypto.Protocol.KDF import PBKDF1, PBKDF2, _S2V + +def t2b(t): return unhexlify(b(t)) + +class PBKDF1_Tests(unittest.TestCase): + + # List of tuples with test data. + # Each tuple is made up by: + # Item #0: a pass phrase + # Item #1: salt (8 bytes encoded in hex) + # Item #2: output key length + # Item #3: iterations to use + # Item #4: expected result (encoded in hex) + _testData = ( + # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf + ("password","78578E5A5D63CB06",16,1000,"DC19847E05C64D2FAF10EBFB4A3D2A20"), + ) + + def test1(self): + v = self._testData[0] + res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1) + self.assertEqual(res, t2b(v[4])) + +class PBKDF2_Tests(unittest.TestCase): + + # List of tuples with test data. + # Each tuple is made up by: + # Item #0: a pass phrase + # Item #1: salt (encoded in hex) + # Item #2: output key length + # Item #3: iterations to use + # Item #4: expected result (encoded in hex) + _testData = ( + # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf + ("password","78578E5A5D63CB06",24,2048,"BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"), + # From RFC 6050 + ("password","73616c74", 20, 1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"), + ("password","73616c74", 20, 2, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), + ("password","73616c74", 20, 4096, "4b007901b765489abead49d926f721d065a429c1"), + ("passwordPASSWORDpassword","73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", + 25, 4096, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"), + ( 'pass\x00word',"7361006c74",16,4096, "56fa6aa75548099dcc37d7f03425e0c3"), + ) + + def test1(self): + # Test only for HMAC-SHA1 as PRF + + def prf(p,s): + return HMAC.new(p,s,SHA1).digest() + + for i in xrange(len(self._testData)): + v = self._testData[i] + res = PBKDF2(v[0], t2b(v[1]), v[2], v[3]) + res2 = PBKDF2(v[0], t2b(v[1]), v[2], v[3], prf) + self.assertEqual(res, t2b(v[4])) + self.assertEqual(res, res2) + +class S2V_Tests(unittest.TestCase): + + # Sequence of test vectors. + # Each test vector is made up by: + # Item #0: a tuple of strings + # Item #1: an AES key + # Item #2: the result + # Item #3: the cipher module S2V is based on + # Everything is hex encoded + _testData = [ + + # RFC5297, A.1 + ( + ( '101112131415161718191a1b1c1d1e1f2021222324252627', + '112233445566778899aabbccddee' ), + 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0', + '85632d07c6e8f37f950acd320a2ecc93', + AES + ), + + # RFC5297, A.2 + ( + ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+ + 'bbaa99887766554433221100', + '102030405060708090a0', + '09f911029d74e35bd84156c5635688c0', + '7468697320697320736f6d6520706c61'+ + '696e7465787420746f20656e63727970'+ + '74207573696e67205349562d414553'), + '7f7e7d7c7b7a79787776757473727170', + '7bdb6e3b432667eb06f4d14bff2fbd0f', + AES + ), + + ] + + def test1(self): + """Verify correctness of test vector""" + for tv in self._testData: + s2v = _S2V.new(t2b(tv[1]), tv[3]) + for s in tv[0]: + s2v.update(t2b(s)) + result = s2v.derive() + self.assertEqual(result, t2b(tv[2])) + + def test2(self): + """Verify that no more than 127(AES) and 63(TDES) + components are accepted.""" + key = bchr(0)*16 + for module in (AES, DES3): + s2v = _S2V.new(key, module) + max_comps = module.block_size*8-1 + for i in xrange(max_comps): + s2v.update(b("XX")) + self.assertRaises(TypeError, s2v.update, b("YY")) + +def get_tests(config={}): + tests = [] + tests += list_test_cases(PBKDF1_Tests) + tests += list_test_cases(PBKDF2_Tests) + tests += list_test_cases(S2V_Tests) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 diff --git a/lib/Crypto/SelfTest/Protocol/test_chaffing.py b/lib/Crypto/SelfTest/Protocol/test_chaffing.py new file mode 100644 index 0000000..5fa0120 --- /dev/null +++ b/lib/Crypto/SelfTest/Protocol/test_chaffing.py @@ -0,0 +1,74 @@ +# +# Test script for Crypto.Protocol.Chaffing +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew Kuchling and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import unittest +from Crypto.Protocol import Chaffing + +text = """\ +When in the Course of human events, it becomes necessary for one people to +dissolve the political bands which have connected them with another, and to +assume among the powers of the earth, the separate and equal station to which +the Laws of Nature and of Nature's God entitle them, a decent respect to the +opinions of mankind requires that they should declare the causes which impel +them to the separation. + +We hold these truths to be self-evident, that all men are created equal, that +they are endowed by their Creator with certain unalienable Rights, that among +these are Life, Liberty, and the pursuit of Happiness. That to secure these +rights, Governments are instituted among Men, deriving their just powers from +the consent of the governed. That whenever any Form of Government becomes +destructive of these ends, it is the Right of the People to alter or to +abolish it, and to institute new Government, laying its foundation on such +principles and organizing its powers in such form, as to them shall seem most +likely to effect their Safety and Happiness. +""" + +class ChaffingTest (unittest.TestCase): + + def runTest(self): + "Simple tests of chaffing and winnowing" + # Test constructors + Chaffing.Chaff() + Chaffing.Chaff(0.5, 1) + self.assertRaises(ValueError, Chaffing.Chaff, factor=-1) + self.assertRaises(ValueError, Chaffing.Chaff, blocksper=-1) + + data = [(1, 'data1', 'data1'), (2, 'data2', 'data2')] + c = Chaffing.Chaff(1.0, 1) + c.chaff(data) + chaff = c.chaff(data) + self.assertEqual(len(chaff), 4) + + c = Chaffing.Chaff(0.0, 1) + chaff = c.chaff(data) + self.assertEqual(len(chaff), 2) + +def get_tests(config={}): + return [ChaffingTest()] + +if __name__ == "__main__": + unittest.main() diff --git a/lib/Crypto/SelfTest/Protocol/test_rfc1751.py b/lib/Crypto/SelfTest/Protocol/test_rfc1751.py new file mode 100644 index 0000000..0878cc5 --- /dev/null +++ b/lib/Crypto/SelfTest/Protocol/test_rfc1751.py @@ -0,0 +1,62 @@ +# +# Test script for Crypto.Util.RFC1751. +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew Kuchling and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import binascii +import unittest +from Crypto.Util import RFC1751 +from Crypto.Util.py3compat import * + +test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), + ('CCAC2AED591056BE4F90FD441C534766', + 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), + ('EFF81F9BFBC65350920CDD7416DE8009', + 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') + ] + +class RFC1751Test_k2e (unittest.TestCase): + + def runTest (self): + "Check converting keys to English" + for key, words in test_data: + key=binascii.a2b_hex(b(key)) + self.assertEqual(RFC1751.key_to_english(key), words) + +class RFC1751Test_e2k (unittest.TestCase): + + def runTest (self): + "Check converting English strings to keys" + for key, words in test_data: + key=binascii.a2b_hex(b(key)) + self.assertEqual(RFC1751.english_to_key(words), key) + +# class RFC1751Test + +def get_tests(config={}): + return [RFC1751Test_k2e(), RFC1751Test_e2k()] + +if __name__ == "__main__": + unittest.main() diff --git a/lib/Crypto/SelfTest/PublicKey/__init__.py b/lib/Crypto/SelfTest/PublicKey/__init__.py new file mode 100644 index 0000000..23a13a4 --- /dev/null +++ b/lib/Crypto/SelfTest/PublicKey/__init__.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/__init__.py: Self-test for public key crypto +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for public-key crypto""" + +__revision__ = "$Id$" + +import os + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.PublicKey import test_DSA; tests += test_DSA.get_tests(config=config) + from Crypto.SelfTest.PublicKey import test_RSA; tests += test_RSA.get_tests(config=config) + + from Crypto.SelfTest.PublicKey import test_import_DSA + tests +=test_import_DSA.get_tests(config=config) + + from Crypto.SelfTest.PublicKey import test_import_RSA + tests += test_import_RSA.get_tests(config=config) + + from Crypto.SelfTest.PublicKey import test_ElGamal; tests += test_ElGamal.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/PublicKey/test_DSA.py b/lib/Crypto/SelfTest/PublicKey/test_DSA.py new file mode 100644 index 0000000..037e087 --- /dev/null +++ b/lib/Crypto/SelfTest/PublicKey/test_DSA.py @@ -0,0 +1,237 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/test_DSA.py: Self-test for the DSA primitive +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.PublicKey.DSA""" + +__revision__ = "$Id$" + +import sys +import os +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +import unittest +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex + +def _sws(s): + """Remove whitespace from a text or byte string""" + if isinstance(s,str): + return "".join(s.split()) + else: + return b("").join(s.split()) + +class DSATest(unittest.TestCase): + # Test vector from "Appendix 5. Example of the DSA" of + # "Digital Signature Standard (DSS)", + # U.S. Department of Commerce/National Institute of Standards and Technology + # FIPS 186-2 (+Change Notice), 2000 January 27. + # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf + + y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 + 9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74 + 858fba33 f44c0669 9630a76b 030ee333""") + + g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb + 3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c + c42e9f6f 464b088c c572af53 e6d78802""") + + p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 + cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac + 49693dfb f83724c2 ec0736ee 31c80291""") + + q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") + + x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") + + k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") + k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") + m = b2a_hex(b("abc")) + m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") + r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") + s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") + + def setUp(self): + global DSA, Random, bytes_to_long, size + from Crypto.PublicKey import DSA + from Crypto import Random + from Crypto.Util.number import bytes_to_long, inverse, size + + self.dsa = DSA + + def test_generate_1arg(self): + """DSA (default implementation) generated key (1 argument)""" + dsaObj = self.dsa.generate(1024) + self._check_private_key(dsaObj) + pub = dsaObj.publickey() + self._check_public_key(pub) + + def test_generate_2arg(self): + """DSA (default implementation) generated key (2 arguments)""" + dsaObj = self.dsa.generate(1024, Random.new().read) + self._check_private_key(dsaObj) + pub = dsaObj.publickey() + self._check_public_key(pub) + + def test_construct_4tuple(self): + """DSA (default implementation) constructed key (4-tuple)""" + (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] + dsaObj = self.dsa.construct((y, g, p, q)) + self._test_verification(dsaObj) + + def test_construct_5tuple(self): + """DSA (default implementation) constructed key (5-tuple)""" + (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] + dsaObj = self.dsa.construct((y, g, p, q, x)) + self._test_signing(dsaObj) + self._test_verification(dsaObj) + + def _check_private_key(self, dsaObj): + # Check capabilities + self.assertEqual(1, dsaObj.has_private()) + self.assertEqual(1, dsaObj.can_sign()) + self.assertEqual(0, dsaObj.can_encrypt()) + self.assertEqual(0, dsaObj.can_blind()) + + # Check dsaObj.[ygpqx] -> dsaObj.key.[ygpqx] mapping + self.assertEqual(dsaObj.y, dsaObj.key.y) + self.assertEqual(dsaObj.g, dsaObj.key.g) + self.assertEqual(dsaObj.p, dsaObj.key.p) + self.assertEqual(dsaObj.q, dsaObj.key.q) + self.assertEqual(dsaObj.x, dsaObj.key.x) + + # Sanity check key data + self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q + self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits + self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 + self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p + self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q + + def _check_public_key(self, dsaObj): + k = a2b_hex(self.k) + m_hash = a2b_hex(self.m_hash) + + # Check capabilities + self.assertEqual(0, dsaObj.has_private()) + self.assertEqual(1, dsaObj.can_sign()) + self.assertEqual(0, dsaObj.can_encrypt()) + self.assertEqual(0, dsaObj.can_blind()) + + # Check dsaObj.[ygpq] -> dsaObj.key.[ygpq] mapping + self.assertEqual(dsaObj.y, dsaObj.key.y) + self.assertEqual(dsaObj.g, dsaObj.key.g) + self.assertEqual(dsaObj.p, dsaObj.key.p) + self.assertEqual(dsaObj.q, dsaObj.key.q) + + # Check that private parameters are all missing + self.assertEqual(0, hasattr(dsaObj, 'x')) + self.assertEqual(0, hasattr(dsaObj.key, 'x')) + + # Sanity check key data + self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q + self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits + self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 + + # Public-only key objects should raise an error when .sign() is called + self.assertRaises(TypeError, dsaObj.sign, m_hash, k) + + # Check __eq__ and __ne__ + self.assertEqual(dsaObj.publickey() == dsaObj.publickey(),True) # assert_ + self.assertEqual(dsaObj.publickey() != dsaObj.publickey(),False) # failIf + + def _test_signing(self, dsaObj): + k = a2b_hex(self.k) + m_hash = a2b_hex(self.m_hash) + r = bytes_to_long(a2b_hex(self.r)) + s = bytes_to_long(a2b_hex(self.s)) + (r_out, s_out) = dsaObj.sign(m_hash, k) + self.assertEqual((r, s), (r_out, s_out)) + + def _test_verification(self, dsaObj): + m_hash = a2b_hex(self.m_hash) + r = bytes_to_long(a2b_hex(self.r)) + s = bytes_to_long(a2b_hex(self.s)) + self.assertEqual(1, dsaObj.verify(m_hash, (r, s))) + self.assertEqual(0, dsaObj.verify(m_hash + b("\0"), (r, s))) + +class DSAFastMathTest(DSATest): + def setUp(self): + DSATest.setUp(self) + self.dsa = DSA.DSAImplementation(use_fast_math=True) + + def test_generate_1arg(self): + """DSA (_fastmath implementation) generated key (1 argument)""" + DSATest.test_generate_1arg(self) + + def test_generate_2arg(self): + """DSA (_fastmath implementation) generated key (2 arguments)""" + DSATest.test_generate_2arg(self) + + def test_construct_4tuple(self): + """DSA (_fastmath implementation) constructed key (4-tuple)""" + DSATest.test_construct_4tuple(self) + + def test_construct_5tuple(self): + """DSA (_fastmath implementation) constructed key (5-tuple)""" + DSATest.test_construct_5tuple(self) + +class DSASlowMathTest(DSATest): + def setUp(self): + DSATest.setUp(self) + self.dsa = DSA.DSAImplementation(use_fast_math=False) + + def test_generate_1arg(self): + """DSA (_slowmath implementation) generated key (1 argument)""" + DSATest.test_generate_1arg(self) + + def test_generate_2arg(self): + """DSA (_slowmath implementation) generated key (2 arguments)""" + DSATest.test_generate_2arg(self) + + def test_construct_4tuple(self): + """DSA (_slowmath implementation) constructed key (4-tuple)""" + DSATest.test_construct_4tuple(self) + + def test_construct_5tuple(self): + """DSA (_slowmath implementation) constructed key (5-tuple)""" + DSATest.test_construct_5tuple(self) + + +def get_tests(config={}): + tests = [] + tests += list_test_cases(DSATest) + try: + from Crypto.PublicKey import _fastmath + tests += list_test_cases(DSAFastMathTest) + except ImportError: + from Crypto.SelfTest.st_common import handle_fastmath_import_error + handle_fastmath_import_error() + tests += list_test_cases(DSASlowMathTest) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/PublicKey/test_ElGamal.py b/lib/Crypto/SelfTest/PublicKey/test_ElGamal.py new file mode 100644 index 0000000..5f33c23 --- /dev/null +++ b/lib/Crypto/SelfTest/PublicKey/test_ElGamal.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/test_ElGamal.py: Self-test for the ElGamal primitive +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.PublicKey.ElGamal""" + +__revision__ = "$Id$" + +import unittest +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex +from Crypto import Random +from Crypto.PublicKey import ElGamal +from Crypto.Util.number import bytes_to_long +from Crypto.Util.py3compat import * + +class ElGamalTest(unittest.TestCase): + + # + # Test vectors + # + # There seem to be no real ElGamal test vectors available in the + # public domain. The following test vectors have been generated + # with libgcrypt 1.5.0. + # + # Encryption + tve=[ + { + # 256 bits + 'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933', + 'g' :'05', + 'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF', + 'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932', + 'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1', + 'pt' :'48656C6C6F207468657265', + 'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7', + 'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68' + }, + + { + # 512 bits + 'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227', + 'g' :'07', + 'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C', + 'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68', + 'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7', + 'pt' :'48656C6C6F207468657265', + 'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B', + 'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0' + } + ] + + # Signature + tvs=[ + { + # 256 bits + 'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7', + 'g' :'05', + 'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7', + 'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB', + 'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F', + 'h' :'48656C6C6F207468657265', + 'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2', + 'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7', + }, + { + # 512 bits + 'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF', + 'g' :'0B', + 'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC', + 'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB', + 'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69', + 'h' :'48656C6C6F207468657265', + 'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F', + 'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE', + } + ] + + def test_generate_128(self): + self._test_random_key(128) + + def test_generate_512(self): + self._test_random_key(512) + + def test_encryption(self): + for tv in self.tve: + for as_longs in (0,1): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + ct = key.encrypt(d['pt'], d['k']) + self.assertEquals(ct[0], d['ct1']) + self.assertEquals(ct[1], d['ct2']) + + def test_decryption(self): + for tv in self.tve: + for as_longs in (0,1): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + pt = key.decrypt((d['ct1'], d['ct2'])) + self.assertEquals(pt, d['pt']) + + def test_signing(self): + for tv in self.tvs: + for as_longs in (0,1): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + sig1, sig2 = key.sign(d['h'], d['k']) + self.assertEquals(sig1, d['sig1']) + self.assertEquals(sig2, d['sig2']) + + def test_verification(self): + for tv in self.tvs: + for as_longs in (0,1): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + # Positive test + res = key.verify( d['h'], (d['sig1'],d['sig2']) ) + self.failUnless(res) + # Negative test + res = key.verify( d['h'], (d['sig1']+1,d['sig2']) ) + self.failIf(res) + + def convert_tv(self, tv, as_longs=0): + """Convert a test vector from textual form (hexadecimal ascii + to either integers or byte strings.""" + key_comps = 'p','g','y','x' + tv2 = {} + for c in tv.keys(): + tv2[c] = a2b_hex(tv[c]) + if as_longs or c in key_comps or c in ('sig1','sig2'): + tv2[c] = bytes_to_long(tv2[c]) + tv2['key']=[] + for c in key_comps: + tv2['key'] += [tv2[c]] + del tv2[c] + return tv2 + + def _test_random_key(self, bits): + elgObj = ElGamal.generate(bits, Random.new().read) + self._check_private_key(elgObj) + self._exercise_primitive(elgObj) + pub = elgObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(elgObj) + + def _check_private_key(self, elgObj): + + # Check capabilities + self.failUnless(elgObj.has_private()) + self.failUnless(elgObj.can_sign()) + self.failUnless(elgObj.can_encrypt()) + + # Sanity check key data + self.failUnless(1<elgObj.g<(elgObj.p-1)) + self.assertEquals(pow(elgObj.g, elgObj.p-1, elgObj.p), 1) + self.failUnless(1<elgObj.x<(elgObj.p-1)) + self.assertEquals(pow(elgObj.g, elgObj.x, elgObj.p), elgObj.y) + + def _check_public_key(self, elgObj): + + # Check capabilities + self.failIf(elgObj.has_private()) + self.failUnless(elgObj.can_sign()) + self.failUnless(elgObj.can_encrypt()) + + # Sanity check key data + self.failUnless(1<elgObj.g<(elgObj.p-1)) + self.assertEquals(pow(elgObj.g, elgObj.p-1, elgObj.p), 1) + + def _exercise_primitive(self, elgObj): + # Test encryption/decryption + plaintext = b("Test") + ciphertext = elgObj.encrypt(plaintext, 123456789L) + plaintextP = elgObj.decrypt(ciphertext) + self.assertEquals(plaintext, plaintextP) + + # Test signature/verification + signature = elgObj.sign(plaintext, 987654321L) + elgObj.verify(plaintext, signature) + + def _exercise_public_primitive(self, elgObj): + plaintext = b("Test") + ciphertext = elgObj.encrypt(plaintext, 123456789L) + +def get_tests(config={}): + tests = [] + tests += list_test_cases(ElGamalTest) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + diff --git a/lib/Crypto/SelfTest/PublicKey/test_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_RSA.py new file mode 100644 index 0000000..32bed88 --- /dev/null +++ b/lib/Crypto/SelfTest/PublicKey/test_RSA.py @@ -0,0 +1,474 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/test_RSA.py: Self-test for the RSA primitive +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.PublicKey.RSA""" + +__revision__ = "$Id$" + +import sys +import os +import pickle +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +import unittest +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex + +class RSATest(unittest.TestCase): + # Test vectors from "RSA-OAEP and RSA-PSS test vectors (.zip file)" + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # See RSADSI's PKCS#1 page at + # http://www.rsa.com/rsalabs/node.asp?id=2125 + + # from oaep-int.txt + + # TODO: PyCrypto treats the message as starting *after* the leading "00" + # TODO: That behaviour should probably be changed in the future. + plaintext = """ + eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2 + ca 82 31 0b 26 dc d8 7d 5c 68 f1 ee a8 f5 52 67 + c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af + f9 3e dc fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db + 4c dc fe 4f f4 77 28 b4 a1 b7 c1 36 2b aa d2 9a + b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9 + 82 fb 3e 87 d0 95 ae b4 04 48 db 97 2f 3a c1 4f + 7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35 3e 2d + """ + + ciphertext = """ + 12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 + 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 + 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 + 53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb + 6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 + 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 + da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d + 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55 + """ + + modulus = """ + bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 + 36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f + b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 + 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f + af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 + ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e + e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f + e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb + """ + + e = 0x11L # public exponent + + prime_factor = """ + c9 7f b1 f0 27 f4 53 f6 34 12 33 ea aa d1 d9 35 + 3f 6c 42 d0 88 66 b1 d0 5a 0f 20 35 02 8b 9d 86 + 98 40 b4 16 66 b4 2e 92 ea 0d a3 b4 32 04 b5 cf + ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03 + """ + + # The same key, in pickled format (from pycrypto 2.3) + # to ensure backward compatibility + pickled_key_2_3 = \ + "(iCrypto.PublicKey.RSA\n_RSAobj\np0\n(dp2\nS'e'\np3\nL17L\nsS'd'\np4"\ + "\nL11646763154293086160147889314553506764606353688284149120983587488"\ + "79382229568306696406525871631480713149376749558222371890533687587223"\ + "51580531956820574156366843733156436163097164007967904900300775223658"\ + "03543233292399245064743971969473468304536714979010219881003396235861"\ + "8370829441895425705728523874962107052993L\nsS'n'\np5\nL1319966490819"\ + "88309815009412231606409998872008467220356704480658206329986017741425"\ + "59273959878490114749026269828326520214759381792655199845793621772998"\ + "40439054838068985140623386496543388290455526885872858516219460533763"\ + "92312680578795692682905599590422046720587710762927130740460442438533"\ + "124053848898103790124491L\nsb." + + def setUp(self): + global RSA, Random, bytes_to_long + from Crypto.PublicKey import RSA + from Crypto import Random + from Crypto.Util.number import bytes_to_long, inverse + self.n = bytes_to_long(a2b_hex(self.modulus)) + self.p = bytes_to_long(a2b_hex(self.prime_factor)) + + # Compute q, d, and u from n, e, and p + self.q = divmod(self.n, self.p)[0] + self.d = inverse(self.e, (self.p-1)*(self.q-1)) + self.u = inverse(self.p, self.q) # u = e**-1 (mod q) + + self.rsa = RSA + + def test_generate_1arg(self): + """RSA (default implementation) generated key (1 argument)""" + rsaObj = self.rsa.generate(1024) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + def test_generate_2arg(self): + """RSA (default implementation) generated key (2 arguments)""" + rsaObj = self.rsa.generate(1024, Random.new().read) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + def test_generate_3args(self): + rsaObj = self.rsa.generate(1024, Random.new().read,e=65537) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + self.assertEqual(65537,rsaObj.e) + + def test_construct_2tuple(self): + """RSA (default implementation) constructed key (2-tuple)""" + pub = self.rsa.construct((self.n, self.e)) + self._check_public_key(pub) + self._check_encryption(pub) + self._check_verification(pub) + + def test_construct_3tuple(self): + """RSA (default implementation) constructed key (3-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d)) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + self._check_signing(rsaObj) + self._check_verification(rsaObj) + + def test_construct_4tuple(self): + """RSA (default implementation) constructed key (4-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p)) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + self._check_signing(rsaObj) + self._check_verification(rsaObj) + + def test_construct_5tuple(self): + """RSA (default implementation) constructed key (5-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) + self._check_private_key(rsaObj) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + self._check_signing(rsaObj) + self._check_verification(rsaObj) + + def test_construct_6tuple(self): + """RSA (default implementation) constructed key (6-tuple)""" + rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q, self.u)) + self._check_private_key(rsaObj) + self._check_encryption(rsaObj) + self._check_decryption(rsaObj) + self._check_signing(rsaObj) + self._check_verification(rsaObj) + + def test_factoring(self): + rsaObj = self.rsa.construct([self.n, self.e, self.d]) + self.failUnless(rsaObj.p==self.p or rsaObj.p==self.q) + self.failUnless(rsaObj.q==self.p or rsaObj.q==self.q) + self.failUnless(rsaObj.q*rsaObj.p == self.n) + + self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n-1]) + + def test_serialization(self): + """RSA (default implementation) serialize/unserialize key""" + rsaObj_orig = self.rsa.generate(1024) + rsaObj = pickle.loads(pickle.dumps(rsaObj_orig)) + self._check_private_key(rsaObj) + self._exercise_primitive(rsaObj) + pub = rsaObj.publickey() + self._check_public_key(pub) + self._exercise_public_primitive(rsaObj) + + plaintext = a2b_hex(self.plaintext) + ciphertext1 = rsaObj_orig.encrypt(plaintext, b("")) + ciphertext2 = rsaObj.encrypt(plaintext, b("")) + self.assertEqual(ciphertext1, ciphertext2) + + if not (3, 0) <= sys.version_info < (3, 1, 2, 'final', 0): + # Unpickling is broken in Python 3 before 3.1.2 due to http://bugs.python.org/issue6137 + def test_serialization_compat(self): + """RSA (default implementation) backward compatibility serialization""" + rsaObj = pickle.loads(b(self.pickled_key_2_3)) + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + ciphertext_result = rsaObj.encrypt(plaintext, b(""))[0] + self.assertEqual(ciphertext_result, ciphertext) + + def _check_private_key(self, rsaObj): + # Check capabilities + self.assertEqual(1, rsaObj.has_private()) + self.assertEqual(1, rsaObj.can_sign()) + self.assertEqual(1, rsaObj.can_encrypt()) + self.assertEqual(1, rsaObj.can_blind()) + + # Check rsaObj.[nedpqu] -> rsaObj.key.[nedpqu] mapping + self.assertEqual(rsaObj.n, rsaObj.key.n) + self.assertEqual(rsaObj.e, rsaObj.key.e) + self.assertEqual(rsaObj.d, rsaObj.key.d) + self.assertEqual(rsaObj.p, rsaObj.key.p) + self.assertEqual(rsaObj.q, rsaObj.key.q) + self.assertEqual(rsaObj.u, rsaObj.key.u) + + # Sanity check key data + self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq + self.assertEqual(1, rsaObj.d * rsaObj.e % ((rsaObj.p-1) * (rsaObj.q-1))) # ed = 1 (mod (p-1)(q-1)) + self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q) + self.assertEqual(1, rsaObj.p > 1) # p > 1 + self.assertEqual(1, rsaObj.q > 1) # q > 1 + self.assertEqual(1, rsaObj.e > 1) # e > 1 + self.assertEqual(1, rsaObj.d > 1) # d > 1 + + def _check_public_key(self, rsaObj): + ciphertext = a2b_hex(self.ciphertext) + + # Check capabilities + self.assertEqual(0, rsaObj.has_private()) + self.assertEqual(1, rsaObj.can_sign()) + self.assertEqual(1, rsaObj.can_encrypt()) + self.assertEqual(1, rsaObj.can_blind()) + + # Check rsaObj.[ne] -> rsaObj.key.[ne] mapping + self.assertEqual(rsaObj.n, rsaObj.key.n) + self.assertEqual(rsaObj.e, rsaObj.key.e) + + # Check that private parameters are all missing + self.assertEqual(0, hasattr(rsaObj, 'd')) + self.assertEqual(0, hasattr(rsaObj, 'p')) + self.assertEqual(0, hasattr(rsaObj, 'q')) + self.assertEqual(0, hasattr(rsaObj, 'u')) + self.assertEqual(0, hasattr(rsaObj.key, 'd')) + self.assertEqual(0, hasattr(rsaObj.key, 'p')) + self.assertEqual(0, hasattr(rsaObj.key, 'q')) + self.assertEqual(0, hasattr(rsaObj.key, 'u')) + + # Sanity check key data + self.assertEqual(1, rsaObj.e > 1) # e > 1 + + # Public keys should not be able to sign or decrypt + self.assertRaises(TypeError, rsaObj.sign, ciphertext, b("")) + self.assertRaises(TypeError, rsaObj.decrypt, ciphertext) + + # Check __eq__ and __ne__ + self.assertEqual(rsaObj.publickey() == rsaObj.publickey(),True) # assert_ + self.assertEqual(rsaObj.publickey() != rsaObj.publickey(),False) # failIf + + def _exercise_primitive(self, rsaObj): + # Since we're using a randomly-generated key, we can't check the test + # vector, but we can make sure encryption and decryption are inverse + # operations. + ciphertext = a2b_hex(self.ciphertext) + + # Test decryption + plaintext = rsaObj.decrypt((ciphertext,)) + + # Test encryption (2 arguments) + (new_ciphertext2,) = rsaObj.encrypt(plaintext, b("")) + self.assertEqual(b2a_hex(ciphertext), b2a_hex(new_ciphertext2)) + + # Test blinded decryption + blinding_factor = Random.new().read(len(ciphertext)-1) + blinded_ctext = rsaObj.blind(ciphertext, blinding_factor) + blinded_ptext = rsaObj.decrypt((blinded_ctext,)) + unblinded_plaintext = rsaObj.unblind(blinded_ptext, blinding_factor) + self.assertEqual(b2a_hex(plaintext), b2a_hex(unblinded_plaintext)) + + # Test signing (2 arguments) + signature2 = rsaObj.sign(ciphertext, b("")) + self.assertEqual((bytes_to_long(plaintext),), signature2) + + # Test verification + self.assertEqual(1, rsaObj.verify(ciphertext, (bytes_to_long(plaintext),))) + + def _exercise_public_primitive(self, rsaObj): + plaintext = a2b_hex(self.plaintext) + + # Test encryption (2 arguments) + (new_ciphertext2,) = rsaObj.encrypt(plaintext, b("")) + + # Exercise verification + rsaObj.verify(new_ciphertext2, (bytes_to_long(plaintext),)) + + def _check_encryption(self, rsaObj): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + + # Test encryption (2 arguments) + (new_ciphertext2,) = rsaObj.encrypt(plaintext, b("")) + self.assertEqual(b2a_hex(ciphertext), b2a_hex(new_ciphertext2)) + + def _check_decryption(self, rsaObj): + plaintext = a2b_hex(self.plaintext) + ciphertext = a2b_hex(self.ciphertext) + + # Test plain decryption + new_plaintext = rsaObj.decrypt((ciphertext,)) + self.assertEqual(b2a_hex(plaintext), b2a_hex(new_plaintext)) + + # Test blinded decryption + blinding_factor = Random.new().read(len(ciphertext)-1) + blinded_ctext = rsaObj.blind(ciphertext, blinding_factor) + blinded_ptext = rsaObj.decrypt((blinded_ctext,)) + unblinded_plaintext = rsaObj.unblind(blinded_ptext, blinding_factor) + self.assertEqual(b2a_hex(plaintext), b2a_hex(unblinded_plaintext)) + + def _check_verification(self, rsaObj): + signature = bytes_to_long(a2b_hex(self.plaintext)) + message = a2b_hex(self.ciphertext) + + # Test verification + t = (signature,) # rsaObj.verify expects a tuple + self.assertEqual(1, rsaObj.verify(message, t)) + + # Test verification with overlong tuple (this is a + # backward-compatibility hack to support some harmless misuse of the + # API) + t2 = (signature, '') + self.assertEqual(1, rsaObj.verify(message, t2)) # extra garbage at end of tuple + + def _check_signing(self, rsaObj): + signature = bytes_to_long(a2b_hex(self.plaintext)) + message = a2b_hex(self.ciphertext) + + # Test signing (2 argument) + self.assertEqual((signature,), rsaObj.sign(message, b(""))) + +class RSAFastMathTest(RSATest): + def setUp(self): + RSATest.setUp(self) + self.rsa = RSA.RSAImplementation(use_fast_math=True) + + def test_generate_1arg(self): + """RSA (_fastmath implementation) generated key (1 argument)""" + RSATest.test_generate_1arg(self) + + def test_generate_2arg(self): + """RSA (_fastmath implementation) generated key (2 arguments)""" + RSATest.test_generate_2arg(self) + + def test_construct_2tuple(self): + """RSA (_fastmath implementation) constructed key (2-tuple)""" + RSATest.test_construct_2tuple(self) + + def test_construct_3tuple(self): + """RSA (_fastmath implementation) constructed key (3-tuple)""" + RSATest.test_construct_3tuple(self) + + def test_construct_4tuple(self): + """RSA (_fastmath implementation) constructed key (4-tuple)""" + RSATest.test_construct_4tuple(self) + + def test_construct_5tuple(self): + """RSA (_fastmath implementation) constructed key (5-tuple)""" + RSATest.test_construct_5tuple(self) + + def test_construct_6tuple(self): + """RSA (_fastmath implementation) constructed key (6-tuple)""" + RSATest.test_construct_6tuple(self) + + def test_factoring(self): + RSATest.test_factoring(self) + + + def test_serialization(self): + """RSA (_fastmath implementation) serialize/unserialize key + """ + RSATest.test_serialization(self) + + if not (3, 0) <= sys.version_info < (3, 1, 2, 'final', 0): + # Unpickling is broken in Python 3 before 3.1.2 due to http://bugs.python.org/issue6137 + def test_serialization_compat(self): + """RSA (_fastmath implementation) backward compatibility serialization + """ + RSATest.test_serialization_compat(self) + + +class RSASlowMathTest(RSATest): + def setUp(self): + RSATest.setUp(self) + self.rsa = RSA.RSAImplementation(use_fast_math=False) + + def test_generate_1arg(self): + """RSA (_slowmath implementation) generated key (1 argument)""" + RSATest.test_generate_1arg(self) + + def test_generate_2arg(self): + """RSA (_slowmath implementation) generated key (2 arguments)""" + RSATest.test_generate_2arg(self) + + def test_construct_2tuple(self): + """RSA (_slowmath implementation) constructed key (2-tuple)""" + RSATest.test_construct_2tuple(self) + + def test_construct_3tuple(self): + """RSA (_slowmath implementation) constructed key (3-tuple)""" + RSATest.test_construct_3tuple(self) + + def test_construct_4tuple(self): + """RSA (_slowmath implementation) constructed key (4-tuple)""" + RSATest.test_construct_4tuple(self) + + def test_construct_5tuple(self): + """RSA (_slowmath implementation) constructed key (5-tuple)""" + RSATest.test_construct_5tuple(self) + + def test_construct_6tuple(self): + """RSA (_slowmath implementation) constructed key (6-tuple)""" + RSATest.test_construct_6tuple(self) + + def test_factoring(self): + RSATest.test_factoring(self) + + def test_serialization(self): + """RSA (_slowmath implementation) serialize/unserialize key""" + RSATest.test_serialization(self) + + if not (3, 0) <= sys.version_info < (3, 1, 2, 'final', 0): + # Unpickling is broken in Python 3 before 3.1.2 due to http://bugs.python.org/issue6137 + def test_serialization_compat(self): + """RSA (_slowmath implementation) backward compatibility serialization + """ + RSATest.test_serialization_compat(self) + +def get_tests(config={}): + tests = [] + tests += list_test_cases(RSATest) + try: + from Crypto.PublicKey import _fastmath + tests += list_test_cases(RSAFastMathTest) + except ImportError: + from Crypto.SelfTest.st_common import handle_fastmath_import_error + handle_fastmath_import_error() + if config.get('slow_tests',1): + tests += list_test_cases(RSASlowMathTest) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_DSA.py b/lib/Crypto/SelfTest/PublicKey/test_import_DSA.py new file mode 100644 index 0000000..1cb6837 --- /dev/null +++ b/lib/Crypto/SelfTest/PublicKey/test_import_DSA.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/test_import_DSA.py: Self-test for importing DSA keys +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +import unittest + +from Crypto.PublicKey import DSA, KeyFormatError +from Crypto.SelfTest.st_common import * +from Crypto.Util.py3compat import * + +from binascii import unhexlify + +class ImportKeyTests(unittest.TestCase): + + y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729L + p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691L + q = 988791743931120302950649732173330531512663554851L + g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232L + x = 540873410045082450874416847965843801027716145253L + + def setUp(self): + + # It is easier to write test vectors in text form, + # and convert them to byte strigs dynamically here + for mname, mvalue in ImportKeyTests.__dict__.items(): + if mname[:4] in ('der_', 'pem_', 'ssh_'): + if mname[:4] == 'der_': + mvalue = unhexlify(tobytes(mvalue)) + mvalue = tobytes(mvalue) + setattr(self, mname, mvalue) + + # 1. SubjectPublicKeyInfo + der_public=\ + '308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6'+\ + '794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91'+\ + '5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47'+\ + '9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c'+\ + '8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c'+\ + 'd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae'+\ + '3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3'+\ + '4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a'+\ + 'ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56'+\ + 'ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1'+\ + '32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4'+\ + 'b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de'+\ + 'b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2'+\ + 'bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559' + + def testImportKey1(self): + key_obj = self.dsa.importKey(self.der_public) + self.failIf(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + + def testExportKey1(self): + tup = (self.y, self.g, self.p, self.q) + key = self.dsa.construct(tup) + encoded = key.exportKey('DER') + self.assertEqual(self.der_public, encoded) + + # 2. + pem_public="""\ +-----BEGIN DSA PUBLIC KEY----- +MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/ +j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtH +mjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2 +qm66YguDLWDDAhUArTL0jNOuDEWhmKYfpLXiAyB2OyMCgYB539w9YU/mNfzrfq6u +NxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa +5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxW +rkP9MA2JJi5O/YmUP5mmUbA4iAOBhQACgYEAgzUqaaEy80hD0qDrmVv/Ti8IOnPw +BJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTne +uaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmA +tPG+TJKpGYb7pVk= +-----END DSA PUBLIC KEY-----""" + + def testImportKey2(self): + for pem in (self.pem_public, tostr(self.pem_public)): + key_obj = self.dsa.importKey(pem) + self.failIf(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + + def testExportKey2(self): + tup = (self.y, self.g, self.p, self.q) + key = self.dsa.construct(tup) + encoded = key.exportKey('PEM') + self.assertEqual(self.pem_public, encoded) + + # 3. OpenSSL/OpenSSH format + der_private=\ + '308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b'+\ + '4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419'+\ + 'c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032'+\ + '342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057'+\ + 'aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076'+\ + '3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc'+\ + '83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0'+\ + '25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618'+\ + '12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99'+\ + 'a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d'+\ + '2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925'+\ + 'a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c'+\ + '7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1'+\ + 'be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065' + + def testImportKey3(self): + key_obj = self.dsa.importKey(self.der_private) + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + def testExportKey3(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + encoded = key.exportKey('DER', pkcs8=False) + self.assertEqual(self.der_private, encoded) + + # 4. + pem_private="""\ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQDnVu4XF/S2eUx8IUckoZdjdCxFVytLP4/ztE876fRM4DmidXaV +7JFWl9p075FPzRsFZg4kGcdh1jn0XS15uALb0j56uLgbR5o4Dh8wkyWEuioLlVAy +NC68g8tcqQbnsNfNb+ZWzstMi1p3EjqMZ1CkgeOwYFev9qpuumILgy1gwwIVAK0y +9IzTrgxFoZimH6S14gMgdjsjAoGAed/cPWFP5jX8636urjcY3C7++0UoKZOsZ0nc +g8Ij2MGIcpYxazsLVEZs9ETzS4LjVU0LkKd4+q8TBvAl2uaj42x/k91brEBSuSNw +BArKcLjVggWZcRkA77yWGBLDVd2b7/4JgdqFxVSAdLQcVq5D/TANiSYuTv2JlD+Z +plGwOIgCgYEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LAD +xXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4s +eUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVkCFF69mj8L +ggadmEIJhrMUIVAldWBl +-----END DSA PRIVATE KEY-----""" + + def testImportKey4(self): + for pem in (self.pem_private, tostr(self.pem_private)): + key_obj = self.dsa.importKey(pem) + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + def testExportKey4(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + encoded = key.exportKey('PEM', pkcs8=False) + self.assertEqual(self.pem_private, encoded) + + # 5. PKCS8 (unencrypted) + der_pkcs8=\ + '3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17'+\ + '17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576'+\ + '95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8'+\ + 'b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656'+\ + 'cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad'+\ + '32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb'+\ + '7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c'+\ + 'f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923'+\ + '70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074'+\ + 'b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82'+\ + '069d98420986b314215025756065' + + def testImportKey5(self): + key_obj = self.dsa.importKey(self.der_pkcs8) + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + def testExportKey5(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + encoded = key.exportKey('DER') + self.assertEqual(self.der_pkcs8, encoded) + encoded = key.exportKey('DER', pkcs8=True) + self.assertEqual(self.der_pkcs8, encoded) + + # 6. + pem_pkcs8="""\ +-----BEGIN PRIVATE KEY----- +MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVX +K0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4 +uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47Bg +V6/2qm66YguDLWDDAhUArTL0jNOuDEWhmKYfpLXiAyB2OyMCgYB539w9YU/mNfzr +fq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG +8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0 +tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAQWAhRevZo/C4IGnZhCCYazFCFQJXVgZQ== +-----END PRIVATE KEY-----""" + + def testImportKey6(self): + for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)): + key_obj = self.dsa.importKey(pem) + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + def testExportKey6(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + encoded = key.exportKey('PEM') + self.assertEqual(self.pem_pkcs8, encoded) + encoded = key.exportKey('PEM', pkcs8=True) + self.assertEqual(self.pem_pkcs8, encoded) + + # 7. OpenSSH/RFC4253 + ssh_pub="""ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk=""" + + def testImportKey7(self): + for ssh in (self.ssh_pub, tostr(self.ssh_pub)): + key_obj = self.dsa.importKey(ssh) + self.failIf(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + + def testExportKey7(self): + tup = (self.y, self.g, self.p, self.q) + key = self.dsa.construct(tup) + encoded = key.exportKey('OpenSSH') + self.assertEqual(self.ssh_pub, encoded) + + # 8. Encrypted OpenSSL/OpenSSH + pem_private_encrypted="""\ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,70B6908939D65E9F2EB999E8729788CE + +4V6GHRDpCrdZ8MBjbyp5AlGUrjvr2Pn2e2zVxy5RBt4FBj9/pa0ae0nnyUPMLSUU +kKyOR0topRYTVRLElm4qVrb5uNZ3hRwfbklr+pSrB7O9eHz9V5sfOQxyODS07JxK +k1OdOs70/ouMXLF9EWfAZOmWUccZKHNblUwg1p1UrZIz5jXw4dUE/zqhvXh6d+iC +ADsICaBCjCrRQJKDp50h3+ndQjkYBKVH+pj8TiQ79U7lAvdp3+iMghQN6YXs9mdI +gFpWw/f97oWM4GHZFqHJ+VSMNFjBiFhAvYV587d7Lk4dhD8sCfbxj42PnfRgUItc +nnPqHxmhMQozBWzYM4mQuo3XbF2WlsNFbOzFVyGhw1Bx1s91qvXBVWJh2ozrW0s6 +HYDV7ZkcTml/4kjA/d+mve6LZ8kuuR1qCiZx6rkffhh1gDN/1Xz3HVvIy/dQ+h9s +5zp7PwUoWbhqp3WCOr156P6gR8qo7OlT6wMh33FSXK/mxikHK136fV2shwTKQVII +rJBvXpj8nACUmi7scKuTWGeUoXa+dwTZVVe+b+L2U1ZM7+h/neTJiXn7u99PFUwu +xVJtxaV37m3aXxtCsPnbBg== +-----END DSA PRIVATE KEY-----""" + + def testImportKey8(self): + for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)): + key_obj = self.dsa.importKey(pem, "PWDTEST") + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + def testExportKey8(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + encoded = key.exportKey('PEM', pkcs8=False, passphrase="PWDTEST") + key = self.dsa.importKey(encoded, "PWDTEST") + self.assertEqual(self.y, key.key.y) + self.assertEqual(self.p, key.key.p) + self.assertEqual(self.q, key.key.q) + self.assertEqual(self.g, key.key.g) + self.assertEqual(self.x, key.key.x) + + # 9. Encrypted PKCS8 + # pbeWithMD5AndDES-CBC + pem_pkcs8_encrypted="""\ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBcTAbBgkqhkiG9w0BBQMwDgQI0GC3BJ/jSw8CAggABIIBUHc1cXZpExIE9tC7 +7ryiW+5ihtF2Ekurq3e408GYSAu5smJjN2bvQXmzRFBz8W38K8eMf1sbWroZ4+zn +kZSbb9nSm5kAa8lR2+oF2k+WRswMR/PTC3f/D9STO2X0QxdrzKgIHEcSGSHp5jTx +aVvbkCDHo9vhBTl6S3ogZ48As/MEro76+9igUwJ1jNhIQZPJ7e20QH5qDpQFFJN4 +CKl2ENSEuwGiqBszItFy4dqH0g63ZGZV/xt9wSO9Rd7SK/EbA/dklOxBa5Y/VItM +gnIhs9XDMoGYyn6F023EicNJm6g/bVQk81BTTma4tm+12TKGdYm+QkeZvCOMZylr +Wv67cKwO3cAXt5C3QXMDgYR64XvuaT5h7C0igMp2afSXJlnbHEbFxQVJlv83T4FM +eZ4k+NQDbEL8GiHmFxzDWQAuPPZKJWEEEV2p/To+WOh+kSDHQw== +-----END ENCRYPTED PRIVATE KEY-----""" + + def testImportKey9(self): + for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)): + key_obj = self.dsa.importKey(pem, "PWDTEST") + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + # 10. Encrypted PKCS8 + # pkcs5PBES2 / + # pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) / + # des-EDE3-CBC (iv=27A1C66C42AFEECE) + # + der_pkcs8_encrypted=\ + '30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c'+\ + '300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1'+\ + 'c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4'+\ + '400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f'+\ + '7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395'+\ + '4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47'+\ + '174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248'+\ + 'e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec'+\ + '21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478'+\ + '7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa'+\ + 'b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426'+\ + '2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770'+\ + '5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9' + + def testImportKey10(self): + key_obj = self.dsa.importKey(self.der_pkcs8_encrypted, "PWDTEST") + self.failUnless(key_obj.has_private()) + self.assertEqual(self.y, key_obj.key.y) + self.assertEqual(self.p, key_obj.key.p) + self.assertEqual(self.q, key_obj.key.q) + self.assertEqual(self.g, key_obj.key.g) + self.assertEqual(self.x, key_obj.key.x) + + def testExportKey10(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read + key._randfunc = randfunc + encoded = key.exportKey('DER', pkcs8=True, passphrase="PWDTEST") + self.assertEqual(self.der_pkcs8_encrypted, encoded) + + # ---- + + def testImportError1(self): + self.assertRaises(KeyFormatError, self.dsa.importKey, self.der_pkcs8_encrypted, "wrongpwd") + + def testExportError2(self): + tup = (self.y, self.g, self.p, self.q, self.x) + key = self.dsa.construct(tup) + self.assertRaises(ValueError, key.exportKey, 'DER', pkcs8=False, passphrase="PWDTEST") + +class ImportKeyTestsSlow(ImportKeyTests): + def setUp(self): + ImportKeyTests.setUp(self) + self.dsa = DSA.DSAImplementation(use_fast_math=0) + +class ImportKeyTestsFast(ImportKeyTests): + def setUp(self): + ImportKeyTests.setUp(self) + self.dsa = DSA.DSAImplementation(use_fast_math=1) + +if __name__ == '__main__': + unittest.main() + +def get_tests(config={}): + tests = [] + try: + from Crypto.PublicKey import _fastmath + tests += list_test_cases(ImportKeyTestsFast) + except ImportError: + pass + tests += list_test_cases(ImportKeyTestsSlow) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py new file mode 100644 index 0000000..ff65e77 --- /dev/null +++ b/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/PublicKey/test_importKey.py: Self-test for importing RSA keys +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +from __future__ import nested_scopes + +__revision__ = "$Id$" + +import unittest + +from Crypto.PublicKey import RSA +from Crypto.SelfTest.st_common import * +from Crypto.Util.py3compat import * +from Crypto.Util.number import inverse +from Crypto.Util import asn1 + +def der2pem(der, text='PUBLIC'): + import binascii + chunks = [ binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48) ] + pem = b('-----BEGIN %s KEY-----\n' % text) + pem += b('').join(chunks) + pem += b('-----END %s KEY-----' % text) + return pem + +class ImportKeyTests(unittest.TestCase): + # 512-bit RSA key generated with openssl + rsaKeyPEM = u'''-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII +q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 +Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI +OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr ++rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK +JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 +n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== +-----END RSA PRIVATE KEY-----''' + + # As above, but this is actually an unencrypted PKCS#8 key + rsaKeyPEM8 = u'''-----BEGIN PRIVATE KEY----- +MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS +ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj +wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK +5BxU3b2/FTn4zL0Y9ntEDeGsMEQCgdQM+sg5AiEA8g8vPh2mGIP2KYCSK9jfVFzk +B8cmJBEDteLFNyMSSiMCIQDKH+kkeSz8yWv6t080Smi0GN9XgzgGSAYAD+KlyZoC +NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx +yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7 +BX85JB8zqwHB +-----END PRIVATE KEY-----''' + + # The same RSA private key as in rsaKeyPEM, but now encrypted + rsaKeyEncryptedPEM=( + + # PEM encryption + # With DES and passphrase 'test' + ('test', u'''-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,AF8F9A40BD2FA2FC + +Ckl9ex1kaVEWhYC2QBmfaF+YPiR4NFkRXA7nj3dcnuFEzBnY5XULupqQpQI3qbfA +u8GYS7+b3toWWiHZivHbAAUBPDIZG9hKDyB9Sq2VMARGsX1yW1zhNvZLIiVJzUHs +C6NxQ1IJWOXzTew/xM2I26kPwHIvadq+/VaT8gLQdjdH0jOiVNaevjWnLgrn1mLP +BCNRMdcexozWtAFNNqSzfW58MJL2OdMi21ED184EFytIc1BlB+FZiGZduwKGuaKy +9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY +IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp +dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s= +-----END RSA PRIVATE KEY-----'''), + + # PKCS8 encryption + ('winter', u'''-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeZIsbW3O+JcCAggA +MBQGCCqGSIb3DQMHBAgSM2p0D8FilgSCAWBhFyP2tiGKVpGj3mO8qIBzinU60ApR +3unvP+N6j7LVgnV2lFGaXbJ6a1PbQXe+2D6DUyBLo8EMXrKKVLqOMGkFMHc0UaV6 +R6MmrsRDrbOqdpTuVRW+NVd5J9kQQh4xnfU/QrcPPt7vpJvSf4GzG0n666Ki50OV +M/feuVlIiyGXY6UWdVDpcOV72cq02eNUs/1JWdh2uEBvA9fCL0c07RnMrdT+CbJQ +NjJ7f8ULtp7xvR9O3Al/yJ4Wv3i4VxF1f3MCXzhlUD4I0ONlr0kJWgeQ80q/cWhw +ntvgJwnCn2XR1h6LA8Wp+0ghDTsL2NhJpWd78zClGhyU4r3hqu1XDjoXa7YCXCix +jCV15+ViDJzlNCwg+W6lRg18sSLkCT7alviIE0U5tHc6UPbbHwT5QqAxAABaP+nZ +CGqJGyiwBzrKebjgSm/KRd4C91XqcsysyH2kKPfT51MLAoD4xelOURBP +-----END ENCRYPTED PRIVATE KEY-----''' + ), + ) + + rsaPublicKeyPEM = u'''-----BEGIN RSA PUBLIC KEY----- +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T +Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ== +-----END RSA PUBLIC KEY-----''' + + # Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM' + rsaPublicKeyOpenSSH = b('''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n''') + + # The private key, in PKCS#1 format encoded with DER + rsaKeyDER = a2b_hex( + '''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe + 913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312 + 2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6 + 7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c + 54ddbdbf1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f + 2f3e1da61883f62980922bd8df545ce407c726241103b5e2c53723124a23 + 022100ca1fe924792cfcc96bfab74f344a68b418df578338064806000fe2 + a5c99a023702210087be1c3029504bcf34ec713d877947447813288975ca + 240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b + c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07 + e4defe43ed91a3ae27bb057f39241f33ab01c1 + '''.replace(" ","")) + + # The private key, in unencrypted PKCS#8 format encoded with DER + rsaKeyDER8 = a2b_hex( + '''30820155020100300d06092a864886f70d01010105000482013f3082013 + b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932 + ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78 + 492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2 + 301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c54ddbdb + f1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f2f3e1da + 61883f62980922bd8df545ce407c726241103b5e2c53723124a23022100c + a1fe924792cfcc96bfab74f344a68b418df578338064806000fe2a5c99a0 + 23702210087be1c3029504bcf34ec713d877947447813288975ca240080a + f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf + 433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4 + 3ed91a3ae27bb057f39241f33ab01c1 + '''.replace(" ","")) + + rsaPublicKeyDER = a2b_hex( + '''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a + a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c + b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502 + 03010001 + '''.replace(" ","")) + + n = long('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16) + e = 65537L + d = long('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16) + p = long('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16) + q = long('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16) + + # This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1} + # mod q) instead! + qInv = long('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16) + pInv = inverse(p,q) + + def testImportKey1(self): + """Verify import of RSAPrivateKey DER SEQUENCE""" + key = self.rsa.importKey(self.rsaKeyDER) + self.failUnless(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey2(self): + """Verify import of SubjectPublicKeyInfo DER SEQUENCE""" + key = self.rsa.importKey(self.rsaPublicKeyDER) + self.failIf(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey3unicode(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" + key = RSA.importKey(self.rsaKeyPEM) + self.assertEqual(key.has_private(),True) # assert_ + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey3bytes(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string""" + key = RSA.importKey(b(self.rsaKeyPEM)) + self.assertEqual(key.has_private(),True) # assert_ + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey4unicode(self): + """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" + key = RSA.importKey(self.rsaPublicKeyPEM) + self.assertEqual(key.has_private(),False) # failIf + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey4bytes(self): + """Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string""" + key = RSA.importKey(b(self.rsaPublicKeyPEM)) + self.assertEqual(key.has_private(),False) # failIf + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey5(self): + """Verifies that the imported key is still a valid RSA pair""" + key = RSA.importKey(self.rsaKeyPEM) + idem = key.encrypt(key.decrypt(b("Test")),0) + self.assertEqual(idem[0],b("Test")) + + def testImportKey6(self): + """Verifies that the imported key is still a valid RSA pair""" + key = RSA.importKey(self.rsaKeyDER) + idem = key.encrypt(key.decrypt(b("Test")),0) + self.assertEqual(idem[0],b("Test")) + + def testImportKey7(self): + """Verify import of OpenSSH public key""" + key = self.rsa.importKey(self.rsaPublicKeyOpenSSH) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + + def testImportKey8(self): + """Verify import of encrypted PrivateKeyInfo DER SEQUENCE""" + for t in self.rsaKeyEncryptedPEM: + key = self.rsa.importKey(t[1], t[0]) + self.failUnless(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey9(self): + """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE""" + key = self.rsa.importKey(self.rsaKeyDER8) + self.failUnless(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey10(self): + """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM""" + key = self.rsa.importKey(self.rsaKeyPEM8) + self.failUnless(key.has_private()) + self.assertEqual(key.n, self.n) + self.assertEqual(key.e, self.e) + self.assertEqual(key.d, self.d) + self.assertEqual(key.p, self.p) + self.assertEqual(key.q, self.q) + + def testImportKey11(self): + """Verify import of RSAPublicKey DER SEQUENCE""" + der = asn1.DerSequence([17, 3]).encode() + key = self.rsa.importKey(der) + self.assertEqual(key.n, 17) + self.assertEqual(key.e, 3) + + def testImportKey12(self): + """Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM""" + der = asn1.DerSequence([17, 3]).encode() + pem = der2pem(der) + key = self.rsa.importKey(pem) + self.assertEqual(key.n, 17) + self.assertEqual(key.e, 3) + + ### + def testExportKey1(self): + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + derKey = key.exportKey("DER") + self.assertEqual(derKey, self.rsaKeyDER) + + def testExportKey2(self): + key = self.rsa.construct([self.n, self.e]) + derKey = key.exportKey("DER") + self.assertEqual(derKey, self.rsaPublicKeyDER) + + def testExportKey3(self): + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + pemKey = key.exportKey("PEM") + self.assertEqual(pemKey, b(self.rsaKeyPEM)) + + def testExportKey4(self): + key = self.rsa.construct([self.n, self.e]) + pemKey = key.exportKey("PEM") + self.assertEqual(pemKey, b(self.rsaPublicKeyPEM)) + + def testExportKey5(self): + key = self.rsa.construct([self.n, self.e]) + openssh_1 = key.exportKey("OpenSSH").split() + openssh_2 = self.rsaPublicKeyOpenSSH.split() + self.assertEqual(openssh_1[0], openssh_2[0]) + self.assertEqual(openssh_1[1], openssh_2[1]) + + def testExportKey7(self): + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + derKey = key.exportKey("DER", pkcs=8) + self.assertEqual(derKey, self.rsaKeyDER8) + + def testExportKey8(self): + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + pemKey = key.exportKey("PEM", pkcs=8) + self.assertEqual(pemKey, b(self.rsaKeyPEM8)) + + def testExportKey9(self): + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertRaises(ValueError, key.exportKey, "invalid-format") + + def testExportKey10(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#1, old PEM encryption + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.exportKey('PEM', 'test') + self.failUnless(tostr(outkey).find('4,ENCRYPTED')!=-1) + self.failUnless(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) + inkey = RSA.importKey(outkey, 'test') + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey11(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#1, old PEM encryption + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.exportKey('PEM', 'test', pkcs=1) + self.failUnless(tostr(outkey).find('4,ENCRYPTED')!=-1) + self.failUnless(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) + inkey = RSA.importKey(outkey, 'test') + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey12(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, old PEM encryption + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.exportKey('PEM', 'test', pkcs=8) + self.failUnless(tostr(outkey).find('4,ENCRYPTED')!=-1) + self.failUnless(tostr(outkey).find('BEGIN PRIVATE KEY')!=-1) + inkey = RSA.importKey(outkey, 'test') + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey13(self): + # Export and re-import the encrypted key. It must match. + # PEM envelope, PKCS#8, PKCS#8 encryption + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.exportKey('PEM', 'test', pkcs=8, + protection='PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') + self.failUnless(tostr(outkey).find('4,ENCRYPTED')==-1) + self.failUnless(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1) + inkey = RSA.importKey(outkey, 'test') + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey14(self): + # Export and re-import the encrypted key. It must match. + # DER envelope, PKCS#8, PKCS#8 encryption + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + outkey = key.exportKey('DER', 'test', pkcs=8) + inkey = RSA.importKey(outkey, 'test') + self.assertEqual(key.n, inkey.n) + self.assertEqual(key.e, inkey.e) + self.assertEqual(key.d, inkey.d) + + def testExportKey15(self): + # Verify that that error an condition is detected when trying to + # use a password with DER encoding and PKCS#1. + key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) + self.assertRaises(ValueError, key.exportKey, 'DER', 'test', 1) + +class ImportKeyTestsSlow(ImportKeyTests): + def setUp(self): + self.rsa = RSA.RSAImplementation(use_fast_math=0) + +class ImportKeyTestsFast(ImportKeyTests): + def setUp(self): + self.rsa = RSA.RSAImplementation(use_fast_math=1) + +if __name__ == '__main__': + unittest.main() + +def get_tests(config={}): + tests = [] + try: + from Crypto.PublicKey import _fastmath + tests += list_test_cases(ImportKeyTestsFast) + except ImportError: + pass + tests += list_test_cases(ImportKeyTestsSlow) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/Fortuna/__init__.py b/lib/Crypto/SelfTest/Random/Fortuna/__init__.py new file mode 100644 index 0000000..81a0e13 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/Fortuna/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Random/Fortuna/__init__.py: Self-test for Fortuna modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for the Crypto.Random.Fortuna package""" + +__revision__ = "$Id$" + +import os + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.Random.Fortuna import test_FortunaAccumulator; tests += test_FortunaAccumulator.get_tests(config=config) + from Crypto.SelfTest.Random.Fortuna import test_FortunaGenerator; tests += test_FortunaGenerator.get_tests(config=config) + from Crypto.SelfTest.Random.Fortuna import test_SHAd256; tests += test_SHAd256.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py b/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py new file mode 100644 index 0000000..c5638e6 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Random/Fortuna/test_FortunaAccumulator.py: Self-test for the FortunaAccumulator module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-tests for Crypto.Random.Fortuna.FortunaAccumulator""" + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * +from Crypto.SelfTest.st_common import assert_disabled + +import unittest +from binascii import b2a_hex + +class FortunaAccumulatorTests(unittest.TestCase): + def setUp(self): + global FortunaAccumulator + from Crypto.Random.Fortuna import FortunaAccumulator + + def test_FortunaPool(self): + """FortunaAccumulator.FortunaPool""" + pool = FortunaAccumulator.FortunaPool() + self.assertEqual(0, pool.length) + self.assertEqual("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", pool.hexdigest()) + + pool.append(b('abc')) + + self.assertEqual(3, pool.length) + self.assertEqual("4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358", pool.hexdigest()) + + pool.append(b("dbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")) + + self.assertEqual(56, pool.length) + self.assertEqual(b('0cffe17f68954dac3a84fb1458bd5ec99209449749b2b308b7cb55812f9563af'), b2a_hex(pool.digest())) + + pool.reset() + + self.assertEqual(0, pool.length) + + pool.append(b('a') * 10**6) + + self.assertEqual(10**6, pool.length) + self.assertEqual(b('80d1189477563e1b5206b2749f1afe4807e5705e8bd77887a60187a712156688'), b2a_hex(pool.digest())) + + def test_which_pools(self): + """FortunaAccumulator.which_pools""" + + # which_pools(0) should trigger an assertion failure (unless using -O or -OO) + if not assert_disabled(): + self.assertRaises(AssertionError, FortunaAccumulator.which_pools, 0) + + self.assertEqual(FortunaAccumulator.which_pools(1), [0]) + self.assertEqual(FortunaAccumulator.which_pools(2), [0, 1]) + self.assertEqual(FortunaAccumulator.which_pools(3), [0]) + self.assertEqual(FortunaAccumulator.which_pools(4), [0, 1, 2]) + self.assertEqual(FortunaAccumulator.which_pools(5), [0]) + self.assertEqual(FortunaAccumulator.which_pools(6), [0, 1]) + self.assertEqual(FortunaAccumulator.which_pools(7), [0]) + self.assertEqual(FortunaAccumulator.which_pools(8), [0, 1, 2, 3]) + for i in range(1, 32): + self.assertEqual(FortunaAccumulator.which_pools(2L**i-1), [0]) + self.assertEqual(FortunaAccumulator.which_pools(2L**i), range(i+1)) + self.assertEqual(FortunaAccumulator.which_pools(2L**i+1), [0]) + self.assertEqual(FortunaAccumulator.which_pools(2L**31), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**32), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**33), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**34), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**35), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**36), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**64), range(32)) + self.assertEqual(FortunaAccumulator.which_pools(2L**128), range(32)) + + def test_accumulator(self): + """FortunaAccumulator.FortunaAccumulator""" + fa = FortunaAccumulator.FortunaAccumulator() + + # This should fail, because we haven't seeded the PRNG yet + self.assertRaises(AssertionError, fa.random_data, 1) + + # Spread some test data across the pools (source number 42) + # This would be horribly insecure in a real system. + for p in range(32): + fa.add_random_event(42, p, b("X") * 32) + self.assertEqual(32+2, fa.pools[p].length) + + # This should still fail, because we haven't seeded the PRNG with 64 bytes yet + self.assertRaises(AssertionError, fa.random_data, 1) + + # Add more data + for p in range(32): + fa.add_random_event(42, p, b("X") * 32) + self.assertEqual((32+2)*2, fa.pools[p].length) + + # The underlying RandomGenerator should get seeded with Pool 0 + # s = SHAd256(chr(42) + chr(32) + "X"*32 + chr(42) + chr(32) + "X"*32) + # = SHA256(h'edd546f057b389155a31c32e3975e736c1dec030ddebb137014ecbfb32ed8c6f') + # = h'aef42a5dcbddab67e8efa118e1b47fde5d697f89beb971b99e6e8e5e89fbf064' + # The counter and the key before reseeding is: + # C_0 = 0 + # K_0 = "\x00" * 32 + # The counter after reseeding is 1, and the new key after reseeding is + # C_1 = 1 + # K_1 = SHAd256(K_0 || s) + # = SHA256(h'0eae3e401389fab86640327ac919ecfcb067359d95469e18995ca889abc119a6') + # = h'aafe9d0409fbaaafeb0a1f2ef2014a20953349d3c1c6e6e3b962953bea6184dd' + # The first block of random data, therefore, is + # r_1 = AES-256(K_1, 1) + # = AES-256(K_1, h'01000000000000000000000000000000') + # = h'b7b86bd9a27d96d7bb4add1b6b10d157' + # The second block of random data is + # r_2 = AES-256(K_1, 2) + # = AES-256(K_1, h'02000000000000000000000000000000') + # = h'2350b1c61253db2f8da233be726dc15f' + # The third and fourth blocks of random data (which become the new key) are + # r_3 = AES-256(K_1, 3) + # = AES-256(K_1, h'03000000000000000000000000000000') + # = h'f23ad749f33066ff53d307914fbf5b21' + # r_4 = AES-256(K_1, 4) + # = AES-256(K_1, h'04000000000000000000000000000000') + # = h'da9667c7e86ba247655c9490e9d94a7c' + # K_2 = r_3 || r_4 + # = h'f23ad749f33066ff53d307914fbf5b21da9667c7e86ba247655c9490e9d94a7c' + # The final counter value is 5. + self.assertEqual("aef42a5dcbddab67e8efa118e1b47fde5d697f89beb971b99e6e8e5e89fbf064", + fa.pools[0].hexdigest()) + self.assertEqual(None, fa.generator.key) + self.assertEqual(0, fa.generator.counter.next_value()) + + result = fa.random_data(32) + + self.assertEqual(b("b7b86bd9a27d96d7bb4add1b6b10d157" "2350b1c61253db2f8da233be726dc15f"), b2a_hex(result)) + self.assertEqual(b("f23ad749f33066ff53d307914fbf5b21da9667c7e86ba247655c9490e9d94a7c"), b2a_hex(fa.generator.key)) + self.assertEqual(5, fa.generator.counter.next_value()) + + def test_accumulator_pool_length(self): + """FortunaAccumulator.FortunaAccumulator minimum pool length""" + fa = FortunaAccumulator.FortunaAccumulator() + + # This test case is hard-coded to assume that FortunaAccumulator.min_pool_size is 64. + self.assertEqual(fa.min_pool_size, 64) + + # The PRNG should not allow us to get random data from it yet + self.assertRaises(AssertionError, fa.random_data, 1) + + # Add 60 bytes, 4 at a time (2 header + 2 payload) to each of the 32 pools + for i in range(15): + for p in range(32): + # Add the bytes to the pool + fa.add_random_event(2, p, b("XX")) + + # The PRNG should not allow us to get random data from it yet + self.assertRaises(AssertionError, fa.random_data, 1) + + # Add 4 more bytes to pool 0 + fa.add_random_event(2, 0, b("XX")) + + # We should now be able to get data from the accumulator + fa.random_data(1) + +def get_tests(config={}): + from Crypto.SelfTest.st_common import list_test_cases + return list_test_cases(FortunaAccumulatorTests) + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py b/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py new file mode 100644 index 0000000..d41bb02 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Random/Fortuna/test_FortunaGenerator.py: Self-test for the FortunaGenerator module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-tests for Crypto.Random.Fortuna.FortunaGenerator""" + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +import unittest +from binascii import b2a_hex + +class FortunaGeneratorTests(unittest.TestCase): + def setUp(self): + global FortunaGenerator + from Crypto.Random.Fortuna import FortunaGenerator + + def test_generator(self): + """FortunaGenerator.AESGenerator""" + fg = FortunaGenerator.AESGenerator() + + # We shouldn't be able to read data until we've seeded the generator + self.assertRaises(Exception, fg.pseudo_random_data, 1) + self.assertEqual(0, fg.counter.next_value()) + + # Seed the generator, which should set the key and increment the counter. + fg.reseed(b("Hello")) + self.assertEqual(b("0ea6919d4361551364242a4ba890f8f073676e82cf1a52bb880f7e496648b565"), b2a_hex(fg.key)) + self.assertEqual(1, fg.counter.next_value()) + + # Read 2 full blocks from the generator + self.assertEqual(b("7cbe2c17684ac223d08969ee8b565616") + # counter=1 + b("717661c0d2f4758bd6ba140bf3791abd"), # counter=2 + b2a_hex(fg.pseudo_random_data(32))) + + # Meanwhile, the generator will have re-keyed itself and incremented its counter + self.assertEqual(b("33a1bb21987859caf2bbfc5615bef56d") + # counter=3 + b("e6b71ff9f37112d0c193a135160862b7"), # counter=4 + b2a_hex(fg.key)) + self.assertEqual(5, fg.counter.next_value()) + + # Read another 2 blocks from the generator + self.assertEqual(b("fd6648ba3086e919cee34904ef09a7ff") + # counter=5 + b("021f77580558b8c3e9248275f23042bf"), # counter=6 + b2a_hex(fg.pseudo_random_data(32))) + + + # Try to read more than 2**20 bytes using the internal function. This should fail. + self.assertRaises(AssertionError, fg._pseudo_random_data, 2**20+1) + +def get_tests(config={}): + from Crypto.SelfTest.st_common import list_test_cases + return list_test_cases(FortunaGeneratorTests) + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/Fortuna/test_SHAd256.py b/lib/Crypto/SelfTest/Random/Fortuna/test_SHAd256.py new file mode 100644 index 0000000..f94db8a --- /dev/null +++ b/lib/Crypto/SelfTest/Random/Fortuna/test_SHAd256.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Random/Fortuna/test_SHAd256.py: Self-test for the SHAd256 hash function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.Fortuna.SHAd256""" + +__revision__ = "$Id$" +from Crypto.Util.py3compat import * + +# This is a list of (expected_result, input[, description]) tuples. +test_data = [ + # I could not find any test vectors for SHAd256, so I made these vectors by + # feeding some sample data into several plain SHA256 implementations + # (including OpenSSL, the "sha256sum" tool, and this implementation). + # This is a subset of the resulting test vectors. The complete list can be + # found at: http://www.dlitz.net/crypto/shad256-test-vectors/ + ('5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456', + '', "'' (empty string)"), + ('4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358', + 'abc'), + ('0cffe17f68954dac3a84fb1458bd5ec99209449749b2b308b7cb55812f9563af', + 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq') +] + +def get_tests(config={}): + from Crypto.Random.Fortuna import SHAd256 + from Crypto.SelfTest.Hash.common import make_hash_tests + return make_hash_tests(SHAd256, "SHAd256", test_data, 32) + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/OSRNG/__init__.py b/lib/Crypto/SelfTest/Random/OSRNG/__init__.py new file mode 100644 index 0000000..44b3fa1 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/OSRNG/__init__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Random/OSRNG/__init__.py: Self-test for OSRNG modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for Crypto.Random.OSRNG package""" + +__revision__ = "$Id$" + +import os + +def get_tests(config={}): + tests = [] + if os.name == 'nt': + from Crypto.SelfTest.Random.OSRNG import test_nt; tests += test_nt.get_tests(config=config) + from Crypto.SelfTest.Random.OSRNG import test_winrandom; tests += test_winrandom.get_tests(config=config) + elif os.name == 'posix': + from Crypto.SelfTest.Random.OSRNG import test_posix; tests += test_posix.get_tests(config=config) + if hasattr(os, 'urandom'): + from Crypto.SelfTest.Random.OSRNG import test_fallback; tests += test_fallback.get_tests(config=config) + from Crypto.SelfTest.Random.OSRNG import test_generic; tests += test_generic.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py b/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py new file mode 100644 index 0000000..41909b0 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_fallback.py: Self-test for the OSRNG.fallback.new() function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.OSRNG.fallback""" + +__revision__ = "$Id$" + +import unittest + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Random.OSRNG.fallback.new()""" + # Import the OSRNG.nt module and try to use it + import Crypto.Random.OSRNG.fallback + randobj = Crypto.Random.OSRNG.fallback.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py b/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py new file mode 100644 index 0000000..2a40974 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_generic.py: Self-test for the OSRNG.new() function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.OSRNG""" + +__revision__ = "$Id$" + +import unittest + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Random.OSRNG.new()""" + # Import the OSRNG module and try to use it + import Crypto.Random.OSRNG + randobj = Crypto.Random.OSRNG.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py b/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py new file mode 100644 index 0000000..a7a8338 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_generic.py: Self-test for the OSRNG.nt.new() function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.OSRNG.nt""" + +__revision__ = "$Id$" + +import unittest + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Random.OSRNG.nt.new()""" + # Import the OSRNG.nt module and try to use it + import Crypto.Random.OSRNG.nt + randobj = Crypto.Random.OSRNG.nt.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py b/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py new file mode 100644 index 0000000..2224afe --- /dev/null +++ b/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_posix.py: Self-test for the OSRNG.posix.new() function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.OSRNG.posix""" + +__revision__ = "$Id$" + +import unittest + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Random.OSRNG.posix.new()""" + # Import the OSRNG.nt module and try to use it + import Crypto.Random.OSRNG.posix + randobj = Crypto.Random.OSRNG.posix.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py b/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py new file mode 100644 index 0000000..3010eb7 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.OSRNG.winrandom""" + +__revision__ = "$Id$" + +import unittest + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Random.OSRNG.winrandom""" + # Import the winrandom module and try to use it + from Crypto.Random.OSRNG import winrandom + randobj = winrandom.new() + x = randobj.get_bytes(16) + y = randobj.get_bytes(16) + self.assertNotEqual(x, y) + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/__init__.py b/lib/Crypto/SelfTest/Random/__init__.py new file mode 100644 index 0000000..f972bf0 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/__init__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Random/__init__.py: Self-test for random number generation modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for random number generators""" + +__revision__ = "$Id$" + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest.Random import Fortuna; tests += Fortuna.get_tests(config=config) + from Crypto.SelfTest.Random import OSRNG; tests += OSRNG.get_tests(config=config) + from Crypto.SelfTest.Random import test_random; tests += test_random.get_tests(config=config) + from Crypto.SelfTest.Random import test_rpoolcompat; tests += test_rpoolcompat.get_tests(config=config) + from Crypto.SelfTest.Random import test__UserFriendlyRNG; tests += test__UserFriendlyRNG.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py b/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py new file mode 100644 index 0000000..771a663 --- /dev/null +++ b/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# Self-tests for the user-friendly Crypto.Random interface +# +# Written in 2013 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for generic Crypto.Random stuff """ + +from __future__ import nested_scopes + +__revision__ = "$Id$" + +import binascii +import pprint +import unittest +import os +import time +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +try: + import multiprocessing +except ImportError: + multiprocessing = None + +import Crypto.Random._UserFriendlyRNG +import Crypto.Random.random + +class RNGForkTest(unittest.TestCase): + + def _get_reseed_count(self): + """ + Get `FortunaAccumulator.reseed_count`, the global count of the + number of times that the PRNG has been reseeded. + """ + rng_singleton = Crypto.Random._UserFriendlyRNG._get_singleton() + rng_singleton._lock.acquire() + try: + return rng_singleton._fa.reseed_count + finally: + rng_singleton._lock.release() + + def runTest(self): + # Regression test for CVE-2013-1445. We had a bug where, under the + # right conditions, two processes might see the same random sequence. + + if sys.platform.startswith('win'): # windows can't fork + assert not hasattr(os, 'fork') # ... right? + return + + # Wait 150 ms so that we don't trigger the rate-limit prematurely. + time.sleep(0.15) + + reseed_count_before = self._get_reseed_count() + + # One or both of these calls together should trigger a reseed right here. + Crypto.Random._UserFriendlyRNG._get_singleton().reinit() + Crypto.Random.get_random_bytes(1) + + reseed_count_after = self._get_reseed_count() + self.assertNotEqual(reseed_count_before, reseed_count_after) # sanity check: test should reseed parent before forking + + rfiles = [] + for i in range(10): + rfd, wfd = os.pipe() + if os.fork() == 0: + # child + os.close(rfd) + f = os.fdopen(wfd, "wb") + + Crypto.Random.atfork() + + data = Crypto.Random.get_random_bytes(16) + + f.write(data) + f.close() + os._exit(0) + # parent + os.close(wfd) + rfiles.append(os.fdopen(rfd, "rb")) + + results = [] + results_dict = {} + for f in rfiles: + data = binascii.hexlify(f.read()) + results.append(data) + results_dict[data] = 1 + f.close() + + if len(results) != len(results_dict.keys()): + raise AssertionError("RNG output duplicated across fork():\n%s" % + (pprint.pformat(results))) + + +# For RNGMultiprocessingForkTest +def _task_main(q): + a = Crypto.Random.get_random_bytes(16) + time.sleep(0.1) # wait 100 ms + b = Crypto.Random.get_random_bytes(16) + q.put(binascii.b2a_hex(a)) + q.put(binascii.b2a_hex(b)) + q.put(None) # Wait for acknowledgment + + +class RNGMultiprocessingForkTest(unittest.TestCase): + + def runTest(self): + # Another regression test for CVE-2013-1445. This is basically the + # same as RNGForkTest, but less compatible with old versions of Python, + # and a little easier to read. + + n_procs = 5 + manager = multiprocessing.Manager() + queues = [manager.Queue(1) for i in range(n_procs)] + + # Reseed the pool + time.sleep(0.15) + Crypto.Random._UserFriendlyRNG._get_singleton().reinit() + Crypto.Random.get_random_bytes(1) + + # Start the child processes + pool = multiprocessing.Pool(processes=n_procs, initializer=Crypto.Random.atfork) + map_result = pool.map_async(_task_main, queues) + + # Get the results, ensuring that no pool processes are reused. + aa = [queues[i].get(30) for i in range(n_procs)] + bb = [queues[i].get(30) for i in range(n_procs)] + res = list(zip(aa, bb)) + + # Shut down the pool + map_result.get(30) + pool.close() + pool.join() + + # Check that the results are unique + if len(set(aa)) != len(aa) or len(set(res)) != len(res): + raise AssertionError("RNG output duplicated across fork():\n%s" % + (pprint.pformat(res),)) + + +def get_tests(config={}): + tests = [] + tests += [RNGForkTest()] + if multiprocessing is not None: + tests += [RNGMultiprocessingForkTest()] + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/test_random.py b/lib/Crypto/SelfTest/Random/test_random.py new file mode 100644 index 0000000..3e85c3c --- /dev/null +++ b/lib/Crypto/SelfTest/Random/test_random.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_generic.py: Self-test for the Crypto.Random.new() function +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Random.new()""" + +__revision__ = "$Id$" + +import unittest +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Random.new()""" + # Import the Random module and try to use it + from Crypto import Random + randobj = Random.new() + x = randobj.read(16) + y = randobj.read(16) + self.assertNotEqual(x, y) + z = Random.get_random_bytes(16) + self.assertNotEqual(x, z) + self.assertNotEqual(y, z) + # Test the Random.random module, which + # implements a subset of Python's random API + # Not implemented: + # seed(), getstate(), setstate(), jumpahead() + # random(), uniform(), triangular(), betavariate() + # expovariate(), gammavariate(), gauss(), + # longnormvariate(), normalvariate(), + # vonmisesvariate(), paretovariate() + # weibullvariate() + # WichmannHill(), whseed(), SystemRandom() + from Crypto.Random import random + x = random.getrandbits(16*8) + y = random.getrandbits(16*8) + self.assertNotEqual(x, y) + # Test randrange + if x>y: + start = y + stop = x + else: + start = x + stop = y + for step in range(1,10): + x = random.randrange(start,stop,step) + y = random.randrange(start,stop,step) + self.assertNotEqual(x, y) + self.assertEqual(start <= x < stop, True) + self.assertEqual(start <= y < stop, True) + self.assertEqual((x - start) % step, 0) + self.assertEqual((y - start) % step, 0) + for i in range(10): + self.assertEqual(random.randrange(1,2), 1) + self.assertRaises(ValueError, random.randrange, start, start) + self.assertRaises(ValueError, random.randrange, stop, start, step) + self.assertRaises(TypeError, random.randrange, start, stop, step, step) + self.assertRaises(TypeError, random.randrange, start, stop, "1") + self.assertRaises(TypeError, random.randrange, "1", stop, step) + self.assertRaises(TypeError, random.randrange, 1, "2", step) + self.assertRaises(ValueError, random.randrange, start, stop, 0) + # Test randint + x = random.randint(start,stop) + y = random.randint(start,stop) + self.assertNotEqual(x, y) + self.assertEqual(start <= x <= stop, True) + self.assertEqual(start <= y <= stop, True) + for i in range(10): + self.assertEqual(random.randint(1,1), 1) + self.assertRaises(ValueError, random.randint, stop, start) + self.assertRaises(TypeError, random.randint, start, stop, step) + self.assertRaises(TypeError, random.randint, "1", stop) + self.assertRaises(TypeError, random.randint, 1, "2") + # Test choice + seq = range(10000) + x = random.choice(seq) + y = random.choice(seq) + self.assertNotEqual(x, y) + self.assertEqual(x in seq, True) + self.assertEqual(y in seq, True) + for i in range(10): + self.assertEqual(random.choice((1,2,3)) in (1,2,3), True) + self.assertEqual(random.choice([1,2,3]) in [1,2,3], True) + if sys.version_info[0] is 3: + self.assertEqual(random.choice(bytearray(b('123'))) in bytearray(b('123')), True) + self.assertEqual(1, random.choice([1])) + self.assertRaises(IndexError, random.choice, []) + self.assertRaises(TypeError, random.choice, 1) + # Test shuffle. Lacks random parameter to specify function. + # Make copies of seq + seq = range(500) + x = list(seq) + y = list(seq) + random.shuffle(x) + random.shuffle(y) + self.assertNotEqual(x, y) + self.assertEqual(len(seq), len(x)) + self.assertEqual(len(seq), len(y)) + for i in range(len(seq)): + self.assertEqual(x[i] in seq, True) + self.assertEqual(y[i] in seq, True) + self.assertEqual(seq[i] in x, True) + self.assertEqual(seq[i] in y, True) + z = [1] + random.shuffle(z) + self.assertEqual(z, [1]) + if sys.version_info[0] == 3: + z = bytearray(b('12')) + random.shuffle(z) + self.assertEqual(b('1') in z, True) + self.assertRaises(TypeError, random.shuffle, b('12')) + self.assertRaises(TypeError, random.shuffle, 1) + self.assertRaises(TypeError, random.shuffle, "11") + self.assertRaises(TypeError, random.shuffle, (1,2)) + # 2to3 wraps a list() around it, alas - but I want to shoot + # myself in the foot here! :D + # if sys.version_info[0] == 3: + # self.assertRaises(TypeError, random.shuffle, range(3)) + # Test sample + x = random.sample(seq, 20) + y = random.sample(seq, 20) + self.assertNotEqual(x, y) + for i in range(20): + self.assertEqual(x[i] in seq, True) + self.assertEqual(y[i] in seq, True) + z = random.sample([1], 1) + self.assertEqual(z, [1]) + z = random.sample((1,2,3), 1) + self.assertEqual(z[0] in (1,2,3), True) + z = random.sample("123", 1) + self.assertEqual(z[0] in "123", True) + z = random.sample(range(3), 1) + self.assertEqual(z[0] in range(3), True) + if sys.version_info[0] == 3: + z = random.sample(b("123"), 1) + self.assertEqual(z[0] in b("123"), True) + z = random.sample(bytearray(b("123")), 1) + self.assertEqual(z[0] in bytearray(b("123")), True) + self.assertRaises(TypeError, random.sample, 1) + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Random/test_rpoolcompat.py b/lib/Crypto/SelfTest/Random/test_rpoolcompat.py new file mode 100644 index 0000000..be538da --- /dev/null +++ b/lib/Crypto/SelfTest/Random/test_rpoolcompat.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for the Crypto.Util.randpool.RandomPool wrapper class""" + +__revision__ = "$Id$" + +import sys +import unittest + +class SimpleTest(unittest.TestCase): + def runTest(self): + """Crypto.Util.randpool.RandomPool""" + # Import the winrandom module and try to use it + from Crypto.Util.randpool import RandomPool + sys.stderr.write("SelfTest: You can ignore the RandomPool_DeprecationWarning that follows.\n") + rpool = RandomPool() + x = rpool.get_bytes(16) + y = rpool.get_bytes(16) + self.assertNotEqual(x, y) + self.assertNotEqual(rpool.entropy, 0) + + rpool.randomize() + rpool.stir('foo') + rpool.add_event('foo') + +def get_tests(config={}): + return [SimpleTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Signature/__init__.py b/lib/Crypto/SelfTest/Signature/__init__.py new file mode 100644 index 0000000..653b66c --- /dev/null +++ b/lib/Crypto/SelfTest/Signature/__init__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Signature/__init__.py: Self-test for signature modules +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for signature modules""" + +__revision__ = "$Id$" + +import os + +def get_tests(config={}): + tests = [] + import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config) + import test_pkcs1_pss; tests += test_pkcs1_pss.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Signature/test_pkcs1_15.py b/lib/Crypto/SelfTest/Signature/test_pkcs1_15.py new file mode 100644 index 0000000..cc94262 --- /dev/null +++ b/lib/Crypto/SelfTest/Signature/test_pkcs1_15.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Signature/test_pkcs1_15.py: Self-test for PKCS#1 v1.5 signatures +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +import unittest + +from Crypto.PublicKey import RSA +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex +from Crypto.Hash import MD2, SHA1, MD5, SHA224, SHA256, SHA384, SHA512,\ + RIPEMD160 +from Crypto import Random +from Crypto.Signature import PKCS1_v1_5 as PKCS +from Crypto.Util.py3compat import * + +def isStr(s): + t = '' + try: + t += s + except TypeError: + return 0 + return 1 + +def rws(t): + """Remove white spaces, tabs, and new lines from a string""" + for c in ['\n', '\t', ' ']: + t = t.replace(c,'') + return t + +def t2b(t): + """Convert a text string with bytes in hex form to a byte string""" + clean = b(rws(t)) + if len(clean)%2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) + +class PKCS1_15_Tests(unittest.TestCase): + + # List of tuples with test data for PKCS#1 v1.5. + # Each tuple is made up by: + # Item #0: dictionary with RSA key component, or key to import + # Item #1: data to hash and sign + # Item #2: signature of the data #1, done with the key #0, after + # hashing it with #3 + # Item #3: hash object generator + + _testData = ( + + # + # Taken from ftp://ftp.rsa.com/pub/pkcs/ascii/examples.asc + # "Some Examples of the PKCS Standards", 1999 + # + ( + + # Private key, from 2.1 + { + 'n':'''0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0 c0 01 c6 + 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51 d0 53 b3 e3 78 2a 1d + e5 dc 5a f4 eb e9 94 68 17 01 14 a1 df e6 7c dc 9a 9a f5 5d + 65 56 20 bb ab''', + 'e':'''01 00 + 01''', + 'd':'''01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e a8 0c 09 + b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0 1d 23 35 6a 7d 44 d6 + bd 8b d5 0e 94 bf c7 23 fa 87 d8 86 2b 75 17 76 91 c1 1d 75 + 76 92 df 88 81''' + }, + # Data to sign, from 3.1 + '''30 81 a4 02 01 00 30 42 31 0b 30 09 06 + 03 55 04 06 13 02 55 53 31 1d 30 1b 06 03 55 04 0a 13 14 + 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f + 6e 31 14 30 12 06 03 55 04 03 13 0b 54 65 73 74 20 55 73 + 65 72 20 31 30 5b 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 + 05 00 03 4a 00 30 47 02 40 + 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0 + c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51 + d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17 + 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab + 02 03 01 00 01''', + # Signature, from 3.2 (at the very end) + '''06 db 36 cb 18 d3 47 5b 9c 01 db 3c 78 95 28 08 + 02 79 bb ae ff 2b 7d 55 8e d6 61 59 87 c8 51 86 + 3f 8a 6c 2c ff bc 89 c3 f7 5a 18 d9 6b 12 7c 71 + 7d 54 d0 d8 04 8d a8 a0 54 46 26 d1 7a 2a 8f be''', + MD2 + ), + + # + # RSA keypair generated with openssl + # + ( + """-----BEGIN RSA PRIVATE KEY----- + MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII + q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 + Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI + OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr + +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK + JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 + n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== + -----END RSA PRIVATE KEY-----""", + "This is a test\x0a", + # + # PKCS#1 signature computed with openssl + # + '''4a700a16432a291a3194646952687d5316458b8b86fb0a25aa30e0dcecdb + 442676759ac63d56ec1499c3ae4c0013c2053cabd5b5804848994541ac16 + fa243a4d''', + SHA1 + ), + + # + # Test vector from http://www.di-mgt.com.au/rsa_alg.html#signpkcs1 + # + ( + { + 'n':'''E08973398DD8F5F5E88776397F4EB005BB5383DE0FB7ABDC7DC775290D052E6D + 12DFA68626D4D26FAA5829FC97ECFA82510F3080BEB1509E4644F12CBBD832CF + C6686F07D9B060ACBEEE34096A13F5F7050593DF5EBA3556D961FF197FC981E6 + F86CEA874070EFAC6D2C749F2DFA553AB9997702A648528C4EF357385774575F''', + 'e':'''010001''', + 'd':'''00A403C327477634346CA686B57949014B2E8AD2C862B2C7D748096A8B91F736 + F275D6E8CD15906027314735644D95CD6763CEB49F56AC2F376E1CEE0EBF282D + F439906F34D86E085BD5656AD841F313D72D395EFE33CBFF29E4030B3D05A28F + B7F18EA27637B07957D32F2BDE8706227D04665EC91BAF8B1AC3EC9144AB7F21''' + }, + "abc", + '''60AD5A78FB4A4030EC542C8974CD15F55384E836554CEDD9A322D5F4135C6267 + A9D20970C54E6651070B0144D43844C899320DD8FA7819F7EBC6A7715287332E + C8675C136183B3F8A1F81EF969418267130A756FDBB2C71D9A667446E34E0EAD + 9CF31BFB66F816F319D0B7E430A5F2891553986E003720261C7E9022C0D9F11F''', + SHA1 + ) + + ) + + def testSign1(self): + for i in range(len(self._testData)): + row = self._testData[i] + # Build the key + if isStr(row[0]): + key = RSA.importKey(row[0]) + else: + comps = [ long(rws(row[0][x]),16) for x in ('n','e','d') ] + key = RSA.construct(comps) + h = row[3].new() + # Data to sign can either be in hex form or not + try: + h.update(t2b(row[1])) + except: + h.update(b(row[1])) + # The real test + signer = PKCS.new(key) + self.failUnless(signer.can_sign()) + s = signer.sign(h) + self.assertEqual(s, t2b(row[2])) + + def testVerify1(self): + for i in range(len(self._testData)): + row = self._testData[i] + # Build the key + if isStr(row[0]): + key = RSA.importKey(row[0]).publickey() + else: + comps = [ long(rws(row[0][x]),16) for x in ('n','e') ] + key = RSA.construct(comps) + h = row[3].new() + # Data to sign can either be in hex form or not + try: + h.update(t2b(row[1])) + except: + h.update(b(row[1])) + # The real test + verifier = PKCS.new(key) + self.failIf(verifier.can_sign()) + result = verifier.verify(h, t2b(row[2])) + self.failUnless(result) + + def testSignVerify(self): + rng = Random.new().read + key = RSA.generate(1024, rng) + + for hashmod in (MD2,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160): + h = hashmod.new() + h.update(b('blah blah blah')) + + signer = PKCS.new(key) + s = signer.sign(h) + result = signer.verify(h, s) + self.failUnless(result) + +class PKCS1_15_NoParams(unittest.TestCase): + """Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in + the algorithm identifier (bug #1119552).""" + + rsakey = """-----BEGIN RSA PRIVATE KEY----- + MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII + q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 + Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI + OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr + +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK + JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 + n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== + -----END RSA PRIVATE KEY-----""" + + msg = b("This is a test\x0a") + + # PKCS1 v1.5 signature of the message computed using SHA-1. + # The digestAlgorithm SEQUENCE does NOT contain the NULL parameter. + signature = '''a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e281893db7401 + 3dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8b19348e0bd7b6f152dfc''' + + def testVerify(self): + verifier = PKCS.new(RSA.importKey(self.rsakey)) + h = SHA1.new(self.msg) + result = verifier.verify(h, t2b(self.signature)) + self.failUnless(result) + +def get_tests(config={}): + tests = [] + tests += list_test_cases(PKCS1_15_Tests) + tests += list_test_cases(PKCS1_15_NoParams) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Signature/test_pkcs1_pss.py b/lib/Crypto/SelfTest/Signature/test_pkcs1_pss.py new file mode 100644 index 0000000..e37e7a1 --- /dev/null +++ b/lib/Crypto/SelfTest/Signature/test_pkcs1_pss.py @@ -0,0 +1,447 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Signature/test_pkcs1_pss.py: Self-test for PKCS#1 PSS signatures +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +from __future__ import nested_scopes + +__revision__ = "$Id$" + +import unittest + +from Crypto.PublicKey import RSA +from Crypto import Random +from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex +from Crypto.Hash import SHA1, MD2, RIPEMD160, SHA224, SHA384, SHA512,\ + SHA256, MD5 +from Crypto.Signature import PKCS1_PSS as PKCS +from Crypto.Util.py3compat import * + +def isStr(s): + t = '' + try: + t += s + except TypeError: + return 0 + return 1 + +def rws(t): + """Remove white spaces, tabs, and new lines from a string""" + for c in ['\t', '\n', ' ']: + t = t.replace(c,'') + return t + +def t2b(t): + """Convert a text string with bytes in hex form to a byte string""" + clean = b(rws(t)) + if len(clean)%2 == 1: + raise ValueError("Even number of characters expected") + return a2b_hex(clean) + +# Helper class to count how many bytes have been requested +# from the key's private RNG, w/o counting those used for blinding +class MyKey: + def __init__(self, key): + self._key = key + self.n = key.n + self.asked = 0 + def _randfunc(self, N): + self.asked += N + return self._key._randfunc(N) + def sign(self, m): + return self._key.sign(m) + def has_private(self): + return self._key.has_private() + def decrypt(self, m): + return self._key.decrypt(m) + def verify(self, m, p): + return self._key.verify(m, p) + def encrypt(self, m, p): + return self._key.encrypt(m, p) + +class PKCS1_PSS_Tests(unittest.TestCase): + + # List of tuples with test data for PKCS#1 PSS + # Each tuple is made up by: + # Item #0: dictionary with RSA key component, or key to import + # Item #1: data to hash and sign + # Item #2: signature of the data #1, done with the key #0, + # and salt #3 after hashing it with #4 + # Item #3: salt + # Item #4: hash object generator + + _testData = ( + + # + # From in pss-vect.txt to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''a2 ba 40 ee 07 e3 b2 bd 2f 02 ce 22 7f 36 a1 95 + 02 44 86 e4 9c 19 cb 41 bb bd fb ba 98 b2 2b 0e + 57 7c 2e ea ff a2 0d 88 3a 76 e6 5e 39 4c 69 d4 + b3 c0 5a 1e 8f ad da 27 ed b2 a4 2b c0 00 fe 88 + 8b 9b 32 c2 2d 15 ad d0 cd 76 b3 e7 93 6e 19 95 + 5b 22 0d d1 7d 4e a9 04 b1 ec 10 2b 2e 4d e7 75 + 12 22 aa 99 15 10 24 c7 cb 41 cc 5e a2 1d 00 ee + b4 1f 7c 80 08 34 d2 c6 e0 6b ce 3b ce 7e a9 a5''', + 'e':'''01 00 01''', + # In the test vector, only p and q were given... + # d is computed offline as e^{-1} mod (p-1)(q-1) + 'd':'''50e2c3e38d886110288dfc68a9533e7e12e27d2aa56 + d2cdb3fb6efa990bcff29e1d2987fb711962860e7391b1ce01 + ebadb9e812d2fbdfaf25df4ae26110a6d7a26f0b810f54875e + 17dd5c9fb6d641761245b81e79f8c88f0e55a6dcd5f133abd3 + 5f8f4ec80adf1bf86277a582894cb6ebcd2162f1c7534f1f49 + 47b129151b71''' + }, + + # Data to sign + '''85 9e ef 2f d7 8a ca 00 30 8b dc 47 11 93 bf 55 + bf 9d 78 db 8f 8a 67 2b 48 46 34 f3 c9 c2 6e 64 + 78 ae 10 26 0f e0 dd 8c 08 2e 53 a5 29 3a f2 17 + 3c d5 0c 6d 5d 35 4f eb f7 8b 26 02 1c 25 c0 27 + 12 e7 8c d4 69 4c 9f 46 97 77 e4 51 e7 f8 e9 e0 + 4c d3 73 9c 6b bf ed ae 48 7f b5 56 44 e9 ca 74 + ff 77 a5 3c b7 29 80 2f 6e d4 a5 ff a8 ba 15 98 + 90 fc''', + # Signature + '''8d aa 62 7d 3d e7 59 5d 63 05 6c 7e c6 59 e5 44 + 06 f1 06 10 12 8b aa e8 21 c8 b2 a0 f3 93 6d 54 + dc 3b dc e4 66 89 f6 b7 95 1b b1 8e 84 05 42 76 + 97 18 d5 71 5d 21 0d 85 ef bb 59 61 92 03 2c 42 + be 4c 29 97 2c 85 62 75 eb 6d 5a 45 f0 5f 51 87 + 6f c6 74 3d ed dd 28 ca ec 9b b3 0e a9 9e 02 c3 + 48 82 69 60 4f e4 97 f7 4c cd 7c 7f ca 16 71 89 + 71 23 cb d3 0d ef 5d 54 a2 b5 53 6a d9 0a 74 7e''', + # Salt + '''e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8 + 3b ce 7e 61''', + # Hash algorithm + SHA1 + ), + + # + # Example 1.1 to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 + 56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 + d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 + 94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df + d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 + c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 + 05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 + ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37''', + 'e':'''01 00 01''', + 'd':'''33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47 + 71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8 + 94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8 + c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a + e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27 + a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c + 31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b + d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25''' + }, + # Message + '''cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 + d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 + 23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 + 6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 + 97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 + d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 + 61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 + cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 + 93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 + a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c + 29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca + b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 + be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed + 1b 73 31 8b 75 0a 01 67 d0''', + # Signature + '''90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71 + fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87 + e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2 + 26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15 + df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9 + c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65 + 98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4 + c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c''', + # Salt + '''de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f + 3e 67 76 af''', + # Hash + SHA1 + ), + + # + # Example 1.2 to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 + 56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 + d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 + 94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df + d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 + c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 + 05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 + ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37''', + 'e':'''01 00 01''', + 'd':'''33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47 + 71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8 + 94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8 + c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a + e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27 + a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c + 31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b + d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25''' + }, + # Message + '''85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c + f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f + 71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 + 22 6b 9e''', + # Signature + '''3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce + fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e + f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db + 0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45 + 17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4 + cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35 + 90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14 + 18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43''', + # Salt + '''ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f + d5 6d f4 2d''', + # Hash + SHA1 + ), + + # + # Example 2.1 to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''01 d4 0c 1b cf 97 a6 8a e7 cd bd 8a 7b f3 e3 4f + a1 9d cc a4 ef 75 a4 74 54 37 5f 94 51 4d 88 fe + d0 06 fb 82 9f 84 19 ff 87 d6 31 5d a6 8a 1f f3 + a0 93 8e 9a bb 34 64 01 1c 30 3a d9 91 99 cf 0c + 7c 7a 8b 47 7d ce 82 9e 88 44 f6 25 b1 15 e5 e9 + c4 a5 9c f8 f8 11 3b 68 34 33 6a 2f d2 68 9b 47 + 2c bb 5e 5c ab e6 74 35 0c 59 b6 c1 7e 17 68 74 + fb 42 f8 fc 3d 17 6a 01 7e dc 61 fd 32 6c 4b 33 + c9''', + 'e':'''01 00 01''', + 'd':'''02 7d 14 7e 46 73 05 73 77 fd 1e a2 01 56 57 72 + 17 6a 7d c3 83 58 d3 76 04 56 85 a2 e7 87 c2 3c + 15 57 6b c1 6b 9f 44 44 02 d6 bf c5 d9 8a 3e 88 + ea 13 ef 67 c3 53 ec a0 c0 dd ba 92 55 bd 7b 8b + b5 0a 64 4a fd fd 1d d5 16 95 b2 52 d2 2e 73 18 + d1 b6 68 7a 1c 10 ff 75 54 5f 3d b0 fe 60 2d 5f + 2b 7f 29 4e 36 01 ea b7 b9 d1 ce cd 76 7f 64 69 + 2e 3e 53 6c a2 84 6c b0 c2 dd 48 6a 39 fa 75 b1''' + }, + # Message + '''da ba 03 20 66 26 3f ae db 65 98 48 11 52 78 a5 + 2c 44 fa a3 a7 6f 37 51 5e d3 36 32 10 72 c4 0a + 9d 9b 53 bc 05 01 40 78 ad f5 20 87 51 46 aa e7 + 0f f0 60 22 6d cb 7b 1f 1f c2 7e 93 60''', + # Signature + '''01 4c 5b a5 33 83 28 cc c6 e7 a9 0b f1 c0 ab 3f + d6 06 ff 47 96 d3 c1 2e 4b 63 9e d9 13 6a 5f ec + 6c 16 d8 88 4b dd 99 cf dc 52 14 56 b0 74 2b 73 + 68 68 cf 90 de 09 9a db 8d 5f fd 1d ef f3 9b a4 + 00 7a b7 46 ce fd b2 2d 7d f0 e2 25 f5 46 27 dc + 65 46 61 31 72 1b 90 af 44 53 63 a8 35 8b 9f 60 + 76 42 f7 8f ab 0a b0 f4 3b 71 68 d6 4b ae 70 d8 + 82 78 48 d8 ef 1e 42 1c 57 54 dd f4 2c 25 89 b5 + b3''', + # Salt + '''57 bf 16 0b cb 02 bb 1d c7 28 0c f0 45 85 30 b7 + d2 83 2f f7''', + SHA1 + ), + + # + # Example 8.1 to be found in + # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + # + ( + # Private key + { + 'n':'''49 53 70 a1 fb 18 54 3c 16 d3 63 1e 31 63 25 5d + f6 2b e6 ee e8 90 d5 f2 55 09 e4 f7 78 a8 ea 6f + bb bc df 85 df f6 4e 0d 97 20 03 ab 36 81 fb ba + 6d d4 1f d5 41 82 9b 2e 58 2d e9 f2 a4 a4 e0 a2 + d0 90 0b ef 47 53 db 3c ee 0e e0 6c 7d fa e8 b1 + d5 3b 59 53 21 8f 9c ce ea 69 5b 08 66 8e de aa + dc ed 94 63 b1 d7 90 d5 eb f2 7e 91 15 b4 6c ad + 4d 9a 2b 8e fa b0 56 1b 08 10 34 47 39 ad a0 73 + 3f''', + 'e':'''01 00 01''', + 'd':'''6c 66 ff e9 89 80 c3 8f cd ea b5 15 98 98 83 61 + 65 f4 b4 b8 17 c4 f6 a8 d4 86 ee 4e a9 13 0f e9 + b9 09 2b d1 36 d1 84 f9 5f 50 4a 60 7e ac 56 58 + 46 d2 fd d6 59 7a 89 67 c7 39 6e f9 5a 6e ee bb + 45 78 a6 43 96 6d ca 4d 8e e3 de 84 2d e6 32 79 + c6 18 15 9c 1a b5 4a 89 43 7b 6a 61 20 e4 93 0a + fb 52 a4 ba 6c ed 8a 49 47 ac 64 b3 0a 34 97 cb + e7 01 c2 d6 26 6d 51 72 19 ad 0e c6 d3 47 db e9''' + }, + # Message + '''81 33 2f 4b e6 29 48 41 5e a1 d8 99 79 2e ea cf + 6c 6e 1d b1 da 8b e1 3b 5c ea 41 db 2f ed 46 70 + 92 e1 ff 39 89 14 c7 14 25 97 75 f5 95 f8 54 7f + 73 56 92 a5 75 e6 92 3a f7 8f 22 c6 99 7d db 90 + fb 6f 72 d7 bb 0d d5 74 4a 31 de cd 3d c3 68 58 + 49 83 6e d3 4a ec 59 63 04 ad 11 84 3c 4f 88 48 + 9f 20 97 35 f5 fb 7f da f7 ce c8 ad dc 58 18 16 + 8f 88 0a cb f4 90 d5 10 05 b7 a8 e8 4e 43 e5 42 + 87 97 75 71 dd 99 ee a4 b1 61 eb 2d f1 f5 10 8f + 12 a4 14 2a 83 32 2e db 05 a7 54 87 a3 43 5c 9a + 78 ce 53 ed 93 bc 55 08 57 d7 a9 fb''', + # Signature + '''02 62 ac 25 4b fa 77 f3 c1 ac a2 2c 51 79 f8 f0 + 40 42 2b 3c 5b af d4 0a 8f 21 cf 0f a5 a6 67 cc + d5 99 3d 42 db af b4 09 c5 20 e2 5f ce 2b 1e e1 + e7 16 57 7f 1e fa 17 f3 da 28 05 2f 40 f0 41 9b + 23 10 6d 78 45 aa f0 11 25 b6 98 e7 a4 df e9 2d + 39 67 bb 00 c4 d0 d3 5b a3 55 2a b9 a8 b3 ee f0 + 7c 7f ec db c5 42 4a c4 db 1e 20 cb 37 d0 b2 74 + 47 69 94 0e a9 07 e1 7f bb ca 67 3b 20 52 23 80 + c5''', + # Salt + '''1d 65 49 1d 79 c8 64 b3 73 00 9b e6 f6 f2 46 7b + ac 4c 78 fa''', + SHA1 + ) + ) + + def testSign1(self): + for i in range(len(self._testData)): + # Build the key + comps = [ long(rws(self._testData[i][0][x]),16) for x in ('n','e','d') ] + key = MyKey(RSA.construct(comps)) + # Hash function + h = self._testData[i][4].new() + # Data to sign + h.update(t2b(self._testData[i][1])) + # Salt + test_salt = t2b(self._testData[i][3]) + key._randfunc = lambda N: test_salt + # The real test + signer = PKCS.new(key) + self.failUnless(signer.can_sign()) + s = signer.sign(h) + self.assertEqual(s, t2b(self._testData[i][2])) + + def testVerify1(self): + for i in range(len(self._testData)): + # Build the key + comps = [ long(rws(self._testData[i][0][x]),16) for x in ('n','e') ] + key = MyKey(RSA.construct(comps)) + # Hash function + h = self._testData[i][4].new() + # Data to sign + h.update(t2b(self._testData[i][1])) + # Salt + test_salt = t2b(self._testData[i][3]) + # The real test + key._randfunc = lambda N: test_salt + verifier = PKCS.new(key) + self.failIf(verifier.can_sign()) + result = verifier.verify(h, t2b(self._testData[i][2])) + self.failUnless(result) + + def testSignVerify(self): + h = SHA1.new() + h.update(b('blah blah blah')) + + rng = Random.new().read + key = MyKey(RSA.generate(1024,rng)) + + # Helper function to monitor what's request from MGF + global mgfcalls + def newMGF(seed,maskLen): + global mgfcalls + mgfcalls += 1 + return bchr(0x00)*maskLen + + # Verify that PSS is friendly to all ciphers + for hashmod in (MD2,MD5,SHA1,SHA224,SHA256,SHA384,RIPEMD160): + h = hashmod.new() + h.update(b('blah blah blah')) + + # Verify that sign() asks for as many random bytes + # as the hash output size + key.asked = 0 + signer = PKCS.new(key) + s = signer.sign(h) + self.failUnless(signer.verify(h, s)) + self.assertEqual(key.asked, h.digest_size) + + h = SHA1.new() + h.update(b('blah blah blah')) + + # Verify that sign() uses a different salt length + for sLen in (0,3,21): + key.asked = 0 + signer = PKCS.new(key, saltLen=sLen) + s = signer.sign(h) + self.assertEqual(key.asked, sLen) + self.failUnless(signer.verify(h, s)) + + # Verify that sign() uses the custom MGF + mgfcalls = 0 + signer = PKCS.new(key, newMGF) + s = signer.sign(h) + self.assertEqual(mgfcalls, 1) + self.failUnless(signer.verify(h, s)) + + # Verify that sign() does not call the RNG + # when salt length is 0, even when a new MGF is provided + key.asked = 0 + mgfcalls = 0 + signer = PKCS.new(key, newMGF, 0) + s = signer.sign(h) + self.assertEqual(key.asked,0) + self.assertEqual(mgfcalls, 1) + self.failUnless(signer.verify(h, s)) + +def get_tests(config={}): + tests = [] + tests += list_test_cases(PKCS1_PSS_Tests) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 diff --git a/lib/Crypto/SelfTest/Util/__init__.py b/lib/Crypto/SelfTest/Util/__init__.py new file mode 100644 index 0000000..f404d0b --- /dev/null +++ b/lib/Crypto/SelfTest/Util/__init__.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/__init__.py: Self-test for utility modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test for utility modules""" + +__revision__ = "$Id$" + +import os + +def get_tests(config={}): + tests = [] + if os.name == 'nt': + from Crypto.SelfTest.Util import test_winrandom; tests += test_winrandom.get_tests(config=config) + from Crypto.SelfTest.Util import test_number; tests += test_number.get_tests(config=config) + from Crypto.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config) + from Crypto.SelfTest.Util import test_Padding; tests += test_Padding.get_tests(config=config) + return tests + +if __name__ == '__main__': + import unittest + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Util/test_Counter.py b/lib/Crypto/SelfTest/Util/test_Counter.py new file mode 100644 index 0000000..7dbfc97 --- /dev/null +++ b/lib/Crypto/SelfTest/Util/test_Counter.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_Counter: Self-test for the Crypto.Util.Counter module +# +# Written in 2009 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-tests for Crypto.Util.Counter""" + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +import unittest + +class CounterTests(unittest.TestCase): + def setUp(self): + global Counter + from Crypto.Util import Counter + + def test_BE_shortcut(self): + """Big endian""" + c = Counter.new(128) + c = Counter.new(128, little_endian=False) + + def test_LE_shortcut(self): + """Little endian""" + c = Counter.new(128, little_endian=True) + + def test_BE_no_shortcut(self): + """Big endian, with disable_shortcut""" + # Just testing API backward-compatibility. disable_shortcut is now a no-op. + c = Counter.new(128, disable_shortcut=True) + c = Counter.new(128, little_endian=False, disable_shortcut=True) + + def test_LE_no_shortcut(self): + """Little endian, shortcut disabled""" + # Just testing API backward-compatibility. disable_shortcut is now a no-op. + c = Counter.new(128, little_endian=True, disable_shortcut=True) + + def test_BE_defaults(self): + """128-bit, Big endian, defaults""" + c = Counter.new(128) + self.assertEqual(1, c.next_value()) + self.assertEqual(b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), c()) + self.assertEqual(2, c.next_value()) + self.assertEqual(b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"), c()) + for i in xrange(3, 256): + self.assertEqual(i, c.next_value()) + self.assertEqual(b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")+bchr(i), c()) + self.assertEqual(256, c.next_value()) + self.assertEqual(b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00"), c()) + + def test_LE_defaults(self): + """128-bit, Little endian, defaults""" + c = Counter.new(128, little_endian=True) + self.assertEqual(1, c.next_value()) + self.assertEqual(b("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), c()) + self.assertEqual(2, c.next_value()) + self.assertEqual(b("\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), c()) + for i in xrange(3, 256): + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i)+b("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), c()) + self.assertEqual(256, c.next_value()) + self.assertEqual(b("\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), c()) + + def test_BE8_wraparound(self): + """8-bit, Big endian, wraparound""" + c = Counter.new(8) + for i in xrange(1, 256): + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i), c()) + self.assertRaises(OverflowError, c.next_value) + self.assertRaises(OverflowError, c) + self.assertRaises(OverflowError, c.next_value) + self.assertRaises(OverflowError, c) + + def test_LE8_wraparound(self): + """8-bit, Little endian, wraparound""" + c = Counter.new(8, little_endian=True) + for i in xrange(1, 256): + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i), c()) + self.assertRaises(OverflowError, c.next_value) + self.assertRaises(OverflowError, c) + self.assertRaises(OverflowError, c.next_value) + self.assertRaises(OverflowError, c) + + def test_BE8_wraparound_allowed(self): + """8-bit, Big endian, wraparound with allow_wraparound=True""" + c = Counter.new(8, allow_wraparound=True) + for i in xrange(1, 256): + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i), c()) + self.assertEqual(0, c.next_value()) + self.assertEqual(b("\x00"), c()) + self.assertEqual(1, c.next_value()) + + def test_LE8_wraparound_allowed(self): + """8-bit, Little endian, wraparound with allow_wraparound=True""" + c = Counter.new(8, little_endian=True, allow_wraparound=True) + for i in xrange(1, 256): + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i), c()) + self.assertEqual(0, c.next_value()) + self.assertEqual(b("\x00"), c()) + self.assertEqual(1, c.next_value()) + + def test_BE8_carry(self): + """8-bit, Big endian, carry attribute""" + c = Counter.new(8) + for i in xrange(1, 256): + self.assertEqual(0, c.carry) + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i), c()) + self.assertEqual(1, c.carry) + + def test_LE8_carry(self): + """8-bit, Little endian, carry attribute""" + c = Counter.new(8, little_endian=True) + for i in xrange(1, 256): + self.assertEqual(0, c.carry) + self.assertEqual(i, c.next_value()) + self.assertEqual(bchr(i), c()) + self.assertEqual(1, c.carry) + +def get_tests(config={}): + from Crypto.SelfTest.st_common import list_test_cases + return list_test_cases(CounterTests) + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Util/test_Padding.py b/lib/Crypto/SelfTest/Util/test_Padding.py new file mode 100644 index 0000000..b8a01ab --- /dev/null +++ b/lib/Crypto/SelfTest/Util/test_Padding.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_Padding.py: Self-test for padding functions +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +import unittest +from binascii import unhexlify as uh + +from Crypto.Util.py3compat import * +from Crypto.SelfTest.st_common import list_test_cases +from Crypto.Util.Padding import pad, unpad + +class PKCS7_Tests(unittest.TestCase): + + def test1(self): + padded = pad(b(""), 4) + self.failUnless(padded == uh(b("04040404"))) + padded = pad(b(""), 4, 'pkcs7') + self.failUnless(padded == uh(b("04040404"))) + back = unpad(padded, 4) + self.failUnless(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4) + self.failUnless(padded == uh(b("1234567804040404"))) + back = unpad(padded, 4) + self.failUnless(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4) + self.failUnless(padded == uh(b("12345601"))) + back = unpad(padded, 4) + self.failUnless(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4) + self.failUnless(padded == uh(b("1234567890030303"))) + back = unpad(padded, 4) + self.failUnless(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, pad, uh(b("12")), 4, 'pkcs8') + + def testn2(self): + self.assertRaises(ValueError, unpad, b("\0\0\0"), 4) + + def testn3(self): + self.assertRaises(ValueError, unpad, b("123456\x02"), 4) + self.assertRaises(ValueError, unpad, b("123456\x00"), 4) + self.assertRaises(ValueError, unpad, b("123456\x05\x05\x05\x05\x05"), 4) + +class X923_Tests(unittest.TestCase): + + def test1(self): + padded = pad(b(""), 4, 'x923') + self.failUnless(padded == uh(b("00000004"))) + back = unpad(padded, 4, 'x923') + self.failUnless(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4, 'x923') + self.failUnless(padded == uh(b("1234567800000004"))) + back = unpad(padded, 4, 'x923') + self.failUnless(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4, 'x923') + self.failUnless(padded == uh(b("12345601"))) + back = unpad(padded, 4, 'x923') + self.failUnless(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4, 'x923') + self.failUnless(padded == uh(b("1234567890000003"))) + back = unpad(padded, 4, 'x923') + self.failUnless(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, unpad, b("123456\x02"), 4, 'x923') + self.assertRaises(ValueError, unpad, b("123456\x00"), 4, 'x923') + self.assertRaises(ValueError, unpad, b("123456\x00\x00\x00\x00\x05"), 4, 'x923') + +class ISO7816_Tests(unittest.TestCase): + + def test1(self): + padded = pad(b(""), 4, 'iso7816') + self.failUnless(padded == uh(b("80000000"))) + back = unpad(padded, 4, 'iso7816') + self.failUnless(back == b("")) + + def test2(self): + padded = pad(uh(b("12345678")), 4, 'iso7816') + self.failUnless(padded == uh(b("1234567880000000"))) + back = unpad(padded, 4, 'iso7816') + self.failUnless(back == uh(b("12345678"))) + + def test3(self): + padded = pad(uh(b("123456")), 4, 'iso7816') + self.failUnless(padded == uh(b("12345680"))) + #import pdb; pdb.set_trace() + back = unpad(padded, 4, 'iso7816') + self.failUnless(back == uh(b("123456"))) + + def test4(self): + padded = pad(uh(b("1234567890")), 4, 'iso7816') + self.failUnless(padded == uh(b("1234567890800000"))) + back = unpad(padded, 4, 'iso7816') + self.failUnless(back == uh(b("1234567890"))) + + def testn1(self): + self.assertRaises(ValueError, unpad, b("123456\x81"), 4, 'iso7816') + +def get_tests(config={}): + tests = [] + tests += list_test_cases(PKCS7_Tests) + tests += list_test_cases(X923_Tests) + tests += list_test_cases(ISO7816_Tests) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + diff --git a/lib/Crypto/SelfTest/Util/test_asn1.py b/lib/Crypto/SelfTest/Util/test_asn1.py new file mode 100644 index 0000000..e40a46f --- /dev/null +++ b/lib/Crypto/SelfTest/Util/test_asn1.py @@ -0,0 +1,657 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_asn.py: Self-test for the Crypto.Util.asn1 module +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-tests for Crypto.Util.asn1""" + +__revision__ = "$Id$" + +import unittest +import sys + +from Crypto.Util.py3compat import * +from Crypto.Util.asn1 import DerObject, DerSetOf, newDerSetOf, DerInteger,\ + DerBitString, newDerBitString, newDerObjectId,\ + DerObjectId, DerNull, DerOctetString,\ + newDerOctetString, DerSequence, newDerSequence,\ + newDerInteger +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +class DerObjectTests(unittest.TestCase): + + def testObjInit1(self): + # Fail with invalid tag format (must be 1 byte) + self.assertRaises(ValueError, DerObject, b('\x00\x99')) + # Fail with invalid implicit tag (must be <0x1F) + self.assertRaises(ValueError, DerObject, 0x1F) + + # ------ + + def testObjEncode1(self): + # No payload + der = DerObject(b('\x02')) + self.assertEquals(der.encode(), b('\x02\x00')) + # Small payload (primitive) + der.payload = b('\x45') + self.assertEquals(der.encode(), b('\x02\x01\x45')) + # Invariant + self.assertEquals(der.encode(), b('\x02\x01\x45')) + # Initialize with numerical tag + der = DerObject(0x04) + der.payload = b('\x45') + self.assertEquals(der.encode(), b('\x04\x01\x45')) + # Initialize with constructed type + der = DerObject(b('\x10'), constructed=True) + self.assertEquals(der.encode(), b('\x30\x00')) + + def testObjEncode2(self): + # Initialize with payload + der = DerObject(0x03, b('\x12\x12')) + self.assertEquals(der.encode(), b('\x03\x02\x12\x12')) + + def testObjEncode3(self): + # Long payload + der = DerObject(b('\x10')) + der.payload = b("0")*128 + self.assertEquals(der.encode(), b('\x10\x81\x80' + "0"*128)) + + def testObjEncode4(self): + # Implicit tags (constructed) + der = DerObject(0x10, implicit=1, constructed=True) + der.payload = b('ppll') + self.assertEquals(der.encode(), b('\xa1\x04ppll')) + # Implicit tags (primitive) + der = DerObject(0x02, implicit=0x1E, constructed=False) + der.payload = b('ppll') + self.assertEquals(der.encode(), b('\x9E\x04ppll')) + + # ----- + + def testObjDecode1(self): + # Decode short payload + der = DerObject(0x02) + der.decode(b('\x02\x02\x01\x02')) + self.assertEquals(der.payload, b("\x01\x02")) + self.assertEquals(der._idOctet, 0x02) + + def testObjDecode2(self): + # Decode long payload + der = DerObject(0x02) + der.decode(b('\x02\x81\x80' + "1"*128)) + self.assertEquals(der.payload, b("1")*128) + self.assertEquals(der._idOctet, 0x02) + + def testObjDecode3(self): + # Decode payload with too much data gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02\xFF')) + # Decode payload with too little data gives error + der = DerObject(0x02) + self.assertRaises(EOFError, der.decode, b('\x02\x02\x01')) + + def testObjDecode4(self): + # Decode implicit tag (primitive) + der = DerObject(0x02, constructed=False, implicit=0xF) + self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) + der.decode(b('\x8F\x01\x00')) + self.assertEquals(der.payload, b('\x00')) + # Decode implicit tag (constructed) + der = DerObject(0x02, constructed=True, implicit=0xF) + self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) + der.decode(b('\xAF\x01\x00')) + self.assertEquals(der.payload, b('\x00')) + + def testObjDecode5(self): + # Decode payload with unexpected tag gives error + der = DerObject(0x02) + self.assertRaises(ValueError, der.decode, b('\x03\x02\x01\x02')) + + def testObjDecode6(self): + # Arbitrary DER object + der = DerObject() + der.decode(b('\x65\x01\x88')) + self.assertEquals(der._idOctet, 0x65) + self.assertEquals(der.payload, b('\x88')) + +class DerIntegerTests(unittest.TestCase): + + def testInit1(self): + der = newDerInteger(1) + self.assertEquals(der.encode(), b('\x02\x01\x01')) + + def testEncode1(self): + # Single-byte integers + # Value 0 + der = DerInteger(0) + self.assertEquals(der.encode(), b('\x02\x01\x00')) + # Value 1 + der = DerInteger(1) + self.assertEquals(der.encode(), b('\x02\x01\x01')) + # Value 127 + der = DerInteger(127) + self.assertEquals(der.encode(), b('\x02\x01\x7F')) + + def testEncode2(self): + # Multi-byte integers + # Value 128 + der = DerInteger(128) + self.assertEquals(der.encode(), b('\x02\x02\x00\x80')) + # Value 0x180 + der = DerInteger(0x180L) + self.assertEquals(der.encode(), b('\x02\x02\x01\x80')) + # One very long integer + der = DerInteger(2L**2048) + self.assertEquals(der.encode(), + b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) + + def testEncode3(self): + # Negative integers + # Value -1 + der = DerInteger(-1) + self.assertEquals(der.encode(), b('\x02\x01\xFF')) + # Value -128 + der = DerInteger(-128) + self.assertEquals(der.encode(), b('\x02\x01\x80')) + # Value + der = DerInteger(-87873) + self.assertEquals(der.encode(), b('\x02\x03\xFE\xA8\xBF')) + + # ----- + + def testDecode1(self): + # Single-byte integer + der = DerInteger() + # Value 0 + der.decode(b('\x02\x01\x00')) + self.assertEquals(der.value, 0) + # Value 1 + der.decode(b('\x02\x01\x01')) + self.assertEquals(der.value, 1) + # Value 127 + der.decode(b('\x02\x01\x7F')) + self.assertEquals(der.value, 127) + + def testDecode2(self): + # Multi-byte integer + der = DerInteger() + # Value 0x180L + der.decode(b('\x02\x02\x01\x80')) + self.assertEquals(der.value,0x180L) + # One very long integer + der.decode( + b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) + self.assertEquals(der.value,2L**2048) + + def testDecode3(self): + # Negative integer + der = DerInteger() + # Value -1 + der.decode(b('\x02\x01\xFF')) + self.assertEquals(der.value, -1) + # Value -32768 + der.decode(b('\x02\x02\x80\x00')) + self.assertEquals(der.value, -32768) + + def testDecode5(self): + # We still accept BER integer format + der = DerInteger() + # Redundant leading zeroes + der.decode(b('\x02\x02\x00\x01')) + self.assertEquals(der.value, 1) + # Redundant leading 0xFF + der.decode(b('\x02\x02\xFF\xFF')) + self.assertEquals(der.value, -1) + # Empty payload + der.decode(b('\x02\x00')) + self.assertEquals(der.value, 0) + + def testErrDecode1(self): + # Wide length field + der = DerInteger() + self.assertRaises(ValueError, der.decode, b('\x02\x81\x01\x01')) + +class DerSequenceTests(unittest.TestCase): + + def testInit1(self): + der = newDerSequence(1, DerInteger(2), '0\x00') + self.assertEquals(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00')) + + def testEncode1(self): + # Empty sequence + der = DerSequence() + self.assertEquals(der.encode(), b('0\x00')) + self.failIf(der.hasOnlyInts()) + # One single-byte integer (zero) + der.append(0) + self.assertEquals(der.encode(), b('0\x03\x02\x01\x00')) + self.assertEquals(der.hasInts(),1) + self.assertEquals(der.hasInts(False),1) + self.failUnless(der.hasOnlyInts()) + self.failUnless(der.hasOnlyInts(False)) + # Invariant + self.assertEquals(der.encode(), b('0\x03\x02\x01\x00')) + + def testEncode2(self): + # Indexing + der = DerSequence() + der.append(0) + der[0] = 1 + self.assertEquals(len(der),1) + self.assertEquals(der[0],1) + self.assertEquals(der[-1],1) + self.assertEquals(der.encode(), b('0\x03\x02\x01\x01')) + # + der[:] = [1] + self.assertEquals(len(der),1) + self.assertEquals(der[0],1) + self.assertEquals(der.encode(), b('0\x03\x02\x01\x01')) + + def testEncode3(self): + # One multi-byte integer (non-zero) + der = DerSequence() + der.append(0x180L) + self.assertEquals(der.encode(), b('0\x04\x02\x02\x01\x80')) + + def testEncode4(self): + # One very long integer + der = DerSequence() + der.append(2L**2048) + self.assertEquals(der.encode(), b('0\x82\x01\x05')+ + b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) + + def testEncode5(self): + der = DerSequence() + der += 1 + der += b('\x30\x00') + self.assertEquals(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00')) + + def testEncode6(self): + # Two positive integers + der = DerSequence() + der.append(0x180L) + der.append(0xFFL) + self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) + self.failUnless(der.hasOnlyInts()) + self.failUnless(der.hasOnlyInts(False)) + # Two mixed integers + der = DerSequence() + der.append(2) + der.append(-2) + self.assertEquals(der.encode(), b('0\x06\x02\x01\x02\x02\x01\xFE')) + self.assertEquals(der.hasInts(), 1) + self.assertEquals(der.hasInts(False), 2) + self.failIf(der.hasOnlyInts()) + self.failUnless(der.hasOnlyInts(False)) + # + der.append(0x01) + der[1:] = [9,8] + self.assertEquals(len(der),3) + self.assertEqual(der[1:],[9,8]) + self.assertEqual(der[1:-1],[9]) + self.assertEquals(der.encode(), b('0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08')) + + def testEncode7(self): + # One integer and another type (no matter what it is) + der = DerSequence() + der.append(0x180L) + der.append(b('\x00\x02\x00\x00')) + self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x00\x02\x00\x00')) + self.failIf(der.hasOnlyInts()) + + #### + + def testDecode1(self): + # Empty sequence + der = DerSequence() + der.decode(b('0\x00')) + self.assertEquals(len(der),0) + # One single-byte integer (zero) + der.decode(b('0\x03\x02\x01\x00')) + self.assertEquals(len(der),1) + self.assertEquals(der[0],0) + # Invariant + der.decode(b('0\x03\x02\x01\x00')) + self.assertEquals(len(der),1) + self.assertEquals(der[0],0) + + def testDecode2(self): + # One single-byte integer (non-zero) + der = DerSequence() + der.decode(b('0\x03\x02\x01\x7f')) + self.assertEquals(len(der),1) + self.assertEquals(der[0],127) + + def testDecode4(self): + # One very long integer + der = DerSequence() + der.decode(b('0\x82\x01\x05')+ + b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ + b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) + self.assertEquals(len(der),1) + self.assertEquals(der[0],2L**2048) + + def testDecode6(self): + # Two integers + der = DerSequence() + der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) + self.assertEquals(len(der),2) + self.assertEquals(der[0],0x180L) + self.assertEquals(der[1],0xFFL) + + def testDecode7(self): + # One integer and 2 other types + der = DerSequence() + der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) + self.assertEquals(len(der),3) + self.assertEquals(der[0],0x180L) + self.assertEquals(der[1],b('\x24\x02\xb6\x63')) + self.assertEquals(der[2],b('\x12\x00')) + + def testDecode8(self): + # Only 2 other types + der = DerSequence() + der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')) + self.assertEquals(len(der),2) + self.assertEquals(der[0],b('\x24\x02\xb6\x63')) + self.assertEquals(der[1],b('\x12\x00')) + self.assertEquals(der.hasInts(), 0) + self.assertEquals(der.hasInts(False), 0) + self.failIf(der.hasOnlyInts()) + self.failIf(der.hasOnlyInts(False)) + + def testErrDecode1(self): + # Not a sequence + der = DerSequence() + self.assertRaises(EOFError, der.decode, b('')) + self.assertRaises(ValueError, der.decode, b('\x00')) + self.assertRaises(EOFError, der.decode, b('\x30')) + + def testErrDecode2(self): + der = DerSequence() + # Too much data + self.assertRaises(ValueError, der.decode, b('\x30\x00\x00')) + + def testErrDecode3(self): + # Wrong length format + der = DerSequence() + # Missing length in sub-item + self.assertRaises(EOFError, der.decode, b('\x30\x04\x02\x01\x01\x00')) + # Valid BER, but invalid DER length + self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01')) + self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01')) + +class DerOctetStringTests(unittest.TestCase): + + def testInit1(self): + der = newDerOctetString(b('\xFF')) + self.assertEquals(der.encode(), b('\x04\x01\xFF')) + + def testEncode1(self): + # Empty sequence + der = DerOctetString() + self.assertEquals(der.encode(), b('\x04\x00')) + # Small payload + der.payload = b('\x01\x02') + self.assertEquals(der.encode(), b('\x04\x02\x01\x02')) + + #### + + def testDecode1(self): + # Empty sequence + der = DerOctetString() + der.decode(b('\x04\x00')) + self.assertEquals(der.payload, b('')) + # Small payload + der.decode(b('\x04\x02\x01\x02')) + self.assertEquals(der.payload, b('\x01\x02')) + + def testErrDecode1(self): + # No leftovers allowed + der = DerOctetString() + self.assertRaises(ValueError, der.decode, b('\x04\x01\x01\xff')) + +class DerNullTests(unittest.TestCase): + + def testEncode1(self): + der = DerNull() + self.assertEquals(der.encode(), b('\x05\x00')) + + #### + + def testDecode1(self): + # Empty sequence + der = DerNull() + der.decode(b('\x05\x00')) + +class DerObjectIdTests(unittest.TestCase): + + def testInit1(self): + der = newDerObjectId("1.1") + self.assertEquals(der.encode(), b('\x06\x01)')) + + def testEncode1(self): + der = DerObjectId('1.2.840.113549.1.1.1') + self.assertEquals(der.encode(), b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) + # + der = DerObjectId() + der.value = '1.2.840.113549.1.1.1' + self.assertEquals(der.encode(), b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) + + #### + + def testDecode1(self): + # Empty sequence + der = DerObjectId() + der.decode(b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) + self.assertEquals(der.value, '1.2.840.113549.1.1.1') + +class DerBitStringTests(unittest.TestCase): + + def testInit1(self): + der = newDerBitString(b("\xFF")) + self.assertEquals(der.encode(), b('\x03\x02\x00\xFF')) + + def testEncode1(self): + # Empty sequence + der = DerBitString() + self.assertEquals(der.encode(), b('\x03\x01\x00')) + # Small payload + der = DerBitString(b('\x01\x02')) + self.assertEquals(der.encode(), b('\x03\x03\x00\x01\x02')) + # Small payload + der = DerBitString() + der.value = b('\x01\x02') + self.assertEquals(der.encode(), b('\x03\x03\x00\x01\x02')) + + #### + + def testDecode1(self): + # Empty sequence + der = DerBitString() + der.decode(b('\x03\x00')) + self.assertEquals(der.value, b('')) + # Small payload + der.decode(b('\x03\x03\x00\x01\x02')) + self.assertEquals(der.value, b('\x01\x02')) + +class DerSetOfTests(unittest.TestCase): + + def testInit1(self): + der = newDerSetOf(DerInteger(1), DerInteger(2)) + self.assertEquals(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02')) + + def testEncode1(self): + # Empty set + der = DerSetOf() + self.assertEquals(der.encode(), b('1\x00')) + # One single-byte integer (zero) + der.add(0) + self.assertEquals(der.encode(), b('1\x03\x02\x01\x00')) + # Invariant + self.assertEquals(der.encode(), b('1\x03\x02\x01\x00')) + + def testEncode2(self): + # Two integers + der = DerSetOf() + der.add(0x180L) + der.add(0xFFL) + self.assertEquals(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) + # Initialize with integers + der = DerSetOf([0x180L, 0xFFL]) + self.assertEquals(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) + + def testEncode3(self): + # One integer and another type (no matter what it is) + der = DerSetOf() + der.add(0x180L) + self.assertRaises(ValueError, der.add, b('\x00\x02\x00\x00')) + + def testEncode4(self): + # Only non integers + der = DerSetOf() + der.add(b('\x01\x00')) + der.add(b('\x01\x01\x01')) + self.assertEquals(der.encode(), b('1\x05\x01\x00\x01\x01\x01')) + + #### + + def testDecode1(self): + # Empty sequence + der = DerSetOf() + der.decode(b('1\x00')) + self.assertEquals(len(der),0) + # One single-byte integer (zero) + der.decode(b('1\x03\x02\x01\x00')) + self.assertEquals(len(der),1) + self.assertEquals(list(der),[0]) + + def testDecode2(self): + # Two integers + der = DerSetOf() + der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff')) + self.assertEquals(len(der),2) + l = list(der) + self.failUnless(0x180 in l) + self.failUnless(0xFF in l) + + def testDecode3(self): + # One integer and 2 other types + der = DerSetOf() + #import pdb; pdb.set_trace() + self.assertRaises(ValueError, der.decode, + b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) + + def testErrDecode1(self): + # No leftovers allowed + der = DerSetOf() + self.assertRaises(ValueError, der.decode, + b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xAA')) + +def get_tests(config={}): + from Crypto.SelfTest.st_common import list_test_cases + listTests = [] + listTests += list_test_cases(DerObjectTests) + listTests += list_test_cases(DerIntegerTests) + listTests += list_test_cases(DerSequenceTests) + listTests += list_test_cases(DerOctetStringTests) + listTests += list_test_cases(DerNullTests) + listTests += list_test_cases(DerObjectIdTests) + listTests += list_test_cases(DerBitStringTests) + listTests += list_test_cases(DerSetOfTests) + return listTests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Util/test_number.py b/lib/Crypto/SelfTest/Util/test_number.py new file mode 100644 index 0000000..ac23e91 --- /dev/null +++ b/lib/Crypto/SelfTest/Util/test_number.py @@ -0,0 +1,338 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_number.py: Self-test for parts of the Crypto.Util.number module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-tests for (some of) Crypto.Util.number""" + +__revision__ = "$Id$" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +import unittest +from Crypto.SelfTest.st_common import assert_disabled + +class MyError(Exception): + """Dummy exception used for tests""" + +# NB: In some places, we compare tuples instead of just output values so that +# if any inputs cause a test failure, we'll be able to tell which ones. + +class MiscTests(unittest.TestCase): + def setUp(self): + global number, math + from Crypto.Util import number + import math + + def test_ceil_shift(self): + """Util.number.ceil_shift""" + if not assert_disabled(): + self.assertRaises(AssertionError, number.ceil_shift, -1, 1) + self.assertRaises(AssertionError, number.ceil_shift, 1, -1) + + # b = 0 + self.assertEqual(0, number.ceil_shift(0, 0)) + self.assertEqual(1, number.ceil_shift(1, 0)) + self.assertEqual(2, number.ceil_shift(2, 0)) + self.assertEqual(3, number.ceil_shift(3, 0)) + + # b = 1 + self.assertEqual(0, number.ceil_shift(0, 1)) + self.assertEqual(1, number.ceil_shift(1, 1)) + self.assertEqual(1, number.ceil_shift(2, 1)) + self.assertEqual(2, number.ceil_shift(3, 1)) + + # b = 2 + self.assertEqual(0, number.ceil_shift(0, 2)) + self.assertEqual(1, number.ceil_shift(1, 2)) + self.assertEqual(1, number.ceil_shift(2, 2)) + self.assertEqual(1, number.ceil_shift(3, 2)) + self.assertEqual(1, number.ceil_shift(4, 2)) + self.assertEqual(2, number.ceil_shift(5, 2)) + self.assertEqual(2, number.ceil_shift(6, 2)) + self.assertEqual(2, number.ceil_shift(7, 2)) + self.assertEqual(2, number.ceil_shift(8, 2)) + self.assertEqual(3, number.ceil_shift(9, 2)) + + for b in range(3, 1+129, 3): # 3, 6, ... , 129 + self.assertEqual(0, number.ceil_shift(0, b)) + + n = 1L + while n <= 2L**(b+2): + (q, r) = divmod(n-1, 2L**b) + expected = q + int(not not r) + self.assertEqual((n-1, b, expected), + (n-1, b, number.ceil_shift(n-1, b))) + + (q, r) = divmod(n, 2L**b) + expected = q + int(not not r) + self.assertEqual((n, b, expected), + (n, b, number.ceil_shift(n, b))) + + (q, r) = divmod(n+1, 2L**b) + expected = q + int(not not r) + self.assertEqual((n+1, b, expected), + (n+1, b, number.ceil_shift(n+1, b))) + + n *= 2 + + def test_ceil_div(self): + """Util.number.ceil_div""" + self.assertRaises(TypeError, number.ceil_div, "1", 1) + self.assertRaises(ZeroDivisionError, number.ceil_div, 1, 0) + self.assertRaises(ZeroDivisionError, number.ceil_div, -1, 0) + + # b = -1 + self.assertEqual(0, number.ceil_div(0, -1)) + self.assertEqual(-1, number.ceil_div(1, -1)) + self.assertEqual(-2, number.ceil_div(2, -1)) + self.assertEqual(-3, number.ceil_div(3, -1)) + + # b = 1 + self.assertEqual(0, number.ceil_div(0, 1)) + self.assertEqual(1, number.ceil_div(1, 1)) + self.assertEqual(2, number.ceil_div(2, 1)) + self.assertEqual(3, number.ceil_div(3, 1)) + + # b = 2 + self.assertEqual(0, number.ceil_div(0, 2)) + self.assertEqual(1, number.ceil_div(1, 2)) + self.assertEqual(1, number.ceil_div(2, 2)) + self.assertEqual(2, number.ceil_div(3, 2)) + self.assertEqual(2, number.ceil_div(4, 2)) + self.assertEqual(3, number.ceil_div(5, 2)) + + # b = 3 + self.assertEqual(0, number.ceil_div(0, 3)) + self.assertEqual(1, number.ceil_div(1, 3)) + self.assertEqual(1, number.ceil_div(2, 3)) + self.assertEqual(1, number.ceil_div(3, 3)) + self.assertEqual(2, number.ceil_div(4, 3)) + self.assertEqual(2, number.ceil_div(5, 3)) + self.assertEqual(2, number.ceil_div(6, 3)) + self.assertEqual(3, number.ceil_div(7, 3)) + + # b = 4 + self.assertEqual(0, number.ceil_div(0, 4)) + self.assertEqual(1, number.ceil_div(1, 4)) + self.assertEqual(1, number.ceil_div(2, 4)) + self.assertEqual(1, number.ceil_div(3, 4)) + self.assertEqual(1, number.ceil_div(4, 4)) + self.assertEqual(2, number.ceil_div(5, 4)) + self.assertEqual(2, number.ceil_div(6, 4)) + self.assertEqual(2, number.ceil_div(7, 4)) + self.assertEqual(2, number.ceil_div(8, 4)) + self.assertEqual(3, number.ceil_div(9, 4)) + + # b = -4 + self.assertEqual(3, number.ceil_div(-9, -4)) + self.assertEqual(2, number.ceil_div(-8, -4)) + self.assertEqual(2, number.ceil_div(-7, -4)) + self.assertEqual(2, number.ceil_div(-6, -4)) + self.assertEqual(2, number.ceil_div(-5, -4)) + self.assertEqual(1, number.ceil_div(-4, -4)) + self.assertEqual(1, number.ceil_div(-3, -4)) + self.assertEqual(1, number.ceil_div(-2, -4)) + self.assertEqual(1, number.ceil_div(-1, -4)) + self.assertEqual(0, number.ceil_div(0, -4)) + self.assertEqual(0, number.ceil_div(1, -4)) + self.assertEqual(0, number.ceil_div(2, -4)) + self.assertEqual(0, number.ceil_div(3, -4)) + self.assertEqual(-1, number.ceil_div(4, -4)) + self.assertEqual(-1, number.ceil_div(5, -4)) + self.assertEqual(-1, number.ceil_div(6, -4)) + self.assertEqual(-1, number.ceil_div(7, -4)) + self.assertEqual(-2, number.ceil_div(8, -4)) + self.assertEqual(-2, number.ceil_div(9, -4)) + + def test_exact_log2(self): + """Util.number.exact_log2""" + self.assertRaises(TypeError, number.exact_log2, "0") + self.assertRaises(ValueError, number.exact_log2, -1) + self.assertRaises(ValueError, number.exact_log2, 0) + self.assertEqual(0, number.exact_log2(1)) + self.assertEqual(1, number.exact_log2(2)) + self.assertRaises(ValueError, number.exact_log2, 3) + self.assertEqual(2, number.exact_log2(4)) + self.assertRaises(ValueError, number.exact_log2, 5) + self.assertRaises(ValueError, number.exact_log2, 6) + self.assertRaises(ValueError, number.exact_log2, 7) + e = 3 + n = 8 + while e < 16: + if n == 2**e: + self.assertEqual(e, number.exact_log2(n), "expected=2**%d, n=%d" % (e, n)) + e += 1 + else: + self.assertRaises(ValueError, number.exact_log2, n) + n += 1 + + for e in range(16, 1+64, 2): + self.assertRaises(ValueError, number.exact_log2, 2L**e-1) + self.assertEqual(e, number.exact_log2(2L**e)) + self.assertRaises(ValueError, number.exact_log2, 2L**e+1) + + def test_exact_div(self): + """Util.number.exact_div""" + + # Positive numbers + self.assertEqual(1, number.exact_div(1, 1)) + self.assertRaises(ValueError, number.exact_div, 1, 2) + self.assertEqual(1, number.exact_div(2, 2)) + self.assertRaises(ValueError, number.exact_div, 3, 2) + self.assertEqual(2, number.exact_div(4, 2)) + + # Negative numbers + self.assertEqual(-1, number.exact_div(-1, 1)) + self.assertEqual(-1, number.exact_div(1, -1)) + self.assertRaises(ValueError, number.exact_div, -1, 2) + self.assertEqual(1, number.exact_div(-2, -2)) + self.assertEqual(-2, number.exact_div(-4, 2)) + + # Zero dividend + self.assertEqual(0, number.exact_div(0, 1)) + self.assertEqual(0, number.exact_div(0, 2)) + + # Zero divisor (allow_divzero == False) + self.assertRaises(ZeroDivisionError, number.exact_div, 0, 0) + self.assertRaises(ZeroDivisionError, number.exact_div, 1, 0) + + # Zero divisor (allow_divzero == True) + self.assertEqual(0, number.exact_div(0, 0, allow_divzero=True)) + self.assertRaises(ValueError, number.exact_div, 1, 0, allow_divzero=True) + + def test_floor_div(self): + """Util.number.floor_div""" + self.assertRaises(TypeError, number.floor_div, "1", 1) + for a in range(-10, 10): + for b in range(-10, 10): + if b == 0: + self.assertRaises(ZeroDivisionError, number.floor_div, a, b) + else: + self.assertEqual((a, b, int(math.floor(float(a) / b))), + (a, b, number.floor_div(a, b))) + + def test_getStrongPrime(self): + """Util.number.getStrongPrime""" + self.assertRaises(ValueError, number.getStrongPrime, 256) + self.assertRaises(ValueError, number.getStrongPrime, 513) + bits = 512 + x = number.getStrongPrime(bits) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1L << bits-1)-1, 1) + self.assertEqual(x < (1L << bits), 1) + e = 2**16+1 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD(x-1, e), 1) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1L << bits-1)-1, 1) + self.assertEqual(x < (1L << bits), 1) + e = 2**16+2 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD((x-1)>>1, e), 1) + self.assertNotEqual(x % 2, 0) + self.assertEqual(x > (1L << bits-1)-1, 1) + self.assertEqual(x < (1L << bits), 1) + + def test_isPrime(self): + """Util.number.isPrime""" + self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime + self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime + self.assertEqual(number.isPrime(1), False) # Regression test: isPrime(1) caused some versions of PyCrypto to crash. + self.assertEqual(number.isPrime(2), True) + self.assertEqual(number.isPrime(3), True) + self.assertEqual(number.isPrime(4), False) + self.assertEqual(number.isPrime(2L**1279-1), True) + self.assertEqual(number.isPrime(-(2L**1279-1)), False) # Regression test: negative numbers should not be prime + # test some known gmp pseudo-primes taken from + # http://www.trnicely.net/misc/mpzspsp.html + for composite in (43 * 127 * 211, 61 * 151 * 211, 15259 * 30517, + 346141L * 692281L, 1007119L * 2014237L, 3589477L * 7178953L, + 4859419L * 9718837L, 2730439L * 5460877L, + 245127919L * 490255837L, 963939391L * 1927878781L, + 4186358431L * 8372716861L, 1576820467L * 3153640933L): + self.assertEqual(number.isPrime(long(composite)), False) + + def test_size(self): + self.assertEqual(number.size(2),2) + self.assertEqual(number.size(3),2) + self.assertEqual(number.size(0xa2),8) + self.assertEqual(number.size(0xa2ba40),8*3) + self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5L), 1024) + +class FastmathTests(unittest.TestCase): + def setUp(self): + global number + from Crypto.Util import number + + def test_negative_number_roundtrip_mpzToLongObj_longObjToMPZ(self): + """Test that mpzToLongObj and longObjToMPZ (internal functions) roundtrip negative numbers correctly.""" + n = -100000000000000000000000000000000000L + e = 2L + k = number._fastmath.rsa_construct(n, e) + self.assertEqual(n, k.n) + self.assertEqual(e, k.e) + + def test_isPrime_randfunc_exception(self): + """Test that when isPrime is called, an exception raised in randfunc is propagated.""" + def randfunc(n): + raise MyError + prime = 3536384141L # Needs to be large enough so that rabinMillerTest will be invoked + self.assertRaises(MyError, number._fastmath.isPrime, prime, randfunc=randfunc) + + def test_getStrongPrime_randfunc_exception(self): + """Test that when getStrongPrime is called, an exception raised in randfunc is propagated.""" + def randfunc(n): + raise MyError + self.assertRaises(MyError, number._fastmath.getStrongPrime, 512, randfunc=randfunc) + + def test_isPrime_randfunc_bogus(self): + """Test that when isPrime is called, an exception is raised if randfunc returns something bogus.""" + def randfunc(n): + return None + prime = 3536384141L # Needs to be large enough so that rabinMillerTest will be invoked + self.assertRaises(TypeError, number._fastmath.isPrime, prime, randfunc=randfunc) + + def test_getStrongPrime_randfunc_bogus(self): + """Test that when getStrongPrime is called, an exception is raised if randfunc returns something bogus.""" + def randfunc(n): + return None + self.assertRaises(TypeError, number._fastmath.getStrongPrime, 512, randfunc=randfunc) + +def get_tests(config={}): + from Crypto.SelfTest.st_common import list_test_cases + tests = list_test_cases(MiscTests) + try: + from Crypto.PublicKey import _fastmath + tests += list_test_cases(FastmathTests) + except ImportError: + from Crypto.SelfTest.st_common import handle_fastmath_import_error + handle_fastmath_import_error() + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/Util/test_winrandom.py b/lib/Crypto/SelfTest/Util/test_winrandom.py new file mode 100644 index 0000000..3fc5145 --- /dev/null +++ b/lib/Crypto/SelfTest/Util/test_winrandom.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self-test suite for Crypto.Util.winrandom""" + +__revision__ = "$Id$" + +import unittest + +class WinRandomImportTest(unittest.TestCase): + def runTest(self): + """winrandom: simple test""" + # Import the winrandom module and try to use it + from Crypto.Util import winrandom + randobj = winrandom.new() + x = randobj.get_bytes(16) + y = randobj.get_bytes(16) + self.assertNotEqual(x, y) + +def get_tests(config={}): + return [WinRandomImportTest()] + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/__init__.py b/lib/Crypto/SelfTest/__init__.py new file mode 100644 index 0000000..cb5782f --- /dev/null +++ b/lib/Crypto/SelfTest/__init__.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/__init__.py: Self-test for PyCrypto +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Self tests + +These tests should perform quickly and can ideally be used every time an +application runs. +""" + +__revision__ = "$Id$" + +import sys +import unittest +from StringIO import StringIO + +class SelfTestError(Exception): + def __init__(self, message, result): + Exception.__init__(self, message, result) + self.message = message + self.result = result + +def run(module=None, verbosity=0, stream=None, tests=None, config=None, **kwargs): + """Execute self-tests. + + This raises SelfTestError if any test is unsuccessful. + + You may optionally pass in a sub-module of SelfTest if you only want to + perform some of the tests. For example, the following would test only the + hash modules: + + Crypto.SelfTest.run(Crypto.SelfTest.Hash) + + """ + if config is None: + config = {} + suite = unittest.TestSuite() + if module is None: + if tests is None: + tests = get_tests(config=config) + suite.addTests(tests) + else: + if tests is None: + suite.addTests(module.get_tests(config=config)) + else: + raise ValueError("'module' and 'tests' arguments are mutually exclusive") + if stream is None: + kwargs['stream'] = StringIO() + else: + kwargs['stream'] = stream + runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs) + result = runner.run(suite) + if not result.wasSuccessful(): + if stream is None: + sys.stderr.write(kwargs['stream'].getvalue()) + raise SelfTestError("Self-test failed", result) + return result + +def get_tests(config={}): + tests = [] + from Crypto.SelfTest import Cipher; tests += Cipher.get_tests(config=config) + from Crypto.SelfTest import Hash; tests += Hash.get_tests(config=config) + from Crypto.SelfTest import Protocol; tests += Protocol.get_tests(config=config) + from Crypto.SelfTest import PublicKey; tests += PublicKey.get_tests(config=config) + from Crypto.SelfTest import Random; tests += Random.get_tests(config=config) + from Crypto.SelfTest import Util; tests += Util.get_tests(config=config) + from Crypto.SelfTest import Signature; tests += Signature.get_tests(config=config) + from Crypto.SelfTest import IO; tests += IO.get_tests(config=config) + return tests + +if __name__ == '__main__': + suite = lambda: unittest.TestSuite(get_tests()) + unittest.main(defaultTest='suite') + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/SelfTest/st_common.py b/lib/Crypto/SelfTest/st_common.py new file mode 100644 index 0000000..e76525c --- /dev/null +++ b/lib/Crypto/SelfTest/st_common.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# +# SelfTest/st_common.py: Common functions for SelfTest modules +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Common functions for SelfTest modules""" + +__revision__ = "$Id$" + +import unittest +import binascii +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +class _list_testloader(unittest.TestLoader): + suiteClass = list + +def list_test_cases(class_): + """Return a list of TestCase instances given a TestCase class + + This is useful when you have defined test* methods on your TestCase class. + """ + return _list_testloader().loadTestsFromTestCase(class_) + +def strip_whitespace(s): + """Remove whitespace from a text or byte string""" + if isinstance(s,str): + return b("".join(s.split())) + else: + return b("").join(s.split()) + +def a2b_hex(s): + """Convert hexadecimal to binary, ignoring whitespace""" + return binascii.a2b_hex(strip_whitespace(s)) + +def b2a_hex(s): + """Convert binary to hexadecimal""" + # For completeness + return binascii.b2a_hex(s) + +def handle_fastmath_import_error(): + import Crypto.PublicKey + import imp + try: + file, pathname, description = imp.find_module("_fastmath", Crypto.PublicKey.__path__) + except ImportError: + sys.stderr.write("SelfTest: warning: not testing _fastmath module (not available)\n") + else: + file.close() + raise ImportError("While the _fastmath module exists, importing " + "it failed. This may point to the gmp or mpir shared library " + "not being in the path. _fastmath was found at %s" % (pathname,)) + +def docstrings_disabled(): + """Returns True if docstrings are disabled (e.g. by using python -OO)""" + return docstrings_disabled.__doc__ is None + +def assert_disabled(): + """Returns True if 'assert' is a no-op (e.g. by using python -O)""" + try: + assert False + except AssertionError: + return False + else: + return True + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Signature/PKCS1_PSS.py b/lib/Crypto/Signature/PKCS1_PSS.py new file mode 100644 index 0000000..fb97b21 --- /dev/null +++ b/lib/Crypto/Signature/PKCS1_PSS.py @@ -0,0 +1,368 @@ +# -*- coding: utf-8 -*- +# +# Signature/PKCS1_PSS.py : PKCS#1 PPS +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""RSA digital signature protocol with appendix according to PKCS#1 PSS. + +See RFC3447__ or the `original RSA Labs specification`__. + +This scheme is more properly called ``RSASSA-PSS``. + +For example, a sender may authenticate a message using SHA-1 and PSS like +this: + + >>> from Crypto.Signature import PKCS1_PSS + >>> from Crypto.Hash import SHA1 + >>> from Crypto.PublicKey import RSA1 + >>> from Crypto import Random + >>> + >>> message = 'To be signed' + >>> key = RSA.importKey(open('privkey.der').read()) + >>> h = SHA1.new() + >>> h.update(message) + >>> signer = PKCS1_PSS.new(key) + >>> signature = signer.sign(h) + +At the receiver side, verification can be done like using the public part of +the RSA key: + + >>> key = RSA.importKey(open('pubkey.der').read()) + >>> h = SHA1.new() + >>> h.update(message) + >>> verifier = PKCS1_PSS.new(key) + >>> if verifier.verify(h, signature): + >>> print "The signature is authentic." + >>> else: + >>> print "The signature is not authentic." + +:undocumented: __revision__, __package__ + +.. __: http://www.ietf.org/rfc/rfc3447.txt +.. __: http://www.rsa.com/rsalabs/node.asp?id=2125 +""" + +# Allow nested scopes in Python 2.1 +# See http://oreilly.com/pub/a/python/2001/04/19/pythonnews.html +from __future__ import nested_scopes + +__revision__ = "$Id$" +__all__ = [ 'new', 'PSS_SigScheme' ] + +from Crypto.Util.py3compat import * +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +import Crypto.Util.number +from Crypto.Util.number import ceil_shift, ceil_div, long_to_bytes +from Crypto.Util.strxor import strxor +from Crypto.Hash import new as Hash_new + +class PSS_SigScheme: + """This signature scheme can perform PKCS#1 PSS RSA signature or verification.""" + + def __init__(self, key, mgfunc, saltLen): + """Initialize this PKCS#1 PSS signature scheme object. + + :Parameters: + key : an RSA key object + If a private half is given, both signature and verification are possible. + If a public half is given, only verification is possible. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + saltLen : int + Length of the salt, in bytes. + """ + self._key = key + self._saltLen = saltLen + self._mgfunc = mgfunc + + def can_sign(self): + """Return True if this cipher object can be used for signing messages.""" + return self._key.has_private() + + def sign(self, mhash): + """Produce the PKCS#1 PSS signature of a message. + + This function is named ``RSASSA-PSS-SIGN``, and is specified in + section 8.1.1 of RFC3447. + + :Parameters: + mhash : hash object + The hash that was carried out over the message. This is an object + belonging to the `Crypto.Hash` module. + + :Return: The PSS signature encoded as a string. + :Raise ValueError: + If the RSA key length is not sufficiently long to deal with the given + hash algorithm. + :Raise TypeError: + If the RSA key has no private half. + + :attention: Modify the salt length and the mask generation function only + if you know what you are doing. + The receiver must use the same parameters too. + """ + # TODO: Verify the key is RSA + + randfunc = self._key._randfunc + + # Set defaults for salt length and mask generation function + if self._saltLen == None: + sLen = mhash.digest_size + else: + sLen = self._saltLen + if self._mgfunc: + mgf = self._mgfunc + else: + mgf = lambda x,y: MGF1(x,y,mhash) + + modBits = Crypto.Util.number.size(self._key.n) + + # See 8.1.1 in RFC3447 + k = ceil_div(modBits,8) # Convert from bits to bytes + # Step 1 + em = EMSA_PSS_ENCODE(mhash, modBits-1, randfunc, mgf, sLen) + # Step 2a (OS2IP) and 2b (RSASP1) + m = self._key.decrypt(em) + # Step 2c (I2OSP) + S = bchr(0x00)*(k-len(m)) + m + return S + + def verify(self, mhash, S): + """Verify that a certain PKCS#1 PSS signature is authentic. + + This function checks if the party holding the private half of the given + RSA key has really signed the message. + + This function is called ``RSASSA-PSS-VERIFY``, and is specified in section + 8.1.2 of RFC3447. + + :Parameters: + mhash : hash object + The hash that was carried out over the message. This is an object + belonging to the `Crypto.Hash` module. + S : string + The signature that needs to be validated. + + :Return: True if verification is correct. False otherwise. + """ + # TODO: Verify the key is RSA + + # Set defaults for salt length and mask generation function + if self._saltLen == None: + sLen = mhash.digest_size + else: + sLen = self._saltLen + if self._mgfunc: + mgf = self._mgfunc + else: + mgf = lambda x,y: MGF1(x,y,mhash) + + modBits = Crypto.Util.number.size(self._key.n) + + # See 8.1.2 in RFC3447 + k = ceil_div(modBits,8) # Convert from bits to bytes + # Step 1 + if len(S) != k: + return False + # Step 2a (O2SIP), 2b (RSAVP1), and partially 2c (I2OSP) + # Note that signature must be smaller than the module + # but RSA.py won't complain about it. + # TODO: Fix RSA object; don't do it here. + em = self._key.encrypt(S, 0)[0] + # Step 2c + emLen = ceil_div(modBits-1,8) + em = bchr(0x00)*(emLen-len(em)) + em + # Step 3 + try: + result = EMSA_PSS_VERIFY(mhash, em, modBits-1, mgf, sLen) + except ValueError: + return False + # Step 4 + return result + +def MGF1(mgfSeed, maskLen, hash): + """Mask Generation Function, described in B.2.1""" + T = b("") + for counter in xrange(ceil_div(maskLen, hash.digest_size)): + c = long_to_bytes(counter, 4) + try: + T = T + hash.new(mgfSeed + c).digest() + except AttributeError: + # hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it + T = T + Hash_new(hash, mgfSeed + c).digest() + assert(len(T)>=maskLen) + return T[:maskLen] + +def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): + """ + Implement the ``EMSA-PSS-ENCODE`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.1.1). + + The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input, + and hash it internally. Here, we expect that the message has already + been hashed instead. + + :Parameters: + mhash : hash object + The hash object that holds the digest of the message being signed. + emBits : int + Maximum length of the final encoding, in bits. + randFunc : callable + An RNG function that accepts as only parameter an int, and returns + a string of random bytes, to be used as salt. + mgf : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + sLen : int + Length of the salt, in bytes. + + :Return: An ``emLen`` byte long string that encodes the hash + (with ``emLen = \ceil(emBits/8)``). + + :Raise ValueError: + When digest or salt length are too big. + """ + + emLen = ceil_div(emBits,8) + + # Bitmask of digits that fill up + lmask = 0 + for i in xrange(8*emLen-emBits): + lmask = lmask>>1 | 0x80 + + # Step 1 and 2 have been already done + # Step 3 + if emLen < mhash.digest_size+sLen+2: + raise ValueError("Digest or salt length are too long for given key size.") + # Step 4 + salt = b("") + if randFunc and sLen>0: + salt = randFunc(sLen) + # Step 5 and 6 + try: + h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt) + except AttributeError: + # hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it + h = Hash_new(mhash, bchr(0x00)*8 + mhash.digest() + salt) + # Step 7 and 8 + db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + salt + # Step 9 + dbMask = mgf(h.digest(), emLen-mhash.digest_size-1) + # Step 10 + maskedDB = strxor(db,dbMask) + # Step 11 + maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] + # Step 12 + em = maskedDB + h.digest() + bchr(0xBC) + return em + +def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): + """ + Implement the ``EMSA-PSS-VERIFY`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.1.2). + + ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, + and hash it internally. Here, we expect that the message has already + been hashed instead. + + :Parameters: + mhash : hash object + The hash object that holds the digest of the message to be verified. + em : string + The signature to verify, therefore proving that the sender really signed + the message that was received. + emBits : int + Length of the final encoding (em), in bits. + mgf : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + sLen : int + Length of the salt, in bytes. + + :Return: 0 if the encoding is consistent, 1 if it is inconsistent. + + :Raise ValueError: + When digest or salt length are too big. + """ + + emLen = ceil_div(emBits,8) + + # Bitmask of digits that fill up + lmask = 0 + for i in xrange(8*emLen-emBits): + lmask = lmask>>1 | 0x80 + + # Step 1 and 2 have been already done + # Step 3 + if emLen < mhash.digest_size+sLen+2: + return False + # Step 4 + if ord(em[-1:])!=0xBC: + return False + # Step 5 + maskedDB = em[:emLen-mhash.digest_size-1] + h = em[emLen-mhash.digest_size-1:-1] + # Step 6 + if lmask & bord(em[0]): + return False + # Step 7 + dbMask = mgf(h, emLen-mhash.digest_size-1) + # Step 8 + db = strxor(maskedDB, dbMask) + # Step 9 + db = bchr(bord(db[0]) & ~lmask) + db[1:] + # Step 10 + if not db.startswith(bchr(0x00)*(emLen-mhash.digest_size-sLen-2) + bchr(0x01)): + return False + # Step 11 + salt = b("") + if sLen: salt = db[-sLen:] + # Step 12 and 13 + try: + hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest() + except AttributeError: + # hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it + hp = Hash_new(mhash, bchr(0x00)*8 + mhash.digest() + salt).digest() + # Step 14 + if h!=hp: + return False + return True + +def new(key, mgfunc=None, saltLen=None): + """Return a signature scheme object `PSS_SigScheme` that + can be used to perform PKCS#1 PSS signature or verification. + + :Parameters: + key : RSA key object + The key to use to sign or verify the message. This is a `Crypto.PublicKey.RSA` object. + Signing is only possible if *key* is a private RSA key. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 is used. + saltLen : int + Length of the salt, in bytes. If not specified, it matches the output + size of the hash function. + + """ + return PSS_SigScheme(key, mgfunc, saltLen) + diff --git a/lib/Crypto/Signature/PKCS1_v1_5.py b/lib/Crypto/Signature/PKCS1_v1_5.py new file mode 100644 index 0000000..6a2e0d0 --- /dev/null +++ b/lib/Crypto/Signature/PKCS1_v1_5.py @@ -0,0 +1,328 @@ +# -*- coding: utf-8 -*- +# +# Signature/PKCS1-v1_5.py : PKCS#1 v1.5 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +""" +RSA digital signature protocol according to PKCS#1 v1.5 + +See RFC3447__ or the `original RSA Labs specification`__. + +This scheme is more properly called ``RSASSA-PKCS1-v1_5``. + +For example, a sender may authenticate a message using SHA-1 like +this: + + >>> from Crypto.Signature import PKCS1_v1_5 + >>> from Crypto.Hash import SHA + >>> from Crypto.PublicKey import RSA + >>> + >>> message = 'To be signed' + >>> key = RSA.importKey(open('privkey.der').read()) + >>> h = SHA.new(message) + >>> signer = PKCS1_v1_5.new(key) + >>> signature = signer.sign(h) + +At the receiver side, verification can be done using the public part of +the RSA key: + + >>> key = RSA.importKey(open('pubkey.der').read()) + >>> h = SHA.new(message) + >>> verifier = PKCS1_v1_5.new(key) + >>> if verifier.verify(h, signature): + >>> print "The signature is authentic." + >>> else: + >>> print "The signature is not authentic." + +:undocumented: __revision__, __package__ + +.. __: http://www.ietf.org/rfc/rfc3447.txt +.. __: http://www.rsa.com/rsalabs/node.asp?id=2125 +""" + +__revision__ = "$Id$" +__all__ = [ 'new', 'PKCS115_SigScheme' ] + +import sys + +import Crypto.Util.number +from Crypto.Util.number import ceil_div +from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +class PKCS115_SigScheme: + """This signature scheme can perform PKCS#1 v1.5 RSA signature or verification.""" + + def __init__(self, key): + """Initialize this PKCS#1 v1.5 signature scheme object. + + :Parameters: + key : an RSA key object + If a private half is given, both signature and verification are possible. + If a public half is given, only verification is possible. + """ + self._key = key + + def can_sign(self): + """Return True if this cipher object can be used for signing messages.""" + return self._key.has_private() + + def sign(self, mhash): + """Produce the PKCS#1 v1.5 signature of a message. + + This function is named ``RSASSA-PKCS1-V1_5-SIGN``, and is specified in + section 8.2.1 of RFC3447. + + :Parameters: + mhash : hash object + The hash that was carried out over the message. This is an object + belonging to the `Crypto.Hash` module. + + :Return: The signature encoded as a string. + :Raise ValueError: + If the RSA key length is not sufficiently long to deal with the given + hash algorithm. + :Raise TypeError: + If the RSA key has no private half. + """ + # TODO: Verify the key is RSA + + # See 8.2.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + + # Step 1 + em = EMSA_PKCS1_V1_5_ENCODE(mhash, k) + # Step 2a (OS2IP) and 2b (RSASP1) + m = self._key.decrypt(em) + # Step 2c (I2OSP) + S = bchr(0x00)*(k-len(m)) + m + return S + + def verify(self, mhash, S): + """Verify that a certain PKCS#1 v1.5 signature is authentic. + + This function checks if the party holding the private half of the key + really signed the message. + + This function is named ``RSASSA-PKCS1-V1_5-VERIFY``, and is specified in + section 8.2.2 of RFC3447. + + :Parameters: + mhash : hash object + The hash that was carried out over the message. This is an object + belonging to the `Crypto.Hash` module. + S : string + The signature that needs to be validated. + + :Return: True if verification is correct. False otherwise. + """ + # TODO: Verify the key is RSA + + # See 8.2.2 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + + # Step 1 + if len(S) != k: + return 0 + # Step 2a (O2SIP) and 2b (RSAVP1) + # Note that signature must be smaller than the module + # but RSA.py won't complain about it. + # TODO: Fix RSA object; don't do it here. + m = self._key.encrypt(S, 0)[0] + # Step 2c (I2OSP) + em1 = bchr(0x00)*(k-len(m)) + m + # Step 3 + try: + em2_with_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, True) + # MD hashes always require NULL params in AlgorithmIdentifier. + # For all others, it is optional. + if _HASH_OIDS[mhash.name].startswith('1.2.840.113549.2.'): # MD2/MD4/MD5 + em2_without_params = em2_with_params + else: + em2_without_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, False) + except ValueError: + return 0 + # Step 4 + # By comparing the full encodings (as opposed to checking each + # of its components one at a time) we avoid attacks to the padding + # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537). + # + return em1==em2_with_params or em1==em2_without_params + +def EMSA_PKCS1_V1_5_ENCODE(hash, emLen, with_hash_parameters=True): + """ + Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined + in PKCS#1 v2.1 (RFC3447, 9.2). + + ``EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input, + and hash it internally. Here, we expect that the message has already + been hashed instead. + + :Parameters: + hash : hash object + The hash object that holds the digest of the message being signed. + emLen : int + The length the final encoding must have, in bytes. + with_hash_parameters: + If True (default), include NULL parameters for the hash + algorithm in the ``digestAlgorithm`` SEQUENCE. + + :attention: the early standard (RFC2313) stated that ``DigestInfo`` + had to be BER-encoded. This means that old signatures + might have length tags in indefinite form, which + is not supported in DER. Such encoding cannot be + reproduced by this function. + + :Return: An ``emLen`` byte long string that encodes the hash. + """ + + # First, build the ASN.1 DER object DigestInfo: + # + # DigestInfo ::= SEQUENCE { + # digestAlgorithm AlgorithmIdentifier, + # digest OCTET STRING + # } + # + # where digestAlgorithm identifies the hash function and shall be an + # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms. + # + # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= { + # { OID id-md2 PARAMETERS NULL }| + # { OID id-md5 PARAMETERS NULL }| + # { OID id-sha1 PARAMETERS NULL }| + # { OID id-sha256 PARAMETERS NULL }| + # { OID id-sha384 PARAMETERS NULL }| + # { OID id-sha512 PARAMETERS NULL } + # } + # + # Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters + # should be omitted. They may be present, but when they are, they shall + # have NULL value. + + if with_hash_parameters: + digestAlgo = DerSequence([ + DerObjectId(_HASH_OIDS[hash.name]).encode(), + DerNull().encode() + ]) + else: + digestAlgo = DerSequence([ + DerObjectId(_HASH_OIDS[hash.name]).encode(), + ]) + digest = DerOctetString(hash.digest()) + digestInfo = DerSequence([ + digestAlgo.encode(), + digest.encode() + ]).encode() + + # We need at least 11 bytes for the remaining data: 3 fixed bytes and + # at least 8 bytes of padding). + if emLen<len(digestInfo)+11: + raise TypeError("Selected hash algorith has a too long digest (%d bytes)." % len(digest)) + PS = bchr(0xFF) * (emLen - len(digestInfo) - 3) + return b("\x00\x01") + PS + bchr(0x00) + digestInfo + +def new(key): + """Return a signature scheme object `PKCS115_SigScheme` that + can be used to perform PKCS#1 v1.5 signature or verification. + + :Parameters: + key : RSA key object + The key to use to sign or verify the message. This is a `Crypto.PublicKey.RSA` object. + Signing is only possible if *key* is a private RSA key. + + """ + return PKCS115_SigScheme(key) + +# AlgorithmIdentifier OIDs for use with PKCS#1 v1.5. +# +# These map names to the associated OIDs. We should try to be compatible +# with the standard library's hashlib modules, where possible. +# +# XXX - These will probably be moved somewhere else soon. +_HASH_OIDS = { + #: id-md2 OBJECT IDENTIFIER ::= { + #: iso(1) member-body(2) us(840) rsadsi(113549) + #: digestAlgorithm(2) 2 + #: } + "MD2": "1.2.840.113549.2.2", + "md2": "1.2.840.113549.2.2", + + #: id-md4 OBJECT IDENTIFIER ::= { + #: iso(1) member-body(2) us(840) rsadsi(113549) + #: digestAlgorithm(2) 4 + #: } + "MD4": "1.2.840.113549.2.4", + "md4": "1.2.840.113549.2.4", + + #: id-md5 OBJECT IDENTIFIER ::= { + #: iso(1) member-body(2) us(840) rsadsi(113549) + #: digestAlgorithm(2) 5 + #: } + "MD5": "1.2.840.113549.2.5", + "md5": "1.2.840.113549.2.5", + + #: id-ripemd160 OBJECT IDENTIFIER ::= { + #: iso(1) identified-organization(3) teletrust(36) + #: algorithm(3) hashAlgorithm(2) ripemd160(1) + #: } + "RIPEMD160": "1.3.36.3.2.1", + "ripemd160": "1.3.36.3.2.1", + + #: id-sha1 OBJECT IDENTIFIER ::= { + #: iso(1) identified-organization(3) oiw(14) secsig(3) + #: algorithms(2) 26 + #: } + "SHA1": "1.3.14.3.2.26", + "sha1": "1.3.14.3.2.26", + + #: id-sha224 OBJECT IDENTIFIER ::= { + #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) + #: nistalgorithm(4) hashalgs(2) 4 + #: } + "SHA224": '2.16.840.1.101.3.4.2.4', + "sha224": '2.16.840.1.101.3.4.2.4', + + #: id-sha256 OBJECT IDENTIFIER ::= { + #: joint-iso-itu-t(2) country(16) us(840) organization(1) + #: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 + #: } + "SHA256": "2.16.840.1.101.3.4.2.1", + "sha256": "2.16.840.1.101.3.4.2.1", + + #: id-sha384 OBJECT IDENTIFIER ::= { + #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) + #: nistalgorithm(4) hashalgs(2) 2 + #: } + "SHA384": '2.16.840.1.101.3.4.2.2', + "sha384": '2.16.840.1.101.3.4.2.2', + + #: id-sha512 OBJECT IDENTIFIER ::= { + #: joint-iso-itu-t(2) + #: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 + #: } + "SHA512": "2.16.840.1.101.3.4.2.3", + "sha512": "2.16.840.1.101.3.4.2.3", + +} + diff --git a/lib/Crypto/Signature/__init__.py b/lib/Crypto/Signature/__init__.py new file mode 100644 index 0000000..ed523b4 --- /dev/null +++ b/lib/Crypto/Signature/__init__.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Digital signature protocols + +A collection of standardized protocols to carry out digital signatures. + +:undocumented: __revision__, __package__ +""" + +__all__ = [ 'PKCS1_v1_5', 'PKCS1_PSS' ] +__revision__ = "$Id$" + + diff --git a/lib/Crypto/Util/Counter.py b/lib/Crypto/Util/Counter.py new file mode 100644 index 0000000..eeff93c --- /dev/null +++ b/lib/Crypto/Util/Counter.py @@ -0,0 +1,138 @@ +# -*- coding: ascii -*- +# +# Util/Counter.py : Fast counter for use with CTR-mode ciphers +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Fast counter functions for CTR cipher modes. + +CTR is a chaining mode for symmetric block encryption or decryption. +Messages are divideded into blocks, and the cipher operation takes +place on each block using the secret key and a unique *counter block*. + +The most straightforward way to fulfil the uniqueness property is +to start with an initial, random *counter block* value, and increment it as +the next block is processed. + +The block ciphers from `Crypto.Cipher` (when configured in *MODE_CTR* mode) +invoke a callable object (the *counter* parameter) to get the next *counter block*. +Unfortunately, the Python calling protocol leads to major performance degradations. + +The counter functions instantiated by this module will be invoked directly +by the ciphers in `Crypto.Cipher`. The fact that the Python layer is bypassed +lead to more efficient (and faster) execution of CTR cipher modes. + +An example of usage is the following: + + >>> from Crypto.Cipher import AES + >>> from Crypto.Util import Counter + >>> from Crypto import Random + >>> + >>> nonce = Random.get_random_bytes(8) + >>> ctr = Counter.new(64, nonce) + >>> key = b'AES-128 symm key' + >>> plaintext = b'X'*1000000 + >>> cipher = AES.new(key, AES.MODE_CTR, counter=ctr) + >>> ciphertext = cipher.encrypt(plaintext) + +:undocumented: __package__ +""" +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +from Crypto.pct_warnings import DisableShortcut_DeprecationWarning +from Crypto.Util import _counter +import struct +import warnings + + +# Factory function +_deprecated = "deprecated" +def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=_deprecated): + """Create a stateful counter block function suitable for CTR encryption modes. + + Each call to the function returns the next counter block. + Each counter block is made up by three parts:: + + prefix || counter value || postfix + + The counter value is incremented by 1 at each call. + + :Parameters: + nbits : integer + Length of the desired counter, in bits. It must be a multiple of 8. + prefix : byte string + The constant prefix of the counter block. By default, no prefix is + used. + suffix : byte string + The constant postfix of the counter block. By default, no suffix is + used. + initial_value : integer + The initial value of the counter. Default value is 1. + overflow : integer + This value is currently ignored. + little_endian : boolean + If *True*, the counter number will be encoded in little endian format. + If *False* (default), in big endian format. + allow_wraparound : boolean + If *True*, the counter will automatically restart from zero after + reaching the maximum value (``2**nbits-1``). + If *False* (default), the object will raise an *OverflowError*. + disable_shortcut : deprecated + This option is a no-op for backward compatibility. It will be removed + in a future version. Don't use it. + :Returns: + The counter block function. + """ + + # Sanity-check the message size + (nbytes, remainder) = divmod(nbits, 8) + if remainder != 0: + # In the future, we might support arbitrary bit lengths, but for now we don't. + raise ValueError("nbits must be a multiple of 8; got %d" % (nbits,)) + if nbytes < 1: + raise ValueError("nbits too small") + elif nbytes > 0xffff: + raise ValueError("nbits too large") + + initval = _encode(initial_value, nbytes, little_endian) + + if disable_shortcut is not _deprecated: # exact object comparison + warnings.warn("disable_shortcut has no effect and is deprecated", DisableShortcut_DeprecationWarning) + + if little_endian: + return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound) + else: + return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound) + +def _encode(n, nbytes, little_endian=False): + retval = [] + n = long(n) + for i in range(nbytes): + if little_endian: + retval.append(bchr(n & 0xff)) + else: + retval.insert(0, bchr(n & 0xff)) + n >>= 8 + return b("").join(retval) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Util/Padding.py b/lib/Crypto/Util/Padding.py new file mode 100644 index 0000000..b8498a3 --- /dev/null +++ b/lib/Crypto/Util/Padding.py @@ -0,0 +1,103 @@ +# +# -*- coding: utf-8 -*- +# +# Util/Padding.py : Functions to manage padding +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +""" Functions to manage padding + +This module provides minimal support for adding and removing standard padding +from data. +""" + +__all__ = [ 'PaddingError', 'pad', 'unpad' ] + +from Crypto.Util.py3compat import * + +class PaddingError(ValueError): + """Exception raised when padding is incorrect and cannot be removed.""" + pass + +def pad(data_to_pad, block_size, style='pkcs7'): + """Apply standard padding. + + :Parameters: + data_to_pad : byte string + The data that needs to be padded. + block_size : integer + The block boundary to use for padding. The output length is guaranteed + to be a multiple of ``block_size``. + style : string + Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. + :Return: + The original data with the appropriate padding added at the end. + """ + + padding_len = block_size-len(data_to_pad)%block_size + if style == 'pkcs7': + padding = bchr(padding_len)*padding_len + elif style == 'x923': + padding = bchr(0)*(padding_len-1) + bchr(padding_len) + elif style == 'iso7816': + padding = bchr(128) + bchr(0)*(padding_len-1) + else: + raise ValueError("Unknown padding style") + return data_to_pad + padding + +def unpad(padded_data, block_size, style='pkcs7'): + """Remove standard padding. + + :Parameters: + padded_data : byte string + A piece of data with padding that needs to be stripped. + block_size : integer + The block boundary to use for padding. The input length + must be a multiple of ``block_size``. + style : string + Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. + :Return: + Data without padding. + :Raises PaddingError: + if the padding is incorrect. + """ + + pdata_len = len(padded_data) + if pdata_len % block_size: + raise PaddingError("Input data is not padded") + if style in ('pkcs7', 'x923'): + padding_len = bord(padded_data[-1]) + if padding_len<1 or padding_len>min(block_size, pdata_len): + raise PaddingError("Padding is incorrect.") + if style == 'pkcs7': + if padded_data[-padding_len:]!=bchr(padding_len)*padding_len: + raise PaddingError("PKCS#7 padding is incorrect.") + else: + if padded_data[-padding_len:-1]!=bchr(0)*(padding_len-1): + raise PaddingError("ANSI X.923 padding is incorrect.") + elif style == 'iso7816': + padding_len = pdata_len - padded_data.rfind(bchr(128)) + if padding_len<1 or padding_len>min(block_size, pdata_len): + raise PaddingError("Padding is incorrect.") + if padding_len>1 and padded_data[1-padding_len:]!=bchr(0)*(padding_len-1): + raise PaddingError("ISO 7816-4 padding is incorrect.") + else: + raise ValueError("Unknown padding style") + return padded_data[:-padding_len] + diff --git a/lib/Crypto/Util/RFC1751.py b/lib/Crypto/Util/RFC1751.py new file mode 100644 index 0000000..9786e6f --- /dev/null +++ b/lib/Crypto/Util/RFC1751.py @@ -0,0 +1,364 @@ +# rfc1751.py : Converts between 128-bit strings and a human-readable +# sequence of words, as defined in RFC1751: "A Convention for +# Human-Readable 128-bit Keys", by Daniel L. McDonald. +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew M. Kuchling and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + + +import binascii +from Crypto.Util.py3compat import * + +binary={0:'0000', 1:'0001', 2:'0010', 3:'0011', 4:'0100', 5:'0101', + 6:'0110', 7:'0111', 8:'1000', 9:'1001', 10:'1010', 11:'1011', + 12:'1100', 13:'1101', 14:'1110', 15:'1111'} + +def _key2bin(s): + "Convert a key into a string of binary digits" + kl=map(lambda x: bord(x), s) + kl=map(lambda x: binary[x>>4]+binary[x&15], kl) + return ''.join(kl) + +def _extract(key, start, length): + """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its + numeric value.""" + k=key[start:start+length] + return reduce(lambda x,y: x*2+ord(y)-48, k, 0) + +def key_to_english (key): + """key_to_english(key:string(2.x)/bytes(3.x)) : string + Transform an arbitrary key into a string containing English words. + The key length must be a multiple of 8. + """ + english='' + for index in range(0, len(key), 8): # Loop over 8-byte subkeys + subkey=key[index:index+8] + # Compute the parity of the key + skbin=_key2bin(subkey) ; p=0 + for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) + # Append parity bits to the subkey + skbin=_key2bin(subkey+bchr((p<<6) & 255)) + for i in range(0, 64, 11): + english=english+wordlist[_extract(skbin, i, 11)]+' ' + + return english[:-1] # Remove the trailing space + +def english_to_key (s): + """english_to_key(string):string(2.x)/bytes(2.x) + Transform a string into a corresponding key. + The string must contain words separated by whitespace; the number + of words must be a multiple of 6. + """ + + L=s.upper().split() ; key=b('') + for index in range(0, len(L), 6): + sublist=L[index:index+6] ; char=9*[0] ; bits=0 + for i in sublist: + index = wordlist.index(i) + shift = (8-(bits+11)%8) %8 + y = index << shift + cl, cc, cr = (y>>16), (y>>8)&0xff, y & 0xff + if (shift>5): + char[bits>>3] = char[bits>>3] | cl + char[(bits>>3)+1] = char[(bits>>3)+1] | cc + char[(bits>>3)+2] = char[(bits>>3)+2] | cr + elif shift>-3: + char[bits>>3] = char[bits>>3] | cc + char[(bits>>3)+1] = char[(bits>>3)+1] | cr + else: char[bits>>3] = char[bits>>3] | cr + bits=bits+11 + subkey=reduce(lambda x,y:x+bchr(y), char, b('')) + + # Check the parity of the resulting key + skbin=_key2bin(subkey) + p=0 + for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) + if (p&3) != _extract(skbin, 64, 2): + raise ValueError, "Parity error in resulting key" + key=key+subkey[0:8] + return key + +wordlist=[ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", + "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", + "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", + "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", + "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", + "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", + "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", + "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", + "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", + "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", + "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", + "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", + "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", + "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", + "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", + "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", + "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", + "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", + "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", + "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", + "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", + "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", + "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", + "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", + "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", + "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", + "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", + "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", + "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", + "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", + "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", + "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", + "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", + "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", + "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", + "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", + "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", + "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", + "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", + "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", + "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", + "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", + "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", + "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", + "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", + "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", + "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", + "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", + "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", + "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", + "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", + "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", + "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", + "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", + "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", + "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", + "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", + "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", + "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", + "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", + "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", + "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", + "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", + "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", + "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM", + "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", + "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", + "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", + "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", + "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", + "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", + "BEAU", "BECK", "BEEF", "BEEN", "BEER", + "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", + "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", + "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", + "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", + "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", + "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", + "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", + "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", + "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", + "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", + "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", + "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", + "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", + "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", + "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", + "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", + "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", + "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", + "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", + "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", + "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", + "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", + "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", + "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", + "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", + "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", + "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", + "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", + "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", + "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", + "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", + "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", + "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", + "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", + "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", + "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", + "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", + "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", + "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", + "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", + "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", + "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", + "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", + "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", + "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", + "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", + "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", + "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", + "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", + "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", + "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", + "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", + "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", + "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", + "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", + "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", + "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", + "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", + "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", + "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", + "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", + "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK", + "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", + "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", + "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", + "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", + "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", + "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", + "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", + "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", + "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", + "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", + "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", + "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", + "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", + "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", + "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", + "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", + "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", + "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", + "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", + "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", + "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", + "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", + "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", + "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", + "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", + "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST", + "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", + "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", + "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", + "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", + "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", + "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", + "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", + "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", + "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", + "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", + "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", + "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", + "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", + "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", + "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", + "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", + "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", + "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", + "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", + "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", + "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", + "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", + "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", + "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", + "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", + "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", + "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", + "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", + "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", + "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", + "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", + "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", + "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA", + "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", + "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD", + "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", + "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", + "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", + "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", + "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", + "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", + "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", + "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", + "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS", + "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", + "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", + "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", + "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", + "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", + "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", + "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", + "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", + "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", + "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", + "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", + "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", + "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", + "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", + "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", + "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", + "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN", + "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", + "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY", + "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", + "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", + "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", + "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", + "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", + "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", + "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", + "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", + "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", + "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", + "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", + "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", + "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", + "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", + "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", + "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE", + "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", + "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", + "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", + "YELL", "YOGA", "YOKE" ] + +if __name__=='__main__': + data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), + ('CCAC2AED591056BE4F90FD441C534766', + 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), + ('EFF81F9BFBC65350920CDD7416DE8009', + 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') + ] + + for key, words in data: + print 'Trying key', key + key=binascii.a2b_hex(key) + w2=key_to_english(key) + if w2!=words: + print 'key_to_english fails on key', repr(key), ', producing', str(w2) + k2=english_to_key(words) + if k2!=key: + print 'english_to_key fails on key', repr(key), ', producing', repr(k2) + + diff --git a/lib/Crypto/Util/__init__.py b/lib/Crypto/Util/__init__.py new file mode 100644 index 0000000..b2030c0 --- /dev/null +++ b/lib/Crypto/Util/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Miscellaneous modules + +Contains useful modules that don't belong into any of the +other Crypto.* subpackages. + +======================== ============================================= +Module Description +======================== ============================================= +`Crypto.Util.number` Number-theoretic functions (primality testing, etc.) +`Crypto.Util.Counter` Fast counter functions for CTR cipher modes. +`Crypto.Util.randpool` Random number generation +`Crypto.Util.RFC1751` Converts between 128-bit keys and human-readable + strings of words. +`Crypto.Util.asn1` Minimal support for ASN.1 DER encoding +`Crypto.Util.Padding` Set of functions for adding and removing padding. +======================== ============================================= + +""" + +__all__ = ['randpool', 'RFC1751', 'number', 'strxor', 'asn1', 'Counter', + 'Padding' ] + +__revision__ = "$Id$" + diff --git a/lib/Crypto/Util/_number_new.py b/lib/Crypto/Util/_number_new.py new file mode 100644 index 0000000..b040025 --- /dev/null +++ b/lib/Crypto/Util/_number_new.py @@ -0,0 +1,119 @@ +# -*- coding: ascii -*- +# +# Util/_number_new.py : utility functions +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +## NOTE: Do not import this module directly. Import these functions from Crypto.Util.number. + +__revision__ = "$Id$" +__all__ = ['ceil_shift', 'ceil_div', 'floor_div', 'exact_log2', 'exact_div'] + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +def ceil_shift(n, b): + """Return ceil(n / 2**b) without performing any floating-point or division operations. + + This is done by right-shifting n by b bits and incrementing the result by 1 + if any '1' bits were shifted out. + """ + if not isinstance(n, (int, long)) or not isinstance(b, (int, long)): + raise TypeError("unsupported operand type(s): %r and %r" % (type(n).__name__, type(b).__name__)) + + assert n >= 0 and b >= 0 # I haven't tested or even thought about negative values + mask = (1L << b) - 1 + if n & mask: + return (n >> b) + 1 + else: + return n >> b + +def ceil_div(a, b): + """Return ceil(a / b) without performing any floating-point operations.""" + + if not isinstance(a, (int, long)) or not isinstance(b, (int, long)): + raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__)) + + (q, r) = divmod(a, b) + if r: + return q + 1 + else: + return q + +def floor_div(a, b): + if not isinstance(a, (int, long)) or not isinstance(b, (int, long)): + raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__)) + + (q, r) = divmod(a, b) + return q + +def exact_log2(num): + """Find and return an integer i >= 0 such that num == 2**i. + + If no such integer exists, this function raises ValueError. + """ + + if not isinstance(num, (int, long)): + raise TypeError("unsupported operand type: %r" % (type(num).__name__,)) + + n = long(num) + if n <= 0: + raise ValueError("cannot compute logarithm of non-positive number") + + i = 0 + while n != 0: + if (n & 1) and n != 1: + raise ValueError("No solution could be found") + i += 1 + n >>= 1 + i -= 1 + + assert num == (1L << i) + return i + +def exact_div(p, d, allow_divzero=False): + """Find and return an integer n such that p == n * d + + If no such integer exists, this function raises ValueError. + + Both operands must be integers. + + If the second operand is zero, this function will raise ZeroDivisionError + unless allow_divzero is true (default: False). + """ + + if not isinstance(p, (int, long)) or not isinstance(d, (int, long)): + raise TypeError("unsupported operand type(s): %r and %r" % (type(p).__name__, type(d).__name__)) + + if d == 0 and allow_divzero: + n = 0 + if p != n * d: + raise ValueError("No solution could be found") + else: + (n, r) = divmod(p, d) + if r != 0: + raise ValueError("No solution could be found") + + assert p == n * d + return n + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Util/_time.py b/lib/Crypto/Util/_time.py new file mode 100644 index 0000000..ff4c6a9 --- /dev/null +++ b/lib/Crypto/Util/_time.py @@ -0,0 +1,28 @@ +# -*- coding: ascii -*- +# +# _time.py : Internal monotonic time module. +# +# Written in 2013 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +try: + from time import monotonic as maybe_monotonic_time +except ImportError: + from time import time as maybe_monotonic_time diff --git a/lib/Crypto/Util/asn1.py b/lib/Crypto/Util/asn1.py new file mode 100644 index 0000000..0e471a3 --- /dev/null +++ b/lib/Crypto/Util/asn1.py @@ -0,0 +1,899 @@ +# -*- coding: ascii -*- +# +# Util/asn1.py : Minimal support for ASN.1 DER binary encoding. +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +""" ASN.1 DER encoding and decoding + +This module provides minimal support for encoding and decoding `ASN.1`_ DER +objects. + +.. _`ASN.1`: ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc + +""" + +from __future__ import nested_scopes + +import sys + +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * + +from Crypto.Util.number import long_to_bytes, bytes_to_long + +__all__ = [ 'DerObject', 'DerInteger', 'DerOctetString', 'DerNull', + 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf', + 'newDerInteger', 'newDerOctetString', 'newDerSequence', + 'newDerObjectId', 'newDerBitString', 'newDerSetOf' ] + +def _isInt(x, onlyNonNegative=False): + test = 0 + try: + test += x + except TypeError: + return False + return not onlyNonNegative or x>=0 + +class BytesIO_EOF(BytesIO): + """This class differs from BytesIO in that an EOFError exception is + raised whenever EOF is reached.""" + + def __init__(self, *params): + BytesIO.__init__(self, *params) + self.setRecord(False) + + def setRecord(self, record): + self._record = record + self._recording = b("") + + def read(self, length): + s = BytesIO.read(self, length) + if len(s)<length: + raise EOFError + if self._record: + self._recording += s + return s + + def read_byte(self): + return self.read(1)[0] + +class NoDerElementError(EOFError): + pass + +class DerObject(object): + """Base class for defining a single DER object. + + This class should never be directly instantiated. + """ + + def __init__(self, asn1Id=None, payload=b(''), implicit=None, constructed=False): + """Initialize the DER object according to a specific ASN.1 type. + + :Parameters: + asn1Id : integer + The universal DER tag identifier for this object + (e.g. 0x10 for a SEQUENCE). If None, the tag is not known + yet. + + payload : byte string + The initial payload of the object. + If not specified, the payload is empty. + + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag *asn1Id*. + + constructed : bool + True when the ASN.1 type is *constructed*. + False when it is *primitive*. + """ + + if asn1Id==None: + self._idOctet = None + return + asn1Id = self._convertTag(asn1Id) + self._implicit = implicit + if implicit: + # In a BER/DER identifier octet: + # * bits 4-0 contain the tag value + # * bit 5 is set if the type is 'construted' + # and unset if 'primitive' + # * bits 7-6 depend on the encoding class + # + # Class | Bit 7, Bit 6 + # universal | 0 0 + # application | 0 1 + # context-spec | 1 0 (default for IMPLICIT) + # private | 1 1 + # + self._idOctet = 0x80 | self._convertTag(implicit) + else: + self._idOctet = asn1Id + if constructed: + self._idOctet |= 0x20 + self.payload = payload + + def _convertTag(self, tag): + """Check if *tag* is a real DER tag. + Convert it from a character to number if necessary. + """ + if not _isInt(tag): + if len(tag)==1: + tag = bord(tag[0]) + # Ensure that tag is a low tag + if not (_isInt(tag) and 0 <= tag < 0x1F): + raise ValueError("Wrong DER tag") + return tag + + def _lengthOctets(self): + """Build length octets according to the current object's payload. + + Return a byte string that encodes the payload length (in + bytes) in a format suitable for DER length octets (L). + """ + payloadLen = len(self.payload) + if payloadLen>127: + encoding = long_to_bytes(payloadLen) + return bchr(len(encoding)+128) + encoding + return bchr(payloadLen) + + def encode(self): + """Return this DER element, fully encoded as a binary byte string.""" + # Concatenate identifier octets, length octets, + # and contents octets + return bchr(self._idOctet) + self._lengthOctets() + self.payload + + def _decodeLen(self, s): + """Decode DER length octets from a file.""" + + length = bord(s.read_byte()) + if length<=127: + return length + payloadLength = bytes_to_long(s.read(length & 0x7F)) + # According to DER (but not BER) the long form is used + # only when the length doesn't fit into 7 bits. + if payloadLength<=127: + raise ValueError("Not a DER length tag (but still valid BER).") + return payloadLength + + def decode(self, derEle): + """Decode a complete DER element, and re-initializes this + object with it. + + :Parameters: + derEle : byte string + A complete DER element. + + :Raise ValueError: + In case of parsing errors. + :Raise EOFError: + If the DER element is too short. + """ + + s = BytesIO_EOF(derEle) + self._decodeFromStream(s) + # There shouldn't be other bytes left + try: + b = s.read_byte() + raise ValueError("Unexpected extra data after the DER structure") + except EOFError: + pass + + def _decodeFromStream(self, s): + """Decode a complete DER element from a file.""" + + try: + idOctet = bord(s.read_byte()) + except EOFError: + raise NoDerElementError + if self._idOctet != None: + if idOctet != self._idOctet: + raise ValueError("Unexpected DER tag") + else: + self._idOctet = idOctet + length = self._decodeLen(s) + self.payload = s.read(length) + +class DerInteger(DerObject): + """Class to model a DER INTEGER. + + An example of encoding is: + + >>> from Crypto.Util.asn1 import DerInteger + >>> from binascii import hexlify, unhexlify + >>> int_der = DerInteger(9) + >>> print hexlify(int_der.encode()) + + which will show ``020109``, the DER encoding of 9. + + And for decoding: + + >>> s = unhexlify(b'020109') + >>> try: + >>> int_der = DerInteger() + >>> int_der.decode(s) + >>> print int_der.value + >>> except (ValueError, EOFError): + >>> print "Not a valid DER INTEGER" + + the output will be ``9``. + """ + + def __init__(self, value=0, implicit=None): + """Initialize the DER object as an INTEGER. + + :Parameters: + value : integer + The value of the integer. + + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for INTEGER (2). + """ + + DerObject.__init__(self, 0x02, b(''), implicit, False) + self.value = value #: The integer value + + def encode(self): + """Return the DER INTEGER, fully encoded as a + binary string.""" + + number = self.value + self.payload = b('') + while True: + self.payload = bchr(number&255) + self.payload + if 128 <= number <= 255: + self.payload = bchr(0x00) + self.payload + if -128 <= number <= 255: + break + number >>= 8 + return DerObject.encode(self) + + def decode(self, derEle): + """Decode a complete DER INTEGER DER, and re-initializes this + object with it. + + :Parameters: + derEle : byte string + A complete INTEGER DER element. + + :Raise ValueError: + In case of parsing errors. + :Raise EOFError: + If the DER element is too short. + """ + DerObject.decode(self, derEle) + + def _decodeFromStream(self, s): + """Decode a complete DER INTEGER from a file.""" + + # Fill up self.payload + DerObject._decodeFromStream(self, s) + + # Derive self.value from self.payload + self.value = 0L + bits = 1 + for i in self.payload: + self.value *= 256 + self.value += bord(i) + bits <<= 8 + if self.payload and bord(self.payload[0]) & 0x80: + self.value -= bits + +def newDerInteger(number): + """Create a DerInteger object, already initialized with an integer.""" + + der = DerInteger(number) + return der + +class DerSequence(DerObject): + """Class to model a DER SEQUENCE. + + This object behaves like a dynamic Python sequence. + + Sub-elements that are INTEGERs behave like Python integers. + + Any other sub-element is a binary string encoded as a complete DER + sub-element (TLV). + + An example of encoding is: + + >>> from Crypto.Util.asn1 import DerSequence, DerInteger + >>> from binascii import hexlify, unhexlify + >>> obj_der = unhexlify('070102') + >>> seq_der = DerSequence([4]) + >>> seq_der.append(9) + >>> seq_der.append(obj_der.encode()) + >>> print hexlify(seq_der.encode()) + + which will show ``3009020104020109070102``, the DER encoding of the + sequence containing ``4``, ``9``, and the object with payload ``02``. + + For decoding: + + >>> s = unhexlify(b'3009020104020109070102') + >>> try: + >>> seq_der = DerSequence() + >>> seq_der.decode(s) + >>> print len(seq_der) + >>> print seq_der[0] + >>> print seq_der[:] + >>> except (ValueError, EOFError): + >>> print "Not a valid DER SEQUENCE" + + the output will be:: + + 3 + 4 + [4L, 9L, b'\x07\x01\x02'] + + """ + + def __init__(self, startSeq=None, implicit=None): + """Initialize the DER object as a SEQUENCE. + + :Parameters: + startSeq : Python sequence + A sequence whose element are either integers or + other DER objects. + + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for SEQUENCE (16). + """ + + DerObject.__init__(self, 0x10, b(''), implicit, True) + if startSeq==None: + self._seq = [] + else: + self._seq = startSeq + + ## A few methods to make it behave like a python sequence + + def __delitem__(self, n): + del self._seq[n] + def __getitem__(self, n): + return self._seq[n] + def __setitem__(self, key, value): + self._seq[key] = value + def __setslice__(self,i,j,sequence): + self._seq[i:j] = sequence + def __delslice__(self,i,j): + del self._seq[i:j] + def __getslice__(self, i, j): + return self._seq[max(0, i):max(0, j)] + def __len__(self): + return len(self._seq) + def __iadd__(self, item): + self._seq.append(item) + return self + def append(self, item): + self._seq.append(item) + return self + + def hasInts(self, onlyNonNegative=True): + """Return the number of items in this sequence that are + integers. + + :Parameters: + onlyNonNegative : boolean + If True, negative integers are not counted in. + """ + def _isInt2(x): + return _isInt(x, onlyNonNegative) + return len(filter(_isInt2, self._seq)) + + def hasOnlyInts(self, onlyNonNegative=True): + """Return True if all items in this sequence are integers + or non-negative integers. + + This function returns False is the sequence is empty, + or at least one member is not an integer. + + :Parameters: + onlyNonNegative : boolean + If True, the presence of negative integers + causes the method to return False.""" + return self._seq and self.hasInts(onlyNonNegative)==len(self._seq) + + def encode(self): + """Return this DER SEQUENCE, fully encoded as a + binary string. + + :Raises ValueError: + If some elements in the sequence are neither integers + nor byte strings. + """ + self.payload = b('') + for item in self._seq: + try: + self.payload += item + except TypeError: + try: + self.payload += DerInteger(item).encode() + except TypeError: + raise ValueError("Trying to DER encode an unknown object") + return DerObject.encode(self) + + def decode(self, derEle): + """Decode a complete DER SEQUENCE, and re-initializes this + object with it. + + :Parameters: + derEle : byte string + A complete SEQUENCE DER element. + + :Raise ValueError: + In case of parsing errors. + :Raise EOFError: + If the DER element is too short. + + DER INTEGERs are decoded into Python integers. Any other DER + element is not decoded. Its validity is not checked. + """ + DerObject.decode(self, derEle) + + def _decodeFromStream(self, s): + """Decode a complete DER SEQUENCE from a file.""" + + self._seq = [] + + # Fill up self.payload + DerObject._decodeFromStream(self, s) + + # Add one item at a time to self.seq, by scanning self.payload + p = BytesIO_EOF(self.payload) + while True: + try: + p.setRecord(True) + der = DerObject() + der._decodeFromStream(p) + + # Parse INTEGERs differently + if der._idOctet != 0x02: + self._seq.append(p._recording) + else: + derInt = DerInteger() + derInt.decode(p._recording) + self._seq.append(derInt.value) + + except NoDerElementError: + break + # end + +def newDerSequence(*der_objs): + """Create a DerSequence object, already initialized with all objects + passed as parameters.""" + + der = DerSequence() + for obj in der_objs: + if isinstance(obj, DerObject): + der += obj.encode() + else: + der += obj + return der + +class DerOctetString(DerObject): + """Class to model a DER OCTET STRING. + + An example of encoding is: + + >>> from Crypto.Util.asn1 import DerOctetString + >>> from binascii import hexlify, unhexlify + >>> os_der = DerOctetString(b'\\xaa') + >>> os_der.payload += b'\\xbb' + >>> print hexlify(os_der.encode()) + + which will show ``0402aabb``, the DER encoding for the byte string + ``b'\\xAA\\xBB'``. + + For decoding: + + >>> s = unhexlify(b'0402aabb') + >>> try: + >>> os_der = DerOctetString() + >>> os_der.decode(s) + >>> print hexlify(os_der.payload) + >>> except (ValueError, EOFError): + >>> print "Not a valid DER OCTET STRING" + + the output will be ``aabb``. + """ + + def __init__(self, value=b(''), implicit=None): + """Initialize the DER object as an OCTET STRING. + + :Parameters: + value : byte string + The initial payload of the object. + If not specified, the payload is empty. + + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OCTET STRING (4). + """ + DerObject.__init__(self, 0x04, value, implicit, False) + +def newDerOctetString(binstring): + """Create a DerOctetString object, already initialized with the binary + string.""" + + if isinstance(binstring, DerObject): + der = DerOctetString(binstring.encode()) + else: + der = DerOctetString(binstring) + return der + +class DerNull(DerObject): + """Class to model a DER NULL element.""" + + def __init__(self): + """Initialize the DER object as a NULL.""" + + DerObject.__init__(self, 0x05, b(''), False) + +class DerObjectId(DerObject): + """Class to model a DER OBJECT ID. + + An example of encoding is: + + >>> from Crypto.Util.asn1 import DerObjectId + >>> from binascii import hexlify, unhexlify + >>> oid_der = DerObjectId("1.2") + >>> oid_der.value += ".840.113549.1.1.1" + >>> print hexlify(oid_der.encode()) + + which will show ``06092a864886f70d010101``, the DER encoding for the + RSA Object Identifier ``1.2.840.113549.1.1.1``. + + For decoding: + + >>> s = unhexlify(b'06092a864886f70d010101') + >>> try: + >>> oid_der = DerObjectId() + >>> oid_der.decode(s) + >>> print oid_der.value + >>> except (ValueError, EOFError): + >>> print "Not a valid DER OBJECT ID" + + the output will be ``1.2.840.113549.1.1.1``. + """ + + def __init__(self, value='', implicit=None): + """Initialize the DER object as an OBJECT ID. + + :Parameters: + value : string + The initial Object Identifier (e.g. "1.2.0.0.6.2"). + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OBJECT ID (6). + """ + DerObject.__init__(self, 0x06, b(''), implicit, False) + self.value = value #: The Object ID, a dot separated list of integers + + def encode(self): + """Return the DER OBJECT ID, fully encoded as a + binary string.""" + + comps = map(int,self.value.split(".")) + if len(comps)<2: + raise ValueError("Not a valid Object Identifier string") + self.payload = bchr(40*comps[0]+comps[1]) + for v in comps[2:]: + enc = [] + while v: + enc.insert(0, (v & 0x7F) | 0x80) + v >>= 7 + enc[-1] &= 0x7F + self.payload += b('').join(map(bchr, enc)) + return DerObject.encode(self) + + def decode(self, derEle): + """Decode a complete DER OBJECT ID, and re-initializes this + object with it. + + :Parameters: + derEle : byte string + A complete DER OBJECT ID. + + :Raise ValueError: + In case of parsing errors. + :Raise EOFError: + If the DER element is too short. + """ + + DerObject.decode(self, derEle) + + def _decodeFromStream(self, s): + """Decode a complete DER OBJECT ID from a file.""" + + # Fill up self.payload + DerObject._decodeFromStream(self, s) + + # Derive self.value from self.payload + p = BytesIO_EOF(self.payload) + comps = list(map(str, divmod(bord(p.read_byte()),40))) + v = 0 + try: + while True: + c = p.read_byte() + v = v*128 + (bord(c) & 0x7F) + if not (bord(c) & 0x80): + comps.append(str(v)) + v = 0 + except EOFError: + pass + self.value = '.'.join(comps) + +def newDerObjectId(dottedstring): + """Create a DerObjectId object, already initialized with the given Object + Identifier (a dotted string).""" + + der = DerObjectId(dottedstring) + return der + +class DerBitString(DerObject): + """Class to model a DER BIT STRING. + + An example of encoding is: + + >>> from Crypto.Util.asn1 import DerBitString + >>> from binascii import hexlify, unhexlify + >>> bs_der = DerBitString(b'\\xaa') + >>> bs_der.value += b'\\xbb' + >>> print hexlify(bs_der.encode()) + + which will show ``040300aabb``, the DER encoding for the bit string + ``b'\\xAA\\xBB'``. + + For decoding: + + >>> s = unhexlify(b'040300aabb') + >>> try: + >>> bs_der = DerBitString() + >>> bs_der.decode(s) + >>> print hexlify(bs_der.value) + >>> except (ValueError, EOFError): + >>> print "Not a valid DER OCTET STRING" + + the output will be ``aabb``. + """ + + def __init__(self, value=b(''), implicit=None): + """Initialize the DER object as a BIT STRING. + + :Parameters: + value : byte string + The initial, packed bit string. + If not specified, the bit string is empty. + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for OCTET STRING (3). + """ + DerObject.__init__(self, 0x03, b(''), implicit, False) + self.value = value #: The bitstring value (packed) + + def encode(self): + """Return the DER BIT STRING, fully encoded as a + binary string.""" + + # Add padding count byte + self.payload = b('\x00') + self.value + return DerObject.encode(self) + + def decode(self, derEle): + """Decode a complete DER BIT STRING, and re-initializes this + object with it. + + :Parameters: + derEle : byte string + A complete DER BIT STRING. + + :Raise ValueError: + In case of parsing errors. + :Raise EOFError: + If the DER element is too short. + """ + + DerObject.decode(self, derEle) + + def _decodeFromStream(self, s): + """Decode a complete DER BIT STRING DER from a file.""" + + # Fill-up self.payload + DerObject._decodeFromStream(self, s) + + if self.payload and bord(self.payload[0])!=0: + raise ValueError("Not a valid BIT STRING") + + # Fill-up self.value + self.value = b('') + # Remove padding count byte + if self.payload: + self.value = self.payload[1:] + +def newDerBitString(binstring): + """Create a DerStringString object, already initialized with the binary + string.""" + + if isinstance(binstring, DerObject): + der = DerBitString(binstring.encode()) + else: + der = DerBitString(binstring) + return der + +class DerSetOf(DerObject): + """Class to model a DER SET OF. + + An example of encoding is: + + >>> from Crypto.Util.asn1 import DerBitString + >>> from binascii import hexlify, unhexlify + >>> so_der = DerSetOf([4,5]) + >>> so_der.add(6) + >>> print hexlify(so_der.encode()) + + which will show ``3109020104020105020106``, the DER encoding + of a SET OF with items 4,5, and 6. + + For decoding: + + >>> s = unhexlify(b'3109020104020105020106') + >>> try: + >>> so_der = DerSetOf() + >>> so_der.decode(s) + >>> print [x for x in so_der] + >>> except (ValueError, EOFError): + >>> print "Not a valid DER SET OF" + + the output will be ``[4L, 5L, 6L]``. + """ + + def __init__(self, startSet=None, implicit=None): + """Initialize the DER object as a SET OF. + + :Parameters: + startSet : container + The initial set of integers or DER encoded objects. + implicit : integer + The IMPLICIT tag to use for the encoded object. + It overrides the universal tag for SET OF (17). + """ + DerObject.__init__(self, 0x11, b(''), implicit, True) + self._seq = [] + self._elemOctet = None + if startSet: + for e in startSet: + self.add(e) + + def __getitem__(self, n): + return self._seq[n] + + def __iter__(self): + return iter(self._seq) + + def __len__(self): + return len(self._seq) + + def add(self, elem): + """Add an element to the set. + + :Parameters: + elem : byte string or integer + An element of the same type of objects already in the set. + It can be an integer or a DER encoded object. + """ + if _isInt(elem): + eo = 0x02 + else: + eo = bord(elem[0]) + if self._elemOctet != eo: + if self._elemOctet: + raise ValueError("New element does not belong to the set") + self._elemOctet = eo + if not elem in self._seq: + self._seq.append(elem) + + def decode(self, derEle): + """Decode a complete SET OF DER element, and re-initializes this + object with it. + + DER INTEGERs are decoded into Python integers. Any other DER + element is left undecoded; its validity is not checked. + + :Parameters: + derEle : byte string + A complete DER BIT SET OF. + + :Raise ValueError: + In case of parsing errors. + :Raise EOFError: + If the DER element is too short. + """ + + DerObject.decode(self, derEle) + + def _decodeFromStream(self, s): + """Decode a complete DER SET OF from a file.""" + + self._seq = [] + + # Fill up self.payload + DerObject._decodeFromStream(self, s) + + # Add one item at a time to self.seq, by scanning self.payload + p = BytesIO_EOF(self.payload) + setIdOctet = -1 + while True: + try: + p.setRecord(True) + der = DerObject() + der._decodeFromStream(p) + + # Verify that all members are of the same type + if setIdOctet < 0: + setIdOctet = der._idOctet + else: + if setIdOctet != der._idOctet: + raise ValueError("Not all elements are of the same DER type") + + # Parse INTEGERs differently + if setIdOctet != 0x02: + self._seq.append(p._recording) + else: + derInt = DerInteger() + derInt.decode(p._recording) + self._seq.append(derInt.value) + + except NoDerElementError: + break + # end + + def encode(self): + """Return this SET OF DER element, fully encoded as a + binary string. + """ + + # Elements in the set must be ordered in lexicographic order + ordered = [] + for item in self._seq: + if _isInt(item): + bys = DerInteger(item).encode() + else: + bys = item + ordered.append(bys) + ordered.sort() + self.payload = b('').join(ordered) + return DerObject.encode(self) + +def newDerSetOf(*der_objs): + """Create a DerSequence object, already initialized with all objects + passed as parameters.""" + + der = DerSetOf() + for obj in der_objs: + if isinstance(obj, DerObject): + der.add(obj.encode()) + else: + der.add(obj) + return der diff --git a/lib/Crypto/Util/number.py b/lib/Crypto/Util/number.py new file mode 100644 index 0000000..2b5beb6 --- /dev/null +++ b/lib/Crypto/Util/number.py @@ -0,0 +1,1456 @@ +# +# number.py : Number-theoretic functions +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew M. Kuchling, Barry A. Warsaw, and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +# + +__revision__ = "$Id$" + +from Crypto.pct_warnings import GetRandomNumber_DeprecationWarning, PowmInsecureWarning +from warnings import warn as _warn +import math +import sys +from Crypto.Util.py3compat import * + +bignum = long +try: + from Crypto.PublicKey import _fastmath +except ImportError: + # For production, we are going to let import issues due to gmp/mpir shared + # libraries not loading slide silently and use slowmath. If you'd rather + # see an exception raised if _fastmath exists but cannot be imported, + # uncomment the below + # + # from distutils.sysconfig import get_config_var + # import inspect, os + # _fm_path = os.path.normpath(os.path.dirname(os.path.abspath( + # inspect.getfile(inspect.currentframe()))) + # +"/../../PublicKey/_fastmath"+get_config_var("SO")) + # if os.path.exists(_fm_path): + # raise ImportError("While the _fastmath module exists, importing "+ + # "it failed. This may point to the gmp or mpir shared library "+ + # "not being in the path. _fastmath was found at "+_fm_path) + _fastmath = None + +# You need libgmp v5 or later to get mpz_powm_sec. Warn if it's not available. +if _fastmath is not None and not _fastmath.HAVE_DECL_MPZ_POWM_SEC: + _warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning) + +# New functions +from _number_new import * + +# Commented out and replaced with faster versions below +## def long2str(n): +## s='' +## while n>0: +## s=chr(n & 255)+s +## n=n>>8 +## return s + +## import types +## def str2long(s): +## if type(s)!=types.StringType: return s # Integers will be left alone +## return reduce(lambda x,y : x*256+ord(y), s, 0L) + +def size (N): + """size(N:long) : int + Returns the size of the number N in bits. + """ + bits = 0 + while N >> bits: + bits += 1 + return bits + +def getRandomNumber(N, randfunc=None): + """Deprecated. Use getRandomInteger or getRandomNBitInteger instead.""" + warnings.warn("Crypto.Util.number.getRandomNumber has confusing semantics"+ + "and has been deprecated. Use getRandomInteger or getRandomNBitInteger instead.", + GetRandomNumber_DeprecationWarning) + return getRandomNBitInteger(N, randfunc) + +def getRandomInteger(N, randfunc=None): + """getRandomInteger(N:int, randfunc:callable):long + Return a random number with at most N bits. + + If randfunc is omitted, then Random.new().read is used. + + This function is for internal use only and may be renamed or removed in + the future. + """ + if randfunc is None: + _import_Random() + randfunc = Random.new().read + + S = randfunc(N>>3) + odd_bits = N % 8 + if odd_bits != 0: + char = ord(randfunc(1)) >> (8-odd_bits) + S = bchr(char) + S + value = bytes_to_long(S) + return value + +def getRandomRange(a, b, randfunc=None): + """getRandomRange(a:int, b:int, randfunc:callable):long + Return a random number n so that a <= n < b. + + If randfunc is omitted, then Random.new().read is used. + + This function is for internal use only and may be renamed or removed in + the future. + """ + range_ = b - a - 1 + bits = size(range_) + value = getRandomInteger(bits, randfunc) + while value > range_: + value = getRandomInteger(bits, randfunc) + return a + value + +def getRandomNBitInteger(N, randfunc=None): + """getRandomInteger(N:int, randfunc:callable):long + Return a random number with exactly N-bits, i.e. a random number + between 2**(N-1) and (2**N)-1. + + If randfunc is omitted, then Random.new().read is used. + + This function is for internal use only and may be renamed or removed in + the future. + """ + value = getRandomInteger (N-1, randfunc) + value |= 2L ** (N-1) # Ensure high bit is set + assert size(value) >= N + return value + +def GCD(x,y): + """GCD(x:long, y:long): long + Return the GCD of x and y. + """ + x = abs(x) ; y = abs(y) + while x > 0: + x, y = y % x, x + return y + +def inverse(u, v): + """inverse(u:long, v:long):long + Return the inverse of u mod v. + """ + u3, v3 = long(u), long(v) + u1, v1 = 1L, 0L + while v3 > 0: + q=divmod(u3, v3)[0] + u1, v1 = v1, u1 - v1*q + u3, v3 = v3, u3 - v3*q + while u1<0: + u1 = u1 + v + return u1 + +# Given a number of bits to generate and a random generation function, +# find a prime number of the appropriate size. + +def getPrime(N, randfunc=None): + """getPrime(N:int, randfunc:callable):long + Return a random N-bit prime number. + + If randfunc is omitted, then Random.new().read is used. + """ + if randfunc is None: + _import_Random() + randfunc = Random.new().read + + number=getRandomNBitInteger(N, randfunc) | 1 + while (not isPrime(number, randfunc=randfunc)): + number=number+2 + return number + + +def _rabinMillerTest(n, rounds, randfunc=None): + """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int + Tests if n is prime. + Returns 0 when n is definitly composite. + Returns 1 when n is probably prime. + Returns 2 when n is definitly prime. + + If randfunc is omitted, then Random.new().read is used. + + This function is for internal use only and may be renamed or removed in + the future. + """ + # check special cases (n==2, n even, n < 2) + if n < 3 or (n & 1) == 0: + return n == 2 + # n might be very large so it might be beneficial to precalculate n-1 + n_1 = n - 1 + # determine m and b so that 2**b * m = n - 1 and b maximal + b = 0 + m = n_1 + while (m & 1) == 0: + b += 1 + m >>= 1 + + tested = [] + # we need to do at most n-2 rounds. + for i in xrange (min (rounds, n-2)): + # randomly choose a < n and make sure it hasn't been tested yet + a = getRandomRange (2, n, randfunc) + while a in tested: + a = getRandomRange (2, n, randfunc) + tested.append (a) + # do the rabin-miller test + z = pow (a, m, n) # (a**m) % n + if z == 1 or z == n_1: + continue + composite = 1 + for r in xrange (b): + z = (z * z) % n + if z == 1: + return 0 + elif z == n_1: + composite = 0 + break + if composite: + return 0 + return 1 + +def getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None): + """getStrongPrime(N:int, e:int, false_positive_prob:float, randfunc:callable):long + Return a random strong N-bit prime number. + In this context p is a strong prime if p-1 and p+1 have at + least one large prime factor. + N should be a multiple of 128 and > 512. + + If e is provided the returned prime p-1 will be coprime to e + and thus suitable for RSA where e is the public exponent. + + The optional false_positive_prob is the statistical probability + that true is returned even though it is not (pseudo-prime). + It defaults to 1e-6 (less than 1:1000000). + Note that the real probability of a false-positive is far less. This is + just the mathematically provable limit. + + randfunc should take a single int parameter and return that + many random bytes as a string. + If randfunc is omitted, then Random.new().read is used. + """ + # This function was implemented following the + # instructions found in the paper: + # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" + # by Robert D. Silverman + # RSA Laboratories + # May 17, 1997 + # which by the time of writing could be freely downloaded here: + # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf + + # Use the accelerator if available + if _fastmath is not None: + return _fastmath.getStrongPrime(long(N), long(e), false_positive_prob, + randfunc) + + if (N < 512) or ((N % 128) != 0): + raise ValueError ("bits must be multiple of 128 and > 512") + + rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) + + # calculate range for X + # lower_bound = sqrt(2) * 2^{511 + 128*x} + # upper_bound = 2^{512 + 128*x} - 1 + x = (N - 512) >> 7; + # We need to approximate the sqrt(2) in the lower_bound by an integer + # expression because floating point math overflows with these numbers + lower_bound = divmod(14142135623730950489L * (2L ** (511 + 128*x)), + 10000000000000000000L)[0] + upper_bound = (1L << (512 + 128*x)) - 1 + # Randomly choose X in calculated range + X = getRandomRange (lower_bound, upper_bound, randfunc) + + # generate p1 and p2 + p = [0, 0] + for i in (0, 1): + # randomly choose 101-bit y + y = getRandomNBitInteger (101, randfunc) + # initialize the field for sieving + field = [0] * 5 * len (sieve_base) + # sieve the field + for prime in sieve_base: + offset = y % prime + for j in xrange ((prime - offset) % prime, len (field), prime): + field[j] = 1 + + # look for suitable p[i] starting at y + result = 0 + for j in range(len(field)): + composite = field[j] + # look for next canidate + if composite: + continue + tmp = y + j + result = _rabinMillerTest (tmp, rabin_miller_rounds) + if result > 0: + p[i] = tmp + break + if result == 0: + raise RuntimeError ("Couln't find prime in field. " + "Developer: Increase field_size") + + # Calculate R + # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 + tmp1 = inverse (p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2 + tmp2 = inverse (p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1 + R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 + + # search for final prime number starting by Y0 + # Y0 = X + (R - X mod p1p2) + increment = p[0] * p[1] + X = X + (R - (X % increment)) + while 1: + is_possible_prime = 1 + # first check candidate against sieve_base + for prime in sieve_base: + if (X % prime) == 0: + is_possible_prime = 0 + break + # if e is given make sure that e and X-1 are coprime + # this is not necessarily a strong prime criterion but useful when + # creating them for RSA where the p-1 and q-1 should be coprime to + # the public exponent e + if e and is_possible_prime: + if e & 1: + if GCD (e, X-1) != 1: + is_possible_prime = 0 + else: + if GCD (e, divmod((X-1),2)[0]) != 1: + is_possible_prime = 0 + + # do some Rabin-Miller-Tests + if is_possible_prime: + result = _rabinMillerTest (X, rabin_miller_rounds) + if result > 0: + break + X += increment + # abort when X has more bits than requested + # TODO: maybe we shouldn't abort but rather start over. + if X >= 1L << N: + raise RuntimeError ("Couln't find prime in field. " + "Developer: Increase field_size") + return X + +def isPrime(N, false_positive_prob=1e-6, randfunc=None): + """isPrime(N:long, false_positive_prob:float, randfunc:callable):bool + Return true if N is prime. + + The optional false_positive_prob is the statistical probability + that true is returned even though it is not (pseudo-prime). + It defaults to 1e-6 (less than 1:1000000). + Note that the real probability of a false-positive is far less. This is + just the mathematically provable limit. + + If randfunc is omitted, then Random.new().read is used. + """ + if _fastmath is not None: + return _fastmath.isPrime(long(N), false_positive_prob, randfunc) + + if N < 3 or N & 1 == 0: + return N == 2 + for p in sieve_base: + if N == p: + return 1 + if N % p == 0: + return 0 + + rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) + return _rabinMillerTest(N, rounds, randfunc) + + +# Improved conversion functions contributed by Barry Warsaw, after +# careful benchmarking + +import struct + +def long_to_bytes(n, blocksize=0): + """long_to_bytes(n:long, blocksize:int) : string + Convert a long integer to a byte string. + + If optional blocksize is given and greater than zero, pad the front of the + byte string with binary zeros so that the length is a multiple of + blocksize. + """ + # after much testing, this algorithm was deemed to be the fastest + s = b('') + n = long(n) + pack = struct.pack + while n > 0: + s = pack('>I', n & 0xffffffffL) + s + n = n >> 32 + # strip off leading zeros + for i in range(len(s)): + if s[i] != b('\000')[0]: + break + else: + # only happens when n == 0 + s = b('\000') + i = 0 + s = s[i:] + # add back some pad bytes. this could be done more efficiently w.r.t. the + # de-padding being done above, but sigh... + if blocksize > 0 and len(s) % blocksize: + s = (blocksize - len(s) % blocksize) * b('\000') + s + return s + +def bytes_to_long(s): + """bytes_to_long(string) : long + Convert a byte string to a long integer. + + This is (essentially) the inverse of long_to_bytes(). + """ + acc = 0L + unpack = struct.unpack + length = len(s) + if length % 4: + extra = (4 - length % 4) + s = b('\000') * extra + s + length = length + extra + for i in range(0, length, 4): + acc = (acc << 32) + unpack('>I', s[i:i+4])[0] + return acc + +# For backwards compatibility... +import warnings +def long2str(n, blocksize=0): + warnings.warn("long2str() has been replaced by long_to_bytes()") + return long_to_bytes(n, blocksize) +def str2long(s): + warnings.warn("str2long() has been replaced by bytes_to_long()") + return bytes_to_long(s) + +def _import_Random(): + # This is called in a function instead of at the module level in order to + # avoid problems with recursive imports + global Random, StrongRandom + from Crypto import Random + from Crypto.Random.random import StrongRandom + + + +# The first 10000 primes used for checking primality. +# This should be enough to eliminate most of the odd +# numbers before needing to do a Rabin-Miller test at all. +sieve_base = ( + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, + 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, + 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, + 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, + 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, + 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, + 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, + 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, + 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, + 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, + 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, + 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, + 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, + 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, + 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, + 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, + 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, + 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, + 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, + 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, + 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, + 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, + 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, + 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, + 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, + 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, + 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, + 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, + 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, + 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, + 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, + 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, + 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, + 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, + 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, + 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, + 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, + 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, + 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, + 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, + 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, + 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, + 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, + 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, + 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, + 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, + 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, + 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, + 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, + 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, + 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, + 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, + 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, + 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, + 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, + 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, + 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, + 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, + 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, + 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, + 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, + 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, + 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, + 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, + 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, + 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, + 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, + 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, + 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, + 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, + 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, + 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, + 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, + 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, + 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, + 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, + 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, + 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, + 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, + 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, + 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, + 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, + 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, + 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, + 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, + 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, + 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, + 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, + 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, + 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, + 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, + 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, + 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, + 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, + 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, + 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, + 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, + 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, + 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, + 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, + 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, + 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, + 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, + 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, + 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, + 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, + 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, + 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, + 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, + 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, + 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, + 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, + 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, + 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, + 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, + 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, + 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, + 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, + 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, + 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, + 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, + 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, + 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, + 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, + 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, + 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, + 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, + 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, + 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, + 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, + 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, + 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, + 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, + 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, + 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, + 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, + 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, + 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, + 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, + 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, + 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, + 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, + 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, + 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, + 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, + 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, + 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, + 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, + 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, + 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, + 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, + 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, + 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, + 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, + 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, + 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, + 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, + 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, + 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, + 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, + 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, + 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, + 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, + 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, + 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, + 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, + 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, + 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, + 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, + 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, + 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, + 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, + 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, + 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, + 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, + 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, + 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, + 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, + 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, + 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, + 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, + 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, + 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, + 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, + 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, + 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, + 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, + 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, + 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, + 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, + 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, + 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, + 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, + 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, + 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, + 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, + 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, + 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, + 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, + 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, + 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, + 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, + 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, + 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, + 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, + 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, + 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, + 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, + 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, + 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, + 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, + 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, + 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, + 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, + 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, + 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, + 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, + 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, + 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, + 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, + 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, + 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, + 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, + 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, + 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, + 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, + 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, + 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, + 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, + 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, + 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, + 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, + 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, + 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, + 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, + 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, + 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, + 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, + 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, + 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, + 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, + 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, + 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, + 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, + 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, + 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, + 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, + 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, + 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, + 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, + 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, + 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, + 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, + 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, + 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, + 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, + 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, + 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, + 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, + 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, + 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, + 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, + 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, + 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, + 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, + 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, + 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, + 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, + 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, + 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, + 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, + 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, + 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, + 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, + 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, + 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, + 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, + 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, + 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, + 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, + 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, + 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, + 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, + 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, + 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, + 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, + 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, + 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, + 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, + 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, + 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, + 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, + 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, + 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, + 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, + 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, + 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, + 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, + 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, + 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, + 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, + 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, + 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, + 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, + 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, + 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, + 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, + 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, + 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, + 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, + 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, + 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, + 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, + 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, + 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, + 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, + 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, + 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, + 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, + 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, + 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, + 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, + 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, + 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, + 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, + 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, + 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, + 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, + 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, + 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, + 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, + 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, + 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, + 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, + 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, + 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, + 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, + 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, + 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, + 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, + 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, + 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, + 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, + 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, + 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, + 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, + 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, + 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, + 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, + 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, + 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, + 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, + 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, + 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, + 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, + 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, + 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, + 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, + 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, + 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, + 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, + 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, + 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, + 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, + 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, + 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, + 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, + 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, + 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, + 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, + 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, + 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, + 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, + 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, + 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, + 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, + 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, + 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, + 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, + 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, + 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, + 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, + 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, + 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, + 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, + 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, + 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, + 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, + 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, + 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, + 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, + 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, + 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, + 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, + 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, + 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, + 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, + 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, + 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, + 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, + 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, + 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, + 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, + 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, + 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, + 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, + 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, + 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, + 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, + 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, + 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, + 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, + 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, + 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, + 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, + 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, + 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, + 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, + 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, + 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, + 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, + 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, + 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, + 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, + 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, + 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, + 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, + 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, + 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, + 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, + 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, + 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, + 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, + 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, + 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, + 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, + 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, + 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, + 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, + 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, + 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, + 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, + 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, + 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, + 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, + 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, + 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, + 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, + 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, + 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, + 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, + 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, + 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, + 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, + 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, + 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, + 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, + 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, + 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, + 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, + 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, + 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, + 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, + 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, + 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, + 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, + 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, + 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, + 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, + 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, + 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, + 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, + 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, + 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, + 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, + 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, + 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, + 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, + 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, + 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, + 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, + 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, + 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, + 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, + 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, + 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, + 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, + 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, + 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, + 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, + 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, + 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, + 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, + 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, + 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, + 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, + 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, + 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, + 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, + 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, + 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, + 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, + 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, + 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, + 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, + 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, + 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, + 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, + 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, + 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, + 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, + 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, + 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, + 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, + 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, + 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, + 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, + 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, + 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, + 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, + 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, + 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, + 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, + 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, + 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, + 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, + 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, + 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, + 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, + 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, + 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, + 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, + 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, + 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, + 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, + 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, + 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, + 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, + 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, + 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, + 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, + 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, + 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, + 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, + 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, + 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, + 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, + 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, + 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, + 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, + 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, + 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, + 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, + 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, + 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, + 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, + 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, + 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, + 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, + 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, + 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, + 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, + 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, + 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, + 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, + 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, + 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, + 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, + 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, + 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, + 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, + 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, + 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, + 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, + 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, + 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, + 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, + 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, + 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, + 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, + 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, + 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, + 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, + 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, + 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, + 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, + 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, + 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, + 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, + 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, + 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, + 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, + 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, + 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, + 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, + 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, + 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, + 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, + 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, + 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, + 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, + 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, + 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, + 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, + 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, + 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, + 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, + 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, + 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, + 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, + 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, + 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, + 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, + 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, + 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, + 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, + 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, + 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, + 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, + 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, + 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, + 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, + 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, + 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, + 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, + 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, + 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, + 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, + 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, + 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, + 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, + 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, + 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, + 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, + 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, + 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, + 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, + 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, + 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, + 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, + 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, + 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, + 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, + 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, + 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, + 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, + 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, + 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, + 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, + 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, + 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, + 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, + 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, + 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, + 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, + 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, + 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, + 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, + 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, + 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, + 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, + 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, + 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, + 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, + 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, + 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, + 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, + 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, + 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, + 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, + 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, + 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, + 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, + 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, + 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, + 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, + 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, + 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, + 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, + 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, + 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, + 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, + 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, + 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, + 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, + 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, + 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, + 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, + 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, + 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, + 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, + 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, + 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, + 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, + 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, + 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, + 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, + 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, + 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, + 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, + 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, + 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, + 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, + 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, + 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, + 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, + 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, + 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, + 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, + 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, + 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, + 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, + 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, + 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, + 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, + 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, + 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, + 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, + 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, + 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, + 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, + 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, + 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, + 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, + 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, + 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, + 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, + 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, + 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, + 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, + 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, + 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, + 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, + 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, + 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, + 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, + 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, + 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, + 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, + 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, + 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, + 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, + 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, + 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, + 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, + 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, + 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, + 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, + 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, + 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, + 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, + 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, + 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, + 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, + 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, + 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, + 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, + 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, + 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, + 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, + 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, + 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, + 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, + 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, + 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, + 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, + 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, + 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, + 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, + 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, + 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, + 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, + 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, + 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, + 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, + 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, + 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, + 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, + 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, + 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, + 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, + 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, + 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, + 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, + 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, + 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, + 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, + 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, + 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, + 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, + 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, + 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, + 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, + 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, + 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, + 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, + 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, + 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, + 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, + 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, + 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, + 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, + 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, + 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, + 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, + 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, + 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, + 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, + 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, + 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, + 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, + 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, + 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, + 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, + 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, + 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, + 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, + 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, + 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, + 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, + 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, + 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, + 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, + 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, + 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, + 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, + 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, + 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, + 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, + 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, + 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, + 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, + 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, + 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, + 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, + 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, + 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, + 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, + 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, + 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, + 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, + 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, + 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, + 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, + 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, + 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, + 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, + 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, + 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, + 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, + 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, + 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, + 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, + 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, + 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, + 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, + 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, + 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, + 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, + 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, + 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, + 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, + 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, + 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, + 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, + 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, + 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, + 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, + 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, + 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, + 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, + 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, + 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, + 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, + 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, + 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, + 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, + 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, + 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, + 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, + 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, + 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, + 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, + 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, + 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, + 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, + 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, + 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, + 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, + 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, + 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, + 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, + 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, + 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, + 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, + 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, + 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, + 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, + 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, + 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, + 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, + 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, + 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, + 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, + 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, + 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, + 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, + 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, + 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, + 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, + 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, + 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, + 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, + 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, + 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, + 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, + 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, + 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, +100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, +100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, +100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, +100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, +100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, +100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, +100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, +100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, +101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, +101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, +101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, +101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, +101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, +101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, +101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, +101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, +101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, +102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, +102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, +102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, +102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, +102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, +102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, +102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, +102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, +102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, +103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, +103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, +103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, +103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, +103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, +103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, +103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, +103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, +104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, +104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, +104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, +104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, +104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, +104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, +) diff --git a/lib/Crypto/Util/py21compat.py b/lib/Crypto/Util/py21compat.py new file mode 100644 index 0000000..658fd36 --- /dev/null +++ b/lib/Crypto/Util/py21compat.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# +# Util/py21compat.py : Compatibility code for Python 2.1 +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Compatibility code for Python 2.1 + +Currently, this just defines: + - True and False + - object + - isinstance +""" + +__revision__ = "$Id$" +__all__ = [] + +import sys +import __builtin__ + +# 'True' and 'False' aren't defined in Python 2.1. Define them. +try: + True, False +except NameError: + (True, False) = (1, 0) + __all__ += ['True', 'False'] + +# New-style classes were introduced in Python 2.2. Defining "object" in Python +# 2.1 lets us use new-style classes in versions of Python that support them, +# while still maintaining backward compatibility with old-style classes +try: + object +except NameError: + class object: pass + __all__ += ['object'] + +# Starting with Python 2.2, isinstance allows a tuple for the second argument. +# Also, builtins like "tuple", "list", "str", "unicode", "int", and "long" +# became first-class types, rather than functions. We want to support +# constructs like: +# isinstance(x, (int, long)) +# So we hack it for Python 2.1. +try: + isinstance(5, (int, long)) +except TypeError: + __all__ += ['isinstance'] + _builtin_type_map = { + tuple: type(()), + list: type([]), + str: type(""), + unicode: type(u""), + int: type(0), + long: type(0L), + } + def isinstance(obj, t): + if not __builtin__.isinstance(t, type(())): + # t is not a tuple + return __builtin__.isinstance(obj, _builtin_type_map.get(t, t)) + else: + # t is a tuple + for typ in t: + if __builtin__.isinstance(obj, _builtin_type_map.get(typ, typ)): + return True + return False + +# +# Python 2.2 introduces the built-in staticmethod(). Python 2.4 turns +# it into a function decorator (@staticmethod). +# +# The following recipe for achieving the same thing in Python 2.1 comes +# from the Python Cookbok ("Implementanting Static Methods"). +# +try: + class A: + def a(): pass + a = staticmethod(a) +except NameError: + class staticmethod: + def __init__(self, anycallable): + self.__call__ = anycallable + __all__ += ['staticmethod'] + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Util/py3compat.py b/lib/Crypto/Util/py3compat.py new file mode 100644 index 0000000..b8b89bf --- /dev/null +++ b/lib/Crypto/Util/py3compat.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# +# Util/py3compat.py : Compatibility code for handling Py3k / Python 2.x +# +# Written in 2010 by Thorsten Behrens +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Compatibility code for handling string/bytes changes from Python 2.x to Py3k + +In Python 2.x, strings (of type ''str'') contain binary data, including encoded +Unicode text (e.g. UTF-8). The separate type ''unicode'' holds Unicode text. +Unicode literals are specified via the u'...' prefix. Indexing or slicing +either type always produces a string of the same type as the original. +Data read from a file is always of '''str'' type. + +In Python 3.x, strings (type ''str'') may only contain Unicode text. The u'...' +prefix and the ''unicode'' type are now redundant. A new type (called +''bytes'') has to be used for binary data (including any particular +''encoding'' of a string). The b'...' prefix allows one to specify a binary +literal. Indexing or slicing a string produces another string. Slicing a byte +string produces another byte string, but the indexing operation produces an +integer. Data read from a file is of '''str'' type if the file was opened in +text mode, or of ''bytes'' type otherwise. + +Since PyCrypto aims at supporting both Python 2.x and 3.x, the following helper +functions are used to keep the rest of the library as independent as possible +from the actual Python version. + +In general, the code should always deal with binary strings, and use integers +instead of 1-byte character strings. + +b(s) + Take a text string literal (with no prefix or with u'...' prefix) and + make a byte string. +bchr(c) + Take an integer and make a 1-character byte string. +bord(c) + Take the result of indexing on a byte string and make an integer. +tobytes(s) + Take a text string, a byte string, or a sequence of character taken from + a byte string and make a byte string. +""" + +__revision__ = "$Id$" + +import sys + +if sys.version_info[0] == 2: + def b(s): + return s + def bchr(s): + return chr(s) + def bstr(s): + return str(s) + def bord(s): + return ord(s) + if sys.version_info[1] == 1: + def tobytes(s): + try: + return s.encode('latin-1') + except: + return ''.join(s) + def tostr(bs): + return unicode(bs, 'latin-1') + else: + def tobytes(s): + if isinstance(s, unicode): + return s.encode("latin-1") + else: + return ''.join(s) + def tostr(bs): + return bs.decode('latin-1') + # In Pyton 2.x, StringIO is a stand-alone module + from StringIO import StringIO as BytesIO +else: + def b(s): + return s.encode("latin-1") # utf-8 would cause some side-effects we don't want + def bchr(s): + return bytes([s]) + def bstr(s): + if isinstance(s,str): + return bytes(s,"latin-1") + else: + return bytes(s) + def bord(s): + return s + def tobytes(s): + if isinstance(s,bytes): + return s + else: + if isinstance(s,str): + return s.encode("latin-1") + else: + return bytes(s) + def tostr(bs): + return bs.decode("latin-1") + # In Pyton 3.x, StringIO is a sub-module of io + from io import BytesIO + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/Util/randpool.py b/lib/Crypto/Util/randpool.py new file mode 100644 index 0000000..8b5a0b7 --- /dev/null +++ b/lib/Crypto/Util/randpool.py @@ -0,0 +1,82 @@ +# +# randpool.py : Cryptographically strong random number generation +# +# Part of the Python Cryptography Toolkit +# +# Written by Andrew M. Kuchling, Mark Moraes, and others +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +# + +__revision__ = "$Id$" + +from Crypto.pct_warnings import RandomPool_DeprecationWarning +import Crypto.Random +import warnings + +class RandomPool: + """Deprecated. Use Random.new() instead. + + See http://www.pycrypto.org/randpool-broken + """ + def __init__(self, numbytes = 160, cipher=None, hash=None, file=None): + warnings.warn("This application uses RandomPool, which is BROKEN in older releases. See http://www.pycrypto.org/randpool-broken", + RandomPool_DeprecationWarning) + self.__rng = Crypto.Random.new() + self.bytes = numbytes + self.bits = self.bytes * 8 + self.entropy = self.bits + + def get_bytes(self, N): + return self.__rng.read(N) + + def _updateEntropyEstimate(self, nbits): + self.entropy += nbits + if self.entropy < 0: + self.entropy = 0 + elif self.entropy > self.bits: + self.entropy = self.bits + + def _randomize(self, N=0, devname="/dev/urandom"): + """Dummy _randomize() function""" + self.__rng.flush() + + def randomize(self, N=0): + """Dummy randomize() function""" + self.__rng.flush() + + def stir(self, s=''): + """Dummy stir() function""" + self.__rng.flush() + + def stir_n(self, N=3): + """Dummy stir_n() function""" + self.__rng.flush() + + def add_event(self, s=''): + """Dummy add_event() function""" + self.__rng.flush() + + def getBytes(self, N): + """Dummy getBytes() function""" + return self.get_bytes(N) + + def addEvent(self, event, s=""): + """Dummy addEvent() function""" + return self.add_event() diff --git a/lib/Crypto/Util/winrandom.py b/lib/Crypto/Util/winrandom.py new file mode 100644 index 0000000..0242815 --- /dev/null +++ b/lib/Crypto/Util/winrandom.py @@ -0,0 +1,28 @@ +# +# Util/winrandom.py : Stub for Crypto.Random.OSRNG.winrandom +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +from Crypto.Random.OSRNG.winrandom import * + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/lib/Crypto/__init__.py b/lib/Crypto/__init__.py new file mode 100644 index 0000000..2834731 --- /dev/null +++ b/lib/Crypto/__init__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Python Cryptography Toolkit + +A collection of cryptographic modules implementing various algorithms +and protocols. + +Subpackages: + +Crypto.Cipher + Secret-key (AES, DES, ARC4) and public-key encryption (RSA PKCS#1) algorithms +Crypto.Hash + Hashing algorithms (MD5, SHA, HMAC) +Crypto.Protocol + Cryptographic protocols (Chaffing, all-or-nothing transform, key derivation + functions). This package does not contain any network protocols. +Crypto.PublicKey + Public-key encryption and signature algorithms (RSA, DSA) +Crypto.Signature + Public-key signature algorithms (RSA PKCS#1) +Crypto.Util + Various useful modules and functions (long-to-string conversion, random number + generation, number theoretic functions) +""" + +__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature', 'IO'] + +__version__ = '2.7a1' # See also below and setup.py +__revision__ = "$Id$" + +# New software should look at this instead of at __version__ above. +version_info = (2, 7, 0, 'alpha', 1) # See also above and setup.py + diff --git a/lib/Crypto/pct_warnings.py b/lib/Crypto/pct_warnings.py new file mode 100644 index 0000000..d6adc5b --- /dev/null +++ b/lib/Crypto/pct_warnings.py @@ -0,0 +1,63 @@ +# -*- coding: ascii -*- +# +# pct_warnings.py : PyCrypto warnings file +# +# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +# +# Base classes. All our warnings inherit from one of these in order to allow +# the user to specifically filter them. +# + +class CryptoWarning(Warning): + """Base class for PyCrypto warnings""" + +class CryptoDeprecationWarning(DeprecationWarning, CryptoWarning): + """Base PyCrypto DeprecationWarning class""" + +class CryptoRuntimeWarning(RuntimeWarning, CryptoWarning): + """Base PyCrypto RuntimeWarning class""" + +# +# Warnings that we might actually use +# + +class RandomPool_DeprecationWarning(CryptoDeprecationWarning): + """Issued when Crypto.Util.randpool.RandomPool is instantiated.""" + +class ClockRewindWarning(CryptoRuntimeWarning): + """Warning for when the system clock moves backwards.""" + +class GetRandomNumber_DeprecationWarning(CryptoDeprecationWarning): + """Issued when Crypto.Util.number.getRandomNumber is invoked.""" + +class DisableShortcut_DeprecationWarning(CryptoDeprecationWarning): + """Issued when Counter.new(disable_shortcut=...) is invoked.""" + +class PowmInsecureWarning(CryptoRuntimeWarning): + """Warning for when _fastmath is built without mpz_powm_sec""" + +# By default, we want this warning to be shown every time we compensate for +# clock rewinding. +import warnings as _warnings +_warnings.filterwarnings('always', category=ClockRewindWarning, append=1) + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4 new file mode 100644 index 0000000..1d38b76 --- /dev/null +++ b/m4/ax_append_flag.m4 @@ -0,0 +1,69 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) +# +# DESCRIPTION +# +# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space +# added in between. +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains +# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly +# FLAG. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_APPEND_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl +AS_VAR_SET_IF(FLAGS, + [case " AS_VAR_GET(FLAGS) " in + *" $1 "*) + AC_RUN_LOG([: FLAGS already contains $1]) + ;; + *) + AC_RUN_LOG([: FLAGS="$FLAGS $1"]) + AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) + ;; + esac], + [AS_VAR_SET(FLAGS,["$1"])]) +AS_VAR_POPDEF([FLAGS])dnl +])dnl AX_APPEND_FLAG diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000..c3a8d69 --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,72 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 new file mode 100644 index 0000000..e2d0d36 --- /dev/null +++ b/m4/ax_check_link_flag.m4 @@ -0,0 +1,71 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the linker or gives an error. +# (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_LINK_FLAG], +[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS $4 $1" + AC_LINK_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + LDFLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_LINK_FLAGS diff --git a/m4/ax_check_preproc_flag.m4 b/m4/ax_check_preproc_flag.m4 new file mode 100644 index 0000000..b1cfef6 --- /dev/null +++ b/m4/ax_check_preproc_flag.m4 @@ -0,0 +1,72 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's +# preprocessor or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the preprocessor's default +# flags when the check is done. The check is thus made with the flags: +# "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the +# preprocessor to issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_PREPROC_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [ + ax_check_save_flags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $4 $1" + AC_PREPROC_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + CPPFLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_PREPROC_FLAGS diff --git a/pct-speedtest.py b/pct-speedtest.py new file mode 100644 index 0000000..4ce18be --- /dev/null +++ b/pct-speedtest.py @@ -0,0 +1,441 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# pct-speedtest.py: Speed test for the Python Cryptography Toolkit +# +# Written in 2009 by Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +import time +import os +import sys + +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5 as RSAES_PKCS1_v1_5 +from Crypto.Signature import PKCS1_PSS, PKCS1_v1_5 as RSASSA_PKCS1_v1_5 +from Crypto.Cipher import AES, ARC2, ARC4, Blowfish, CAST, DES3, DES, XOR +from Crypto.Hash import HMAC, MD2, MD4, MD5, SHA224, SHA256, SHA384, SHA512, CMAC +from Crypto.Random import get_random_bytes +import Crypto.Util.Counter +from Crypto.Util.number import bytes_to_long +try: + from Crypto.Hash import SHA1 +except ImportError: + # Maybe it's called SHA + from Crypto.Hash import SHA as SHA1 +try: + from Crypto.Hash import RIPEMD160 +except ImportError: + # Maybe it's called RIPEMD + try: + from Crypto.Hash import RIPEMD as RIPEMD160 + except ImportError: + # Some builds of PyCrypto don't have the RIPEMD module + RIPEMD160 = None + +try: + import hashlib + import hmac +except ImportError: # Some builds/versions of Python don't have a hashlib module + hashlib = hmac = None + +# os.urandom() is less noisy when profiling, but it doesn't exist in Python < 2.4 +try: + urandom = os.urandom +except AttributeError: + urandom = get_random_bytes + +from Crypto.Random import random as pycrypto_random +import random as stdlib_random + +class Benchmark: + + def __init__(self): + self.__random_data = None + + def random_keys(self, bytes, n=10**5): + """Return random keys of the specified number of bytes. + + If this function has been called before with the same number of bytes, + cached keys are used instead of randomly generating new ones. + """ + return self.random_blocks(bytes, n) + + def random_blocks(self, bytes_per_block, blocks): + bytes = bytes_per_block * blocks + data = self.random_data(bytes) + retval = [] + for i in range(blocks): + p = i * bytes_per_block + retval.append(data[p:p+bytes_per_block]) + return retval + + def random_data(self, bytes): + if self.__random_data is None: + self.__random_data = self._random_bytes(bytes) + return self.__random_data + elif bytes == len(self.__random_data): + return self.__random_data + elif bytes < len(self.__random_data): + return self.__random_data[:bytes] + else: + self.__random_data += self._random_bytes(bytes - len(self.__random_data)) + return self.__random_data + + def _random_bytes(self, b): + return urandom(b) + + def announce_start(self, test_name): + sys.stdout.write("%s: " % (test_name,)) + sys.stdout.flush() + + def announce_result(self, value, units): + sys.stdout.write("%.2f %s\n" % (value, units)) + sys.stdout.flush() + + def test_random_module(self, module_name, module): + self.announce_start("%s.choice" % (module_name,)) + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + t0 = time.time() + for i in range(5000): + module.choice(alphabet) + t = time.time() + invocations_per_second = 5000 / (t - t0) + self.announce_result(invocations_per_second, "invocations/sec") + + def test_pubkey_setup(self, pubkey_name, module, key_bytes): + self.announce_start("%s pubkey setup" % (pubkey_name,)) + keys = self.random_keys(key_bytes)[:5] + + t0 = time.time() + for k in keys: + module.generate(key_bytes*8) + t = time.time() + pubkey_setups_per_second = len(keys) / (t - t0) + self.announce_result(pubkey_setups_per_second, "Keys/sec") + + def test_key_setup(self, cipher_name, module, key_bytes, mode): + self.announce_start("%s key setup" % (cipher_name,)) + + # Generate random keys for use with the tests + keys = self.random_keys(key_bytes, n=5000) + + if hasattr(module, "MODE_CCM") and mode==module.MODE_CCM: + iv = b"\xAA"*8 + else: + iv = b"\xAA"*module.block_size + + # Perform key setups + if mode is None: + t0 = time.time() + for k in keys: + module.new(k) + t = time.time() + else: + t0 = time.time() + + if mode==module.MODE_CTR: + for k in keys: + ctr = Crypto.Util.Counter.new(module.block_size*8, + initial_value=bytes_to_long(iv)) + module.new(k, module.MODE_CTR, counter=ctr) + else: + for k in keys: + module.new(k, mode, iv) + t = time.time() + + key_setups_per_second = len(keys) / (t - t0) + self.announce_result(key_setups_per_second/1000, "kKeys/sec") + + def test_encryption(self, cipher_name, module, key_bytes, mode): + self.announce_start("%s encryption" % (cipher_name,)) + + # Generate random keys for use with the tests + rand = self.random_data(key_bytes + module.block_size) + key, iv = rand[:key_bytes], rand[key_bytes:] + blocks = self.random_blocks(16384, 1000) + if mode is None: + cipher = module.new(key) + elif mode == "CTR-BE": + from Crypto.Util import Counter + cipher = module.new(key, module.MODE_CTR, counter=Counter.new(module.block_size*8, little_endian=False)) + elif mode == "CTR-LE": + from Crypto.Util import Counter + cipher = module.new(key, module.MODE_CTR, counter=Counter.new(module.block_size*8, little_endian=True)) + elif hasattr(module, 'MODE_CCM') and mode==module.MODE_CCM: + cipher = module.new(key, mode, iv[:8], msg_len=len(rand)*len(blocks)) + elif mode==module.MODE_CTR: + ctr = Crypto.Util.Counter.new(module.block_size*8, + initial_value=bytes_to_long(iv), + allow_wraparound=True) + cipher = module.new(key, module.MODE_CTR, counter=ctr) + else: + cipher = module.new(key, mode, iv) + + # Perform encryption + t0 = time.time() + for b in blocks: + cipher.encrypt(b) + t = time.time() + + encryption_speed = (len(blocks) * len(blocks[0])) / (t - t0) + self.announce_result(encryption_speed / 10**6, "MBps") + + def test_hash_small(self, hash_name, hash_constructor, digest_size): + self.announce_start("%s (%d-byte inputs)" % (hash_name, digest_size)) + + blocks = self.random_blocks(digest_size, 10000) + + # Initialize hashes + t0 = time.time() + for b in blocks: + hash_constructor(b).digest() + t = time.time() + + hashes_per_second = len(blocks) / (t - t0) + self.announce_result(hashes_per_second / 1000, "kHashes/sec") + + def test_hash_large(self, hash_name, hash_constructor, digest_size): + self.announce_start("%s (single large input)" % (hash_name,)) + + blocks = self.random_blocks(16384, 10000) + + # Perform hashing + t0 = time.time() + h = hash_constructor() + for b in blocks: + h.update(b) + h.digest() + t = time.time() + + hash_speed = len(blocks) * len(blocks[0]) / (t - t0) + self.announce_result(hash_speed / 10**6, "MBps") + + def test_hmac_small(self, mac_name, hmac_constructor, digestmod, digest_size): + keys = iter(self.random_keys(digest_size)) + if sys.version_info[0] == 2: + mac_constructor = lambda data=None: hmac_constructor(keys.next(), data, digestmod) + else: + mac_constructor = lambda data=None: hmac_constructor(keys.__next__(), data, digestmod) + self.test_hash_small(mac_name, mac_constructor, digest_size) + + def test_hmac_large(self, mac_name, hmac_constructor, digestmod, digest_size): + key = self.random_keys(digest_size)[0] + mac_constructor = lambda data=None: hmac_constructor(key, data, digestmod) + self.test_hash_large(mac_name, mac_constructor, digest_size) + + def test_cmac_small(self, mac_name, cmac_constructor, ciphermod, key_size): + keys = iter(self.random_keys(key_size)) + if sys.version_info[0] == 2: + mac_constructor = lambda data=None: cmac_constructor(keys.next(), data, ciphermod) + else: + mac_constructor = lambda data=None: cmac_constructor(keys.__next__(), data, ciphermod) + self.test_hash_small(mac_name, mac_constructor, ciphermod.block_size) + + def test_cmac_large(self, mac_name, cmac_constructor, ciphermod, key_size): + key = self.random_keys(key_size)[0] + mac_constructor = lambda data=None: cmac_constructor(key, data, ciphermod) + self.test_hash_large(mac_name, mac_constructor, ciphermod.block_size) + + def test_pkcs1_sign(self, scheme_name, scheme_constructor, hash_name, hash_constructor, digest_size): + self.announce_start("%s signing %s (%d-byte inputs)" % (scheme_name, hash_name, digest_size)) + + # Make a key + k = RSA.generate(2048) + sigscheme = scheme_constructor(k) + + # Make some hashes + blocks = self.random_blocks(digest_size, 50) + hashes = [] + for b in blocks: + hashes.append(hash_constructor(b)) + + # Perform signing + t0 = time.time() + for h in hashes: + sigscheme.sign(h) + t = time.time() + + speed = len(hashes) / (t - t0) + self.announce_result(speed, "sigs/sec") + + def test_pkcs1_verify(self, scheme_name, scheme_constructor, hash_name, hash_constructor, digest_size): + self.announce_start("%s verification %s (%d-byte inputs)" % (scheme_name, hash_name, digest_size)) + + # Make a key + k = RSA.generate(2048) + sigscheme = scheme_constructor(k) + + # Make some hashes + blocks = self.random_blocks(digest_size, 50) + hashes = [] + for b in blocks: + hashes.append(hash_constructor(b)) + + # Make some signatures + signatures = [] + for h in hashes: + signatures.append(sigscheme.sign(h)) + + # Double the list, to make timing better + hashes = hashes + hashes + signatures = signatures + signatures + + # Perform verification + t0 = time.time() + for h, s in zip(hashes, signatures): + sigscheme.verify(h, s) + t = time.time() + + speed = len(hashes) / (t - t0) + self.announce_result(speed, "sigs/sec") + + def run(self): + pubkey_specs = [ + ("RSA(1024)", RSA, int(1024/8)), + ("RSA(2048)", RSA, int(2048/8)), + ("RSA(4096)", RSA, int(4096/8)), + ] + block_specs = [ + ("DES", DES, 8), + ("DES3", DES3, 24), + ("AES128", AES, 16), + ("AES192", AES, 24), + ("AES256", AES, 32), + ("Blowfish(256)", Blowfish, 32), + ("CAST(40)", CAST, 5), + ("CAST(80)", CAST, 10), + ("CAST(128)", CAST, 16), + ] + stream_specs = [ + ("ARC2(128)", ARC2, 16), + ("ARC4(128)", ARC4, 16), + ("XOR(24)", XOR, 3), + ("XOR(256)", XOR, 32), + ] + hash_specs = [ + ("MD2", MD2), + ("MD4", MD4), + ("MD5", MD5), + ("SHA1", SHA1), + ("SHA224", SHA224), + ("SHA256", SHA256), + ("SHA384", SHA384), + ("SHA512", SHA512), + ] + if RIPEMD160 is not None: + hash_specs += [("RIPEMD160", RIPEMD160)] + + hashlib_specs = [] + if hashlib is not None: + if hasattr(hashlib, 'md5'): hashlib_specs.append(("hashlib.md5", hashlib.md5)) + if hasattr(hashlib, 'sha1'): hashlib_specs.append(("hashlib.sha1", hashlib.sha1)) + if hasattr(hashlib, 'sha224'): hashlib_specs.append(("hashlib.sha224", hashlib.sha224)) + if hasattr(hashlib, 'sha256'): hashlib_specs.append(("hashlib.sha256", hashlib.sha256)) + if hasattr(hashlib, 'sha384'): hashlib_specs.append(("hashlib.sha384", hashlib.sha384)) + if hasattr(hashlib, 'sha512'): hashlib_specs.append(("hashlib.sha512", hashlib.sha512)) + + # stdlib random + self.test_random_module("stdlib random", stdlib_random) + + # Crypto.Random.random + self.test_random_module("Crypto.Random.random", pycrypto_random) + + # Crypto.PublicKey + for pubkey_name, module, key_bytes in pubkey_specs: + self.test_pubkey_setup(pubkey_name, module, key_bytes) + + # Crypto.Cipher (block ciphers) + for cipher_name, module, key_bytes in block_specs: + self.test_key_setup("%s-CBC" % (cipher_name,), module, key_bytes, module.MODE_CBC) + self.test_encryption("%s-CBC" % (cipher_name,), module, key_bytes, module.MODE_CBC) + self.test_encryption("%s-CFB-8" % (cipher_name,), module, key_bytes, module.MODE_CFB) + self.test_encryption("%s-OFB" % (cipher_name,), module, key_bytes, module.MODE_OFB) + self.test_encryption("%s-ECB" % (cipher_name,), module, key_bytes, module.MODE_ECB) + + self.test_key_setup("%s-CTR" % (cipher_name,), module, key_bytes, module.MODE_CTR) + self.test_encryption("%s-CTR" % (cipher_name,), module, key_bytes, module.MODE_CTR) + + self.test_encryption("%s-OPENPGP" % (cipher_name,), module, key_bytes, module.MODE_OPENPGP) + self.test_encryption("%s-CTR-BE" % (cipher_name,), module, key_bytes, "CTR-BE") + self.test_encryption("%s-CTR-LE" % (cipher_name,), module, key_bytes, "CTR-LE") + + if hasattr(module, "MODE_CCM"): + self.test_key_setup("%s-CCM" % (cipher_name,), module, key_bytes, module.MODE_CCM) + self.test_encryption("%s-CCM" % (cipher_name,), module, key_bytes, module.MODE_CCM) + + if hasattr(module, "MODE_EAX"): + self.test_key_setup("%s-EAX" % (cipher_name,), module, key_bytes, module.MODE_EAX) + self.test_encryption("%s-EAX" % (cipher_name,), module, key_bytes, module.MODE_EAX) + + if hasattr(module, "MODE_GCM"): + self.test_key_setup("%s-GCM" % (cipher_name,), module, key_bytes, module.MODE_GCM) + self.test_encryption("%s-GCM" % (cipher_name,), module, key_bytes, module.MODE_GCM) + + # Crypto.Cipher (stream ciphers) + for cipher_name, module, key_bytes in stream_specs: + self.test_key_setup(cipher_name, module, key_bytes, None) + self.test_encryption(cipher_name, module, key_bytes, None) + + # Crypto.Hash + for hash_name, module in hash_specs: + self.test_hash_small(hash_name, module.new, module.digest_size) + self.test_hash_large(hash_name, module.new, module.digest_size) + + # standard hashlib + for hash_name, func in hashlib_specs: + self.test_hash_small(hash_name, func, func().digest_size) + self.test_hash_large(hash_name, func, func().digest_size) + + # PyCrypto HMAC + for hash_name, module in hash_specs: + self.test_hmac_small("HMAC-"+hash_name, HMAC.new, module, module.digest_size) + self.test_hmac_large("HMAC-"+hash_name, HMAC.new, module, module.digest_size) + + # standard hmac + hashlib + for hash_name, func in hashlib_specs: + self.test_hmac_small("hmac+"+hash_name, hmac.HMAC, func, func().digest_size) + self.test_hmac_large("hmac+"+hash_name, hmac.HMAC, func, func().digest_size) + + # CMAC + for cipher_name, module, key_size in (("AES128", AES, 16),): + self.test_cmac_small(cipher_name+"-CMAC", CMAC.new, module, key_size) + self.test_cmac_large(cipher_name+"-CMAC", CMAC.new, module, key_size) + + # PKCS1_v1_5 (sign) + Crypto.Hash + for hash_name, module in hash_specs: + self.test_pkcs1_sign("PKCS#1-v1.5", RSASSA_PKCS1_v1_5.new, hash_name, module.new, module.digest_size) + + # PKCS1_PSS (sign) + Crypto.Hash + for hash_name, module in hash_specs: + self.test_pkcs1_sign("PKCS#1-PSS", PKCS1_PSS.new, hash_name, module.new, module.digest_size) + + # PKCS1_v1_5 (verify) + Crypto.Hash + for hash_name, module in hash_specs: + self.test_pkcs1_verify("PKCS#1-v1.5", RSASSA_PKCS1_v1_5.new, hash_name, module.new, module.digest_size) + + # PKCS1_PSS (verify) + Crypto.Hash + for hash_name, module in hash_specs: + self.test_pkcs1_verify("PKCS#1-PSS", PKCS1_PSS.new, hash_name, module.new, module.digest_size) + +if __name__ == '__main__': + Benchmark().run() + +# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/python-3-changes.txt b/python-3-changes.txt new file mode 100644 index 0000000..b135bfe --- /dev/null +++ b/python-3-changes.txt @@ -0,0 +1,109 @@ +Py code: + +setup.py invokes 2to3 automatically. This handles int/long and print issues, + among others. +setup.py will touch nt.py on win32 after build and build again. This is + necessary so 2to3 can do its magic on that file. + +There are still a lot of places in the code that need manual attention even + with 2to3. They mostly have to do with string (2.x) vs. byte/unicode (3.x) + representation + +Use "if sys.version_info[0] == 2:" where needed. Ideally, most of the + conditional code can be in py3compat. + +Replace str(x) with bstr(x) if bytes were intended. Becomes str(x) in 2.x and + bytes(x) in 3.x through py3compat module. +Replace chr(x) with bchr(x) if bytes were intended. Becomes chr(x) in 2.x and + bytes([x]) in 3.x through py3compat module. +Replace ord(x) with bord(x) if bytes were intended. Becomes ord(x) in 2.x and + x in 3.x through py3compat module. + +Comparing a string index to a string literal needs to be changed in 3.x, as + b'string'[0] returns an integer, not b's'. +The comparison can be fixed by indexing the right side, too: + "if s[0]==b('\x30')[0]:" or "if self.typeTag!=self.typeTags['SEQUENCE'][0]:" + +String literals need to be bytes if bytes were intended. +Replace "x" with b("x") if bytes were intended. Becomes "x" in 2.x, and + s.encode("x","latin-1") in 3.x through py3compat module. +For example, '"".join' is replaced by 'b("").join', and 's = ""' becomes + 's = b("")'. +Search for \x to find literals that may have been intended as byte strings +!! However, where a human-readable ASCII text string output was intended, + such as in AllOrNothing.undigest(), leave as a string literal !! + +Only load py21compat.py + "if sys.version_info[0] == 2 and sys.version_info[1] == 1:" . + The assignment to True, False generates syntax errors in 3.x, and >= 2.2 don't + need the compatibility code. + +Where print is used with >> to redirect, use a separate function instead. + See setup.py for an example + +The string module has been changed in 3.x. It lost join and split, maketrans + now expects bytes, and so on. +Replace string.join(a,b) with b.join(a). +Replace string.split(a) with a.split(). +Replace body of white-space-stripping functions with 'return "".join(s.split())' + +Integer division via the "/" operator can return a float in 3.x. This causes + issues in Util.number.getStrongPrime. As 2.1 does not support the "//" + operator, divmod(a,b)[0] is used instead, to conform with an existing practice + throughout the rest of the pycrypto code base. + +Do not use assert_/failUnless or failIf. These are deprecated and are scheduled + to be removed in Python 3.3 and 3.4. +Use instead assertEqual(expr,True) for assert_ and assertEqual(expr,False) for + failIf + +Added unit tests for Crypto.Random.random. Fixed random.shuffle(). +random.sample() changed to no longer fail on Python 2.1. + +Added unit test for Crypto.Protocol.AllOrNothing. +AllOrNothing changed to no longer fail occasionally. + +C code: + +Extended "pycrypto_compat.h". It handles #define's for Python 3.x forward + compatibility + +#include "pycrypto_compat.h" +// All other local includes after this, so they can benefit from the +// definitions in pycrypto_compat.h + +The compat header #defines IS_PY3K if compiling on 3.x +The compat header #defines PyBytes_*, PyUnicode_*, PyBytesObject to resolve to + their PyString* counterparts if compiling on 2.x. +PyLong_* can be dangerous depending on code construct (think an if that runs + PyInt_* with else PyLong_*), +therefore it is #defined in each individual module if needed and safe to do so. + +PyString_* has been replaced with PyBytes_* or PyUnicode_* depending on intent +PyStringObject has been replaced with PyBytesObject or PyUnicodeObject + depending on intent. +PyInt_* has been replaced with PyLong_*, where safe to do (in all cases so far) + +The C code uses "#ifdef IS_PY3K" liberally. +Code duplication has been avoided. + +Module initialization and module structure differ significantly in 3.x. + Conditionals take care of it. + +myModuleType.ob_type assignment conditionally becomes PyTypeReady for 3.x. + +getattr cannot be used to check against custom attributes in 3.x. For 3.x, + conditional code uses getattro and PyUnicode_CompareWithASCIIString instead + of strcmp + +hexdigest() needed to be changed to return a Unicode object with 3.x + + +TODO for extra credit: +- Check for type of string in functions and throw an error when it's not + correct. While at it, ensure that functions observe the guidelines below + re type. + This is friendlier than just relying on Python's errors. +- Make sure DerSequence slicing is tested, since I took the explicit slice + functions away in 3.x + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..5269e9d --- /dev/null +++ b/setup.py @@ -0,0 +1,527 @@ +#! /usr/bin/env python +# +# setup.py : Distutils setup script +# +# Part of the Python Cryptography Toolkit +# +# =================================================================== +# Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation; +# All Rights Reserved +# +# This file contains code from the Python 2.2 setup.py module (the +# "Original Code"), with modifications made after it was incorporated +# into PyCrypto (the "Modifications"). +# +# To the best of our knowledge, the Python Software Foundation is the +# copyright holder of the Original Code, and has licensed it under the +# Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for +# details. +# +# The Modifications to this file are dedicated to the public domain. +# To the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. No rights are +# reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +__revision__ = "$Id$" + +from distutils import core +from distutils.ccompiler import new_compiler +from distutils.core import Extension, Command +from distutils.command.build import build +from distutils.command.build_ext import build_ext +import distutils.sysconfig +import os, sys, re +import struct + +if sys.version[0:1] == '1': + raise RuntimeError ("The Python Cryptography Toolkit requires " + "Python 2.x or 3.x to build.") + +if sys.platform == 'win32': + HTONS_LIBS = ['ws2_32'] + plat_ext = [ + Extension("Crypto.Random.OSRNG.winrandom", + libraries = HTONS_LIBS + ['advapi32'], + include_dirs=['src/'], + sources=["src/winrand.c"]) + ] +else: + HTONS_LIBS = [] + plat_ext = [] + +# For test development: Set this to 1 to build with gcov support. +# Use "gcov -p -o build/temp.*/src build/temp.*/src/*.gcda" to build the +# .gcov files +USE_GCOV = 0 + + +try: + # Python 3 + from distutils.command.build_py import build_py_2to3 as build_py +except ImportError: + # Python 2 + from distutils.command.build_py import build_py + +# List of pure Python modules that will be excluded from the binary packages. +# The list consists of (package, module_name) tuples +if sys.version_info[0] == 2: + EXCLUDE_PY = [] +else: + EXCLUDE_PY = [ + # We don't want Py3k to choke on the 2.x compat code + ('Crypto.Util', 'py21compat'), + ] + if sys.platform != "win32": # Avoid nt.py, as 2to3 can't fix it w/o winrandom + EXCLUDE_PY += [('Crypto.Random.OSRNG','nt')] + +# Work around the print / print() issue with Python 2.x and 3.x. We only need +# to print at one point of the code, which makes this easy + +def PrintErr(*args, **kwd): + fout = kwd.get("file", sys.stderr) + w = fout.write + if args: + w(str(args[0])) + sep = kwd.get("sep", " ") + for a in args[1:]: + w(sep) + w(str(a)) + w(kwd.get("end", "\n")) + +def endianness_macro(): + s = struct.pack("@I", 0x33221100) + if s == "\x00\x11\x22\x33".encode(): # little endian + return ('PCT_LITTLE_ENDIAN', 1) + elif s == "\x33\x22\x11\x00".encode(): # big endian + return ('PCT_BIG_ENDIAN', 1) + raise AssertionError("Machine is neither little-endian nor big-endian") + +class PCTBuildExt (build_ext): + def build_extensions(self): + # Detect which modules should be compiled + self.detect_modules() + + # Tweak compiler options + if self.compiler.compiler_type in ('unix', 'cygwin', 'mingw32'): + # Make assert() statements always work + self.__remove_compiler_option("-DNDEBUG") + + if USE_GCOV: # TODO - move this to configure.ac + self.__add_compiler_option("-fprofile-arcs") + self.__add_compiler_option("-ftest-coverage") + self.compiler.libraries += ['gcov'] + + # Python 2.1 and 2.2 don't respect the LDFLAGS environment variable. Hack it. + if sys.version_info < (2, 3, 'final', 0): + if os.environ.get('LDFLAGS'): # Set from ./buildenv (ultimately provided by autoconf) + for opt in os.environ['LDFLAGS'].split(" "): + opt = opt.strip() + if not opt: continue + self.compiler.linker_so.append(opt) + + # Call the superclass's build_extensions method + build_ext.build_extensions(self) + + def detect_modules (self): + # Read the config.h file (usually generated by autoconf) + if self.compiler.compiler_type == 'msvc': + # Add special include directory for MSVC (because MSVC is special) + self.compiler.include_dirs.insert(0, "src/inc-msvc/") + ac = self.__read_autoconf("src/inc-msvc/config.h") + else: + ac = self.__read_autoconf("src/config.h") + + # Detect libgmp or libmpir and don't build _fastmath if both are missing. + if ac.get("HAVE_LIBGMP"): + # Default; no changes needed + pass + elif ac.get("HAVE_LIBMPIR"): + # Change library to libmpir if libgmp is missing + self.__change_extension_lib(["Crypto.PublicKey._fastmath"], + ['mpir']) + # And if this is MSVC, we need to add a linker option + # to make a static libmpir link well into a dynamic _fastmath + if self.compiler.compiler_type == 'msvc': + self.__add_extension_link_option(["Crypto.PublicKey._fastmath"], + ["/NODEFAULTLIB:LIBCMT"]) + else: + # No MP library; use _slowmath. + PrintErr ("warning: GMP or MPIR library not found; Not building "+ + "Crypto.PublicKey._fastmath.") + self.__remove_extensions(["Crypto.PublicKey._fastmath"]) + + # Detect if we have AES-NI instrincs available + if not ac.get("HAVE_WMMINTRIN_H"): + # AES-NI instrincs not available + self.__remove_extensions(["Crypto.Cipher._AESNI"]) + elif not (ac.get("HAVE_POSIX_MEMALIGN") or ac.get("HAVE_ALIGNED_ALLOC") + or ac.get("HAVE__ALIGNED_MALLOC")): + # no function to allocate aligned memory is available + self.__remove_extensions(["Crypto.Cipher._AESNI"]) + elif ac.get("HAVE_MAES"): + # -maes has to be passed to the compiler to use the AES-NI instrincs + self.__add_extension_compile_option(["Crypto.Cipher._AESNI"], + ["-maes"]) + + def __add_extension_compile_option(self, names, options): + """Add compiler options for the specified extension(s)""" + for extension in self.extensions: + if extension.name in names: + extension.extra_compile_args = options + + def __add_extension_link_option(self, names, options): + """Add linker options for the specified extension(s)""" + i = 0 + while i < len(self.extensions): + if self.extensions[i].name in names: + self.extensions[i].extra_link_args = options + i += 1 + + def __change_extension_lib(self, names, libs): + """Change the libraries to be used for the specified extension(s)""" + i = 0 + while i < len(self.extensions): + if self.extensions[i].name in names: + self.extensions[i].libraries = libs + i += 1 + + def __remove_extensions(self, names): + """Remove the specified extension(s) from the list of extensions + to build""" + i = 0 + while i < len(self.extensions): + if self.extensions[i].name in names: + del self.extensions[i] + continue + i += 1 + + def __remove_compiler_option(self, option): + """Remove the specified compiler option. + + Return true if the option was found. Return false otherwise. + """ + found = 0 + for attrname in ('compiler', 'compiler_so'): + compiler = getattr(self.compiler, attrname, None) + if compiler is not None: + while option in compiler: + compiler.remove(option) + found += 1 + return found + + def __add_compiler_option(self, option): + for attrname in ('compiler', 'compiler_so'): + compiler = getattr(self.compiler, attrname, None) + if compiler is not None: + compiler.append(option) + + def __read_autoconf(self, filename): + rx_define = re.compile(r"""^#define (\S+) (?:(\d+)|(".*"))$""") + + result = {} + f = open(filename, "r") + try: + config_lines = f.read().replace("\r\n", "\n").split("\n") + for line in config_lines: + m = rx_define.search(line) + if not m: continue + sym = m.group(1) + n = m.group(2) + s = m.group(3) + if n: + result[sym] = int(n) + elif s: + result[sym] = eval(s) # XXX - hack to unescape C-style string + else: + continue + finally: + f.close() + return result + + def run(self): + # Run the commands that this one depends on (i.e. build_configure) + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + class unmodified: pass # sentinel value + orig_cc = unmodified + try: + # Set environment variables generated by the configure script + if os.path.exists("buildenv"): + try: + f = open("buildenv", "r") + for line in f.readlines(): + if line.startswith("#") or not line.strip(): + continue + k, v = line.split("=", 1) + k, v = k.strip(), v.strip() + os.environ[k] = v + finally: + f.close() + + # Python 2.1 and 2.2 don't respect the CC environment variable by default. Monkey-patch it. + if sys.version_info < (2, 3, 'final', 0) and os.environ.get('CC'): + distutils.sysconfig.get_config_vars() # populates distutils.sysconfig._config_vars + orig_cc = distutils.sysconfig._config_vars['CC'] + distutils.sysconfig._config_vars['CC'] = os.environ['CC'] + + # Build the extension modules + build_ext.run(self) + + finally: + if orig_cc is not unmodified: + # Undo monkey-patch + distutils.sysconfig._config_vars['CC'] = orig_cc + + + def has_configure(self): + compiler = new_compiler(compiler=self.compiler) + return compiler.compiler_type != 'msvc' + + sub_commands = [ ('build_configure', has_configure) ] + build_ext.sub_commands + +class PCTBuildConfigure(Command): + description = "Generate config.h using ./configure (autoconf)" + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if not os.path.exists("config.status"): + if hasattr(os, "chmod"): + import stat + os.chmod("configure", stat.S_IRUSR | stat.S_IWUSR | + stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | + stat.S_IROTH | stat.S_IXOTH) + cmd = "sh configure" # we use "sh" here so that it'll work on mingw32 with standard python.org binaries + if self.verbose < 1: + cmd += " -q" + if os.system(cmd) != 0: + raise RuntimeError("autoconf error") + +class PCTBuildPy(build_py): + def find_package_modules(self, package, package_dir, *args, **kwargs): + modules = build_py.find_package_modules(self, package, package_dir, + *args, **kwargs) + + # Exclude certain modules + retval = [] + for item in modules: + pkg, module = item[:2] + if (pkg, module) in EXCLUDE_PY: + continue + retval.append(item) + return retval + + +class TestCommand(Command): + + description = "Run self-test" + + # Long option name, short option name, description + user_options = [ + ('skip-slow-tests', None, + 'Skip slow tests'), + ('module=', 'm', 'Test a single module (e.g. Cipher, PublicKey)') + ] + + def initialize_options(self): + self.build_dir = None + self.skip_slow_tests = None + self.module = None + + def finalize_options(self): + self.set_undefined_options('install', ('build_lib', 'build_dir')) + self.config = {'slow_tests': not self.skip_slow_tests} + + def run(self): + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + # Run SelfTest + self.announce("running self-tests") + old_path = sys.path[:] + try: + sys.path.insert(0, self.build_dir) + from Crypto import SelfTest + moduleObj = None + if self.module: + if self.module.count('.')==0: + # Test a whole a sub-package + full_module = "Crypto.SelfTest." + self.module + module_name = self.module + else: + # Test only a module + # Assume only one dot is present + comps = self.module.split('.') + module_name = "test_" + comps[1] + full_module = "Crypto.SelfTest." + comps[0] + "." + module_name + # Import sub-package or module + moduleObj = __import__( full_module, globals(), locals(), module_name ) + SelfTest.run(module=moduleObj, verbosity=self.verbose, stream=sys.stdout, config=self.config) + finally: + # Restore sys.path + sys.path[:] = old_path + + # Run slower self-tests + self.announce("running extended self-tests") + + sub_commands = [ ('build', None) ] + +kw = {'name':"pycrypto", + 'version':"2.7a1", # See also: lib/Crypto/__init__.py + 'description':"Cryptographic modules for Python.", + 'author':"Dwayne C. Litzenberger", + 'author_email':"dlitz@dlitz.net", + 'url':"http://www.pycrypto.org/", + + 'cmdclass' : {'build_configure': PCTBuildConfigure, 'build_ext': PCTBuildExt, 'build_py': PCTBuildPy, 'test': TestCommand }, + 'packages' : ["Crypto", "Crypto.Hash", "Crypto.Cipher", "Crypto.Util", + "Crypto.Random", + "Crypto.Random.Fortuna", + "Crypto.Random.OSRNG", + "Crypto.SelfTest", + "Crypto.SelfTest.Cipher", + "Crypto.SelfTest.Hash", + "Crypto.SelfTest.Protocol", + "Crypto.SelfTest.PublicKey", + "Crypto.SelfTest.Random", + "Crypto.SelfTest.Random.Fortuna", + "Crypto.SelfTest.Random.OSRNG", + "Crypto.SelfTest.Util", + "Crypto.SelfTest.Signature", + "Crypto.SelfTest.IO", + "Crypto.Protocol", + "Crypto.PublicKey", + "Crypto.Signature", + "Crypto.IO"], + 'package_dir' : { "Crypto": "lib/Crypto" }, + 'ext_modules': plat_ext + [ + # _fastmath (uses GNU mp library) + Extension("Crypto.PublicKey._fastmath", + include_dirs=['src/'], + libraries=['gmp'], + sources=["src/_fastmath.c"]), + + # Hash functions + Extension("Crypto.Hash.MD2", + include_dirs=['src/'], + sources=["src/MD2.c"]), + Extension("Crypto.Hash.MD4", + include_dirs=['src/'], + sources=["src/MD4.c"]), + Extension("Crypto.Hash.SHA256", + include_dirs=['src/'], + sources=["src/SHA256.c"]), + Extension("Crypto.Hash.SHA224", + include_dirs=['src/'], + sources=["src/SHA224.c"]), + Extension("Crypto.Hash.SHA384", + include_dirs=['src/'], + sources=["src/SHA384.c"]), + Extension("Crypto.Hash.SHA512", + include_dirs=['src/'], + sources=["src/SHA512.c"]), + Extension("Crypto.Hash.RIPEMD160", + include_dirs=['src/'], + sources=["src/RIPEMD160.c"], + define_macros=[endianness_macro()]), + + # Block encryption algorithms + Extension("Crypto.Cipher._AES", + include_dirs=['src/'], + sources=["src/AES.c"]), + Extension("Crypto.Cipher._AESNI", + include_dirs=['src/'], + sources=["src/AESNI.c"]), + Extension("Crypto.Cipher._ARC2", + include_dirs=['src/'], + sources=["src/ARC2.c"]), + Extension("Crypto.Cipher._Blowfish", + include_dirs=['src/'], + sources=["src/Blowfish.c"]), + Extension("Crypto.Cipher._CAST", + include_dirs=['src/'], + sources=["src/CAST.c"]), + Extension("Crypto.Cipher._DES", + include_dirs=['src/', 'src/libtom/'], + sources=["src/DES.c"]), + Extension("Crypto.Cipher._DES3", + include_dirs=['src/', 'src/libtom/'], + sources=["src/DES3.c"]), + + # Stream ciphers + Extension("Crypto.Cipher._ARC4", + include_dirs=['src/'], + sources=["src/ARC4.c"]), + Extension("Crypto.Cipher._XOR", + include_dirs=['src/'], + sources=["src/XOR.c"]), + + # Utility modules + Extension("Crypto.Util.strxor", + include_dirs=['src/'], + sources=['src/strxor.c']), + Extension("Crypto.Util.cpuid", + include_dirs=['src/'], + sources=['src/cpuid.c']), + Extension("Crypto.Util.galois", + include_dirs=['src/'], + sources=['src/galois.c']), + + # Counter modules + Extension("Crypto.Util._counter", + include_dirs=['src/'], + sources=['src/_counter.c']), + ] +} + +# If we're running Python 2.3, add extra information +if hasattr(core, 'setup_keywords'): + if 'classifiers' in core.setup_keywords: + kw['classifiers'] = [ + 'Development Status :: 5 - Production/Stable', + 'License :: Public Domain', + 'Intended Audience :: Developers', + 'Operating System :: Unix', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: MacOS :: MacOS X', + 'Topic :: Security :: Cryptography', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + ] + +core.setup(**kw) + +def touch(path): + import os, time + now = time.time() + try: + # assume it's there + os.utime(path, (now, now)) + except os.error: + PrintErr("Failed to update timestamp of "+path) + +# PY3K: Workaround for winrandom.pyd not existing during the first pass. +# It needs to be there for 2to3 to fix the import in nt.py +if (sys.platform == 'win32' and sys.version_info[0] == 3 and + 'build' in sys.argv[1:]): + PrintErr("\nSecond pass to allow 2to3 to fix nt.py. No cause for alarm.\n") + touch("./lib/Crypto/Random/OSRNG/nt.py") + core.setup(**kw) diff --git a/src/AES.c b/src/AES.c new file mode 100644 index 0000000..1e705da --- /dev/null +++ b/src/AES.c @@ -0,0 +1,1463 @@ +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> + * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> + * @author Paulo Barreto <paulo.barreto@terra.com.br> + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pycrypto_common.h" +#include <assert.h> +#include <stdlib.h> + +#define MODULE_NAME _AES +#define BLOCK_SIZE 16 +#define KEY_SIZE 0 + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +typedef struct { + u32 ek[ 4*(MAXNR+1) ]; + u32 dk[ 4*(MAXNR+1) ]; + int rounds; +} block_state; + +static void rijndaelEncrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); +static void rijndaelDecrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]); + +#ifdef INTERMEDIATE_VALUE_KAT +static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); +static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); +#endif /* INTERMEDIATE_VALUE_KAT */ + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) + +#ifdef _MSC_VER +#define GETU32(p) SWAP(*((u32 *)(p))) +#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ + +static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { + int i = 0; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } + } + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { + int Nr, i, j; + u32 temp; + + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return Nr; +} + +static void rijndaelEncrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); +} + +static void rijndaelDecrypt(u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(pt , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(pt + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(pt + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(pt + 12, s3); +} + +#ifdef INTERMEDIATE_VALUE_KAT + +static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { + int r; + u32 s0, s1, s2, s3, t0, t1, t2, t3; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(block ) ^ rk[0]; + s1 = GETU32(block + 4) ^ rk[1]; + s2 = GETU32(block + 8) ^ rk[2]; + s3 = GETU32(block + 12) ^ rk[3]; + rk += 4; + + /* + * Nr - 1 full rounds: + */ + for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[0]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[1]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[2]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + rk += 4; + + } + + /* + * apply last round and + * map cipher state to byte array block: + */ + if (rounds == Nr) { + t0 = + (Te4[(s0 >> 24) ] & 0xff000000) ^ + (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + t1 = + (Te4[(s1 >> 24) ] & 0xff000000) ^ + (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + t2 = + (Te4[(s2 >> 24) ] & 0xff000000) ^ + (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + t3 = + (Te4[(s3 >> 24) ] & 0xff000000) ^ + (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(s2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + PUTU32(block , s0); + PUTU32(block + 4, s1); + PUTU32(block + 8, s2); + PUTU32(block + 12, s3); +} + +static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { + int r; + u32 s0, s1, s2, s3, t0, t1, t2, t3; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(block ) ^ rk[0]; + s1 = GETU32(block + 4) ^ rk[1]; + s2 = GETU32(block + 8) ^ rk[2]; + s3 = GETU32(block + 12) ^ rk[3]; + rk += 4; + + /* + * Nr - 1 full rounds: + */ + for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[0]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[1]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[2]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[3]; + + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + rk += 4; + + } + + /* + * complete the last round and + * map cipher state to byte array block: + */ + t0 = + (Td4[(s0 >> 24) ] & 0xff000000) ^ + (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s1 ) & 0xff] & 0x000000ff); + t1 = + (Td4[(s1 >> 24) ] & 0xff000000) ^ + (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s2 ) & 0xff] & 0x000000ff); + t2 = + (Td4[(s2 >> 24) ] & 0xff000000) ^ + (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s3 ) & 0xff] & 0x000000ff); + t3 = + (Td4[(s3 >> 24) ] & 0xff000000) ^ + (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(s0 ) & 0xff] & 0x000000ff); + + if (rounds == Nr) { + t0 ^= rk[0]; + t1 ^= rk[1]; + t2 ^= rk[2]; + t3 ^= rk[3]; + } + + PUTU32(block , t0); + PUTU32(block + 4, t1); + PUTU32(block + 8, t2); + PUTU32(block + 12, t3); +} + +#endif /* INTERMEDIATE_VALUE_KAT */ + +static void block_init(block_state *state, unsigned char *key, + int keylen) +{ + int Nr = 0; + + if (keylen != 16 && keylen != 24 && keylen != 32) { + PyErr_SetString(PyExc_ValueError, + "AES key must be either 16, 24, or 32 bytes long"); + return; + } + switch (keylen) { + case(16): Nr = 10; break; + case(24): Nr = 12; break; + case(32): Nr = 14; break; + } + state->rounds = Nr; + rijndaelKeySetupEnc(state->ek, key, keylen*8); + rijndaelKeySetupDec(state->dk, key, keylen*8); +} + +static void block_finalize(block_state* self) +{ +} + +static void block_encrypt(block_state *self, u8 *in, u8 *out) +{ + rijndaelEncrypt(self->ek, self->rounds, in, out); +} + +static void block_decrypt(block_state *self, u8 *in, u8 *out) +{ + rijndaelDecrypt(self->dk, self->rounds, in, out); +} + +#include "block_template.c" diff --git a/src/AESNI.c b/src/AESNI.c new file mode 100644 index 0000000..3f1e061 --- /dev/null +++ b/src/AESNI.c @@ -0,0 +1,283 @@ +/* + * AESNI.c: AES using AES-NI instructions + * + * Written in 2013 by Sebastian Ramacher <sebastian@ramacher.at> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +#include "pycrypto_common.h" +#include <wmmintrin.h> +#include <stdlib.h> +#if defined(HAVE__ALIGNED_MALLOC) +#include <malloc.h> +#endif + +#define MODULE_NAME _AESNI +#define BLOCK_SIZE 16 +#define KEY_SIZE 0 + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +typedef unsigned char u8; + +typedef struct { + __m128i* ek; + __m128i* dk; + int rounds; +} block_state; + +/* Wrapper functions for malloc and free with memory alignment */ +#if defined(HAVE_ALIGNED_ALLOC) /* aligned_alloc is defined by C11 */ +# define aligned_malloc_wrapper aligned_alloc +# define aligned_free_wrapper free +#elif defined(HAVE_POSIX_MEMALIGN) /* posix_memalign is defined by POSIX */ +static void* aligned_malloc_wrapper(size_t alignment, size_t size) +{ + void* tmp = NULL; + int err = posix_memalign(&tmp, alignment, size); + if (err != 0) { + /* posix_memalign does NOT set errno on failure; the error is returned */ + errno = err; + return NULL; + } + return tmp; +} +# define aligned_free_wrapper free +#elif defined(HAVE__ALIGNED_MALLOC) /* _aligned_malloc is available on Windows */ +static void* aligned_malloc_wrapper(size_t alignment, size_t size) +{ + /* NB: _aligned_malloc takes its args in the opposite order from aligned_alloc */ + return _aligned_malloc(size, alignment); +} +# define aligned_free_wrapper _aligned_free +#else +# error "No function to allocate/free aligned memory is available." +#endif + +/* Helper functions to expand keys */ + +static __m128i aes128_keyexpand(__m128i key) +{ + key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); + key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); + return _mm_xor_si128(key, _mm_slli_si128(key, 4)); +} + +static __m128i aes192_keyexpand_2(__m128i key, __m128i key2) +{ + key = _mm_shuffle_epi32(key, 0xff); + key2 = _mm_xor_si128(key2, _mm_slli_si128(key2, 4)); + return _mm_xor_si128(key, key2); +} + +#define KEYEXP128_H(K1, K2, I, S) _mm_xor_si128(aes128_keyexpand(K1), \ + _mm_shuffle_epi32(_mm_aeskeygenassist_si128(K2, I), S)) + +#define KEYEXP128(K, I) KEYEXP128_H(K, K, I, 0xff) +#define KEYEXP192(K1, K2, I) KEYEXP128_H(K1, K2, I, 0x55) +#define KEYEXP192_2(K1, K2) aes192_keyexpand_2(K1, K2) +#define KEYEXP256(K1, K2, I) KEYEXP128_H(K1, K2, I, 0xff) +#define KEYEXP256_2(K1, K2) KEYEXP128_H(K1, K2, 0x00, 0xaa) + +/* Encryption key setup */ +static void aes_key_setup_enc(__m128i rk[], const u8* cipherKey, int keylen) +{ + switch (keylen) { + case 16: + { + /* 128 bit key setup */ + rk[0] = _mm_loadu_si128((const __m128i*) cipherKey); + rk[1] = KEYEXP128(rk[0], 0x01); + rk[2] = KEYEXP128(rk[1], 0x02); + rk[3] = KEYEXP128(rk[2], 0x04); + rk[4] = KEYEXP128(rk[3], 0x08); + rk[5] = KEYEXP128(rk[4], 0x10); + rk[6] = KEYEXP128(rk[5], 0x20); + rk[7] = KEYEXP128(rk[6], 0x40); + rk[8] = KEYEXP128(rk[7], 0x80); + rk[9] = KEYEXP128(rk[8], 0x1B); + rk[10] = KEYEXP128(rk[9], 0x36); + break; + } + case 24: + { + /* 192 bit key setup */ + __m128i temp[2]; + rk[0] = _mm_loadu_si128((const __m128i*) cipherKey); + rk[1] = _mm_loadu_si128((const __m128i*) (cipherKey+16)); + temp[0] = KEYEXP192(rk[0], rk[1], 0x01); + temp[1] = KEYEXP192_2(temp[0], rk[1]); + rk[1] = (__m128i)_mm_shuffle_pd((__m128d)rk[1], (__m128d)temp[0], 0); + rk[2] = (__m128i)_mm_shuffle_pd((__m128d)temp[0], (__m128d)temp[1], 1); + rk[3] = KEYEXP192(temp[0], temp[1], 0x02); + rk[4] = KEYEXP192_2(rk[3], temp[1]); + temp[0] = KEYEXP192(rk[3], rk[4], 0x04); + temp[1] = KEYEXP192_2(temp[0], rk[4]); + rk[4] = (__m128i)_mm_shuffle_pd((__m128d)rk[4], (__m128d)temp[0], 0); + rk[5] = (__m128i)_mm_shuffle_pd((__m128d)temp[0], (__m128d)temp[1], 1); + rk[6] = KEYEXP192(temp[0], temp[1], 0x08); + rk[7] = KEYEXP192_2(rk[6], temp[1]); + temp[0] = KEYEXP192(rk[6], rk[7], 0x10); + temp[1] = KEYEXP192_2(temp[0], rk[7]); + rk[7] = (__m128i)_mm_shuffle_pd((__m128d)rk[7], (__m128d)temp[0], 0); + rk[8] = (__m128i)_mm_shuffle_pd((__m128d)temp[0], (__m128d)temp[1], 1); + rk[9] = KEYEXP192(temp[0], temp[1], 0x20); + rk[10] = KEYEXP192_2(rk[9], temp[1]); + temp[0] = KEYEXP192(rk[9], rk[10], 0x40); + temp[1] = KEYEXP192_2(temp[0], rk[10]); + rk[10] = (__m128i)_mm_shuffle_pd((__m128d)rk[10], (__m128d) temp[0], 0); + rk[11] = (__m128i)_mm_shuffle_pd((__m128d)temp[0],(__m128d) temp[1], 1); + rk[12] = KEYEXP192(temp[0], temp[1], 0x80); + break; + } + case 32: + { + /* 256 bit key setup */ + rk[0] = _mm_loadu_si128((const __m128i*) cipherKey); + rk[1] = _mm_loadu_si128((const __m128i*) (cipherKey+16)); + rk[2] = KEYEXP256(rk[0], rk[1], 0x01); + rk[3] = KEYEXP256_2(rk[1], rk[2]); + rk[4] = KEYEXP256(rk[2], rk[3], 0x02); + rk[5] = KEYEXP256_2(rk[3], rk[4]); + rk[6] = KEYEXP256(rk[4], rk[5], 0x04); + rk[7] = KEYEXP256_2(rk[5], rk[6]); + rk[8] = KEYEXP256(rk[6], rk[7], 0x08); + rk[9] = KEYEXP256_2(rk[7], rk[8]); + rk[10] = KEYEXP256(rk[8], rk[9], 0x10); + rk[11] = KEYEXP256_2(rk[9], rk[10]); + rk[12] = KEYEXP256(rk[10], rk[11], 0x20); + rk[13] = KEYEXP256_2(rk[11], rk[12]); + rk[14] = KEYEXP256(rk[12], rk[13], 0x40); + break; + } + } +} + +/* Decryption key setup */ +static void aes_key_setup_dec(__m128i dk[], const __m128i ek[], int rounds) +{ + dk[rounds] = ek[0]; + for (int i = 1; i < rounds; ++i) { + dk[rounds - i] = _mm_aesimc_si128(ek[i]); + } + dk[0] = ek[rounds]; +} + +static void block_init(block_state* self, unsigned char* key, int keylen) +{ + int nr = 0; + switch (keylen) { + case 16: nr = 10; break; + case 24: nr = 12; break; + case 32: nr = 14; break; + default: + PyErr_SetString(PyExc_ValueError, + "AES key must be either 16, 24, or 32 bytes long"); + return; + } + + /* ensure that self->ek and self->dk are aligned to 16 byte boundaries */ + void* tek = aligned_malloc_wrapper(16, (nr + 1) * sizeof(__m128i)); + void* tdk = aligned_malloc_wrapper(16, (nr + 1) * sizeof(__m128i)); + if (!tek || !tdk) { + aligned_free_wrapper(tek); + aligned_free_wrapper(tdk); + PyErr_SetString(PyExc_MemoryError, + "failed to allocate memory for keys"); + return; + } + + self->ek = tek; + self->dk = tdk; + + self->rounds = nr; + aes_key_setup_enc(self->ek, key, keylen); + aes_key_setup_dec(self->dk, self->ek, nr); +} + +static void block_finalize(block_state* self) +{ + /* overwrite contents of ek and dk */ + memset(self->ek, 0, (self->rounds + 1) * sizeof(__m128i)); + memset(self->dk, 0, (self->rounds + 1) * sizeof(__m128i)); + + aligned_free_wrapper(self->ek); + aligned_free_wrapper(self->dk); +} + +static void block_encrypt(block_state* self, const u8* in, u8* out) +{ + __m128i m = _mm_loadu_si128((const __m128i*) in); + /* first 9 rounds */ + m = _mm_xor_si128(m, self->ek[0]); + m = _mm_aesenc_si128(m, self->ek[1]); + m = _mm_aesenc_si128(m, self->ek[2]); + m = _mm_aesenc_si128(m, self->ek[3]); + m = _mm_aesenc_si128(m, self->ek[4]); + m = _mm_aesenc_si128(m, self->ek[5]); + m = _mm_aesenc_si128(m, self->ek[6]); + m = _mm_aesenc_si128(m, self->ek[7]); + m = _mm_aesenc_si128(m, self->ek[8]); + m = _mm_aesenc_si128(m, self->ek[9]); + if (self->rounds != 10) { + /* two additional rounds for AES-192/256 */ + m = _mm_aesenc_si128(m, self->ek[10]); + m = _mm_aesenc_si128(m, self->ek[11]); + if (self->rounds == 14) { + /* another two additional rounds for AES-256 */ + m = _mm_aesenc_si128(m, self->ek[12]); + m = _mm_aesenc_si128(m, self->ek[13]); + } + } + m = _mm_aesenclast_si128(m, self->ek[self->rounds]); + _mm_storeu_si128((__m128i*) out, m); +} + +static void block_decrypt(block_state* self, const u8* in, u8* out) +{ + __m128i m = _mm_loadu_si128((const __m128i*) in); + /* first 9 rounds */ + m = _mm_xor_si128(m, self->dk[0]); + m = _mm_aesdec_si128(m, self->dk[1]); + m = _mm_aesdec_si128(m, self->dk[2]); + m = _mm_aesdec_si128(m, self->dk[3]); + m = _mm_aesdec_si128(m, self->dk[4]); + m = _mm_aesdec_si128(m, self->dk[5]); + m = _mm_aesdec_si128(m, self->dk[6]); + m = _mm_aesdec_si128(m, self->dk[7]); + m = _mm_aesdec_si128(m, self->dk[8]); + m = _mm_aesdec_si128(m, self->dk[9]); + if (self->rounds != 10) { + /* two additional rounds for AES-192/256 */ + m = _mm_aesdec_si128(m, self->dk[10]); + m = _mm_aesdec_si128(m, self->dk[11]); + if (self->rounds == 14) { + /* another two additional rounds for AES-256 */ + m = _mm_aesdec_si128(m, self->dk[12]); + m = _mm_aesdec_si128(m, self->dk[13]); + } + } + m = _mm_aesdeclast_si128(m, self->dk[self->rounds]); + _mm_storeu_si128((__m128i*) out, m); +} + +#include "block_template.c" diff --git a/src/ARC2.c b/src/ARC2.c new file mode 100644 index 0000000..71858f6 --- /dev/null +++ b/src/ARC2.c @@ -0,0 +1,224 @@ +/* + * rc2.c : Source code for the RC2 block cipher + * + * Part of the Python Cryptography Toolkit + * + * =================================================================== + * This file appears to contain code from the ARC2 implementation + * "rc2.c" implementation (the "Original Code"), with modifications made + * after it was incorporated into PyCrypto (the "Modifications"). + * + * To the best of our knowledge, the Original Code was placed into the + * public domain by its (anonymous) author: + * + * ********************************************************************** + * * To commemorate the 1996 RSA Data Security Conference, the following * + * * code is released into the public domain by its author. Prost! * + * * * + * * This cipher uses 16-bit words and little-endian byte ordering. * + * * I wonder which processor it was optimized for? * + * * * + * * Thanks to CodeView, SoftIce, and D86 for helping bring this code to * + * * the public. * + * ********************************************************************** + * + * The Modifications to this file are dedicated to the public domain. + * To the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. No rights are + * reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" +#include <string.h> + +#define MODULE_NAME _ARC2 +#define BLOCK_SIZE 8 +#define KEY_SIZE 0 +#define PCT_ARC2_MODULE /* Defined to get ARC2's additional keyword arguments */ + +typedef uint32_t U32; +typedef uint16_t U16; +typedef uint8_t U8; + +typedef struct +{ + U16 xkey[64]; + int effective_keylen; +} block_state; + +static void +block_encrypt(block_state *self, U8 *in, U8 *out) +{ + U16 x76, x54, x32, x10; + int i; + + x76 = (in[7] << 8) + in[6]; + x54 = (in[5] << 8) + in[4]; + x32 = (in[3] << 8) + in[2]; + x10 = (in[1] << 8) + in[0]; + + for (i = 0; i < 16; i++) + { + x10 += (x32 & ~x76) + (x54 & x76) + self->xkey[4*i+0]; + x10 = (x10 << 1) + (x10 >> 15 & 1); + + x32 += (x54 & ~x10) + (x76 & x10) + self->xkey[4*i+1]; + x32 = (x32 << 2) + (x32 >> 14 & 3); + + x54 += (x76 & ~x32) + (x10 & x32) + self->xkey[4*i+2]; + x54 = (x54 << 3) + (x54 >> 13 & 7); + + x76 += (x10 & ~x54) + (x32 & x54) + self->xkey[4*i+3]; + x76 = (x76 << 5) + (x76 >> 11 & 31); + + if (i == 4 || i == 10) { + x10 += self->xkey[x76 & 63]; + x32 += self->xkey[x10 & 63]; + x54 += self->xkey[x32 & 63]; + x76 += self->xkey[x54 & 63]; + } + } + + out[0] = (U8)x10; + out[1] = (U8)(x10 >> 8); + out[2] = (U8)x32; + out[3] = (U8)(x32 >> 8); + out[4] = (U8)x54; + out[5] = (U8)(x54 >> 8); + out[6] = (U8)x76; + out[7] = (U8)(x76 >> 8); +} + + +static void +block_decrypt(block_state *self, U8 *in, U8 *out) +{ + U16 x76, x54, x32, x10; + int i; + + x76 = (in[7] << 8) + in[6]; + x54 = (in[5] << 8) + in[4]; + x32 = (in[3] << 8) + in[2]; + x10 = (in[1] << 8) + in[0]; + + i = 15; + do { + x76 &= 65535; + x76 = (x76 << 11) + (x76 >> 5); + x76 -= (x10 & ~x54) + (x32 & x54) + self->xkey[4*i+3]; + + x54 &= 65535; + x54 = (x54 << 13) + (x54 >> 3); + x54 -= (x76 & ~x32) + (x10 & x32) + self->xkey[4*i+2]; + + x32 &= 65535; + x32 = (x32 << 14) + (x32 >> 2); + x32 -= (x54 & ~x10) + (x76 & x10) + self->xkey[4*i+1]; + + x10 &= 65535; + x10 = (x10 << 15) + (x10 >> 1); + x10 -= (x32 & ~x76) + (x54 & x76) + self->xkey[4*i+0]; + + if (i == 5 || i == 11) { + x76 -= self->xkey[x54 & 63]; + x54 -= self->xkey[x32 & 63]; + x32 -= self->xkey[x10 & 63]; + x10 -= self->xkey[x76 & 63]; + } + } while (i--); + + out[0] = (U8)x10; + out[1] = (U8)(x10 >> 8); + out[2] = (U8)x32; + out[3] = (U8)(x32 >> 8); + out[4] = (U8)x54; + out[5] = (U8)(x54 >> 8); + out[6] = (U8)x76; + out[7] = (U8)(x76 >> 8); +} + + +static void +block_init(block_state *self, U8 *key, int keylength) +{ + U8 x; + U16 i; + /* 256-entry permutation table, probably derived somehow from pi */ + static const U8 permute[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 + }; + + if ((U32)keylength > sizeof(self->xkey)) { + PyErr_SetString(PyExc_ValueError, + "ARC2 key length must be less than 128 bytes"); + return; + } + + memcpy(self->xkey, key, keylength); + + /* Phase 1: Expand input key to 128 bytes */ + if (keylength < 128) { + i = 0; + x = ((U8 *)self->xkey)[keylength-1]; + do { + x = permute[(x + ((U8 *)self->xkey)[i++]) & 255]; + ((U8 *)self->xkey)[keylength++] = x; + } while (keylength < 128); + } + + /* Phase 2 - reduce effective key size to "effective_keylen" */ + keylength = (self->effective_keylen+7) >> 3; + i = 128-keylength; + x = permute[((U8 *)self->xkey)[i] & (255 >> + (7 & + ((self->effective_keylen %8 ) ? 8-(self->effective_keylen%8): 0)) + )]; + ((U8 *)self->xkey)[i] = x; + + while (i--) { + x = permute[ x ^ ((U8 *)self->xkey)[i+keylength] ]; + ((U8 *)self->xkey)[i] = x; + } + + /* Phase 3 - copy to self->xkey in little-endian order */ + i = 63; + do { + self->xkey[i] = ((U8 *)self->xkey)[2*i] + + (((U8 *)self->xkey)[2*i+1] << 8); + } while (i--); +} + +static void +block_finalize(block_state* self) +{ +} + +#include "block_template.c" diff --git a/src/ARC4.c b/src/ARC4.c new file mode 100644 index 0000000..a125fab --- /dev/null +++ b/src/ARC4.c @@ -0,0 +1,90 @@ + +/* + * arc4.c : Implementation for the Alleged-RC4 stream cipher + * + * Part of the Python Cryptography Toolkit + * + * Originally written by: A.M. Kuchling + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" + +#define MODULE_NAME _ARC4 +#define BLOCK_SIZE 1 +#define KEY_SIZE 0 + +typedef struct +{ + unsigned char state[256]; + unsigned char x,y; +} stream_state; + +/* Encryption and decryption are symmetric */ +#define stream_decrypt stream_encrypt + +static void stream_encrypt(stream_state *self, unsigned char *block, + int len) +{ + register int i, x=self->x, y=self->y; + + for (i=0; i<len; i++) + { + x = (x + 1) % 256; + y = (y + self->state[x]) % 256; + { + register int t; /* Exchange state[x] and state[y] */ + t = self->state[x]; + self->state[x] = self->state[y]; + self->state[y] = t; + } + { + register int xorIndex; /* XOR the data with the stream data */ + xorIndex=(self->state[x]+self->state[y]) % 256; + block[i] ^= self->state[xorIndex]; + } + } + self->x=x; + self->y=y; +} + + +static void stream_init(stream_state *self, unsigned char *key, int keylen) +{ + register int i, index1, index2; + + for(i=0; i<256; i++) self->state[i]=i; + self->x=0; self->y=0; + index1=0; index2=0; + for(i=0; i<256; i++) + { + register int t; + index2 = ( key[index1] + self->state[i] + index2) % 256; + t = self->state[i]; + self->state[i] = self->state[index2]; + self->state[index2] = t; + index1 = (index1 + 1) % keylen; + } +} + +#include "stream_template.c" + + diff --git a/src/Blowfish-tables.h b/src/Blowfish-tables.h new file mode 100644 index 0000000..b152cb2 --- /dev/null +++ b/src/Blowfish-tables.h @@ -0,0 +1,258 @@ +/* + * + * Blowfish-tables.h : Initial-value tables for Blowfish + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * ======================================================================= + * The contents of this file are dedicated to the public domain. To the extent + * that dedication to the public domain is not available, everyone is granted a + * worldwide, perpetual, royalty-free, non-exclusive license to exercise all + * rights associated with the contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ======================================================================= + * + * Country of origin: Canada + */ +#ifndef BLOWFISH_TABLES_H +#define BLOWFISH_TABLES_H + +/* The hexadecimal digits of pi, less 3. */ + +static const uint32_t initial_P[18] = { + 0x243f6a88u, 0x85a308d3u, 0x13198a2eu, 0x03707344u, 0xa4093822u, + 0x299f31d0u, 0x082efa98u, 0xec4e6c89u, 0x452821e6u, 0x38d01377u, + 0xbe5466cfu, 0x34e90c6cu, 0xc0ac29b7u, 0xc97c50ddu, 0x3f84d5b5u, + 0xb5470917u, 0x9216d5d9u, 0x8979fb1bu +}; + +static const uint32_t initial_S1[256] = { + 0xd1310ba6u, 0x98dfb5acu, 0x2ffd72dbu, 0xd01adfb7u, 0xb8e1afedu, + 0x6a267e96u, 0xba7c9045u, 0xf12c7f99u, 0x24a19947u, 0xb3916cf7u, + 0x0801f2e2u, 0x858efc16u, 0x636920d8u, 0x71574e69u, 0xa458fea3u, + 0xf4933d7eu, 0x0d95748fu, 0x728eb658u, 0x718bcd58u, 0x82154aeeu, + 0x7b54a41du, 0xc25a59b5u, 0x9c30d539u, 0x2af26013u, 0xc5d1b023u, + 0x286085f0u, 0xca417918u, 0xb8db38efu, 0x8e79dcb0u, 0x603a180eu, + 0x6c9e0e8bu, 0xb01e8a3eu, 0xd71577c1u, 0xbd314b27u, 0x78af2fdau, + 0x55605c60u, 0xe65525f3u, 0xaa55ab94u, 0x57489862u, 0x63e81440u, + 0x55ca396au, 0x2aab10b6u, 0xb4cc5c34u, 0x1141e8ceu, 0xa15486afu, + 0x7c72e993u, 0xb3ee1411u, 0x636fbc2au, 0x2ba9c55du, 0x741831f6u, + 0xce5c3e16u, 0x9b87931eu, 0xafd6ba33u, 0x6c24cf5cu, 0x7a325381u, + 0x28958677u, 0x3b8f4898u, 0x6b4bb9afu, 0xc4bfe81bu, 0x66282193u, + 0x61d809ccu, 0xfb21a991u, 0x487cac60u, 0x5dec8032u, 0xef845d5du, + 0xe98575b1u, 0xdc262302u, 0xeb651b88u, 0x23893e81u, 0xd396acc5u, + 0x0f6d6ff3u, 0x83f44239u, 0x2e0b4482u, 0xa4842004u, 0x69c8f04au, + 0x9e1f9b5eu, 0x21c66842u, 0xf6e96c9au, 0x670c9c61u, 0xabd388f0u, + 0x6a51a0d2u, 0xd8542f68u, 0x960fa728u, 0xab5133a3u, 0x6eef0b6cu, + 0x137a3be4u, 0xba3bf050u, 0x7efb2a98u, 0xa1f1651du, 0x39af0176u, + 0x66ca593eu, 0x82430e88u, 0x8cee8619u, 0x456f9fb4u, 0x7d84a5c3u, + 0x3b8b5ebeu, 0xe06f75d8u, 0x85c12073u, 0x401a449fu, 0x56c16aa6u, + 0x4ed3aa62u, 0x363f7706u, 0x1bfedf72u, 0x429b023du, 0x37d0d724u, + 0xd00a1248u, 0xdb0fead3u, 0x49f1c09bu, 0x075372c9u, 0x80991b7bu, + 0x25d479d8u, 0xf6e8def7u, 0xe3fe501au, 0xb6794c3bu, 0x976ce0bdu, + 0x04c006bau, 0xc1a94fb6u, 0x409f60c4u, 0x5e5c9ec2u, 0x196a2463u, + 0x68fb6fafu, 0x3e6c53b5u, 0x1339b2ebu, 0x3b52ec6fu, 0x6dfc511fu, + 0x9b30952cu, 0xcc814544u, 0xaf5ebd09u, 0xbee3d004u, 0xde334afdu, + 0x660f2807u, 0x192e4bb3u, 0xc0cba857u, 0x45c8740fu, 0xd20b5f39u, + 0xb9d3fbdbu, 0x5579c0bdu, 0x1a60320au, 0xd6a100c6u, 0x402c7279u, + 0x679f25feu, 0xfb1fa3ccu, 0x8ea5e9f8u, 0xdb3222f8u, 0x3c7516dfu, + 0xfd616b15u, 0x2f501ec8u, 0xad0552abu, 0x323db5fau, 0xfd238760u, + 0x53317b48u, 0x3e00df82u, 0x9e5c57bbu, 0xca6f8ca0u, 0x1a87562eu, + 0xdf1769dbu, 0xd542a8f6u, 0x287effc3u, 0xac6732c6u, 0x8c4f5573u, + 0x695b27b0u, 0xbbca58c8u, 0xe1ffa35du, 0xb8f011a0u, 0x10fa3d98u, + 0xfd2183b8u, 0x4afcb56cu, 0x2dd1d35bu, 0x9a53e479u, 0xb6f84565u, + 0xd28e49bcu, 0x4bfb9790u, 0xe1ddf2dau, 0xa4cb7e33u, 0x62fb1341u, + 0xcee4c6e8u, 0xef20cadau, 0x36774c01u, 0xd07e9efeu, 0x2bf11fb4u, + 0x95dbda4du, 0xae909198u, 0xeaad8e71u, 0x6b93d5a0u, 0xd08ed1d0u, + 0xafc725e0u, 0x8e3c5b2fu, 0x8e7594b7u, 0x8ff6e2fbu, 0xf2122b64u, + 0x8888b812u, 0x900df01cu, 0x4fad5ea0u, 0x688fc31cu, 0xd1cff191u, + 0xb3a8c1adu, 0x2f2f2218u, 0xbe0e1777u, 0xea752dfeu, 0x8b021fa1u, + 0xe5a0cc0fu, 0xb56f74e8u, 0x18acf3d6u, 0xce89e299u, 0xb4a84fe0u, + 0xfd13e0b7u, 0x7cc43b81u, 0xd2ada8d9u, 0x165fa266u, 0x80957705u, + 0x93cc7314u, 0x211a1477u, 0xe6ad2065u, 0x77b5fa86u, 0xc75442f5u, + 0xfb9d35cfu, 0xebcdaf0cu, 0x7b3e89a0u, 0xd6411bd3u, 0xae1e7e49u, + 0x00250e2du, 0x2071b35eu, 0x226800bbu, 0x57b8e0afu, 0x2464369bu, + 0xf009b91eu, 0x5563911du, 0x59dfa6aau, 0x78c14389u, 0xd95a537fu, + 0x207d5ba2u, 0x02e5b9c5u, 0x83260376u, 0x6295cfa9u, 0x11c81968u, + 0x4e734a41u, 0xb3472dcau, 0x7b14a94au, 0x1b510052u, 0x9a532915u, + 0xd60f573fu, 0xbc9bc6e4u, 0x2b60a476u, 0x81e67400u, 0x08ba6fb5u, + 0x571be91fu, 0xf296ec6bu, 0x2a0dd915u, 0xb6636521u, 0xe7b9f9b6u, + 0xff34052eu, 0xc5855664u, 0x53b02d5du, 0xa99f8fa1u, 0x08ba4799u, + 0x6e85076au +}; + +static const uint32_t initial_S2[256] = { + 0x4b7a70e9u, 0xb5b32944u, 0xdb75092eu, 0xc4192623u, 0xad6ea6b0u, + 0x49a7df7du, 0x9cee60b8u, 0x8fedb266u, 0xecaa8c71u, 0x699a17ffu, + 0x5664526cu, 0xc2b19ee1u, 0x193602a5u, 0x75094c29u, 0xa0591340u, + 0xe4183a3eu, 0x3f54989au, 0x5b429d65u, 0x6b8fe4d6u, 0x99f73fd6u, + 0xa1d29c07u, 0xefe830f5u, 0x4d2d38e6u, 0xf0255dc1u, 0x4cdd2086u, + 0x8470eb26u, 0x6382e9c6u, 0x021ecc5eu, 0x09686b3fu, 0x3ebaefc9u, + 0x3c971814u, 0x6b6a70a1u, 0x687f3584u, 0x52a0e286u, 0xb79c5305u, + 0xaa500737u, 0x3e07841cu, 0x7fdeae5cu, 0x8e7d44ecu, 0x5716f2b8u, + 0xb03ada37u, 0xf0500c0du, 0xf01c1f04u, 0x0200b3ffu, 0xae0cf51au, + 0x3cb574b2u, 0x25837a58u, 0xdc0921bdu, 0xd19113f9u, 0x7ca92ff6u, + 0x94324773u, 0x22f54701u, 0x3ae5e581u, 0x37c2dadcu, 0xc8b57634u, + 0x9af3dda7u, 0xa9446146u, 0x0fd0030eu, 0xecc8c73eu, 0xa4751e41u, + 0xe238cd99u, 0x3bea0e2fu, 0x3280bba1u, 0x183eb331u, 0x4e548b38u, + 0x4f6db908u, 0x6f420d03u, 0xf60a04bfu, 0x2cb81290u, 0x24977c79u, + 0x5679b072u, 0xbcaf89afu, 0xde9a771fu, 0xd9930810u, 0xb38bae12u, + 0xdccf3f2eu, 0x5512721fu, 0x2e6b7124u, 0x501adde6u, 0x9f84cd87u, + 0x7a584718u, 0x7408da17u, 0xbc9f9abcu, 0xe94b7d8cu, 0xec7aec3au, + 0xdb851dfau, 0x63094366u, 0xc464c3d2u, 0xef1c1847u, 0x3215d908u, + 0xdd433b37u, 0x24c2ba16u, 0x12a14d43u, 0x2a65c451u, 0x50940002u, + 0x133ae4ddu, 0x71dff89eu, 0x10314e55u, 0x81ac77d6u, 0x5f11199bu, + 0x043556f1u, 0xd7a3c76bu, 0x3c11183bu, 0x5924a509u, 0xf28fe6edu, + 0x97f1fbfau, 0x9ebabf2cu, 0x1e153c6eu, 0x86e34570u, 0xeae96fb1u, + 0x860e5e0au, 0x5a3e2ab3u, 0x771fe71cu, 0x4e3d06fau, 0x2965dcb9u, + 0x99e71d0fu, 0x803e89d6u, 0x5266c825u, 0x2e4cc978u, 0x9c10b36au, + 0xc6150ebau, 0x94e2ea78u, 0xa5fc3c53u, 0x1e0a2df4u, 0xf2f74ea7u, + 0x361d2b3du, 0x1939260fu, 0x19c27960u, 0x5223a708u, 0xf71312b6u, + 0xebadfe6eu, 0xeac31f66u, 0xe3bc4595u, 0xa67bc883u, 0xb17f37d1u, + 0x018cff28u, 0xc332ddefu, 0xbe6c5aa5u, 0x65582185u, 0x68ab9802u, + 0xeecea50fu, 0xdb2f953bu, 0x2aef7dadu, 0x5b6e2f84u, 0x1521b628u, + 0x29076170u, 0xecdd4775u, 0x619f1510u, 0x13cca830u, 0xeb61bd96u, + 0x0334fe1eu, 0xaa0363cfu, 0xb5735c90u, 0x4c70a239u, 0xd59e9e0bu, + 0xcbaade14u, 0xeecc86bcu, 0x60622ca7u, 0x9cab5cabu, 0xb2f3846eu, + 0x648b1eafu, 0x19bdf0cau, 0xa02369b9u, 0x655abb50u, 0x40685a32u, + 0x3c2ab4b3u, 0x319ee9d5u, 0xc021b8f7u, 0x9b540b19u, 0x875fa099u, + 0x95f7997eu, 0x623d7da8u, 0xf837889au, 0x97e32d77u, 0x11ed935fu, + 0x16681281u, 0x0e358829u, 0xc7e61fd6u, 0x96dedfa1u, 0x7858ba99u, + 0x57f584a5u, 0x1b227263u, 0x9b83c3ffu, 0x1ac24696u, 0xcdb30aebu, + 0x532e3054u, 0x8fd948e4u, 0x6dbc3128u, 0x58ebf2efu, 0x34c6ffeau, + 0xfe28ed61u, 0xee7c3c73u, 0x5d4a14d9u, 0xe864b7e3u, 0x42105d14u, + 0x203e13e0u, 0x45eee2b6u, 0xa3aaabeau, 0xdb6c4f15u, 0xfacb4fd0u, + 0xc742f442u, 0xef6abbb5u, 0x654f3b1du, 0x41cd2105u, 0xd81e799eu, + 0x86854dc7u, 0xe44b476au, 0x3d816250u, 0xcf62a1f2u, 0x5b8d2646u, + 0xfc8883a0u, 0xc1c7b6a3u, 0x7f1524c3u, 0x69cb7492u, 0x47848a0bu, + 0x5692b285u, 0x095bbf00u, 0xad19489du, 0x1462b174u, 0x23820e00u, + 0x58428d2au, 0x0c55f5eau, 0x1dadf43eu, 0x233f7061u, 0x3372f092u, + 0x8d937e41u, 0xd65fecf1u, 0x6c223bdbu, 0x7cde3759u, 0xcbee7460u, + 0x4085f2a7u, 0xce77326eu, 0xa6078084u, 0x19f8509eu, 0xe8efd855u, + 0x61d99735u, 0xa969a7aau, 0xc50c06c2u, 0x5a04abfcu, 0x800bcadcu, + 0x9e447a2eu, 0xc3453484u, 0xfdd56705u, 0x0e1e9ec9u, 0xdb73dbd3u, + 0x105588cdu, 0x675fda79u, 0xe3674340u, 0xc5c43465u, 0x713e38d8u, + 0x3d28f89eu, 0xf16dff20u, 0x153e21e7u, 0x8fb03d4au, 0xe6e39f2bu, + 0xdb83adf7u +}; + +static const uint32_t initial_S3[256] = { + 0xe93d5a68u, 0x948140f7u, 0xf64c261cu, 0x94692934u, 0x411520f7u, + 0x7602d4f7u, 0xbcf46b2eu, 0xd4a20068u, 0xd4082471u, 0x3320f46au, + 0x43b7d4b7u, 0x500061afu, 0x1e39f62eu, 0x97244546u, 0x14214f74u, + 0xbf8b8840u, 0x4d95fc1du, 0x96b591afu, 0x70f4ddd3u, 0x66a02f45u, + 0xbfbc09ecu, 0x03bd9785u, 0x7fac6dd0u, 0x31cb8504u, 0x96eb27b3u, + 0x55fd3941u, 0xda2547e6u, 0xabca0a9au, 0x28507825u, 0x530429f4u, + 0x0a2c86dau, 0xe9b66dfbu, 0x68dc1462u, 0xd7486900u, 0x680ec0a4u, + 0x27a18deeu, 0x4f3ffea2u, 0xe887ad8cu, 0xb58ce006u, 0x7af4d6b6u, + 0xaace1e7cu, 0xd3375fecu, 0xce78a399u, 0x406b2a42u, 0x20fe9e35u, + 0xd9f385b9u, 0xee39d7abu, 0x3b124e8bu, 0x1dc9faf7u, 0x4b6d1856u, + 0x26a36631u, 0xeae397b2u, 0x3a6efa74u, 0xdd5b4332u, 0x6841e7f7u, + 0xca7820fbu, 0xfb0af54eu, 0xd8feb397u, 0x454056acu, 0xba489527u, + 0x55533a3au, 0x20838d87u, 0xfe6ba9b7u, 0xd096954bu, 0x55a867bcu, + 0xa1159a58u, 0xcca92963u, 0x99e1db33u, 0xa62a4a56u, 0x3f3125f9u, + 0x5ef47e1cu, 0x9029317cu, 0xfdf8e802u, 0x04272f70u, 0x80bb155cu, + 0x05282ce3u, 0x95c11548u, 0xe4c66d22u, 0x48c1133fu, 0xc70f86dcu, + 0x07f9c9eeu, 0x41041f0fu, 0x404779a4u, 0x5d886e17u, 0x325f51ebu, + 0xd59bc0d1u, 0xf2bcc18fu, 0x41113564u, 0x257b7834u, 0x602a9c60u, + 0xdff8e8a3u, 0x1f636c1bu, 0x0e12b4c2u, 0x02e1329eu, 0xaf664fd1u, + 0xcad18115u, 0x6b2395e0u, 0x333e92e1u, 0x3b240b62u, 0xeebeb922u, + 0x85b2a20eu, 0xe6ba0d99u, 0xde720c8cu, 0x2da2f728u, 0xd0127845u, + 0x95b794fdu, 0x647d0862u, 0xe7ccf5f0u, 0x5449a36fu, 0x877d48fau, + 0xc39dfd27u, 0xf33e8d1eu, 0x0a476341u, 0x992eff74u, 0x3a6f6eabu, + 0xf4f8fd37u, 0xa812dc60u, 0xa1ebddf8u, 0x991be14cu, 0xdb6e6b0du, + 0xc67b5510u, 0x6d672c37u, 0x2765d43bu, 0xdcd0e804u, 0xf1290dc7u, + 0xcc00ffa3u, 0xb5390f92u, 0x690fed0bu, 0x667b9ffbu, 0xcedb7d9cu, + 0xa091cf0bu, 0xd9155ea3u, 0xbb132f88u, 0x515bad24u, 0x7b9479bfu, + 0x763bd6ebu, 0x37392eb3u, 0xcc115979u, 0x8026e297u, 0xf42e312du, + 0x6842ada7u, 0xc66a2b3bu, 0x12754cccu, 0x782ef11cu, 0x6a124237u, + 0xb79251e7u, 0x06a1bbe6u, 0x4bfb6350u, 0x1a6b1018u, 0x11caedfau, + 0x3d25bdd8u, 0xe2e1c3c9u, 0x44421659u, 0x0a121386u, 0xd90cec6eu, + 0xd5abea2au, 0x64af674eu, 0xda86a85fu, 0xbebfe988u, 0x64e4c3feu, + 0x9dbc8057u, 0xf0f7c086u, 0x60787bf8u, 0x6003604du, 0xd1fd8346u, + 0xf6381fb0u, 0x7745ae04u, 0xd736fcccu, 0x83426b33u, 0xf01eab71u, + 0xb0804187u, 0x3c005e5fu, 0x77a057beu, 0xbde8ae24u, 0x55464299u, + 0xbf582e61u, 0x4e58f48fu, 0xf2ddfda2u, 0xf474ef38u, 0x8789bdc2u, + 0x5366f9c3u, 0xc8b38e74u, 0xb475f255u, 0x46fcd9b9u, 0x7aeb2661u, + 0x8b1ddf84u, 0x846a0e79u, 0x915f95e2u, 0x466e598eu, 0x20b45770u, + 0x8cd55591u, 0xc902de4cu, 0xb90bace1u, 0xbb8205d0u, 0x11a86248u, + 0x7574a99eu, 0xb77f19b6u, 0xe0a9dc09u, 0x662d09a1u, 0xc4324633u, + 0xe85a1f02u, 0x09f0be8cu, 0x4a99a025u, 0x1d6efe10u, 0x1ab93d1du, + 0x0ba5a4dfu, 0xa186f20fu, 0x2868f169u, 0xdcb7da83u, 0x573906feu, + 0xa1e2ce9bu, 0x4fcd7f52u, 0x50115e01u, 0xa70683fau, 0xa002b5c4u, + 0x0de6d027u, 0x9af88c27u, 0x773f8641u, 0xc3604c06u, 0x61a806b5u, + 0xf0177a28u, 0xc0f586e0u, 0x006058aau, 0x30dc7d62u, 0x11e69ed7u, + 0x2338ea63u, 0x53c2dd94u, 0xc2c21634u, 0xbbcbee56u, 0x90bcb6deu, + 0xebfc7da1u, 0xce591d76u, 0x6f05e409u, 0x4b7c0188u, 0x39720a3du, + 0x7c927c24u, 0x86e3725fu, 0x724d9db9u, 0x1ac15bb4u, 0xd39eb8fcu, + 0xed545578u, 0x08fca5b5u, 0xd83d7cd3u, 0x4dad0fc4u, 0x1e50ef5eu, + 0xb161e6f8u, 0xa28514d9u, 0x6c51133cu, 0x6fd5c7e7u, 0x56e14ec4u, + 0x362abfceu, 0xddc6c837u, 0xd79a3234u, 0x92638212u, 0x670efa8eu, + 0x406000e0u +}; + +static const uint32_t initial_S4[256] = { + 0x3a39ce37u, 0xd3faf5cfu, 0xabc27737u, 0x5ac52d1bu, 0x5cb0679eu, + 0x4fa33742u, 0xd3822740u, 0x99bc9bbeu, 0xd5118e9du, 0xbf0f7315u, + 0xd62d1c7eu, 0xc700c47bu, 0xb78c1b6bu, 0x21a19045u, 0xb26eb1beu, + 0x6a366eb4u, 0x5748ab2fu, 0xbc946e79u, 0xc6a376d2u, 0x6549c2c8u, + 0x530ff8eeu, 0x468dde7du, 0xd5730a1du, 0x4cd04dc6u, 0x2939bbdbu, + 0xa9ba4650u, 0xac9526e8u, 0xbe5ee304u, 0xa1fad5f0u, 0x6a2d519au, + 0x63ef8ce2u, 0x9a86ee22u, 0xc089c2b8u, 0x43242ef6u, 0xa51e03aau, + 0x9cf2d0a4u, 0x83c061bau, 0x9be96a4du, 0x8fe51550u, 0xba645bd6u, + 0x2826a2f9u, 0xa73a3ae1u, 0x4ba99586u, 0xef5562e9u, 0xc72fefd3u, + 0xf752f7dau, 0x3f046f69u, 0x77fa0a59u, 0x80e4a915u, 0x87b08601u, + 0x9b09e6adu, 0x3b3ee593u, 0xe990fd5au, 0x9e34d797u, 0x2cf0b7d9u, + 0x022b8b51u, 0x96d5ac3au, 0x017da67du, 0xd1cf3ed6u, 0x7c7d2d28u, + 0x1f9f25cfu, 0xadf2b89bu, 0x5ad6b472u, 0x5a88f54cu, 0xe029ac71u, + 0xe019a5e6u, 0x47b0acfdu, 0xed93fa9bu, 0xe8d3c48du, 0x283b57ccu, + 0xf8d56629u, 0x79132e28u, 0x785f0191u, 0xed756055u, 0xf7960e44u, + 0xe3d35e8cu, 0x15056dd4u, 0x88f46dbau, 0x03a16125u, 0x0564f0bdu, + 0xc3eb9e15u, 0x3c9057a2u, 0x97271aecu, 0xa93a072au, 0x1b3f6d9bu, + 0x1e6321f5u, 0xf59c66fbu, 0x26dcf319u, 0x7533d928u, 0xb155fdf5u, + 0x03563482u, 0x8aba3cbbu, 0x28517711u, 0xc20ad9f8u, 0xabcc5167u, + 0xccad925fu, 0x4de81751u, 0x3830dc8eu, 0x379d5862u, 0x9320f991u, + 0xea7a90c2u, 0xfb3e7bceu, 0x5121ce64u, 0x774fbe32u, 0xa8b6e37eu, + 0xc3293d46u, 0x48de5369u, 0x6413e680u, 0xa2ae0810u, 0xdd6db224u, + 0x69852dfdu, 0x09072166u, 0xb39a460au, 0x6445c0ddu, 0x586cdecfu, + 0x1c20c8aeu, 0x5bbef7ddu, 0x1b588d40u, 0xccd2017fu, 0x6bb4e3bbu, + 0xdda26a7eu, 0x3a59ff45u, 0x3e350a44u, 0xbcb4cdd5u, 0x72eacea8u, + 0xfa6484bbu, 0x8d6612aeu, 0xbf3c6f47u, 0xd29be463u, 0x542f5d9eu, + 0xaec2771bu, 0xf64e6370u, 0x740e0d8du, 0xe75b1357u, 0xf8721671u, + 0xaf537d5du, 0x4040cb08u, 0x4eb4e2ccu, 0x34d2466au, 0x0115af84u, + 0xe1b00428u, 0x95983a1du, 0x06b89fb4u, 0xce6ea048u, 0x6f3f3b82u, + 0x3520ab82u, 0x011a1d4bu, 0x277227f8u, 0x611560b1u, 0xe7933fdcu, + 0xbb3a792bu, 0x344525bdu, 0xa08839e1u, 0x51ce794bu, 0x2f32c9b7u, + 0xa01fbac9u, 0xe01cc87eu, 0xbcc7d1f6u, 0xcf0111c3u, 0xa1e8aac7u, + 0x1a908749u, 0xd44fbd9au, 0xd0dadecbu, 0xd50ada38u, 0x0339c32au, + 0xc6913667u, 0x8df9317cu, 0xe0b12b4fu, 0xf79e59b7u, 0x43f5bb3au, + 0xf2d519ffu, 0x27d9459cu, 0xbf97222cu, 0x15e6fc2au, 0x0f91fc71u, + 0x9b941525u, 0xfae59361u, 0xceb69cebu, 0xc2a86459u, 0x12baa8d1u, + 0xb6c1075eu, 0xe3056a0cu, 0x10d25065u, 0xcb03a442u, 0xe0ec6e0eu, + 0x1698db3bu, 0x4c98a0beu, 0x3278e964u, 0x9f1f9532u, 0xe0d392dfu, + 0xd3a0342bu, 0x8971f21eu, 0x1b0a7441u, 0x4ba3348cu, 0xc5be7120u, + 0xc37632d8u, 0xdf359f8du, 0x9b992f2eu, 0xe60b6f47u, 0x0fe3f11du, + 0xe54cda54u, 0x1edad891u, 0xce6279cfu, 0xcd3e7e6fu, 0x1618b166u, + 0xfd2c1d05u, 0x848fd2c5u, 0xf6fb2299u, 0xf523f357u, 0xa6327623u, + 0x93a83531u, 0x56cccd02u, 0xacf08162u, 0x5a75ebb5u, 0x6e163697u, + 0x88d273ccu, 0xde966292u, 0x81b949d0u, 0x4c50901bu, 0x71c65614u, + 0xe6c6c7bdu, 0x327a140au, 0x45e1d006u, 0xc3f27b9au, 0xc9aa53fdu, + 0x62a80f00u, 0xbb25bfe2u, 0x35bdd2f6u, 0x71126905u, 0xb2040222u, + 0xb6cbcf7cu, 0xcd769c2bu, 0x53113ec0u, 0x1640e3d3u, 0x38abbd60u, + 0x2547adf0u, 0xba38209cu, 0xf746ce76u, 0x77afa1c5u, 0x20756060u, + 0x85cbfe4eu, 0x8ae88dd8u, 0x7aaaf9b0u, 0x4cf9aa7eu, 0x1948c25cu, + 0x02fb8a8cu, 0x01c36ae4u, 0xd6ebe1f9u, 0x90d4f869u, 0xa65cdea0u, + 0x3f09252du, 0xc208e69fu, 0xb74e6132u, 0xce77e25bu, 0x578fdfe3u, + 0x3ac372e6u +}; + +#endif /* BLOWFISH_TABLES_H */ +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/Blowfish.c b/src/Blowfish.c new file mode 100644 index 0000000..f1ab55a --- /dev/null +++ b/src/Blowfish.c @@ -0,0 +1,240 @@ +/* + * + * Blowfish.c : Blowfish implementation + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * ======================================================================= + * The contents of this file are dedicated to the public domain. To the extent + * that dedication to the public domain is not available, everyone is granted a + * worldwide, perpetual, royalty-free, non-exclusive license to exercise all + * rights associated with the contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ======================================================================= + * + * Country of origin: Canada + * + * The Blowfish algorithm is documented at + * http://www.schneier.com/paper-blowfish-fse.html + */ + +#include "pycrypto_common.h" +#include "Blowfish-tables.h" +#include <assert.h> +#include <string.h> + +#define MODULE_NAME _Blowfish +#define BLOCK_SIZE 8 /* 64-bit block size */ +#define KEY_SIZE 0 /* variable key size */ + +#define BLOWFISH_MAGIC 0xf9d565deu +typedef struct { + uint32_t magic; + + /* P permutation */ + uint32_t P[18]; + + /* Subkeys (S-boxes) */ + uint32_t S1[256]; + uint32_t S2[256]; + uint32_t S3[256]; + uint32_t S4[256]; +} Blowfish_state; + +/* The Blowfish round function F. Everything is taken modulo 2**32 */ +#define F(a, b, c, d) (((a) + (b)) ^ (c)) + (d) + +static inline uint32_t bytes_to_word(const unsigned char *in) +{ + /* big endian */ + return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3]; +} + +static inline void word_to_bytes(uint32_t w, unsigned char *out) +{ + /* big endian */ + out[0] = (w >> 24) & 0xff; + out[1] = (w >> 16) & 0xff; + out[2] = (w >> 8) & 0xff; + out[3] = w & 0xff; +} + +static inline void inline_encrypt(Blowfish_state *self, uint32_t *pxL, uint32_t *pxR) +{ + int i; + uint32_t xL = *pxL; + uint32_t xR = *pxR; + uint32_t tmp; + + for (i = 0; i < 16; i++) { + xL ^= self->P[i]; + + /* a || b || c || d = xL (big endian) */ + xR ^= F(self->S1[(xL >> 24) & 0xff], /* S1[a] */ + self->S2[(xL >> 16) & 0xff], /* S2[b] */ + self->S3[(xL >> 8) & 0xff], /* S3[c] */ + self->S4[xL & 0xff]); /* S4[d] */ + + /* Swap xL, xR */ + tmp = xL; xL = xR; xR = tmp; + } + + /* Swap xL, xR */ + tmp = xL; xL = xR; xR = tmp; + + xR ^= self->P[16]; + xL ^= self->P[17]; + + *pxL = xL; + *pxR = xR; +} + +static inline void inline_decrypt(Blowfish_state *self, uint32_t *pxL, uint32_t *pxR) +{ + int i; + uint32_t xL = *pxL; + uint32_t xR = *pxR; + uint32_t tmp; + + xL ^= self->P[17]; + xR ^= self->P[16]; + + /* Swap xL, xR */ + tmp = xL; xL = xR; xR = tmp; + + for (i = 15; i >= 0; i--) { + /* Swap xL, xR */ + tmp = xL; xL = xR; xR = tmp; + + /* a || b || c || d = xL (big endian) */ + xR ^= F(self->S1[(xL >> 24) & 0xff], /* S1[a] */ + self->S2[(xL >> 16) & 0xff], /* S2[b] */ + self->S3[(xL >> 8) & 0xff], /* S3[c] */ + self->S4[xL & 0xff]); /* S4[d] */ + + xL ^= self->P[i]; + } + + *pxL = xL; + *pxR = xR; +} + +static void Blowfish_encrypt(Blowfish_state *self, const unsigned char *in, unsigned char *out) +{ + uint32_t xL, xR; + + /* Make sure the object is initialized */ + assert(self->magic == BLOWFISH_MAGIC); + + /* big endian */ + xL = bytes_to_word(in); + xR = bytes_to_word(in+4); + + inline_encrypt(self, &xL, &xR); + + /* big endian */ + word_to_bytes(xL, out); + word_to_bytes(xR, out+4); +} + +static void Blowfish_decrypt(Blowfish_state *self, const unsigned char *in, unsigned char *out) +{ + uint32_t xL, xR; + + /* Make sure the object is initialized */ + assert(self->magic == BLOWFISH_MAGIC); + + /* big endian */ + xL = bytes_to_word(in); + xR = bytes_to_word(in+4); + + inline_decrypt(self, &xL, &xR); + + /* big endian */ + word_to_bytes(xL, out); + word_to_bytes(xR, out+4); +} + +static void Blowfish_init(Blowfish_state *self, const unsigned char *key, int keylen) +{ + uint32_t word; + int i; + uint32_t xL, xR; + + self->magic = 0; + + if (keylen < 1) { + PyErr_SetString(PyExc_ValueError, "Key cannot be empty"); + return; + } else if (keylen > 56) { + PyErr_SetString(PyExc_ValueError, "Maximum key size is 448 bits"); + return; + } + + /* Initialize the P-array with the digits of Pi, and XOR it with the key */ + word = 0; + for (i = 0; i < 18*4; i++) { + word = (word << 8) | key[i % keylen]; + if ((i & 3) == 3) { + self->P[i >> 2] = initial_P[i >> 2] ^ word; + word = 0; + } + } + + /* Initialize the S-boxes with more digits of Pi */ + memcpy(self->S1, initial_S1, 256*sizeof(uint32_t)); + memcpy(self->S2, initial_S2, 256*sizeof(uint32_t)); + memcpy(self->S3, initial_S3, 256*sizeof(uint32_t)); + memcpy(self->S4, initial_S4, 256*sizeof(uint32_t)); + + /* Stir the subkeys */ + xL = xR = 0; + for (i = 0; i < 18; i += 2) { + inline_encrypt(self, &xL, &xR); + self->P[i] = xL; + self->P[i+1] = xR; + } + for (i = 0; i < 256; i += 2) { + inline_encrypt(self, &xL, &xR); + self->S1[i] = xL; + self->S1[i+1] = xR; + } + for (i = 0; i < 256; i += 2) { + inline_encrypt(self, &xL, &xR); + self->S2[i] = xL; + self->S2[i+1] = xR; + } + for (i = 0; i < 256; i += 2) { + inline_encrypt(self, &xL, &xR); + self->S3[i] = xL; + self->S3[i+1] = xR; + } + for (i = 0; i < 256; i += 2) { + inline_encrypt(self, &xL, &xR); + self->S4[i] = xL; + self->S4[i+1] = xR; + } + + self->magic = BLOWFISH_MAGIC; +} + +#define block_state Blowfish_state +#define block_init Blowfish_init +#define block_encrypt Blowfish_encrypt +#define block_decrypt Blowfish_decrypt + +static void block_finalize(block_state *self) +{ +} + +#include "block_template.c" + +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/CAST.c b/src/CAST.c new file mode 100644 index 0000000..d7b00f3 --- /dev/null +++ b/src/CAST.c @@ -0,0 +1,458 @@ +/* + cast.c -- implementation of CAST-128 (aka CAST5) as described in RFC2144 + + Written in 1997 by Wim Lewis <wiml@hhhh.org> based entirely on RFC2144. + Minor modifications made in 2002 by Andrew M. Kuchling <amk@amk.ca>. + + =================================================================== + The contents of this file are dedicated to the public domain. To + the extent that dedication to the public domain is not available, + everyone is granted a worldwide, perpetual, royalty-free, + non-exclusive license to exercise all rights associated with the + contents of this file for any purpose whatsoever. + No rights are reserved. + + 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 AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + =================================================================== + + Consult your local laws for possible restrictions on use, distribution, and + import/export. RFC2144 states that this algorithm "is available worldwide + on a royalty-free basis for commercial and non-commercial uses". + + This code is a pretty straightforward transliteration of the RFC into C. + It has not been optimized much at all: byte-order-independent arithmetic + operations are used where order-dependent pointer ops or unions might be + faster; the code could be rearranged to give the optimizer a better + chance to speed things up; etc. + + This code requires a vaguely ANSI-ish compiler. + + compile -DTEST to include main() which performs the tests + specified in RFC2144 + + Tested with gcc 2.5.8 on i486, i586, i686, hp pa-risc, mc68040, sparc; + also with gcc 2.7.2 and (with minor changes) native Sun compiler on sparc + +*/ + +#include "pycrypto_common.h" + +#define MODULE_NAME _CAST +#define BLOCK_SIZE 8 +#define KEY_SIZE 0 + +/* adjust these according to your compiler/platform. On some machines + uint32 will have to be a long. It's OK if uint32 is more than 32 bits. */ +typedef uint32_t uint32; +typedef uint8_t uint8; + +/* this struct probably belongs in cast.h */ +typedef struct { + /* masking and rotate keys */ + uint32 Km[16]; + uint8 Kr[16]; + /* number of rounds (depends on original unpadded keylength) */ + int rounds; +} block_state; + +/* these are the eight 32*256 S-boxes */ +#include "cast5.c" + +/* fetch a uint32 from an array of uint8s (with a given offset) */ +#define fetch(ptr, base) (((((( ptr[base]<< 8 ) | ptr[base+1] )<< 8 ) | ptr[base+2] )<< 8 ) | ptr[base+3]) + +/* this is the round function f(D, Km, Kr) */ +static uint32 castfunc(uint32 D, uint32 Kmi, uint8 Kri, int type) +{ + uint32 I, f; + short Ia, Ib, Ic, Id; + + switch(type) { + case 0: + I = (Kmi + D) ; + break; + case 1: + I = (Kmi ^ D) ; + break; + default: + case 2: + I = (Kmi - D) ; + break; + } + + I &= 0xFFFFFFFF; + I = ( I << Kri ) | ( I >> ( 32-Kri ) ); + Ia = ( I >> 24 ) & 0xFF; + Ib = ( I >> 16 ) & 0xFF; + Ic = ( I >> 8 ) & 0xFF; + Id = ( I ) & 0xFF; + + switch(type) { + case 0: + f = ((S1[Ia] ^ S2[Ib]) - S3[Ic]) + S4[Id]; + break; + case 1: + f = ((S1[Ia] - S2[Ib]) + S3[Ic]) ^ S4[Id]; + break; + default: + case 2: + f = ((S1[Ia] + S2[Ib]) ^ S3[Ic]) - S4[Id]; + break; + } + + return f; +} + +/* encrypts/decrypts one block of data according to the key schedule + pointed to by `key'. Encrypts if decrypt=0, otherwise decrypts. */ +static void castcrypt(block_state *key, uint8 *block, int decrypt) +{ + uint32 L, R, tmp, f; + uint32 Kmi; + uint8 Kri; + short functype, round; + + L = fetch(block, 0); + R = fetch(block, 4); + +/* printf("L0 = %08x R0 = %08x\n", L, R); */ + + for(round = 0; round < key->rounds; round ++) { + + if (!decrypt) { + Kmi = key->Km[round]; + Kri = key->Kr[round]; + functype = round % 3; + } else { + Kmi = key->Km[(key->rounds) - round - 1]; + Kri = key->Kr[(key->rounds) - round - 1]; + functype = (((key->rounds) - round - 1) % 3); + } + + f = castfunc(R, Kmi, Kri, functype); + + tmp = L; + L = R; + R = tmp ^ f; + +/* printf("L%d = %08x R%d = %08x\n", round+1, L, round+1, R); */ + } + + block[0] = ( R & 0xFF000000 ) >> 24; + block[1] = ( R & 0x00FF0000 ) >> 16; + block[2] = ( R & 0x0000FF00 ) >> 8; + block[3] = ( R & 0x000000FF ); + block[4] = ( L & 0xFF000000 ) >> 24; + block[5] = ( L & 0x00FF0000 ) >> 16; + block[6] = ( L & 0x0000FF00 ) >> 8; + block[7] = ( L & 0x000000FF ); +} + +/* fetch a uint8 from an array of uint32s */ +#define b(a,n) (((a)[n/4] >> (24-((n&3)*8))) & 0xFF) + +/* key schedule round functions */ + +#define XZRound(T, F, ki1, ki2, ki3, ki4, \ + si11, si12, si13, si14, si15,\ + si25,\ + si35,\ + si45 ) \ + T[0] = F[ki1] ^ S5[si11 ] ^ S6[si12 ] ^ S7[si13 ] ^ S8[si14 ] ^ S7[si15];\ + T[1] = F[ki2] ^ S5[b(T, 0)] ^ S6[b(T,2)] ^ S7[b(T, 1)] ^ S8[b(T,3)] ^ S8[si25];\ + T[2] = F[ki3] ^ S5[b(T, 7)] ^ S6[b(T,6)] ^ S7[b(T, 5)] ^ S8[b(T,4)] ^ S5[si35];\ + T[3] = F[ki4] ^ S5[b(T,10)] ^ S6[b(T,9)] ^ S7[b(T,11)] ^ S8[b(T,8)] ^ S6[si45]; + +#define zxround() XZRound(z, x, 0, 2, 3, 1, \ + b(x,13), b(x,15), b(x,12), b(x,14),\ + b(x, 8), b(x,10), b(x, 9), b(x,11)) + +#define xzround() XZRound(x, z, 2, 0, 1, 3, \ + b(z,5), b(z,7), b(z,4), b(z,6), \ + b(z,0), b(z,2), b(z,1), b(z,3)) + +#define Kround(T, base, F,\ + i11, i12, i13, i14, i15,\ + i21, i22, i23, i24, i25,\ + i31, i32, i33, i34, i35,\ + i41, i42, i43, i44, i45)\ + T[base+0] = S5[b(F,i11)] ^ S6[b(F,i12)] ^ S7[b(F,i13)] ^ S8[b(F,i14)] ^ S5[b(F,i15)];\ + T[base+1] = S5[b(F,i21)] ^ S6[b(F,i22)] ^ S7[b(F,i23)] ^ S8[b(F,i24)] ^ S6[b(F,i25)];\ + T[base+2] = S5[b(F,i31)] ^ S6[b(F,i32)] ^ S7[b(F,i33)] ^ S8[b(F,i34)] ^ S7[b(F,i35)];\ + T[base+3] = S5[b(F,i41)] ^ S6[b(F,i42)] ^ S7[b(F,i43)] ^ S8[b(F,i44)] ^ S8[b(F,i45)]; + +/* generates sixteen 32-bit subkeys based on a 4x32-bit input key; + modifies the input key *in as well. */ +static void schedulekeys_half(uint32 *in, uint32 *keys) +{ + uint32 x[4], z[4]; + + x[0] = in[0]; + x[1] = in[1]; + x[2] = in[2]; + x[3] = in[3]; + + zxround(); + Kround(keys, 0, z, + 8, 9, 7, 6, 2, + 10, 11, 5, 4, 6, + 12, 13, 3, 2, 9, + 14, 15, 1, 0, 12); + xzround(); + Kround(keys, 4, x, + 3, 2, 12, 13, 8, + 1, 0, 14, 15, 13, + 7, 6, 8, 9, 3, + 5, 4, 10, 11, 7); + zxround(); + Kround(keys, 8, z, + 3, 2, 12, 13, 9, + 1, 0, 14, 15, 12, + 7, 6, 8, 9, 2, + 5, 4, 10, 11, 6); + xzround(); + Kround(keys, 12, x, + 8, 9, 7, 6, 3, + 10, 11, 5, 4, 7, + 12, 13, 3, 2, 8, + 14, 15, 1, 0, 13); + + in[0] = x[0]; + in[1] = x[1]; + in[2] = x[2]; + in[3] = x[3]; +} + +/* generates a key schedule from an input key */ +static void castschedulekeys(block_state *schedule, uint8 *key, int keybytes) +{ + uint32 x[4]; + uint8 paddedkey[16]; + uint32 Kr_wide[16]; + int i; + + for(i = 0; i < keybytes; i++) + paddedkey[i] = key[i]; + for( ; i < 16 ; i++) + paddedkey[i] = 0; + + if (keybytes <= 10) + schedule->rounds = 12; + else + schedule->rounds = 16; + + x[0] = fetch(paddedkey, 0); + x[1] = fetch(paddedkey, 4); + x[2] = fetch(paddedkey, 8); + x[3] = fetch(paddedkey, 12); + + schedulekeys_half(x, schedule->Km); + schedulekeys_half(x, Kr_wide); + + for(i = 0; i < 16; i ++) { + /* The Kr[] subkeys are used for 32-bit circular shifts, + so we only need to keep them modulo 32 */ + schedule->Kr[i] = (uint8)(Kr_wide[i] & 0x1F); + } +} + +#ifdef TEST + +/* This performs a variety of encryptions and verifies that the results + match those specified in RFC2144 appendix B. Also verifies that + decryption restores the original data. */ + +#include <stdio.h> + +static block_state sched; + +void encrypt(key, keylen, in, out) + uint8 *key; + int keylen; + uint8 *in, *out; +{ + int i; + uint8 k[16]; + + castschedulekeys(&sched, key, keylen); + + for(i = 0; i < 8; i++) + out[i] = in[i]; + castcrypt(&sched, out, 0); +} + +void tst(key, keylen, data, result) + uint8 *key; + int keylen; + uint8 *data, *result; +{ + uint8 d[8]; + int i; + + encrypt(key, keylen, data, d); + + for(i = 0; i < 8; i++) + if (d[i] != result[i]) + break; + + if (i == 8) { + printf("-- test ok (encrypt)\n"); + } else { + for(i = 0; i < 8; i++) + printf(" %02x", d[i]); + printf(" (computed)\n"); + for(i = 0; i < 8; i++) + printf(" %02x", result[i]); + printf(" (expected)\n"); + } + + /* uses key schedule already set up */ + castcrypt(&sched, d, 1); + if (bcmp(d, data, 8)) + printf(" test FAILED (decrypt)\n"); + else + printf(" test ok (decrypt)\n"); + +} + +uint8 key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; +uint8 data[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + +/* expected results of encrypting the above with 128, 80, and 40 + bits of key length */ +uint8 out1[8] = { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; +uint8 out2[8] = { 0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B }; +uint8 out3[8] = { 0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E }; + +/* expected results of the "full maintenance test" */ +uint8 afinal[16] = { 0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6, + 0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92 }; +uint8 bfinal[16] = { 0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71, + 0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E }; + +main() +{ + /* Appendix B.1 : Single Plaintext-Key-Ciphertext Sets */ + tst(key, 16, data, out1); + tst(key, 10, data, out2); + tst(key, 5, data, out3); + + /* Appendix B.2 : Full Maintenance Test */ + { + uint8 abuf[16]; + uint8 bbuf[16]; + int i; + + bcopy(key, abuf, 16); + bcopy(key, bbuf, 16); + + printf("\nrunning full maintenance test...\n"); + + for(i = 0; i < 1000000; i++) { + castschedulekeys(&sched, bbuf, 16); + castcrypt(&sched, abuf, 0); + castcrypt(&sched, abuf+8, 0); + + castschedulekeys(&sched, abuf, 16); + castcrypt(&sched, bbuf, 0); + castcrypt(&sched, bbuf+8, 0); + + if (!(i % 10000)) { + fprintf(stdout, "\r%d%% ", i / 10000); + fflush(stdout); + } + } + + printf("\r \r"); + + for(i = 0; i < 16; i ++) + if (abuf[i] != afinal[i] || bbuf[i] != bfinal[i]) + break; + + if(i == 16) { + printf("-- full maintenance test ok\n"); + } else { + for(i = 0; i < 16; i++) + printf(" %02x", abuf[i]); + printf("\n"); + for(i = 0; i < 16; i++) + printf(" %02x", bbuf[i]); + printf("\n"); + } + + printf("running maintenance test in reverse...\n"); + for(i = 0; i < 1000000; i++) { + castschedulekeys(&sched, abuf, 16); + castcrypt(&sched, bbuf+8, 1); + castcrypt(&sched, bbuf, 1); + + castschedulekeys(&sched, bbuf, 16); + castcrypt(&sched, abuf+8, 1); + castcrypt(&sched, abuf, 1); + + if (!(i % 10000)) { + fprintf(stdout, "\r%d%% ", i / 10000); + fflush(stdout); + } + } + + printf("\r \r"); + if (bcmp(abuf, key, 16) || bcmp(bbuf, key, 16)) + printf("-- reverse maintenance test FAILED\n"); + else + printf("-- reverse maintenance test ok\n"); + } +} + +#endif + +static void +block_init(block_state *self, unsigned char *key, int keylength) +{ + /* presumably this will optimize out */ + if (sizeof(uint32) < 4 || sizeof(uint8) != 1) { + PyErr_SetString(PyExc_SystemError, + "CAST module compiled with bad typedefs!"); + } + + /* make sure the key length is within bounds */ + if (keylength < 5 || keylength > 16) { + PyErr_SetString(PyExc_ValueError, "CAST key must be " + "at least 5 bytes and no more than 16 bytes long"); + return; + } + + /* do the actual key schedule setup */ + castschedulekeys(self, key, keylength); +} + +static void +block_finalize(block_state* self) +{ +} + +static void +block_encrypt(block_state *self, unsigned char *in, + unsigned char *out) +{ + memcpy(out, in, 8); + castcrypt(self, out, 0); +} + +static void block_decrypt(block_state *self, + unsigned char *in, + unsigned char *out) +{ + memcpy(out, in, 8); + castcrypt(self, out, 1); +} + +#include "block_template.c" diff --git a/src/DES.c b/src/DES.c new file mode 100644 index 0000000..2987956 --- /dev/null +++ b/src/DES.c @@ -0,0 +1,132 @@ +/* + * DES.c: DES/3DES support for PyCrypto using LibTomCrypt + * + * Written in 2009 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + * Country of origin: Canada + */ + +#include "pycrypto_common.h" + +/* Setting this will cause LibTomCrypt to return CRYPT_INVALID_ARG when its + * assert-like LTC_ARGCHK macro fails. */ +#define ARGTYPE 4 + +/* Include the actial DES implementation */ +#include "libtom/tomcrypt_des.c" + +#include <assert.h> + +typedef struct { + symmetric_key sk; +} block_state; + +static void ltcseterr(int rc) +{ + /* error */ + switch (rc) { + case CRYPT_INVALID_ARG: + PyErr_SetString(PyExc_AssertionError, "CRYPT_INVALID_ARG"); + break; + + case CRYPT_INVALID_KEYSIZE: +#ifdef PCT_DES3_MODULE + PyErr_SetString(PyExc_ValueError, "Invalid key size (must be either 16 or 24 bytes long)"); +#else + PyErr_SetString(PyExc_ValueError, "Invalid key size (must be 8 bytes long)"); +#endif + break; + + case CRYPT_INVALID_ROUNDS: + PyErr_SetString(PyExc_ValueError, "Invalid number of rounds specified"); + break; + + default: + PyErr_Format(PyExc_RuntimeError, + "unexpected run-time error (LTC#%d)", rc); + } +} + +static void block_init(block_state *self, unsigned char *key, int keylen) +{ + int rc; +#ifdef PCT_DES3_MODULE + int i; + unsigned char keybuf[24]; + if (keylen == 16) { + /* "Two-key 3DES" mode, where the 3DES key is K1,K2,K1 */ + for (i = 0; i < 16; i++) { + keybuf[i] = key[i]; + } + for (i = 0; i < 8; i++) { + keybuf[i+16] = key[i]; + } + rc = des3_setup(keybuf, 24, 0, &self->sk); + for (i = 0; i < 24; i++) { /* TODO: securely zeroize this */ + keybuf[i] = 0; + } + } else { + rc = des3_setup(key, keylen, 0, &self->sk); + } +#else + rc = des_setup(key, keylen, 0, &self->sk); +#endif + if (rc != CRYPT_OK) { + ltcseterr(rc); + } +} + +static void block_finalize(block_state *self) +{ +} + +static void block_encrypt(block_state *self, unsigned char *in, unsigned char *out) +{ + int rc; +#ifdef PCT_DES3_MODULE + rc = des3_ecb_encrypt(in, out, &self->sk); +#else + rc = des_ecb_encrypt(in, out, &self->sk); +#endif + assert(rc == CRYPT_OK); +} + +static void block_decrypt(block_state *self, unsigned char *in, unsigned char *out) +{ + int rc; +#ifdef PCT_DES3_MODULE + rc = des3_ecb_decrypt(in, out, &self->sk); +#else + rc = des_ecb_decrypt(in, out, &self->sk); +#endif + assert(rc == CRYPT_OK); +} + +#ifdef PCT_DES3_MODULE +# define MODULE_NAME _DES3 /* triple DES */ +# define BLOCK_SIZE 8 /* 64-bit block size */ +# define KEY_SIZE 0 /* variable key size (can be 128 or 192 bits (including parity) */ +#else +# define MODULE_NAME _DES /* single DES */ +# define BLOCK_SIZE 8 /* 64-bit block size */ +# define KEY_SIZE 8 /* 64-bit keys (including parity) */ +#endif +#include "block_template.c" diff --git a/src/DES3.c b/src/DES3.c new file mode 100644 index 0000000..c23de1a --- /dev/null +++ b/src/DES3.c @@ -0,0 +1,26 @@ +/* + * DES3.c: 3DES support for PyCrypto using LibTomCrypt + * + * Written in 2009 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ +#define PCT_DES3_MODULE +#include "DES.c" diff --git a/src/MD2.c b/src/MD2.c new file mode 100644 index 0000000..86ea859 --- /dev/null +++ b/src/MD2.c @@ -0,0 +1,158 @@ + +/* + * md2.c : MD2 hash algorithm. + * + * Part of the Python Cryptography Toolkit + * + * Originally written by: A.M. Kuchling + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + + +#include "pycrypto_common.h" +#include <string.h> + +#define MODULE_NAME MD2 +#define DIGEST_SIZE 16 +#define BLOCK_SIZE 64 + +static char MODULE__doc__[] = + "MD2 cryptographic hash algorithm.\n" + "\n" + "MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import MD2\n" + " >>>\n" + " >>> h = MD2.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.\n" + "\n" + "This algorithm is both slow and insecure. Do not use it for new designs.\n" + "\n" + ".. _RFC1319: http://tools.ietf.org/html/rfc1319\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +typedef uint8_t U8; +typedef uint32_t U32; + +typedef struct { + U8 C[16], X[48]; + unsigned int count; + U8 buf[16]; +} hash_state; + +static void hash_init (hash_state *ptr) +{ + memset(ptr->X, 0, 48); + memset(ptr->C, 0, 16); + ptr->count=0; +} + +static U8 S[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 +}; + +static void +hash_copy(hash_state *src, hash_state *dest) +{ + dest->count=src->count; + memcpy(dest->buf, src->buf, dest->count); + memcpy(dest->X, src->X, 48); + memcpy(dest->C, src->C, 16); +} + + +static void hash_update (hash_state *self, const U8 *buf, U32 len) +{ + U32 L; + while (len) + { + L=(16-self->count) < len ? (16-self->count) : len; + memcpy(self->buf+self->count, buf, L); + self->count+=L; + buf+=L; + len-=L; + if (self->count==16) + { + U8 t; + int i,j; + + self->count=0; + memcpy(self->X+16, self->buf, 16); + t=self->C[15]; + for(i=0; i<16; i++) + { + self->X[32+i]=self->X[16+i]^self->X[i]; + t=self->C[i]^=S[self->buf[i]^t]; + } + + t=0; + for(i=0; i<18; i++) + { + for(j=0; j<48; j++) + t=self->X[j]^=S[t]; + t=(t+i) & 0xFF; + } + } + } +} + +static PyObject * +hash_digest (const hash_state *self) +{ + U8 padding[16]; + U32 padlen; + hash_state temp; + unsigned int i; + + memcpy(&temp, self, sizeof(hash_state)); + padlen= 16-self->count; + for(i=0; i<padlen; i++) padding[i]=padlen; + hash_update(&temp, padding, padlen); + hash_update(&temp, temp.C, 16); + return PyBytes_FromStringAndSize((char *) temp.X, 16); +} + +#include "hash_template.c" diff --git a/src/MD4.c b/src/MD4.c new file mode 100644 index 0000000..2d38339 --- /dev/null +++ b/src/MD4.c @@ -0,0 +1,242 @@ + +/* + * md4.c : MD4 hash algorithm. + * + * Part of the Python Cryptography Toolkit + * + * Originally written by: A.M. Kuchling + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" +#include <string.h> + +#define MODULE_NAME MD4 +#define DIGEST_SIZE 16 +#define BLOCK_SIZE 64 + +static char MODULE__doc__[] = + "MD4 cryptographic hash algorithm.\n" + "\n" + "MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import MD4\n" + " >>>\n" + " >>> h = MD4.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.\n" + "\n" + "This algorithm is insecure. Do not use it for new designs.\n" + "\n" + ".. _RFC1320: http://tools.ietf.org/html/rfc1320\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +typedef uint32_t U32; +typedef uint8_t U8; +#define U32_MAX (U32)4294967295 + +typedef struct { + U32 A,B,C,D, count; + U32 len1, len2; + U8 buf[64]; +} hash_state; + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROL(x, n) (((x) << n) | ((x) >> (32-n) )) + +static void +hash_init (hash_state *ptr) +{ + ptr->A=(U32)0x67452301; + ptr->B=(U32)0xefcdab89; + ptr->C=(U32)0x98badcfe; + ptr->D=(U32)0x10325476; + ptr->count=ptr->len1=ptr->len2=0; +} + +static void +hash_copy(hash_state *src, hash_state *dest) +{ + dest->len1=src->len1; + dest->len2=src->len2; + dest->A=src->A; + dest->B=src->B; + dest->C=src->C; + dest->D=src->D; + dest->count=src->count; + memcpy(dest->buf, src->buf, dest->count); +} + +static void +hash_update (hash_state *self, const U8 *buf, U32 len) +{ + U32 L; + + if ((self->len1+(len<<3))<self->len1) + { + self->len2++; + } + self->len1+=len<< 3; + self->len2+=len>>29; + while (len>0) + { + L=(64-self->count) < len ? (64-self->count) : len; + memcpy(self->buf+self->count, buf, L); + self->count+=L; + buf+=L; + len-=L; + if (self->count==64) + { + U32 X[16], A, B, C, D; + int i,j; + self->count=0; + for(i=j=0; j<16; i+=4, j++) + X[j]=((U32)self->buf[i] + ((U32)self->buf[i+1]<<8) + + ((U32)self->buf[i+2]<<16) + ((U32)self->buf[i+3]<<24)); + + + A=self->A; B=self->B; C=self->C; D=self->D; + +#define function(a,b,c,d,k,s) a=ROL(a+F(b,c,d)+X[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function +#define function(a,b,c,d,k,s) a=ROL(a+G(b,c,d)+X[k]+(U32)0x5a827999,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function +#define function(a,b,c,d,k,s) a=ROL(a+H(b,c,d)+X[k]+(U32)0x6ed9eba1,s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + self->A+=A; self->B+=B; self->C+=C; self->D+=D; + } + } +} + +static PyObject * +hash_digest (const hash_state *self) +{ + U8 digest[16]; + static U8 s[8]; + U32 padlen, oldlen1, oldlen2; + hash_state temp; + static U8 padding[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + memcpy(&temp, self, sizeof(hash_state)); + oldlen1=temp.len1; oldlen2=temp.len2; /* Save current length */ + padlen= (56<=self->count) ? 56-self->count+64: 56-self->count; + hash_update(&temp, padding, padlen); + s[0]= oldlen1 & 255; + s[1]=(oldlen1 >> 8) & 255; + s[2]=(oldlen1 >> 16) & 255; + s[3]=(oldlen1 >> 24) & 255; + s[4]= oldlen2 & 255; + s[5]=(oldlen2 >> 8) & 255; + s[6]=(oldlen2 >> 16) & 255; + s[7]=(oldlen2 >> 24) & 255; + hash_update(&temp, s, 8); + + digest[ 0]= temp.A & 255; + digest[ 1]=(temp.A >> 8) & 255; + digest[ 2]=(temp.A >> 16) & 255; + digest[ 3]=(temp.A >> 24) & 255; + digest[ 4]= temp.B & 255; + digest[ 5]=(temp.B >> 8) & 255; + digest[ 6]=(temp.B >> 16) & 255; + digest[ 7]=(temp.B >> 24) & 255; + digest[ 8]= temp.C & 255; + digest[ 9]=(temp.C >> 8) & 255; + digest[10]=(temp.C >> 16) & 255; + digest[11]=(temp.C >> 24) & 255; + digest[12]= temp.D & 255; + digest[13]=(temp.D >> 8) & 255; + digest[14]=(temp.D >> 16) & 255; + digest[15]=(temp.D >> 24) & 255; + + return PyBytes_FromStringAndSize((char *) digest, 16); +} + +#include "hash_template.c" diff --git a/src/RIPEMD160.c b/src/RIPEMD160.c new file mode 100644 index 0000000..8b33bab --- /dev/null +++ b/src/RIPEMD160.c @@ -0,0 +1,443 @@ +/* + * + * RIPEMD160.c : RIPEMD-160 implementation + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + * Country of origin: Canada + * + * This implementation (written in C) is based on an implementation the author + * wrote in Python. + * + * This implementation was written with reference to the RIPEMD-160 + * specification, which is available at: + * http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/ + * + * It is also documented in the _Handbook of Applied Cryptography_, as + * Algorithm 9.55. It's on page 30 of the following PDF file: + * http://www.cacr.math.uwaterloo.ca/hac/about/chap9.pdf + * + * The RIPEMD-160 specification doesn't really tell us how to do padding, but + * since RIPEMD-160 is inspired by MD4, you can use the padding algorithm from + * RFC 1320. + * + * According to http://www.users.zetnet.co.uk/hopwood/crypto/scan/md.html: + * "RIPEMD-160 is big-bit-endian, little-byte-endian, and left-justified." + */ + +#include "pycrypto_common.h" +#include <assert.h> +#include <string.h> + +#define RIPEMD160_DIGEST_SIZE 20 +#define BLOCK_SIZE 64 + +static char MODULE__doc__[] = + "RIPEMD-160 cryptographic hash algorithm.\n" + "\n" + "RIPEMD-160_ produces the 160 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import RIPEMD160\n" + " >>>\n" + " >>> h = RIPEMD160.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest\n" + "with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.\n" + "\n" + "This algorithm is considered secure, although it has not been scrutinized as\n" + "extensively as SHA-1. Moreover, it provides an informal security level of just\n" + "80bits.\n" + "\n" + ".. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +#define RIPEMD160_MAGIC 0x9f19dd68u +typedef struct { + uint32_t magic; + uint32_t h[5]; /* The current hash state */ + uint64_t length; /* Total number of _bits_ (not bytes) added to the + hash. This includes bits that have been buffered + but not not fed through the compression function yet. */ + union { + uint32_t w[16]; + uint8_t b[64]; + } buf; + uint8_t bufpos; /* number of bytes currently in the buffer */ +} ripemd160_state; + + +/* cyclic left-shift the 32-bit word n left by s bits */ +#define ROL(s, n) (((n) << (s)) | ((n) >> (32-(s)))) + +/* Initial values for the chaining variables. + * This is just 0123456789ABCDEFFEDCBA9876543210F0E1D2C3 in little-endian. */ +static const uint32_t initial_h[5] = { 0x67452301u, 0xEFCDAB89u, 0x98BADCFEu, 0x10325476u, 0xC3D2E1F0u }; + +/* Ordering of message words. Based on the permutations rho(i) and pi(i), defined as follows: + * + * rho(i) := { 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }[i] 0 <= i <= 15 + * + * pi(i) := 9*i + 5 (mod 16) + * + * Line | Round 1 | Round 2 | Round 3 | Round 4 | Round 5 + * -------+-----------+-----------+-----------+-----------+----------- + * left | id | rho | rho^2 | rho^3 | rho^4 + * right | pi | rho pi | rho^2 pi | rho^3 pi | rho^4 pi + */ + +/* Left line */ +static const uint8_t RL[5][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* Round 1: id */ + { 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }, /* Round 2: rho */ + { 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 }, /* Round 3: rho^2 */ + { 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 }, /* Round 4: rho^3 */ + { 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 } /* Round 5: rho^4 */ +}; + +/* Right line */ +static const uint8_t RR[5][16] = { + { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 }, /* Round 1: pi */ + { 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 }, /* Round 2: rho pi */ + { 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 }, /* Round 3: rho^2 pi */ + { 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 }, /* Round 4: rho^3 pi */ + { 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 } /* Round 5: rho^4 pi */ +}; + +/* + * Shifts - Since we don't actually re-order the message words according to + * the permutations above (we could, but it would be slower), these tables + * come with the permutations pre-applied. + */ + +/* Shifts, left line */ +static const uint8_t SL[5][16] = { + { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 }, /* Round 1 */ + { 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 }, /* Round 2 */ + { 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 }, /* Round 3 */ + { 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 }, /* Round 4 */ + { 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 } /* Round 5 */ +}; + +/* Shifts, right line */ +static const uint8_t SR[5][16] = { + { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 }, /* Round 1 */ + { 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 }, /* Round 2 */ + { 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 }, /* Round 3 */ + { 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 }, /* Round 4 */ + { 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 } /* Round 5 */ +}; + +/* Boolean functions */ + +#define F1(x, y, z) ((x) ^ (y) ^ (z)) +#define F2(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define F3(x, y, z) (((x) | ~(y)) ^ (z)) +#define F4(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define F5(x, y, z) ((x) ^ ((y) | ~(z))) + +/* Round constants, left line */ +static const uint32_t KL[5] = { + 0x00000000u, /* Round 1: 0 */ + 0x5A827999u, /* Round 2: floor(2**30 * sqrt(2)) */ + 0x6ED9EBA1u, /* Round 3: floor(2**30 * sqrt(3)) */ + 0x8F1BBCDCu, /* Round 4: floor(2**30 * sqrt(5)) */ + 0xA953FD4Eu /* Round 5: floor(2**30 * sqrt(7)) */ +}; + +/* Round constants, right line */ +static const uint32_t KR[5] = { + 0x50A28BE6u, /* Round 1: floor(2**30 * cubert(2)) */ + 0x5C4DD124u, /* Round 2: floor(2**30 * cubert(3)) */ + 0x6D703EF3u, /* Round 3: floor(2**30 * cubert(5)) */ + 0x7A6D76E9u, /* Round 4: floor(2**30 * cubert(7)) */ + 0x00000000u /* Round 5: 0 */ +}; + +static void ripemd160_init(ripemd160_state *self) +{ + + memcpy(self->h, initial_h, RIPEMD160_DIGEST_SIZE); + memset(&self->buf, 0, sizeof(self->buf)); + self->length = 0; + self->bufpos = 0; + self->magic = RIPEMD160_MAGIC; +} + +/* NB: This is not currently called in the hash object's destructor. */ +static void ripemd160_wipe(ripemd160_state *self) +{ + memset(self, 0, sizeof(ripemd160_state)); + self->magic = 0; +} + +static inline void byteswap32(uint32_t *v) +{ + union { uint32_t w; uint8_t b[4]; } x, y; + + x.w = *v; + y.b[0] = x.b[3]; + y.b[1] = x.b[2]; + y.b[2] = x.b[1]; + y.b[3] = x.b[0]; + *v = y.w; + + /* Wipe temporary variables */ + x.w = y.w = 0; +} + +static inline void byteswap_digest(uint32_t *p) +{ + unsigned int i; + + for (i = 0; i < 4; i++) { + byteswap32(p++); + byteswap32(p++); + byteswap32(p++); + byteswap32(p++); + } +} + +/* The RIPEMD160 compression function. Operates on self->buf */ +static void ripemd160_compress(ripemd160_state *self) +{ + uint8_t w, round; + uint32_t T; + uint32_t AL, BL, CL, DL, EL; /* left line */ + uint32_t AR, BR, CR, DR, ER; /* right line */ + + /* Sanity check */ + assert(self->magic == RIPEMD160_MAGIC); + assert(self->bufpos == 64); + if (self->magic != RIPEMD160_MAGIC || self->bufpos != 64) { + ripemd160_wipe(self); + return; /* error */ + } + + /* Byte-swap the buffer if we're on a big-endian machine */ +#ifdef PCT_BIG_ENDIAN + byteswap_digest(self->buf.w); +#endif + + /* Load the left and right lines with the initial state */ + AL = AR = self->h[0]; + BL = BR = self->h[1]; + CL = CR = self->h[2]; + DL = DR = self->h[3]; + EL = ER = self->h[4]; + + /* Round 1 */ + round = 0; + for (w = 0; w < 16; w++) { /* left line */ + T = ROL(SL[round][w], AL + F1(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL; + AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T; + } + for (w = 0; w < 16; w++) { /* right line */ + T = ROL(SR[round][w], AR + F5(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER; + AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T; + } + + /* Round 2 */ + round++; + for (w = 0; w < 16; w++) { /* left line */ + T = ROL(SL[round][w], AL + F2(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL; + AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T; + } + for (w = 0; w < 16; w++) { /* right line */ + T = ROL(SR[round][w], AR + F4(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER; + AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T; + } + + /* Round 3 */ + round++; + for (w = 0; w < 16; w++) { /* left line */ + T = ROL(SL[round][w], AL + F3(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL; + AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T; + } + for (w = 0; w < 16; w++) { /* right line */ + T = ROL(SR[round][w], AR + F3(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER; + AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T; + } + + /* Round 4 */ + round++; + for (w = 0; w < 16; w++) { /* left line */ + T = ROL(SL[round][w], AL + F4(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL; + AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T; + } + for (w = 0; w < 16; w++) { /* right line */ + T = ROL(SR[round][w], AR + F2(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER; + AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T; + } + + /* Round 5 */ + round++; + for (w = 0; w < 16; w++) { /* left line */ + T = ROL(SL[round][w], AL + F5(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL; + AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T; + } + for (w = 0; w < 16; w++) { /* right line */ + T = ROL(SR[round][w], AR + F1(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER; + AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T; + } + + /* Final mixing stage */ + T = self->h[1] + CL + DR; + self->h[1] = self->h[2] + DL + ER; + self->h[2] = self->h[3] + EL + AR; + self->h[3] = self->h[4] + AL + BR; + self->h[4] = self->h[0] + BL + CR; + self->h[0] = T; + + /* Clear the buffer and wipe the temporary variables */ + T = AL = BL = CL = DL = EL = AR = BR = CR = DR = ER = 0; + memset(&self->buf, 0, sizeof(self->buf)); + self->bufpos = 0; +} + +static void ripemd160_update(ripemd160_state *self, const unsigned char *p, int length) +{ + unsigned int bytes_needed; + + /* Some assertions */ + assert(self->magic == RIPEMD160_MAGIC); + assert(p != NULL && length >= 0); + + /* NDEBUG is probably defined, so check for invalid inputs explicitly. */ + if (self->magic != RIPEMD160_MAGIC || p == NULL || length < 0) { + /* error */ + ripemd160_wipe(self); + return; + } + + /* We never leave a full buffer */ + assert(self->bufpos < 64); + + while (length > 0) { + /* Figure out how many bytes we need to fill the internal buffer. */ + bytes_needed = 64 - self->bufpos; + + if ((unsigned int) length >= bytes_needed) { + /* We have enough bytes, so copy them into the internal buffer and run + * the compression function. */ + memcpy(&self->buf.b[self->bufpos], p, bytes_needed); + self->bufpos += bytes_needed; + self->length += bytes_needed << 3; /* length is in bits */ + p += bytes_needed; + ripemd160_compress(self); + length -= bytes_needed; + continue; + } + + /* We do not have enough bytes to fill the internal buffer. + * Copy what's there and return. */ + memcpy(&self->buf.b[self->bufpos], p, length); + self->bufpos += length; + self->length += length << 3; /* length is in bits */ + return; + } +} + +static void ripemd160_copy(const ripemd160_state *source, ripemd160_state *dest) +{ + memcpy(dest, source, sizeof(ripemd160_state)); +} + +static int ripemd160_digest(const ripemd160_state *self, unsigned char *out) +{ + ripemd160_state tmp; + + assert(self->magic == RIPEMD160_MAGIC); + assert(out != NULL); + if (self->magic != RIPEMD160_MAGIC || out == NULL) { + return 0; + } + + ripemd160_copy(self, &tmp); + + /* Append the padding */ + tmp.buf.b[tmp.bufpos++] = 0x80; + + if (tmp.bufpos > 56) { + tmp.bufpos = 64; + ripemd160_compress(&tmp); + } + + /* Append the length */ + tmp.buf.w[14] = (uint32_t) (tmp.length & 0xFFFFffffu); + tmp.buf.w[15] = (uint32_t) ((tmp.length >> 32) & 0xFFFFffffu); +#ifdef PCT_BIG_ENDIAN + byteswap32(&tmp.buf.w[14]); + byteswap32(&tmp.buf.w[15]); +#endif + tmp.bufpos = 64; + ripemd160_compress(&tmp); + + /* Copy the final state into the output buffer */ +#ifdef PCT_BIG_ENDIAN + byteswap_digest(tmp.h); +#endif + memcpy(out, &tmp.h, RIPEMD160_DIGEST_SIZE); + + if (tmp.magic == RIPEMD160_MAGIC) { + /* success */ + ripemd160_wipe(&tmp); + return 1; + } else { + /* error */ + ripemd160_wipe(&tmp); + memset(out, 0, RIPEMD160_DIGEST_SIZE); + return 0; + } +} + +/* Template definitions */ +#define MODULE_NAME RIPEMD160 +#define DIGEST_SIZE RIPEMD160_DIGEST_SIZE +#define hash_state ripemd160_state +#define hash_init ripemd160_init +#define hash_update ripemd160_update +#define hash_copy ripemd160_copy +static PyObject *hash_digest(hash_state *self) +{ + char buf[DIGEST_SIZE]; + PyObject *retval; + + if (ripemd160_digest(self, (unsigned char *) buf)) { + retval = PyBytes_FromStringAndSize(buf, DIGEST_SIZE); + } else { + PyErr_SetString(PyExc_RuntimeError, "Internal error occurred while executing ripemd160_digest"); + retval = NULL; + } + + memset(buf, 0, DIGEST_SIZE); + return retval; +} + +#include "hash_template.c" + +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/SHA224.c b/src/SHA224.c new file mode 100644 index 0000000..2a31c2d --- /dev/null +++ b/src/SHA224.c @@ -0,0 +1,98 @@ +/* + * An implementation of the SHA-224 hash function. + * + * The Federal Information Processing Standards (FIPS) Specification + * can be found here (FIPS 180-3): + * http://csrc.nist.gov/publications/PubsFIPS.html + * + * Written in 2010 by Lorenz Quack <don@amberfisharts.com> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" + +#define MODULE_NAME SHA224 +#define DIGEST_SIZE (224/8) +#define BLOCK_SIZE (512/8) +#define WORD_SIZE 4 +#define SCHEDULE_SIZE 64 + +static char MODULE__doc__[] = + "SHA-224 cryptographic hash algorithm.\n" + "\n" + "SHA-224 belongs to the SHA-2_ family of cryptographic hashes.\n" + "It produces the 224 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import SHA224\n" + " >>>\n" + " >>> h = SHA224.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "*SHA* stands for Secure Hash Algorithm.\n" + "\n" + ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +#include "hash_SHA2.h" + +/* Initial Values H */ +static const sha2_word_t H[8] = { + 0xc1059ed8, + 0x367cd507, + 0x3070dd17, + 0xf70e5939, + 0xffc00b31, + 0x68581511, + 0x64f98fa7, + 0xbefa4fa4 +}; + +/* the Constants K */ +static const sha2_word_t K[SCHEDULE_SIZE] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, + 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, + 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, + 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, + 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, + 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, + 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, + 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, + 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* SHA-224 specific functions */ +#define Sigma0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define Sigma1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define Gamma0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) +#define Gamma1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) + +#include "hash_SHA2_template.c" + diff --git a/src/SHA256.c b/src/SHA256.c new file mode 100644 index 0000000..effae6e --- /dev/null +++ b/src/SHA256.c @@ -0,0 +1,98 @@ +/* + * An implementation of the SHA-256 hash function. + * + * The Federal Information Processing Standards (FIPS) Specification + * can be found here (FIPS 180-3): + * http://csrc.nist.gov/publications/PubsFIPS.html + * + * Written in 2010 by Lorenz Quack <don@amberfisharts.com> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" + +#define MODULE_NAME SHA256 +#define DIGEST_SIZE (256/8) +#define BLOCK_SIZE (512/8) +#define WORD_SIZE 4 +#define SCHEDULE_SIZE 64 + +static char MODULE__doc__[] = + "SHA-256 cryptographic hash algorithm.\n" + "\n" + "SHA-256 belongs to the SHA-2_ family of cryptographic hashes.\n" + "It produces the 256 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import SHA256\n" + " >>>\n" + " >>> h = SHA256.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "*SHA* stands for Secure Hash Algorithm.\n" + "\n" + ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +#include "hash_SHA2.h" + +/* Initial Values H */ +static const sha2_word_t H[8] = { + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 +}; + +/* the Constants K */ +static const sha2_word_t K[SCHEDULE_SIZE] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, + 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, + 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, + 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, + 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, + 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, + 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, + 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, + 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* SHA-256 specific functions */ +#define Sigma0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define Sigma1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define Gamma0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) +#define Gamma1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) + +#include "hash_SHA2_template.c" + diff --git a/src/SHA384.c b/src/SHA384.c new file mode 100644 index 0000000..a7c527b --- /dev/null +++ b/src/SHA384.c @@ -0,0 +1,104 @@ +/* + * An implementation of the SHA-384 hash function. + * + * The Federal Information Processing Standards (FIPS) Specification + * can be found here (FIPS 180-3): + * http://csrc.nist.gov/publications/PubsFIPS.html + * + * Written in 2010 by Lorenz Quack <don@amberfisharts.com> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" + +#define MODULE_NAME SHA384 +#define DIGEST_SIZE (384/8) +#define BLOCK_SIZE (1024/8) +#define WORD_SIZE 8 +#define SCHEDULE_SIZE 80 + +static char MODULE__doc__[] = + "SHA-384 cryptographic hash algorithm.\n" + "\n" + "SHA-384 belongs to the SHA-2_ family of cryptographic hashes.\n" + "It produces the 384 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import SHA384\n" + " >>>\n" + " >>> h = SHA384.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "*SHA* stands for Secure Hash Algorithm.\n" + "\n" + ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +#include "hash_SHA2.h" + +/* Initial Values H */ +static const sha2_word_t H[8] = { + 0xcbbb9d5dc1059ed8, + 0x629a292a367cd507, + 0x9159015a3070dd17, + 0x152fecd8f70e5939, + 0x67332667ffc00b31, + 0x8eb44a8768581511, + 0xdb0c2e0d64f98fa7, + 0x47b5481dbefa4fa4 +}; + +/* the Constants K */ +static const sha2_word_t K[SCHEDULE_SIZE] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +}; + +/* SHA-384 specific functions */ +#define Sigma0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define Sigma1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define Gamma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define Gamma1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6)) + +#include "hash_SHA2_template.c" diff --git a/src/SHA512.c b/src/SHA512.c new file mode 100644 index 0000000..f2afefb --- /dev/null +++ b/src/SHA512.c @@ -0,0 +1,104 @@ +/* + * An implementation of the SHA-512 hash function. + * + * The Federal Information Processing Standards (FIPS) Specification + * can be found here (FIPS 180-3): + * http://csrc.nist.gov/publications/PubsFIPS.html + * + * Written in 2010 by Lorenz Quack <don@amberfisharts.com> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" + +#define MODULE_NAME SHA512 +#define DIGEST_SIZE (512/8) +#define BLOCK_SIZE (1024/8) +#define WORD_SIZE 8 +#define SCHEDULE_SIZE 80 + +static char MODULE__doc__[] = + "SHA-512 cryptographic hash algorithm.\n" + "\n" + "SHA-512 belongs to the SHA-2_ family of cryptographic hashes.\n" + "It produces the 512 bit digest of a message.\n" + "\n" + " >>> from Crypto.Hash import SHA512\n" + " >>>\n" + " >>> h = SHA512.new()\n" + " >>> h.update(b'Hello')\n" + " >>> print h.hexdigest()\n" + "\n" + "*SHA* stands for Secure Hash Algorithm.\n" + "\n" + ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf\n" + "\n" + ":Variables:\n" + " block_size\n" + " The internal block size of the hash algorithm in bytes.\n" + " digest_size\n" + " The size of the resulting hash in bytes.\n"; + +#include "hash_SHA2.h" + +/* Initial Values H */ +static const sha2_word_t H[8] = { + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179 +}; + +/* the Constants K */ +static const sha2_word_t K[SCHEDULE_SIZE] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +}; + +/* SHA-512 specific functions */ +#define Sigma0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define Sigma1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define Gamma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define Gamma1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6)) + +#include "hash_SHA2_template.c" diff --git a/src/XOR.c b/src/XOR.c new file mode 100644 index 0000000..d994749 --- /dev/null +++ b/src/XOR.c @@ -0,0 +1,76 @@ +/* + * xor.c : Source for the trivial cipher which XORs the message with the key. + * The key can be up to 32 bytes long. + * + * Part of the Python Cryptography Toolkit + * + * Contributed by Barry Warsaw and others. + * + * ======================================================================= + * The contents of this file are dedicated to the public domain. To the + * extent that dedication to the public domain is not available, everyone + * is granted a worldwide, perpetual, royalty-free, non-exclusive license + * to exercise all rights associated with the contents of this file for + * any purpose whatsoever. No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ======================================================================= + */ + +#include "pycrypto_common.h" + +#define MODULE_NAME _XOR +#define BLOCK_SIZE 1 +#define KEY_SIZE 0 + +#define MAX_KEY_SIZE 32 + +typedef struct +{ + unsigned char key[MAX_KEY_SIZE]; + int keylen, last_pos; +} stream_state; + +static void +stream_init(stream_state *self, unsigned char *key, int len) +{ + int i; + + if (len > MAX_KEY_SIZE) + { + PyErr_Format(PyExc_ValueError, + "XOR key must be no longer than %d bytes", + MAX_KEY_SIZE); + return; + } + self->keylen = len; + self->last_pos = 0; + + for(i=0; i<len; i++) + { + self->key[i] = key[i]; + } +} + +/* Encryption and decryption are symmetric */ +#define stream_decrypt stream_encrypt + +static void stream_encrypt(stream_state *self, unsigned char *block, + int len) +{ + int i, j = self->last_pos; + for(i=0; i<len; i++, j=(j+1) % self->keylen) + { + block[i] ^= self->key[j]; + } + self->last_pos = j; +} + +#include "stream_template.c" diff --git a/src/_counter.c b/src/_counter.c new file mode 100644 index 0000000..59ceb54 --- /dev/null +++ b/src/_counter.c @@ -0,0 +1,545 @@ +/* + * _counter.c: Fast counter for use with CTR-mode ciphers + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +#include "pycrypto_common.h" +#include <assert.h> +#include <stddef.h> +#include <string.h> +#include "_counter.h" + +/* NB: This can be called multiple times for a given object, via the __init__ method. Be careful. */ +static int +CounterObject_init(PCT_CounterObject *self, PyObject *args, PyObject *kwargs) +{ + PyBytesObject *prefix=NULL, *suffix=NULL, *initval=NULL; + int allow_wraparound = 0; + Py_ssize_t size; + + static char *kwlist[] = {"prefix", "suffix", "initval", "allow_wraparound", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "SSS|i", kwlist, &prefix, &suffix, &initval, &allow_wraparound)) + return -1; + + /* Check string size and set nbytes */ + size = PyBytes_GET_SIZE(initval); + if (size < 1) { + PyErr_SetString(PyExc_ValueError, "initval length too small (must be >= 1 byte)"); + return -1; + } else if (size > 0xffff) { + PyErr_SetString(PyExc_ValueError, "initval length too large (must be <= 65535 bytes)"); + return -1; + } + self->nbytes = (uint16_t) size; + + /* Check prefix length */ + size = PyBytes_GET_SIZE(prefix); + assert(size >= 0); + if (size > 0xffff) { + PyErr_SetString(PyExc_ValueError, "prefix length too large (must be <= 65535 bytes)"); + return -1; + } + + /* Check suffix length */ + size = PyBytes_GET_SIZE(suffix); + assert(size >= 0); + if (size > 0xffff) { + PyErr_SetString(PyExc_ValueError, "suffix length too large (must be <= 65535 bytes)"); + return -1; + } + + /* Set prefix, being careful to properly discard any old reference */ + Py_CLEAR(self->prefix); + Py_INCREF(prefix); + self->prefix = prefix; + + /* Set prefix, being careful to properly discard any old reference */ + Py_CLEAR(self->suffix); + Py_INCREF(suffix); + self->suffix = suffix; + + /* Free old buffer (if any) */ + if (self->val) { + PyMem_Free(self->val); + self->val = self->p = NULL; + self->buf_size = 0; + } + + /* Allocate new buffer */ + /* buf_size won't overflow because the length of each string will always be <= 0xffff */ + self->buf_size = PyBytes_GET_SIZE(prefix) + PyBytes_GET_SIZE(suffix) + self->nbytes; + self->val = self->p = PyMem_Malloc(self->buf_size); + if (self->val == NULL) { + self->buf_size = 0; + return -1; + } + self->p = self->val + PyBytes_GET_SIZE(prefix); + + /* Sanity-check pointers */ + assert(self->val <= self->p); + assert(self->buf_size >= 0); + assert(self->p + self->nbytes <= self->val + self->buf_size); + assert(self->val + PyBytes_GET_SIZE(self->prefix) == self->p); + assert(PyBytes_GET_SIZE(self->prefix) + self->nbytes + PyBytes_GET_SIZE(self->suffix) == self->buf_size); + + /* Copy the prefix, suffix, and initial value into the buffer. */ + memcpy(self->val, PyBytes_AS_STRING(prefix), PyBytes_GET_SIZE(prefix)); + memcpy(self->p, PyBytes_AS_STRING(initval), self->nbytes); + memcpy(self->p + self->nbytes, PyBytes_AS_STRING(suffix), PyBytes_GET_SIZE(suffix)); + + /* Set allow_wraparound */ + self->allow_wraparound = allow_wraparound; + + /* Clear the carry flag */ + self->carry = 0; + + return 0; +} + +static void +CounterObject_dealloc(PCT_CounterObject *self) +{ + /* Free the buffer */ + if (self->val) { + memset(self->val, 0, self->buf_size); /* wipe the buffer before freeing it */ + PyMem_Free(self->val); + self->val = self->p = NULL; + self->buf_size = 0; + } + + /* Deallocate the prefix and suffix, if they are present. */ + Py_CLEAR(self->prefix); + Py_CLEAR(self->suffix); + + /* Free this object */ + PyObject_Del(self); +} + +static inline PyObject * +_CounterObject_next_value(PCT_CounterObject *self, int little_endian) +{ + unsigned int i; + int increment; + uint8_t *p; + PyObject *eight = NULL; + PyObject *ch = NULL; + PyObject *y = NULL; + PyObject *x = NULL; + + if (self->carry && !self->allow_wraparound) { + PyErr_SetString(PyExc_OverflowError, + "counter wrapped without allow_wraparound"); + goto err_out; + } + + eight = PyInt_FromLong(8); + if (!eight) + goto err_out; + + /* Make a new Python long integer */ + x = PyLong_FromUnsignedLong(0); + if (!x) + goto err_out; + + if (little_endian) { + /* little endian */ + p = self->p + self->nbytes - 1; + increment = -1; + } else { + /* big endian */ + p = self->p; + increment = 1; + } + for (i = 0; i < self->nbytes; i++, p += increment) { + /* Sanity check pointer */ + assert(self->p <= p); + assert(p < self->p + self->nbytes); + + /* ch = ord(p) */ + Py_CLEAR(ch); /* delete old ch */ + ch = PyInt_FromLong((long) *p); + if (!ch) + goto err_out; + + /* y = x << 8 */ + Py_CLEAR(y); /* delete old y */ + y = PyNumber_Lshift(x, eight); + if (!y) + goto err_out; + + /* x = y | ch */ + Py_CLEAR(x); /* delete old x */ + x = PyNumber_Or(y, ch); + } + + Py_CLEAR(eight); + Py_CLEAR(ch); + Py_CLEAR(y); + return x; + +err_out: + Py_CLEAR(eight); + Py_CLEAR(ch); + Py_CLEAR(y); + Py_CLEAR(x); + return NULL; +} + +static PyObject * +CounterLEObject_next_value(PCT_CounterObject *self, PyObject *args) +{ + return _CounterObject_next_value(self, 1); +} + +static PyObject * +CounterBEObject_next_value(PCT_CounterObject *self, PyObject *args) +{ + return _CounterObject_next_value(self, 0); +} + +static void +CounterLEObject_increment(PCT_CounterObject *self) +{ + unsigned int i, tmp, carry; + uint8_t *p; + + assert(sizeof(i) >= sizeof(self->nbytes)); + + carry = 1; + p = self->p; + for (i = 0; i < self->nbytes; i++, p++) { + /* Sanity check pointer */ + assert(self->p <= p); + assert(p < self->p + self->nbytes); + + tmp = *p + carry; + carry = tmp >> 8; /* This will only ever be 0 or 1 */ + *p = tmp & 0xff; + } + self->carry = carry; +} + +static void +CounterBEObject_increment(PCT_CounterObject *self) +{ + unsigned int i, tmp, carry; + uint8_t *p; + + assert(sizeof(i) >= sizeof(self->nbytes)); + + carry = 1; + p = self->p + self->nbytes-1; + for (i = 0; i < self->nbytes; i++, p--) { + /* Sanity check pointer */ + assert(self->p <= p); + assert(p < self->p + self->nbytes); + + tmp = *p + carry; + carry = tmp >> 8; /* This will only ever be 0 or 1 */ + *p = tmp & 0xff; + } + self->carry = carry; +} + +static PyObject * +CounterObject_call(PCT_CounterObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *retval; + + if (self->carry && !self->allow_wraparound) { + PyErr_SetString(PyExc_OverflowError, + "counter wrapped without allow_wraparound"); + return NULL; + } + + retval = (PyObject *)PyBytes_FromStringAndSize((const char *)self->val, self->buf_size); + + self->inc_func(self); + + return retval; +} + +static PyMethodDef CounterLEObject_methods[] = { + {"next_value", (PyCFunction)CounterLEObject_next_value, METH_VARARGS, + "Get the numerical value of next value of the counter."}, + + {NULL} /* sentinel */ +}; + +static PyMethodDef CounterBEObject_methods[] = { + {"next_value", (PyCFunction)CounterBEObject_next_value, METH_VARARGS, + "Get the numerical value of next value of the counter."}, + + {NULL} /* sentinel */ +}; + +/* Python 2.1 doesn't allow us to assign methods or attributes to an object, + * so we hack it here. */ + +static PyObject * +CounterLEObject_getattro(PyObject *s, PyObject *attr) +{ + PCT_CounterObject *self = (PCT_CounterObject *)s; + if (!PyString_Check(attr)) + goto generic; + + if (PyString_CompareWithASCIIString(attr, "carry") == 0) { + return PyInt_FromLong((long)self->carry); + } + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr(s, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(CounterLEObject_methods, (PyObject *)self, PyString_AsString(attr)); +#endif +} + +static PyObject * +CounterBEObject_getattro(PyObject *s, PyObject *attr) +{ + PCT_CounterObject *self = (PCT_CounterObject *)s; + if (!PyString_Check(attr)) + goto generic; + + if (PyString_CompareWithASCIIString(attr, "carry") == 0) { + return PyInt_FromLong((long)self->carry); + } + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr(s, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(CounterBEObject_methods, (PyObject *)self, PyString_AsString(attr)); +#endif +} + +static PyTypeObject +PCT_CounterLEType = { + PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + "_counter.CounterLE", /* tp_name */ + sizeof(PCT_CounterObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)CounterObject_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)CounterObject_call, /* tp_call */ + 0, /* tp_str */ + CounterLEObject_getattro, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "Counter (little endian)", /* tp_doc */ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + CounterLEObject_methods, /*tp_methods*/ +#endif +}; + +static PyTypeObject +PCT_CounterBEType = { + PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + "_counter.CounterBE", /* tp_name */ + sizeof(PCT_CounterObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)CounterObject_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)CounterObject_call, /* tp_call */ + 0, /* tp_str */ + CounterBEObject_getattro, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "Counter (big endian)", /* tp_doc */ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + CounterBEObject_methods, /*tp_methods*/ +#endif +}; + +/* + * Python 2.1 doesn't seem to allow a C equivalent of the __init__ method, so + * we use the module-level functions newLE and newBE here. + */ +static PyObject * +CounterLE_new(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PCT_CounterObject *obj = NULL; + + /* Create the new object */ + obj = PyObject_New(PCT_CounterObject, &PCT_CounterLEType); + if (obj == NULL) { + return NULL; + } + + /* Zero the custom portion of the structure */ + memset(&obj->prefix, 0, sizeof(PCT_CounterObject) - offsetof(PCT_CounterObject, prefix)); + + /* Call the object's initializer. Delete the object if this fails. */ + if (CounterObject_init(obj, args, kwargs) != 0) { + return NULL; + } + + /* Set the inc_func pointer */ + obj->inc_func = (void (*)(void *))CounterLEObject_increment; + + /* Return the object */ + return (PyObject *)obj; +} + +static PyObject * +CounterBE_new(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PCT_CounterObject *obj = NULL; + + /* Create the new object */ + obj = PyObject_New(PCT_CounterObject, &PCT_CounterBEType); + if (obj == NULL) { + return NULL; + } + + /* Zero the custom portion of the structure */ + memset(&obj->prefix, 0, sizeof(PCT_CounterObject) - offsetof(PCT_CounterObject, prefix)); + + /* Call the object's initializer. Delete the object if this fails. */ + if (CounterObject_init(obj, args, kwargs) != 0) { + return NULL; + } + + /* Set the inc_func pointer */ + obj->inc_func = (void (*)(void *))CounterBEObject_increment; + + /* Return the object */ + return (PyObject *)obj; +} + +/* + * Module-level method table and module initialization function + */ + +static PyMethodDef module_methods[] = { + {"_newLE", (PyCFunction) CounterLE_new, METH_VARARGS|METH_KEYWORDS, NULL}, + {"_newBE", (PyCFunction) CounterBE_new, METH_VARARGS|METH_KEYWORDS, NULL}, + {NULL, NULL, 0, NULL} /* end-of-list sentinel value */ +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_counter", + NULL, + -1, + module_methods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +PyMODINIT_FUNC +#ifdef IS_PY3K +PyInit__counter(void) +#else +init_counter(void) +#endif +{ + PyObject *m = NULL; + + if (PyType_Ready(&PCT_CounterLEType) < 0) + goto errout; + if (PyType_Ready(&PCT_CounterBEType) < 0) + goto errout; + + /* Initialize the module */ +#ifdef IS_PY3K + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("_counter", module_methods); +#endif + if (m == NULL) + goto errout; + + /* Add the counter types to the module so that epydoc can see them, and so + * that we can access them in the block cipher modules. */ + PyObject_SetAttrString(m, "CounterBE", (PyObject *)&PCT_CounterBEType); + PyObject_SetAttrString(m, "CounterLE", (PyObject *)&PCT_CounterLEType); + + /* Allow block_template.c to do an ABI check */ + PyModule_AddIntConstant(m, "_PCT_CTR_ABI_VERSION", PCT_CTR_ABI_VERSION); + + +out: + /* Final error check */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + goto out; +} + +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/_counter.h b/src/_counter.h new file mode 100644 index 0000000..df2091f --- /dev/null +++ b/src/_counter.h @@ -0,0 +1,44 @@ +/* + * _counter.h: Fast counter for use with CTR-mode ciphers + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ +#ifndef PCT__COUNTER_H +#define PCT__COUNTER_H + +#include "pycrypto_common.h" + +#define PCT_CTR_ABI_VERSION 1 /* Bump this whenever the structure below changes */ + +typedef struct { + PyObject_HEAD + PyBytesObject *prefix; /* Prefix (useful for a nonce) */ + PyBytesObject *suffix; /* Suffix (useful for a nonce) */ + uint8_t *val; /* Buffer for our output string */ + Py_ssize_t buf_size;/* Size of the buffer */ + uint8_t *p; /* Pointer to the part of the buffer that we're allowed to update */ + uint16_t nbytes; /* The number of bytes that from .p that are part of the counter */ + void (*inc_func)(void *); /* Pointer to the counter increment function */ + int carry; /* This gets set by Counter*Object_increment when the counter wraps around */ + int allow_wraparound; /* When this is false, we raise OverflowError on next_value() or __call__() when the counter wraps around */ +} PCT_CounterObject; + +#endif /* PCT__COUNTER_H */ diff --git a/src/_fastmath.c b/src/_fastmath.c new file mode 100644 index 0000000..7d486c2 --- /dev/null +++ b/src/_fastmath.c @@ -0,0 +1,2649 @@ +/* + * _fastmath.c: Accelerator module that uses GMP for faster numerics. + * + * Part of the Python Cryptography Toolkit + * + * Written by Paul Swartz, Andrew Kuchling, Joris Bontje, and others + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + * $Id$ + */ + +#include "pycrypto_common.h" +#include <stdio.h> +#include <string.h> +#include <longintrepr.h> /* for conversions */ +#if HAVE_LIBGMP +# include <gmp.h> +#elif HAVE_LIBMPIR +# include <mpir.h> +#else +# error "Neither HAVE_LIBGMP nor HAVE_LIBMPIR are set. Can't build." +#endif + +/* If available, use mpz_powm_sec to avoid timing attacks. + * See the talk by Geremy Condra - + * "PyCon 2011: Through the Side Channel: Timing and Implementation Attacks in Python" + * http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-through-the-side-channel-timing-and-implementation-attacks-in-python-4897955 + */ +#if HAVE_DECL_MPZ_POWM_SEC +#define MPZ_POWM mpz_powm_sec +#else +#define MPZ_POWM mpz_powm +#endif + +#define SIEVE_BASE_SIZE (sizeof (sieve_base) / sizeof (sieve_base[0])) + +#ifdef IS_PY3K +#define OB_SIZE(p) ((p)->ob_base.ob_size) +#else +#define OB_SIZE(p) ((p)->ob_size) +#endif + +static unsigned int sieve_base[10000]; +static int rabinMillerTest (mpz_t n, int rounds, PyObject *randfunc); + +static void +longObjToMPZ (mpz_t m, PyLongObject * p) +{ + int size, i; + long negative; + mpz_t temp, temp2; + mpz_init (temp); + mpz_init (temp2); + if (OB_SIZE(p) > 0) { + size = OB_SIZE(p); + negative = 1; + } else { + size = -OB_SIZE(p); + negative = -1; + } + mpz_set_ui (m, 0); + for (i = 0; i < size; i++) + { + mpz_set_ui (temp, p->ob_digit[i]); + mpz_mul_2exp (temp2, temp, PyLong_SHIFT * i); + mpz_add (m, m, temp2); + } + mpz_mul_si(m, m, negative); + mpz_clear (temp); + mpz_clear (temp2); +} + +static PyObject * +mpzToLongObj (mpz_t m) +{ + /* borrowed from gmpy */ + int size = (mpz_sizeinbase (m, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT; + int sgn; + int i; + mpz_t temp; + PyLongObject *l = _PyLong_New (size); + if (!l) + return NULL; + sgn = mpz_sgn(m); + mpz_init(temp); + mpz_mul_si(temp, m, sgn); + for (i = 0; i < size; i++) + { + l->ob_digit[i] = (digit) (mpz_get_ui (temp) & PyLong_MASK); + mpz_fdiv_q_2exp (temp, temp, PyLong_SHIFT); + } + i = size; + while ((i > 0) && (l->ob_digit[i - 1] == 0)) + i--; + OB_SIZE(l) = i * sgn; + mpz_clear (temp); + return (PyObject *) l; +} + +typedef struct +{ + PyObject_HEAD mpz_t y; + mpz_t g; + mpz_t p; + mpz_t q; + mpz_t x; +} +dsaKey; + +typedef struct +{ + PyObject_HEAD mpz_t n; + mpz_t e; + mpz_t d; + mpz_t p; + mpz_t q; + mpz_t u; +} +rsaKey; + +static PyObject *rsaKey_new (PyObject *, PyObject *); +static PyObject *dsaKey_new (PyObject *, PyObject *); + +static void dsaKey_dealloc (dsaKey *); +static PyObject *dsaKey_getattro (dsaKey *, PyObject *); +static PyObject *dsaKey__sign (dsaKey *, PyObject *); +static PyObject *dsaKey__verify (dsaKey *, PyObject *); +static PyObject *dsaKey_size (dsaKey *, PyObject *); +static PyObject *dsaKey_has_private (dsaKey *, PyObject *); + +static void rsaKey_dealloc (rsaKey *); +static PyObject *rsaKey_getattro (rsaKey *, PyObject *); +static PyObject *rsaKey__encrypt (rsaKey *, PyObject *); +static PyObject *rsaKey__decrypt (rsaKey *, PyObject *); +static PyObject *rsaKey__verify (rsaKey *, PyObject *); +static PyObject *rsaKey__blind (rsaKey *, PyObject *); +static PyObject *rsaKey__unblind (rsaKey *, PyObject *); +static PyObject *rsaKey_size (rsaKey *, PyObject *); +static PyObject *rsaKey_has_private (rsaKey *, PyObject *); + +static int +dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s) +{ + mpz_t temp; + if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0) + { + return 1; + } + mpz_init (temp); + MPZ_POWM (r, key->g, k, key->p); + mpz_mod (r, r, key->q); + mpz_invert (s, k, key->q); + mpz_mul (temp, key->x, r); + mpz_add (temp, m, temp); + mpz_mul (s, s, temp); + mpz_mod (s, s, key->q); + mpz_clear (temp); + return 0; +} + +static int +dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s) +{ + int result; + mpz_t u1, u2, v1, v2, w; + if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 || + mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0) + return 0; + mpz_init (u1); + mpz_init (u2); + mpz_init (v1); + mpz_init (v2); + mpz_init (w); + mpz_invert (w, s, key->q); + mpz_mul (u1, m, w); + mpz_mod (u1, u1, key->q); + mpz_mul (u2, r, w); + mpz_mod (u2, u2, key->q); + MPZ_POWM (v1, key->g, u1, key->p); + MPZ_POWM (v2, key->y, u2, key->p); + mpz_mul (w, v1, v2); + mpz_mod (w, w, key->p); + mpz_mod (w, w, key->q); + if (mpz_cmp (r, w) == 0) + result = 1; + else + result = 0; + mpz_clear (u1); + mpz_clear (u2); + mpz_clear (v1); + mpz_clear (v2); + mpz_clear (w); + return result; +} + + +static int +rsaEncrypt (rsaKey * key, mpz_t v) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + MPZ_POWM (v, v, key->e, key->n); + return 0; +} + +static int +rsaDecrypt (rsaKey * key, mpz_t v) +{ + mpz_t m1, m2, h; + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_size (key->d) == 0) + { + return 2; + } + + if ((mpz_size (key->p) != 0) && (mpz_size (key->q) != 0) && + (mpz_size (key->u) != 0)) + { + /* fast path */ + mpz_init(m1); + mpz_init(m2); + mpz_init(h); + + /* m1 = c ^ (d mod (p-1)) mod p */ + mpz_sub_ui(h, key->p, 1); + mpz_fdiv_r(h, key->d, h); + MPZ_POWM(m1, v, h, key->p); + /* m2 = c ^ (d mod (q-1)) mod q */ + mpz_sub_ui(h, key->q, 1); + mpz_fdiv_r(h, key->d, h); + MPZ_POWM(m2, v, h, key->q); + /* h = u * ( m2 - m1 + q) mod q */ + mpz_sub(h, m2, m1); + if (mpz_sgn(h)==-1) + mpz_add(h, h, key->q); + mpz_mul(h, key->u, h); + mpz_mod(h, h, key->q); + /* m = m1 + h * p */ + mpz_mul(h, h, key->p); + mpz_add(v, m1, h); + /* ready */ + + mpz_clear(m1); + mpz_clear(m2); + mpz_clear(h); + return 0; + } + + /* slow */ + MPZ_POWM (v, v, key->d, key->n); + return 0; +} + +static int +rsaBlind (rsaKey * key, mpz_t v, mpz_t b) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_cmp (b, key->n) >= 0) + { + return 2; + } + MPZ_POWM (b, b, key->e, key->n); + mpz_mul (v, v, b); + mpz_mod (v, v, key->n); + return 0; +} + +static int +rsaUnBlind (rsaKey * key, mpz_t v, mpz_t b) +{ + if (mpz_cmp (v, key->n) >= 0) + { + return 1; + } + if (mpz_cmp (b, key->n) >= 0) + { + return 2; + } + if (!mpz_invert (b, b, key->n)) + { + return 3; + } + mpz_mul (v, v, b); + mpz_mod (v, v, key->n); + return 0; +} + +static PyMethodDef dsaKey__methods__[] = { + {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS, + "Sign the given long."}, + {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS, + "Verify that the signature is valid."}, + {"size", (PyCFunction) dsaKey_size, METH_VARARGS, + "Return the number of bits that this key can handle."}, + {"has_private", (PyCFunction) dsaKey_has_private, METH_VARARGS, + "Return 1 or 0 if this key does/doesn't have a private key."}, + {NULL, NULL, 0, NULL} +}; + +static PyMethodDef rsaKey__methods__[] = { + {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS, + "Encrypt the given long."}, + {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS, + "Decrypt the given long."}, + {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS, + "Sign the given long."}, + {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS, + "Verify that the signature is valid."}, + {"_blind", (PyCFunction) rsaKey__blind, METH_VARARGS, + "Blind the given long."}, + {"_unblind", (PyCFunction) rsaKey__unblind, METH_VARARGS, + "Unblind the given long."}, + {"size", (PyCFunction) rsaKey_size, METH_VARARGS, + "Return the number of bits that this key can handle."}, + {"has_private", (PyCFunction) rsaKey_has_private, METH_VARARGS, + "Return 1 or 0 if this key does/doesn't have a private key."}, + {NULL, NULL, 0, NULL} +}; + +static PyObject *fastmathError; /* raised on errors */ + +static PyTypeObject dsaKeyType = { + PyVarObject_HEAD_INIT (NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + "dsaKey", + sizeof (dsaKey), + 0, + (destructor) dsaKey_dealloc, /* dealloc */ + 0, /* print */ + 0, /* getattr */ + 0, /* setattr */ + 0, /* compare */ + 0, /* repr */ + 0, /* as_number */ + 0, /* as_sequence */ + 0, /* as_mapping */ + 0, /* hash */ + 0, /* call */ + 0, /*tp_str*/ + (getattrofunc) dsaKey_getattro, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + dsaKey__methods__, /*tp_methods*/ +#endif +}; + +static PyTypeObject rsaKeyType = { + PyVarObject_HEAD_INIT (NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + "rsaKey", /*tp_name*/ + sizeof (rsaKey), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) rsaKey_dealloc, /* dealloc */ + 0, /* print */ + 0, /* getattr */ + 0, /* setattr */ + 0, /* compare */ + 0, /* repr */ + 0, /* as_number */ + 0, /* as_sequence */ + 0, /* as_mapping */ + 0, /* hash */ + 0, /* call */ + 0, /*tp_str*/ + (getattrofunc) rsaKey_getattro, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + rsaKey__methods__, /*tp_methods*/ +#endif +}; + +static PyObject * +dsaKey_new (PyObject * self, PyObject * args) +{ + PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL; + dsaKey *key; + if (!PyArg_ParseTuple(args, "O!O!O!O!|O!", &PyLong_Type, &y, + &PyLong_Type, &g, &PyLong_Type, &p, + &PyLong_Type, &q, &PyLong_Type, &x)) + return NULL; + + key = PyObject_New (dsaKey, &dsaKeyType); + if (key == NULL) + return NULL; + mpz_init (key->y); + mpz_init (key->g); + mpz_init (key->p); + mpz_init (key->q); + mpz_init (key->x); + longObjToMPZ (key->y, y); + longObjToMPZ (key->g, g); + longObjToMPZ (key->p, p); + longObjToMPZ (key->q, q); + if (x) + { + longObjToMPZ (key->x, x); + } + return (PyObject *) key; +} + +static void +dsaKey_dealloc (dsaKey * key) +{ + mpz_clear (key->y); + mpz_clear (key->g); + mpz_clear (key->p); + mpz_clear (key->q); + mpz_clear (key->x); + PyObject_Del (key); +} + +static PyObject * +dsaKey_getattro (dsaKey * key, PyObject *attr) +{ + if (!PyString_Check(attr)) + goto generic; + if (PyString_CompareWithASCIIString(attr,"y") == 0) + return mpzToLongObj (key->y); + else if (PyString_CompareWithASCIIString(attr, "g") == 0) + return mpzToLongObj (key->g); + else if (PyString_CompareWithASCIIString(attr, "p") == 0) + return mpzToLongObj (key->p); + else if (PyString_CompareWithASCIIString(attr, "q") == 0) + return mpzToLongObj (key->q); + else if (PyString_CompareWithASCIIString(attr, "x") == 0) + { + if (mpz_size (key->x) == 0) + { + PyErr_SetString (PyExc_AttributeError, + "dsaKey instance has no attribute 'x'"); + return NULL; + } + return mpzToLongObj (key->x); + } + else + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr((PyObject *) key, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(dsaKey__methods__, (PyObject *)key, PyString_AsString(attr)); +#endif +} + +static PyObject * +dsaKey__sign (dsaKey * key, PyObject * args) +{ + PyObject *lm, *lk, *lr, *ls, *retval; + mpz_t m, k, r, s; + int result; + if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm, + &PyLong_Type, &lk)) + { + return NULL; + } + mpz_init (m); + mpz_init (k); + mpz_init (r); + mpz_init (s); + longObjToMPZ (m, (PyLongObject *) lm); + longObjToMPZ (k, (PyLongObject *) lk); + result = dsaSign (key, m, k, r, s); + if (result == 1) + { + PyErr_SetString (PyExc_ValueError, "K not between 2 and q"); + return NULL; + } + lr = mpzToLongObj (r); + ls = mpzToLongObj (s); + if (lr == NULL || ls == NULL) goto errout; + mpz_clear (m); + mpz_clear (k); + mpz_clear (r); + mpz_clear (s); + retval = Py_BuildValue ("(NN)", lr, ls); + if (retval == NULL) goto errout; + return retval; + +errout: + Py_XDECREF(lr); + Py_XDECREF(ls); + return NULL; +} + +static PyObject * +dsaKey__verify (dsaKey * key, PyObject * args) +{ + PyObject *lm, *lr, *ls; + mpz_t m, r, s; + int result; + if (!PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm, + &PyLong_Type, &lr, &PyLong_Type, &ls)) + { + return NULL; + } + mpz_init (m); + mpz_init (r); + mpz_init (s); + longObjToMPZ (m, (PyLongObject *) lm); + longObjToMPZ (r, (PyLongObject *) lr); + longObjToMPZ (s, (PyLongObject *) ls); + result = dsaVerify (key, m, r, s); + mpz_clear (m); + mpz_clear (r); + mpz_clear (s); + if (result) { + Py_INCREF(Py_True); + return Py_True; + } else { + Py_INCREF(Py_False); + return Py_False; + } +} + +static PyObject * +dsaKey_size (dsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1); +} + +static PyObject * +dsaKey_has_private (dsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + if (mpz_size (key->x) == 0) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + +/** + * Compute key->p and key->q from the key with private exponent only. + * Return 0 if factoring was succesful, 1 otherwise. + */ +static int factorize_N_from_D(rsaKey *key) +{ + mpz_t ktot, t, a, k, cand, nminus1, cand2; + unsigned long cnt; + int spotted; + + mpz_init(ktot); + mpz_init(t); + mpz_init(a); + mpz_init(k); + mpz_init(cand); + mpz_init(nminus1); + mpz_init(cand2); + + mpz_sub_ui(nminus1, key->n, 1); + + /** See _slowmath.py **/ + mpz_mul(ktot, key->e, key->d); + mpz_sub_ui(ktot, ktot, 1); + mpz_set(t, ktot); + cnt = mpz_scan1(t, 0); + mpz_fdiv_q_2exp(t,t,cnt); + mpz_set_ui(a, 2); + for (spotted=0; (!spotted) && (mpz_cmp_ui(a,100)<0); mpz_add_ui(a,a,2)) { + mpz_set(k, t); + for (; (mpz_cmp(k,ktot)<0); mpz_mul_ui(k,k,2)) { + mpz_powm(cand,a,k,key->n); + if ((mpz_cmp_ui(cand,1)==0) || (mpz_cmp(cand,nminus1)==0)) + continue; + mpz_powm_ui(cand2,cand,2,key->n); + if (mpz_cmp_ui(cand2,1)==0) { + mpz_add_ui(cand,cand,1); + mpz_gcd(key->p, cand, key->n); + spotted=1; + break; + } + } + } + if (spotted) + mpz_divexact(key->q, key->n, key->p); + + mpz_clear(ktot); + mpz_clear(t); + mpz_clear(a); + mpz_clear(k); + mpz_clear(cand); + mpz_clear(nminus1); + mpz_clear(cand2); + + return (spotted?0:1); +} + +static PyObject * +rsaKey_new (PyObject * self, PyObject * args) +{ + PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, + *u = NULL; + rsaKey *key; + + if (!PyArg_ParseTuple(args, "O!O!|O!O!O!O!", &PyLong_Type, &n, + &PyLong_Type, &e, &PyLong_Type, &d, + &PyLong_Type, &p, &PyLong_Type, &q, + &PyLong_Type, &u)) + return NULL; + + key = PyObject_New (rsaKey, &rsaKeyType); + if (key == NULL) + return NULL; + mpz_init (key->n); + mpz_init (key->e); + mpz_init (key->d); + mpz_init (key->p); + mpz_init (key->q); + mpz_init (key->u); + longObjToMPZ (key->n, n); + longObjToMPZ (key->e, e); + if (!d) + { + return (PyObject *) key; + } + longObjToMPZ (key->d, d); + if (p && q) + { + longObjToMPZ (key->p, p); + longObjToMPZ (key->q, q); + } else { + if (factorize_N_from_D(key)) + { + Py_DECREF(key); + PyErr_SetString(PyExc_ValueError, + "Unable to compute factors p and q from exponent d."); + return NULL; + } + } + if (u) { + longObjToMPZ (key->u, u); + } else { + mpz_invert (key->u, key->p, key->q); + } + return (PyObject *) key; +} + +static void +rsaKey_dealloc (rsaKey * key) +{ + mpz_clear (key->n); + mpz_clear (key->e); + mpz_clear (key->d); + mpz_clear (key->p); + mpz_clear (key->q); + mpz_clear (key->u); + PyObject_Del (key); +} + +static PyObject * +rsaKey_getattro (rsaKey * key, PyObject *attr) +{ + if (!PyString_Check(attr)) + goto generic; + if (PyString_CompareWithASCIIString(attr, "n") == 0) + return mpzToLongObj (key->n); + else if (PyString_CompareWithASCIIString(attr, "e") == 0) + return mpzToLongObj (key->e); + else if (PyString_CompareWithASCIIString(attr, "d") == 0) + { + if (mpz_size (key->d) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'd'"); + return NULL; + } + return mpzToLongObj (key->d); + } + else if (PyString_CompareWithASCIIString(attr, "p") == 0) + { + if (mpz_size (key->p) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'p'"); + return NULL; + } + return mpzToLongObj (key->p); + } + else if (PyString_CompareWithASCIIString(attr, "q") == 0) + { + if (mpz_size (key->q) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'q'"); + return NULL; + } + return mpzToLongObj (key->q); + } + else if (PyString_CompareWithASCIIString(attr, "u") == 0) + { + if (mpz_size (key->u) == 0) + { + PyErr_SetString(PyExc_AttributeError, + "rsaKey instance has no attribute 'u'"); + return NULL; + } + return mpzToLongObj (key->u); + } + else + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr((PyObject *) key, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(rsaKey__methods__, (PyObject *)key, PyString_AsString(attr)); +#endif +} + +static PyObject * +rsaKey__encrypt (rsaKey * key, PyObject * args) +{ + PyObject *l, *r, *retval; + mpz_t v; + int result; + if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) + { + return NULL; + } + mpz_init (v); + longObjToMPZ (v, (PyLongObject *) l); + result = rsaEncrypt (key, v); + if (result == 1) + { + PyErr_SetString (PyExc_ValueError, "Plaintext too large"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + if (r == NULL) return NULL; + mpz_clear (v); + retval = Py_BuildValue ("N", r); + if (retval == NULL) { + Py_DECREF(r); + return NULL; + } + return retval; +} + +static PyObject * +rsaKey__decrypt (rsaKey * key, PyObject * args) +{ + PyObject *l, *r, *retval; + mpz_t v; + int result; + if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)) + { + return NULL; + } + mpz_init (v); + longObjToMPZ (v, (PyLongObject *) l); + result = rsaDecrypt (key, v); + if (result == 1) + { + PyErr_SetString (PyExc_ValueError, + "Ciphertext too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (PyExc_TypeError, + "Private key not available in this object"); + return NULL; + } + r = mpzToLongObj (v); + if (r == NULL) return NULL; + mpz_clear (v); + retval = Py_BuildValue ("N", r); + if (retval == NULL) { + Py_DECREF(r); + return NULL; + } + return retval; +} + +static PyObject * +rsaKey__verify (rsaKey * key, PyObject * args) +{ + PyObject *l, *lsig; + mpz_t v, vsig; + if (!PyArg_ParseTuple(args, "O!O!", + &PyLong_Type, &l, &PyLong_Type, &lsig)) + { + return NULL; + } + mpz_init (v); + mpz_init (vsig); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vsig, (PyLongObject *) lsig); + rsaEncrypt (key, vsig); + if (mpz_cmp (v, vsig) == 0) { + Py_INCREF(Py_True); + return Py_True; + } + else { + Py_INCREF(Py_False); + return Py_False; + } +} + +static PyObject * +rsaKey__blind (rsaKey * key, PyObject * args) +{ + PyObject *l, *lblind, *r, *retval; + mpz_t v, vblind; + int result; + if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, + &PyLong_Type, &lblind)) + { + return NULL; + } + mpz_init (v); + mpz_init (vblind); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vblind, (PyLongObject *) lblind); + result = rsaBlind (key, v, vblind); + if (result == 1) + { + PyErr_SetString (PyExc_ValueError, "Message too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (PyExc_ValueError, "Blinding factor too large"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + if (r == NULL) + return NULL; + mpz_clear (v); + mpz_clear (vblind); + retval = Py_BuildValue ("N", r); + if (retval == NULL) { + Py_DECREF(r); + return NULL; + } + return retval; +} + +static PyObject * +rsaKey__unblind (rsaKey * key, PyObject * args) +{ + PyObject *l, *lblind, *r, *retval; + mpz_t v, vblind; + int result; + if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, + &PyLong_Type, &lblind)) + { + return NULL; + } + mpz_init (v); + mpz_init (vblind); + longObjToMPZ (v, (PyLongObject *) l); + longObjToMPZ (vblind, (PyLongObject *) lblind); + result = rsaUnBlind (key, v, vblind); + if (result == 1) + { + PyErr_SetString (PyExc_ValueError, "Message too large"); + return NULL; + } + else if (result == 2) + { + PyErr_SetString (PyExc_ValueError, "Blinding factor too large"); + return NULL; + } + else if (result == 3) + { + PyErr_SetString (PyExc_ValueError, "Inverse doesn't exist"); + return NULL; + } + r = (PyObject *) mpzToLongObj (v); + if (r == NULL) return NULL; + mpz_clear (v); + mpz_clear (vblind); + retval = Py_BuildValue ("N", r); + if (retval == NULL) { + Py_DECREF(r); + return NULL; + } + return retval; +} + +static PyObject * +rsaKey_size (rsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1); +} + +static PyObject * +rsaKey_has_private (rsaKey * key, PyObject * args) +{ + if (!PyArg_ParseTuple (args, "")) + return NULL; + if (mpz_size (key->d) == 0) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + + +static PyObject * +isPrime (PyObject * self, PyObject * args, PyObject * kwargs) +{ + unsigned int i, rounds; + double false_positive_prob=1e-6; + PyObject *l, *randfunc=NULL; + mpz_t n; + int result; + static char *kwlist[] = {"N", "false_positive_prob", "randfunc", NULL}; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O!|dO:isPrime", kwlist, + &PyLong_Type, &l, &false_positive_prob, + &randfunc)) + { + return NULL; + } + mpz_init (n); + longObjToMPZ (n, (PyLongObject *) l); + + Py_BEGIN_ALLOW_THREADS; + /* first check if n is known to be prime and do some trial division */ + for (i = 0; i < SIEVE_BASE_SIZE; ++i) + { + if (mpz_cmp_ui (n, sieve_base[i]) == 0) + { + result = 2; + goto cleanup; + } + if (mpz_divisible_ui_p (n, sieve_base[i])) + { + result = 0; + goto cleanup; + } + } + /* do some rounds of Rabin-Miller-Tests */ + rounds = (unsigned int)ceil (-log (false_positive_prob) / log (4)); + Py_BLOCK_THREADS; + result = rabinMillerTest(n, rounds, randfunc); + Py_UNBLOCK_THREADS; + +cleanup: + mpz_clear (n); + Py_END_ALLOW_THREADS; + + if (result < 0) { + return NULL; + } else if (result == 0) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + + + +inline size_t size (mpz_t n) +{ + return mpz_sizeinbase (n, 2); +} + +void bytes_to_mpz (mpz_t result, const unsigned char *bytes, size_t size) +{ + unsigned long i; + mpz_t tmp; + mpz_init (tmp); + Py_BEGIN_ALLOW_THREADS; + mpz_set_ui (result, 0); + for (i = 0; i < size; ++i) + { + /* get current byte */ + mpz_set_ui (tmp, (unsigned long)bytes[i]); + /* left shift and add */ + mpz_mul_2exp (tmp, tmp, 8 * i); + mpz_add (result, result, tmp); + } + mpz_clear (tmp); + Py_END_ALLOW_THREADS; +} + + +/* Returns a new reference to a rng from the Crypto.Random module. */ +static PyObject * +getRNG (void) +{ + /* PyModule_GetDict, PyDict_GetItemString return a borrowed ref */ + PyObject *module, *module_dict, *new_func, *rng; + + module = PyImport_ImportModule ("Crypto.Random"); + if (!module) + return NULL; + module_dict = PyModule_GetDict (module); + Py_DECREF (module); + new_func = PyDict_GetItemString (module_dict, "new"); + if (new_func == NULL) { + PyErr_SetString (PyExc_RuntimeError, + "Crypto.Random.new is missing."); + return NULL; + } + if (!PyCallable_Check (new_func)) + { + PyErr_SetString (PyExc_RuntimeError, + "Crypto.Random.new is not callable."); + return NULL; + } + rng = PyObject_CallObject (new_func, NULL); + return rng; +} + + +/* Sets n to a rangom number with at most `bits` bits . + * If randfunc is provided it should be a callable which takes a single int + * parameter and return as many random bytes as a python string. + * Returns 1 on success + * Returns 0 on error (most likly a python error) + * The thread should be holding the GIL. The function does nothing to check + * this. (PyGILState_Ensure() was only introduced in python2.3 and we want to + * support 2.1) + */ +static int +getRandomInteger (mpz_t n, unsigned long bits, PyObject *randfunc_) +{ + PyObject *arglist=NULL, *randfunc=NULL, *rng=NULL, *rand_bytes=NULL; + int return_val = 1; + unsigned long bytes = bits / 8; + unsigned long odd_bits = bits % 8; + /* generate 1 to 8 bits too many. + we will remove them later by right-shifting */ + bytes++; + /* we need to handle the cases where randfunc is NULL or None */ + if ((randfunc_ == NULL) || (randfunc_ == Py_None)) + { + rng = getRNG(); + if (!rng) + { + return_val = 0; + goto cleanup; + } + randfunc = PyObject_GetAttrString (rng, "read"); + } + else + { + randfunc = randfunc_; + } + + if (!PyCallable_Check (randfunc)) + { + PyErr_SetString (PyExc_TypeError, "randfunc must be callable"); + return_val = 0; + goto cleanup; + } + + arglist = Py_BuildValue ("(l)", (long)bytes); + if (arglist == NULL) { + return_val = 0; + goto cleanup; + } + rand_bytes = PyObject_CallObject (randfunc, arglist); + if (rand_bytes == NULL) { + return_val = 0; + goto cleanup; + } + if (!PyBytes_Check (rand_bytes)) + { + PyErr_SetString (PyExc_TypeError, + "randfunc must return a string of random bytes"); + return_val = 0; + goto cleanup; + } + + bytes_to_mpz (n, (unsigned char *)PyBytes_AsString(rand_bytes), bytes); + /* remove superflous bits by right-shifting */ + mpz_fdiv_q_2exp (n, n, 8 - odd_bits); + +cleanup: + Py_XDECREF (arglist); + Py_XDECREF (rand_bytes); + if (rng) + { + Py_XDECREF (randfunc); + Py_DECREF (rng); + } + return return_val; +} + + +/* Sets n to a rangom number with exactly `bits` random bits. + * randfunc should be either NULL, PyNone or a callable which takes a single + * integer parameter and return as many random bytes as a python string. + * Returns 1 on success + * Returns 0 on error (most likly a python error) + * The thread should be holding the GIL. The function does nothing to check + * this. (PyGILState_Ensure() was only introduced in python2.3 and we want to + * support 2.1) + */ +static int +getRandomNBitInteger (mpz_t n, unsigned long bits, PyObject *randfunc) +{ + if (!getRandomInteger (n, bits, randfunc)) + return 0; + /* set the MSB to ensure n really has the correct number of bits. */ + mpz_setbit (n, bits); + return 1; +} + + +/* Sets n to a random number so that lower_bound <= n < upper_bound . + * If randfunc is provided it should be a callable which takes a single int + * parameter and return as many random bytes as a python string. + * Returns 1 on success + * Returns 0 on error (most likly a python error) + * The thread should be holding the GIL. The function does nothing to check + * this. (PyGILState_Ensure() was only introduced in python2.3 and we want to + * support 2.1) + */ +static int +getRandomRange (mpz_t n, mpz_t lower_bound, mpz_t upper_bound, + PyObject *randfunc) +{ + size_t bits; + mpz_t range; + mpz_init (range); + mpz_sub (range, upper_bound, lower_bound); + mpz_sub_ui (range, range, 1); + bits = size (range); + + do + { + if (!getRandomInteger (n, bits, randfunc)) + { + mpz_clear (range); + return 0; + } + } while (mpz_cmp (n, range) > 0); + + mpz_clear (range); + mpz_add (n, n, lower_bound); + return 1; +} + + + +static void +sieve_field (char *field, unsigned long field_size, mpz_t start) +{ + mpz_t mpz_offset; + unsigned int offset; + unsigned int i, j; + + mpz_init (mpz_offset); + + for (i = 0; i < SIEVE_BASE_SIZE; ++i) + { + mpz_mod_ui (mpz_offset, start, sieve_base[i]); + offset = mpz_get_ui (mpz_offset); + for (j = (sieve_base[i] - offset) % sieve_base[i]; j < field_size; j += sieve_base[i]) + { + field[j] = 1; + } + } + + mpz_clear (mpz_offset); +} + + +#define MAX_RABIN_MILLER_ROUNDS 255 + +/* Tests if n is prime. + * Returns 0 when n is definitly composite. + * Returns 1 when n is probably prime. + * Returns -1 when there is an error. + * every round reduces the chance of a false positive be at least 1/4. + * + * If randfunc is omitted, then the python version Random.new().read is used. + * + * The thread should be holding the GIL. The function does nothing to check + * this. (PyGILState_Ensure() was only introduced in python2.3 and we want to + * support 2.1) + */ +static int +rabinMillerTest (mpz_t n, int rounds, PyObject *randfunc) +{ + int base_was_tested; + unsigned long i, j, b, composite; + int return_val = 1; + mpz_t a, m, z, n_1, tmp; + mpz_t tested[MAX_RABIN_MILLER_ROUNDS]; + + if (rounds > MAX_RABIN_MILLER_ROUNDS) + { + /* PyErr_Warn is deprecated, but we use it for backward + * compatibility with Python < 2.5. Eventually, it will need + * to be replaced with PyErr_WarnEx with the stacklevel + * argument set to 1 */ + PyErr_Warn(PyExc_RuntimeWarning, + "rounds to Rabin-Miller-Test exceeds maximum. " + "rounds will be set to the maximum.\n" + "Go complain to the devs about it if you like."); + rounds = MAX_RABIN_MILLER_ROUNDS; + } + + Py_BEGIN_ALLOW_THREADS; + /* check special cases (n==2, n even, n < 2) */ + if ((mpz_tstbit (n, 0) == 0) || (mpz_cmp_ui (n, 3) < 0)) { + return_val = (mpz_cmp_ui (n, 2) == 0); + Py_BLOCK_THREADS; + return return_val; + } + + mpz_init (tmp); + mpz_init (n_1); + mpz_init (a); + mpz_init (m); + mpz_init (z); + mpz_sub_ui (n_1, n, 1); + b = mpz_scan1 (n_1, 0); + mpz_fdiv_q_2exp (m, n_1, b); + + if (mpz_fits_ulong_p (n) && (mpz_get_ui (n) - 2 < (unsigned long)rounds)) + rounds = mpz_get_ui (n) - 2; + for (i = 0; i < (unsigned long)rounds; ++i) + { + mpz_set_ui (tmp, 2); + do + { + base_was_tested = 0; + Py_BLOCK_THREADS; + if (!getRandomRange (a, tmp, n, randfunc)) + { + return_val = -1; + Py_UNBLOCK_THREADS; + goto cleanup; + } + Py_UNBLOCK_THREADS; + for (j = 0; j < i; j++) + { + if (mpz_cmp (a, tested[j]) == 0) + { + base_was_tested = 1; + break; + } + } + } while (base_was_tested); + mpz_init_set (tested[i], a); + MPZ_POWM (z, a, m, n); + if ((mpz_cmp_ui (z, 1) == 0) || (mpz_cmp (z, n_1) == 0)) + continue; + composite = 1; + for (j = 0; j < b; ++j) + { + /* z = (z * z) % n */ + mpz_mul (z, z, z); + mpz_mod (z, z, n); + if (mpz_cmp_ui (z, 1) == 0) + { + return_val = 0; + goto cleanup; + } + else if (mpz_cmp (z, n_1) == 0) + { + composite = 0; + break; + } + } + + if (composite) + { + return_val = 0; + goto cleanup; + } + } + +cleanup: + mpz_clear (tmp); + mpz_clear (n_1); + mpz_clear (a); + mpz_clear (m); + mpz_clear (z); + Py_END_ALLOW_THREADS; + return return_val; +} + + +/* getStrongPrime() generates a number p which is with a high probability a + * prime for which the following is true: + * p+1 has at least one large prime factor + * p-1 has at least one large prime factor + * This functions was implemented following the instructions found in the paper + * "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" + * by Robert D. Silverman + * RSA Laboratories + * May 17, 1997 + * which by the time of writing could be obtained here: + * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf + */ +static PyObject * +getStrongPrime (PyObject *self, PyObject *args, PyObject *kwargs) +{ + unsigned long i, j, bits, x, e=0; + mpz_t p[2], y[2], R, X; + mpz_t tmp[2], lower_bound, upper_bound, range, increment; + mpf_t tmp_bound; + char *field; + double false_positive_prob = 1e-6; + int rabin_miller_rounds, is_possible_prime, error = 0, result; + PyObject *prime, *randfunc=NULL; + static char *kwlist[] = {"N", "e", "false_positive_prob", "randfunc", NULL}; + unsigned long base_size = SIEVE_BASE_SIZE; + unsigned long field_size = 5 * base_size; + int res; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "l|ldO:getStrongPrime", + kwlist, &bits, &e, &false_positive_prob, + &randfunc)) + { + return NULL; + } + + if ((bits < 512) || ((bits % 128) != 0)) + { + PyErr_SetString (PyExc_ValueError, + "bits must be multiple of 128 and > 512"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS; + rabin_miller_rounds = (int)ceil (-log (false_positive_prob) / log (4)); + /* The variable names y, p, X and R correspond to + * the names in the paper mentioned above + */ + mpz_init2 (y[0], 101); + mpz_init2 (y[1], 101); + mpz_init2 (p[0], 121); + mpz_init2 (p[1], 121); + mpz_init2 (X, bits); + mpz_init2 (R, bits); + mpz_init2 (increment, 242); + mpz_init (tmp[0]); + mpz_init (tmp[1]); + mpz_init2 (lower_bound, bits); + mpz_init2 (upper_bound, bits); + mpf_init (tmp_bound); + mpz_init (range); + + /* calculate range for X + * lower_bound = sqrt(2) * 2^{511 + 128*x} + * upper_bound = 2^{512 + 128*x} - 1 + */ + x = (bits - 512) / 128; + mpf_sqrt_ui (tmp_bound, 2); + mpf_mul_2exp (tmp_bound, tmp_bound, 511 + 128 * x); + mpf_ceil (tmp_bound, tmp_bound); + mpz_set_f (lower_bound, tmp_bound); + mpz_set_ui (upper_bound, 1); + mpz_mul_2exp (upper_bound, upper_bound, 512 + 128 * x); + mpz_sub_ui (upper_bound, upper_bound, 1); + mpz_sub (range, upper_bound, lower_bound); + + /* Randomly choose X, y[0] and y[1] */ + Py_BLOCK_THREADS; + res = 1; + res &= getRandomRange (X, lower_bound, upper_bound, randfunc); + res &= getRandomNBitInteger (y[0], 101, randfunc); + res &= getRandomNBitInteger (y[1], 101, randfunc); + Py_UNBLOCK_THREADS; + if (!res) + { + error = 1; + goto cleanup; + } + + /* generate p1 and p2 */ + for (i = 0; i < 2; ++i) + { + /* generate p[i] */ + /* initialize the field for sieving */ + field = (char*)calloc (field_size, 1); + sieve_field (field, field_size, y[i]); + + result = 0; + for (j = 0; j < field_size; ++j) + { + /* look for next canidate */ + if (field[j]) + continue; + mpz_add_ui (tmp[0], y[i], j); + Py_BLOCK_THREADS; + result = rabinMillerTest(tmp[0], rabin_miller_rounds, randfunc); + Py_UNBLOCK_THREADS; + if (result > 0) + break; + else if (result < 0) + { + error = 1; + goto cleanup; + } + } + free (field); + if (!result) + { + error = 1; + Py_BLOCK_THREADS; + PyErr_SetString (PyExc_RuntimeError, + "Couln't find prime in field. " + "Developer: Increase field_size"); + /* unblock threads because we acquire the GIL after cleanup */ + Py_UNBLOCK_THREADS; + goto cleanup; + } + mpz_set (p[i], tmp[0]); + } + + /* Calculate R + * R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 + */ + mpz_invert (tmp[0], p[1], p[0]); /* p2^-1 mod p1 */ + mpz_invert (tmp[1], p[0], p[1]); /* p1^-1 mod p2 */ + mpz_mul (tmp[0], tmp[0], p[1]); /* (p2^-1 mod p1)*p2 */ + mpz_mul (tmp[1], tmp[1], p[0]); /* (p1^-1 mod p2)*p1 */ + mpz_sub (R, tmp[0], tmp[1]); /* (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 */ + + /* search for final prime number starting by Y0 + * Y0 = X + (R - X mod p1p2) + */ + mpz_mul (increment, p[0], p[1]); /* p1 * p2 */ + mpz_mod (tmp[0], X, increment); /* X mod (p1*p2) */ + mpz_sub (tmp[1], R, tmp[0]); /* R - X mod (p1*p2) */ + mpz_add (X, X, tmp[1]); /* X + (R - X mod (p1*p2)) */ + while (1) + { + is_possible_prime = 1; + /* first check canidate against sieve_base */ + for (j = 0; j < base_size; ++j) + { + if (mpz_divisible_ui_p (X, sieve_base[j])) + { + is_possible_prime = 0; + break; + } + } + /* if e is given check for some more constrains */ + if (e && is_possible_prime) + { + /* if e is odd make sure that e and X-1 are coprime */ + if (e & 1) + { + mpz_sub_ui (tmp[0], X, 1); + if (mpz_gcd_ui (NULL, tmp[0], e) != 1) + is_possible_prime = 0; + } + /* if e is even make sure that e and (X-1)/2 are coprime. */ + else + { + mpz_sub_ui (tmp[0], X, 1); + mpz_divexact_ui (tmp[0], tmp[0], 2); + if (mpz_gcd_ui (NULL, tmp[0], e) != 1) + is_possible_prime = 0; + } + } + /* let gmp do some Rabin-Miller-Tests */ + if (is_possible_prime) + { + Py_BLOCK_THREADS; + result = rabinMillerTest(X, rabin_miller_rounds, randfunc); + Py_UNBLOCK_THREADS; + if (result > 0) + break; + else if (result < 0) + { + error = 1; + goto cleanup; + } + } + mpz_add (X, X, increment); + /* abort when X is larger than upper_bound */ + /* TODO: maybe we shouldn't abort but rather start over. + * X probably was an unfortunate choice. */ + if (mpz_cmp (X, upper_bound) >= 0) + { + error = 1; + Py_BLOCK_THREADS; + PyErr_SetString (PyExc_RuntimeError, + "Couln't find prime in field. " + "Developer: Increase field_size"); + /* unblock threads because we acquire the GIL after cleanup */ + Py_UNBLOCK_THREADS; + goto cleanup; + } + } + +cleanup: + mpz_clear (range); + mpz_clear (increment); + mpz_clear (upper_bound); + mpz_clear (lower_bound); + mpz_clear (R); + mpz_clear (tmp[1]); + mpz_clear (tmp[0]); + mpz_clear (p[1]); + mpz_clear (p[0]); + mpz_clear (y[1]); + mpz_clear (y[0]); + /* mpzToLongObj uses Python API so we must acquire the GIL */ + Py_END_ALLOW_THREADS; + if (error) + prime = NULL; + else + prime = mpzToLongObj (X); + mpz_clear (X); + return prime; +} + + + +static PyMethodDef _fastmath__methods__[] = { + {"dsa_construct", dsaKey_new, METH_VARARGS}, + {"rsa_construct", rsaKey_new, METH_VARARGS}, + {"isPrime", (PyCFunction)isPrime, METH_VARARGS | METH_KEYWORDS}, + {"getStrongPrime", (PyCFunction)getStrongPrime, METH_VARARGS | METH_KEYWORDS}, + {NULL, NULL} +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_fastmath", + NULL, + -1, + _fastmath__methods__, + NULL, + NULL, + NULL, + NULL +}; +#endif + +PyMODINIT_FUNC +#ifdef IS_PY3K +PyInit__fastmath (void) +#else +init_fastmath (void) +#endif +{ + PyObject *m = NULL; + + if (PyType_Ready(&rsaKeyType) < 0) + goto errout; + if (PyType_Ready(&dsaKeyType) < 0) + goto errout; + + /* Initialize the module */ +#ifdef IS_PY3K + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule ("_fastmath", _fastmath__methods__); +#endif + if (m == NULL) + goto errout; + + fastmathError = PyErr_NewException ("_fastmath.error", NULL, NULL); + if (fastmathError == NULL) + goto errout; + PyObject_SetAttrString(m, "error", fastmathError); + + PyModule_AddIntConstant(m, "HAVE_DECL_MPZ_POWM_SEC", HAVE_DECL_MPZ_POWM_SEC); + +out: + /* Final error check */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + Py_CLEAR(fastmathError); + goto out; +} + +/* The first 10000 primes to be used as a base for sieving */ +static unsigned int sieve_base[10000] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, + 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, + 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, + 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, + 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, + 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, + 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, + 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, + 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, + 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, + 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, + 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, + 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, + 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, + 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, + 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, + 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, + 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, + 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, + 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, + 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, + 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, + 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, + 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, + 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, + 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, + 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, + 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, + 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, + 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, + 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, + 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, + 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, + 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, + 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, + 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, + 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, + 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, + 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, + 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, + 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, + 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, + 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, + 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, + 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, + 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, + 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, + 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, + 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, + 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, + 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, + 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, + 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, + 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, + 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, + 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, + 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, + 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, + 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, + 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, + 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, + 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, + 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, + 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, + 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, + 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, + 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, + 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, + 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, + 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, + 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, + 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, + 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, + 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, + 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, + 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, + 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, + 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, + 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, + 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, + 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, + 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, + 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, + 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, + 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, + 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, + 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, + 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, + 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, + 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, + 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, + 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, + 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, + 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, + 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, + 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, + 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, + 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, + 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, + 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, + 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, + 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, + 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, + 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, + 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, + 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, + 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, + 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, + 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, + 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, + 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, + 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, + 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, + 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, + 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, + 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, + 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, + 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, + 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, + 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, + 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, + 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, + 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, + 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, + 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, + 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, + 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, + 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, + 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, + 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, + 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, + 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, + 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, + 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, + 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, + 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, + 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, + 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, + 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, + 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, + 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, + 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, + 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, + 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, + 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, + 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, + 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, + 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, + 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, + 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, + 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, + 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, + 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, + 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, + 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, + 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, + 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, + 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, + 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, + 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, + 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, + 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, + 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, + 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, + 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, + 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, + 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, + 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, + 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, + 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, + 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, + 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, + 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, + 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, + 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, + 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, + 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, + 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, + 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, + 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, + 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, + 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, + 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, + 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, + 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, + 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, + 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, + 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, + 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, + 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, + 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, + 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, + 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, + 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, + 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, + 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, + 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, + 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, + 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, + 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, + 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, + 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, + 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, + 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, + 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, + 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, + 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, + 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, + 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, + 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, + 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, + 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, + 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, + 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, + 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, + 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, + 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, + 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, + 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, + 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, + 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, + 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, + 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, + 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, + 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, + 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, + 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, + 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, + 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, + 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, + 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, + 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, + 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, + 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, + 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, + 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, + 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, + 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, + 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, + 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, + 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, + 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, + 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, + 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, + 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, + 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, + 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, + 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, + 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, + 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, + 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, + 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, + 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, + 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, + 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, + 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, + 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, + 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, + 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, + 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, + 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, + 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, + 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, + 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, + 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, + 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, + 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, + 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, + 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, + 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, + 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, + 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, + 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, + 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, + 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, + 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, + 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, + 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, + 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, + 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, + 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, + 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, + 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, + 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, + 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, + 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, + 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, + 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, + 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, + 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, + 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, + 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, + 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, + 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, + 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, + 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, + 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, + 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, + 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, + 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, + 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, + 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, + 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, + 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, + 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, + 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, + 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, + 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, + 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, + 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, + 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, + 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, + 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, + 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, + 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, + 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, + 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, + 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, + 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, + 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, + 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, + 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, + 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, + 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, + 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, + 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, + 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, + 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, + 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, + 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, + 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, + 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, + 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, + 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, + 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, + 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, + 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, + 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, + 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, + 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, + 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, + 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, + 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, + 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, + 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, + 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, + 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, + 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, + 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, + 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, + 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, + 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, + 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, + 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, + 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, + 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, + 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, + 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, + 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, + 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, + 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, + 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, + 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, + 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, + 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, + 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, + 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, + 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, + 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, + 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, + 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, + 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, + 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, + 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, + 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, + 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, + 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, + 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, + 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, + 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, + 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, + 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, + 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, + 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, + 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, + 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, + 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, + 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, + 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, + 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, + 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, + 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, + 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, + 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, + 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, + 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, + 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, + 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, + 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, + 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, + 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, + 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, + 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, + 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, + 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, + 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, + 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, + 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, + 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, + 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, + 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, + 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, + 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, + 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, + 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, + 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, + 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, + 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, + 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, + 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, + 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, + 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, + 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, + 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, + 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, + 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, + 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, + 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, + 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, + 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, + 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, + 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, + 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, + 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, + 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, + 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, + 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, + 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, + 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, + 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, + 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, + 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, + 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, + 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, + 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, + 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, + 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, + 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, + 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, + 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, + 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, + 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, + 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, + 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, + 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, + 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, + 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, + 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, + 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, + 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, + 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, + 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, + 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, + 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, + 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, + 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, + 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, + 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, + 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, + 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, + 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, + 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, + 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, + 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, + 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, + 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, + 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, + 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, + 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, + 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, + 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, + 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, + 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, + 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, + 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, + 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, + 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, + 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, + 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, + 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, + 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, + 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, + 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, + 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, + 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, + 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, + 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, + 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, + 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, + 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, + 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, + 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, + 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, + 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, + 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, + 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, + 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, + 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, + 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, + 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, + 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, + 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, + 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, + 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, + 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, + 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, + 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, + 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, + 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, + 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, + 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, + 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, + 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, + 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, + 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, + 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, + 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, + 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, + 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, + 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, + 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, + 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, + 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, + 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, + 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, + 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, + 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, + 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, + 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, + 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, + 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, + 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, + 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, + 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, + 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, + 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, + 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, + 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, + 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, + 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, + 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, + 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, + 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, + 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, + 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, + 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, + 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, + 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, + 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, + 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, + 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, + 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, + 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, + 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, + 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, + 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, + 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, + 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, + 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, + 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, + 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, + 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, + 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, + 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, + 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, + 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, + 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, + 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, + 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, + 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, + 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, + 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, + 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, + 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, + 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, + 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, + 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, + 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, + 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, + 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, + 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, + 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, + 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, + 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, + 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, + 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, + 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, + 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, + 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, + 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, + 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, + 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, + 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, + 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, + 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, + 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, + 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, + 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, + 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, + 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, + 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, + 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, + 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, + 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, + 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, + 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, + 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, + 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, + 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, + 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, + 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, + 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, + 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, + 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, + 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, + 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, + 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, + 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, + 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, + 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, + 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, + 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, + 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, + 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, + 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, + 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, + 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, + 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, + 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, + 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, + 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, + 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, + 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, + 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, + 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, + 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, + 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, + 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, + 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, + 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, + 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, + 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, + 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, + 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, + 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, + 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, + 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, + 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, + 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, + 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, + 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, + 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, + 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, + 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, + 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, + 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, + 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, + 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, + 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, + 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, + 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, + 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, + 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, + 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, + 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, + 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, + 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, + 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, + 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, + 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, + 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, + 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, + 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, + 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, + 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, + 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, + 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, + 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, + 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, + 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, + 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, + 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, + 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, + 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, + 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, + 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, + 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, + 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, + 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, + 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, + 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, + 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, + 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, + 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, + 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, + 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, + 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, + 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, + 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, + 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, + 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, + 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, + 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, + 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, + 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, + 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, + 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, + 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, + 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, + 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, + 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, + 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, + 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, + 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, + 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, + 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, + 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, + 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, + 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, + 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, + 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, + 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, + 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, + 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, + 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, + 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, + 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, + 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, + 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, + 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, + 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, + 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, + 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, + 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, + 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, + 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, + 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, + 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, + 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, + 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, + 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, + 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, + 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, + 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, + 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, + 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, + 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, + 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, + 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, + 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, + 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, + 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, + 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, + 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, + 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, + 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, + 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, + 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, + 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, + 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, + 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, + 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, + 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, + 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, + 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, + 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, + 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, + 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, + 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, + 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, + 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, + 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, + 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, + 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, + 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, + 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, + 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, + 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, + 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, + 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, + 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, + 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, + 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, + 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, + 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, + 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, + 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, + 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, + 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, + 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, + 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, + 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, + 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, + 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, + 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, + 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, + 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, + 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, + 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, + 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, + 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, + 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, + 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, + 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, + 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, + 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, + 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, + 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, + 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, + 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, + 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, + 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, + 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, + 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, + 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, + 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, + 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, + 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, + 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, + 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, + 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, + 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, + 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, + 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, + 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, + 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, + 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, + 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, + 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, + 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, + 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, + 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, + 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, + 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, + 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, + 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, + 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, + 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, + 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, + 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, + 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, + 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, + 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, + 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, + 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, + 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, + 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, + 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, + 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, + 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, + 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, + 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, + 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, + 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, + 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, + 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, + 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, + 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, + 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, + 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, + 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, + 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, + 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, + 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, + 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, + 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, + 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, + 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, + 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, + 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, + 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, + 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, + 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, + 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, + 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, + 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, + 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, + 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, + 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, + 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, + 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, + 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, + 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, + 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, + 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, + 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, + 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, + 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, + 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, + 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, + 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, + 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, + 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, + 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, + 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, + 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, + 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, + 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, + 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, + 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, + 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, + 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, + 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, + 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, + 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, + 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, + 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, + 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, + 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, + 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, + 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, + 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, + 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, + 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, + 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, + 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, + 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, + 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, + 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, + 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, + 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, + 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, + 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, + 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, + 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, +100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, +100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, +100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, +100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, +100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, +100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, +100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, +100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, +101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, +101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, +101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, +101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, +101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, +101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, +101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, +101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, +101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, +102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, +102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, +102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, +102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, +102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, +102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, +102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, +102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, +102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, +103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, +103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, +103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, +103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, +103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, +103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, +103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, +103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, +104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, +104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, +104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, +104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, +104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, +104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729 +}; diff --git a/src/block_template.c b/src/block_template.c new file mode 100644 index 0000000..99aee43 --- /dev/null +++ b/src/block_template.c @@ -0,0 +1,841 @@ + +/* -*- C -*- */ +/* + * block_template.c : Generic framework for block encryption algorithms + * + * Written by Andrew Kuchling and others + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +#include "pycrypto_common.h" +#include "modsupport.h" +#include <string.h> +#include "_counter.h" + +/* Cipher operation modes */ + +#define MODE_ECB 1 +#define MODE_CBC 2 +#define MODE_CFB 3 +#define MODE_PGP 4 +#define MODE_OFB 5 +#define MODE_CTR 6 + +#define _STR(x) #x +#define _XSTR(x) _STR(x) +#define _PASTE(x,y) x##y +#define _PASTE2(x,y) _PASTE(x,y) +#ifdef IS_PY3K +#define _MODULE_NAME _PASTE2(PyInit_,MODULE_NAME) +#else +#define _MODULE_NAME _PASTE2(init,MODULE_NAME) +#endif +#define _MODULE_STRING _XSTR(MODULE_NAME) + +/* Object references for the counter_shortcut */ +static PyObject *_counter_module = NULL; +static PyTypeObject *PCT_CounterBEType = NULL; +static PyTypeObject *PCT_CounterLEType = NULL; + +typedef struct +{ + PyObject_HEAD + int mode, count, segment_size; + unsigned char IV[BLOCK_SIZE], oldCipher[BLOCK_SIZE]; + PyObject *counter; + int counter_shortcut; + block_state st; +} ALGobject; + +/* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C. + * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize + */ +staticforward PyTypeObject ALGtype; + +static ALGobject * +newALGobject(void) +{ + ALGobject * new; + new = PyObject_New(ALGobject, &ALGtype); + new->mode = MODE_ECB; + new->counter = NULL; + new->counter_shortcut = 0; + return new; +} + +static void +ALGdealloc(PyObject *ptr) +{ + ALGobject *self = (ALGobject *)ptr; + block_finalize(&self->st); + + /* Overwrite the contents of the object */ + Py_XDECREF(self->counter); + self->counter = NULL; + memset(self->IV, 0, BLOCK_SIZE); + memset(self->oldCipher, 0, BLOCK_SIZE); + memset((char*)&(self->st), 0, sizeof(block_state)); + self->mode = self->count = self->segment_size = 0; + PyObject_Del(ptr); +} + + + +static char ALGnew__doc__[] = +"new(key, [mode], [IV]): Return a new " _MODULE_STRING " encryption object."; + +static char *kwlist[] = {"key", "mode", "IV", "counter", "segment_size", +#ifdef PCT_ARC2_MODULE + "effective_keylen", +#endif + NULL}; + +static ALGobject * +ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) +{ + unsigned char *key, *IV; + ALGobject * new=NULL; + int keylen, IVlen=0, mode=MODE_ECB, segment_size=0; + PyObject *counter = NULL; + int counter_shortcut = 0; +#ifdef PCT_ARC2_MODULE + int effective_keylen = 1024; /* this is a weird default, but it's compatible with old versions of PyCrypto */ +#endif + /* Set default values */ + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#|is#Oi" +#ifdef PCT_ARC2_MODULE + "i" +#endif + , kwlist, + &key, &keylen, &mode, &IV, &IVlen, + &counter, &segment_size +#ifdef PCT_ARC2_MODULE + , &effective_keylen +#endif + )) + { + return NULL; + } + + if (mode<MODE_ECB || mode>MODE_CTR) + { + PyErr_Format(PyExc_ValueError, + "Unknown cipher feedback mode %i", + mode); + return NULL; + } + if (mode == MODE_PGP) { + PyErr_Format(PyExc_ValueError, + "MODE_PGP is not supported anymore"); + return NULL; + } + if (KEY_SIZE!=0 && keylen!=KEY_SIZE) + { + PyErr_Format(PyExc_ValueError, + "Key must be %i bytes long, not %i", + KEY_SIZE, keylen); + return NULL; + } + if (KEY_SIZE==0 && keylen==0) + { + PyErr_SetString(PyExc_ValueError, + "Key cannot be the null string"); + return NULL; + } + if (IVlen != 0 && mode == MODE_ECB) + { + PyErr_Format(PyExc_ValueError, "ECB mode does not use IV"); + return NULL; + } + if (IVlen != 0 && mode == MODE_CTR) + { + PyErr_Format(PyExc_ValueError, + "CTR mode needs counter parameter, not IV"); + return NULL; + } + if (IVlen != BLOCK_SIZE && mode != MODE_ECB && mode != MODE_CTR) + { + PyErr_Format(PyExc_ValueError, + "IV must be %i bytes long", BLOCK_SIZE); + return NULL; + } + + /* Mode-specific checks */ + if (mode == MODE_CFB) { + if (segment_size == 0) segment_size = 8; + if (segment_size < 1 || segment_size > BLOCK_SIZE*8 || ((segment_size & 7) != 0)) { + PyErr_Format(PyExc_ValueError, + "segment_size must be multiple of 8 (bits) " + "between 1 and %i", BLOCK_SIZE*8); + return NULL; + } + } + if (mode == MODE_CTR) { + if (counter == NULL) { + PyErr_SetString(PyExc_TypeError, + "'counter' keyword parameter is required with CTR mode"); + return NULL; + } else if (Py_TYPE(counter) == PCT_CounterBEType || Py_TYPE(counter) == PCT_CounterLEType) { + counter_shortcut = 1; + } else if (!PyCallable_Check(counter)) { + PyErr_SetString(PyExc_ValueError, + "'counter' parameter must be a callable object"); + return NULL; + } + } else { + if (counter != NULL) { + PyErr_SetString(PyExc_ValueError, + "'counter' parameter only useful with CTR mode"); + return NULL; + } + } + + /* Cipher-specific checks */ +#ifdef PCT_ARC2_MODULE + if (effective_keylen<0 || effective_keylen>1024) { + PyErr_Format(PyExc_ValueError, + "RC2: effective_keylen must be between 0 and 1024, not %i", + effective_keylen); + return NULL; + } +#endif + + /* Copy parameters into object */ + new = newALGobject(); + new->segment_size = segment_size; + new->counter = counter; + Py_XINCREF(counter); + new->counter_shortcut = counter_shortcut; +#ifdef PCT_ARC2_MODULE + new->st.effective_keylen = effective_keylen; +#endif + + block_init(&(new->st), key, keylen); + if (PyErr_Occurred()) + { + Py_DECREF(new); + return NULL; + } + memset(new->IV, 0, BLOCK_SIZE); + memset(new->oldCipher, 0, BLOCK_SIZE); + memcpy(new->IV, IV, IVlen); + new->mode = mode; + new->count=BLOCK_SIZE; /* stores how many bytes in new->oldCipher have been used */ + return new; +} + +static char ALG_Encrypt__doc__[] = +"Encrypt the provided string of binary data."; + +static PyObject * +ALG_Encrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + unsigned char temp[BLOCK_SIZE]; + int i, j, len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len==0) /* Handle empty string */ + { + return PyBytes_FromStringAndSize(NULL, 0); + } + if ( (len % BLOCK_SIZE) !=0 && + (self->mode!=MODE_CFB) && + (self->mode!=MODE_OFB) && + (self->mode!=MODE_CTR)) + { + PyErr_Format(PyExc_ValueError, + "Input strings must be " + "a multiple of %i in length", + BLOCK_SIZE); + return NULL; + } + if (self->mode == MODE_CFB && + (len % (self->segment_size/8) !=0)) { + PyErr_Format(PyExc_ValueError, + "Input strings must be a multiple of " + "the segment size %i in length", + self->segment_size/8); + return NULL; + } + + buffer=malloc(len); + if (buffer==NULL) + { + PyErr_SetString(PyExc_MemoryError, + "No memory available in " + _MODULE_STRING " encrypt"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS; + switch(self->mode) + { + case(MODE_ECB): + for(i=0; i<len; i+=BLOCK_SIZE) + { + block_encrypt(&(self->st), str+i, buffer+i); + } + break; + + case(MODE_CBC): + for(i=0; i<len; i+=BLOCK_SIZE) + { + for(j=0; j<BLOCK_SIZE; j++) + { + temp[j]=str[i+j]^self->IV[j]; + } + block_encrypt(&(self->st), temp, buffer+i); + memcpy(self->IV, buffer+i, BLOCK_SIZE); + } + break; + + case(MODE_CFB): + for(i=0; i<len; i+=self->segment_size/8) + { + block_encrypt(&(self->st), self->IV, temp); + for (j=0; j<self->segment_size/8; j++) { + buffer[i+j] = str[i+j] ^ temp[j]; + } + if (self->segment_size == BLOCK_SIZE * 8) { + /* s == b: segment size is identical to + the algorithm block size */ + memcpy(self->IV, buffer + i, BLOCK_SIZE); + } + else if ((self->segment_size % 8) == 0) { + int sz = self->segment_size/8; + memmove(self->IV, self->IV + sz, + BLOCK_SIZE-sz); + memcpy(self->IV + BLOCK_SIZE - sz, buffer + i, + sz); + } + else { + /* segment_size is not a multiple of 8; + currently this can't happen */ + } + } + break; + + case(MODE_OFB): + /* OFB mode is a stream cipher whose keystream is generated by encrypting the previous ciphered output. + * - self->IV stores the current keystream block + * - self->count indicates the current offset within the current keystream block + * - str stores the input string + * - buffer stores the output string + * - len indicates the length of the input and output strings + * - i indicates the current offset within the input and output strings + * (len-i) is the number of bytes remaining to encrypt + * (BLOCK_SIZE-self->count) is the number of bytes remaining in the current keystream block + */ + i = 0; + while(i < len) + { + /* If we don't need more than what remains of the current keystream block, then just XOR it in */ + if (len-i <= BLOCK_SIZE-self->count) { /* remaining_bytes_to_encrypt <= remaining_bytes_in_IV */ + /* XOR until the input is used up */ + for(j=0; j<(len-i); j++) { + assert(i+j < len); + assert(self->count+j < BLOCK_SIZE); + buffer[i+j] = self->IV[self->count+j] ^ str[i+j]; + } + self->count += len-i; + i = len; + continue; + } + + /* Use up the current keystream block */ + for(j=0; j<BLOCK_SIZE-self->count; j++) { + assert(i+j < len); + assert(self->count+j < BLOCK_SIZE); + buffer[i+j] = self->IV[self->count+j] ^ str[i+j]; + } + i += BLOCK_SIZE-self->count; + self->count = BLOCK_SIZE; + + /* Generate a new keystream block */ + block_encrypt(&(self->st), self->IV, temp); + memcpy(self->IV, temp, BLOCK_SIZE); + + /* Move the pointer to the start of the keystream */ + self->count = 0; + } + break; + + case(MODE_CTR): + /* CTR mode is a stream cipher whose keystream is generated by encrypting unique counter values. + * - self->counter points to the Counter callable, which is + * responsible for generating keystream blocks + * - self->count indicates the current offset within the current keystream block + * - self->IV stores the current keystream block + * - str stores the input string + * - buffer stores the output string + * - len indicates the length if the input and output strings + * - i indicates the current offset within the input and output strings + * - (len-i) is the number of bytes remaining to encrypt + * - (BLOCK_SIZE-self->count) is the number of bytes remaining in the current keystream block + */ + i = 0; + while (i < len) { + /* If we don't need more than what remains of the current keystream block, then just XOR it in */ + if (len-i <= BLOCK_SIZE-self->count) { /* remaining_bytes_to_encrypt <= remaining_bytes_in_IV */ + /* XOR until the input is used up */ + for(j=0; j<(len-i); j++) { + assert(i+j < len); + assert(self->count+j < BLOCK_SIZE); + buffer[i+j] = (self->IV[self->count+j] ^= str[i+j]); + } + self->count += len-i; + i = len; + continue; + } + + /* Use up the current keystream block */ + for(j=0; j<BLOCK_SIZE-self->count; j++) { + assert(i+j < len); + assert(self->count+j < BLOCK_SIZE); + buffer[i+j] = (self->IV[self->count+j] ^= str[i+j]); + } + i += BLOCK_SIZE-self->count; + self->count = BLOCK_SIZE; + + /* Generate a new keystream block */ + if (self->counter_shortcut) { + /* CTR mode shortcut: If we're using Util.Counter, + * bypass the normal Python function call mechanism + * and manipulate the counter directly. */ + + PCT_CounterObject *ctr = (PCT_CounterObject *)(self->counter); + if (ctr->carry && !ctr->allow_wraparound) { + Py_BLOCK_THREADS; + PyErr_SetString(PyExc_OverflowError, + "counter wrapped without allow_wraparound"); + free(buffer); + return NULL; + } + if (ctr->buf_size != BLOCK_SIZE) { + Py_BLOCK_THREADS; + PyErr_Format(PyExc_TypeError, + "CTR counter function returned " + "string of length %zi, not %i", + ctr->buf_size, BLOCK_SIZE); + free(buffer); + return NULL; + } + block_encrypt(&(self->st), + (unsigned char *)ctr->val, + self->IV); + ctr->inc_func(ctr); + } else { + PyObject *ctr; + Py_BLOCK_THREADS; + ctr = PyObject_CallObject(self->counter, NULL); + if (ctr == NULL) { + free(buffer); + return NULL; + } + if (!PyBytes_Check(ctr)) + { + PyErr_SetString(PyExc_TypeError, + "CTR counter function didn't return a bytestring"); + Py_DECREF(ctr); + free(buffer); + return NULL; + } + if (PyBytes_Size(ctr) != BLOCK_SIZE) { + PyErr_Format(PyExc_TypeError, + "CTR counter function returned " + "bytestring not of length %i", + BLOCK_SIZE); + Py_DECREF(ctr); + free(buffer); + return NULL; + } + Py_UNBLOCK_THREADS; + block_encrypt(&(self->st), (unsigned char *)PyBytes_AsString(ctr), + self->IV); + Py_BLOCK_THREADS; + Py_DECREF(ctr); + Py_UNBLOCK_THREADS; + } + + /* Move the pointer to the start of the keystream block */ + self->count = 0; + } + break; + + default: + Py_BLOCK_THREADS; + PyErr_Format(PyExc_SystemError, + "Unknown ciphertext feedback mode %i; " + "this shouldn't happen", + self->mode); + free(buffer); + return NULL; + } + Py_END_ALLOW_THREADS; + result=PyBytes_FromStringAndSize((char *) buffer, len); + free(buffer); + return(result); +} + +static char ALG_Decrypt__doc__[] = +"decrypt(string): Decrypt the provided string of binary data."; + + + + +static PyObject * +ALG_Decrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + unsigned char temp[BLOCK_SIZE]; + int i, j, len; + PyObject *result; + + /* CTR and OFB mode decryption is identical to encryption */ + if (self->mode == MODE_CTR || self->mode == MODE_OFB) + return ALG_Encrypt(self, args); + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len==0) /* Handle empty string */ + { + return PyBytes_FromStringAndSize(NULL, 0); + } + if ( (len % BLOCK_SIZE) !=0 && (self->mode!=MODE_CFB)) + { + PyErr_Format(PyExc_ValueError, + "Input strings must be " + "a multiple of %i in length", + BLOCK_SIZE); + return NULL; + } + if (self->mode == MODE_CFB && + (len % (self->segment_size/8) !=0)) { + PyErr_Format(PyExc_ValueError, + "Input strings must be a multiple of " + "the segment size %i in length", + self->segment_size/8); + return NULL; + } + buffer=malloc(len); + if (buffer==NULL) + { + PyErr_SetString(PyExc_MemoryError, + "No memory available in " _MODULE_STRING + " decrypt"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS; + switch(self->mode) + { + case(MODE_ECB): + for(i=0; i<len; i+=BLOCK_SIZE) + { + block_decrypt(&(self->st), str+i, buffer+i); + } + break; + + case(MODE_CBC): + for(i=0; i<len; i+=BLOCK_SIZE) + { + memcpy(self->oldCipher, self->IV, BLOCK_SIZE); + block_decrypt(&(self->st), str+i, temp); + for(j=0; j<BLOCK_SIZE; j++) + { + buffer[i+j]=temp[j]^self->IV[j]; + self->IV[j]=str[i+j]; + } + } + break; + + case(MODE_CFB): + for(i=0; i<len; i+=self->segment_size/8) + { + block_encrypt(&(self->st), self->IV, temp); + for (j=0; j<self->segment_size/8; j++) { + buffer[i+j] = str[i+j]^temp[j]; + } + if (self->segment_size == BLOCK_SIZE * 8) { + /* s == b: segment size is identical to + the algorithm block size */ + memcpy(self->IV, str + i, BLOCK_SIZE); + } + else if ((self->segment_size % 8) == 0) { + int sz = self->segment_size/8; + memmove(self->IV, self->IV + sz, + BLOCK_SIZE-sz); + memcpy(self->IV + BLOCK_SIZE - sz, str + i, + sz); + } + else { + /* segment_size is not a multiple of 8; + currently this can't happen */ + } + } + break; + + default: + Py_BLOCK_THREADS; + PyErr_Format(PyExc_SystemError, + "Unknown ciphertext feedback mode %i; " + "this shouldn't happen", + self->mode); + free(buffer); + return NULL; + } + Py_END_ALLOW_THREADS; + result=PyBytes_FromStringAndSize((char *) buffer, len); + free(buffer); + return(result); +} + +/* ALG object methods */ +static PyMethodDef ALGmethods[] = +{ + {"encrypt", (PyCFunction) ALG_Encrypt, METH_O, ALG_Encrypt__doc__}, + {"decrypt", (PyCFunction) ALG_Decrypt, METH_O, ALG_Decrypt__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static int +ALGsetattr(PyObject *ptr, char *name, PyObject *v) +{ + ALGobject *self=(ALGobject *)ptr; + if (strcmp(name, "IV") != 0) + { + PyErr_Format(PyExc_AttributeError, + "non-existent block cipher object attribute '%s'", + name); + return -1; + } + if (v==NULL) + { + PyErr_SetString(PyExc_AttributeError, + "Can't delete IV attribute of block cipher object"); + return -1; + } + if (!PyBytes_Check(v)) + { + PyErr_SetString(PyExc_TypeError, + "IV attribute of block cipher object must be bytestring"); + return -1; + } + if (PyBytes_Size(v)!=BLOCK_SIZE) + { + PyErr_Format(PyExc_ValueError, + _MODULE_STRING " IV must be %i bytes long", + BLOCK_SIZE); + return -1; + } + memcpy(self->IV, PyBytes_AsString(v), BLOCK_SIZE); + return 0; +} + +static PyObject * +ALGgetattro(PyObject *s, PyObject *attr) +{ + ALGobject *self = (ALGobject*)s; + + if (!PyString_Check(attr)) + goto generic; + + if (PyString_CompareWithASCIIString(attr, "IV") == 0) + { + return(PyBytes_FromStringAndSize((char *) self->IV, BLOCK_SIZE)); + } + if (PyString_CompareWithASCIIString(attr, "mode") == 0) + { + return(PyInt_FromLong((long)(self->mode))); + } + if (PyString_CompareWithASCIIString(attr, "block_size") == 0) + { + return PyInt_FromLong(BLOCK_SIZE); + } + if (PyString_CompareWithASCIIString(attr, "key_size") == 0) + { + return PyInt_FromLong(KEY_SIZE); + } + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr(s, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(ALGmethods, (PyObject *)self, PyString_AsString(attr)); +#endif +} + +/* List of functions defined in the module */ + +static struct PyMethodDef modulemethods[] = +{ + {"new", (PyCFunction) ALGnew, METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject ALGtype = +{ + PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + _MODULE_STRING, /*tp_name*/ + sizeof(ALGobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) ALGdealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + ALGsetattr, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc) 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence */ + 0, /*tp_as_mapping */ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + ALGgetattro, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + ALGmethods, /*tp_methods*/ +#endif +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "Crypto.Cipher." _MODULE_STRING, + NULL, + -1, + modulemethods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +/* Initialization function for the module */ +PyMODINIT_FUNC +_MODULE_NAME (void) +{ + PyObject *m = NULL; + PyObject *abiver = NULL; + PyObject *__all__ = NULL; + + if (PyType_Ready(&ALGtype) < 0) + goto errout; + + /* Create the module and add the functions */ +#ifdef IS_PY3K + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("Crypto.Cipher." _MODULE_STRING, modulemethods); +#endif + if (m == NULL) + goto errout; + + /* Add the type object to the module (using the name of the module itself), + * so that its methods docstrings are discoverable by introspection tools. */ + PyObject_SetAttrString(m, _MODULE_STRING, (PyObject *)&ALGtype); + + /* Add some symbolic constants to the module */ + PyModule_AddIntConstant(m, "MODE_ECB", MODE_ECB); + PyModule_AddIntConstant(m, "MODE_CBC", MODE_CBC); + PyModule_AddIntConstant(m, "MODE_CFB", MODE_CFB); + PyModule_AddIntConstant(m, "MODE_PGP", MODE_PGP); /** Vestigial **/ + PyModule_AddIntConstant(m, "MODE_OFB", MODE_OFB); + PyModule_AddIntConstant(m, "MODE_CTR", MODE_CTR); + PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); + PyModule_AddIntConstant(m, "key_size", KEY_SIZE); + + /* Import CounterBE and CounterLE from the _counter module */ + Py_CLEAR(_counter_module); + _counter_module = PyImport_ImportModule("Crypto.Util._counter"); + if (_counter_module == NULL) + goto errout; + PCT_CounterBEType = (PyTypeObject *)PyObject_GetAttrString(_counter_module, "CounterBE"); + PCT_CounterLEType = (PyTypeObject *)PyObject_GetAttrString(_counter_module, "CounterLE"); + + /* Simple ABI version check in case the user doesn't re-compile all of + * the modules during an upgrade. */ + abiver = PyObject_GetAttrString(_counter_module, "_PCT_CTR_ABI_VERSION"); + if (PCT_CounterBEType == NULL || PyType_Check((PyObject *)PCT_CounterBEType) < 0 || + PCT_CounterLEType == NULL || PyType_Check((PyObject *)PCT_CounterLEType) < 0 || + abiver == NULL || PyInt_CheckExact(abiver) < 0 || PyInt_AS_LONG(abiver) != PCT_CTR_ABI_VERSION) + { + PyErr_SetString(PyExc_ImportError, "Crypto.Util._counter ABI mismatch. Was PyCrypto incorrectly compiled?"); + goto errout; + } + + /* Create __all__ (to help generate documentation) */ + __all__ = PyList_New(10); + if (__all__ == NULL) + goto errout; + PyList_SetItem(__all__, 0, PyString_FromString(_MODULE_STRING)); /* This is the ALGType object */ + PyList_SetItem(__all__, 1, PyString_FromString("new")); + PyList_SetItem(__all__, 2, PyString_FromString("MODE_ECB")); + PyList_SetItem(__all__, 3, PyString_FromString("MODE_CBC")); + PyList_SetItem(__all__, 4, PyString_FromString("MODE_CFB")); + PyList_SetItem(__all__, 5, PyString_FromString("MODE_PGP")); + PyList_SetItem(__all__, 6, PyString_FromString("MODE_OFB")); + PyList_SetItem(__all__, 7, PyString_FromString("MODE_CTR")); + PyList_SetItem(__all__, 8, PyString_FromString("block_size")); + PyList_SetItem(__all__, 9, PyString_FromString("key_size")); + PyObject_SetAttrString(m, "__all__", __all__); + +out: + /* Final error check */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + Py_CLEAR(abiver); + Py_CLEAR(__all__); + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + Py_CLEAR(_counter_module); + Py_CLEAR(PCT_CounterBEType); + Py_CLEAR(PCT_CounterLEType); + goto out; +} +/* vim:set ts=4 sw=4 sts=0 noexpandtab: */ diff --git a/src/cast5.c b/src/cast5.c new file mode 100644 index 0000000..a86615e --- /dev/null +++ b/src/cast5.c @@ -0,0 +1,438 @@ +/* + These are the S-boxes for CAST5 as given in RFC 2144. +*/ + +#include "pycrypto_common.h" + +static const uint32 S1[256] = { +0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, +0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, +0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, +0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, +0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, +0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, +0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, +0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, +0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, +0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, +0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, +0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, +0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, +0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, +0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, +0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, +0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, +0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, +0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, +0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, +0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, +0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, +0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, +0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, +0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, +0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, +0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, +0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, +0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, +0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, +0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, +0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, +0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, +0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, +0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, +0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, +0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, +0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, +0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, +0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, +0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, +0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, +0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, +0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, +0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, +0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, +0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, +0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, +0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, +0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, +0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, +0x5c8165bf }; + +static const uint32 S2[256] = { +0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, +0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, +0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, +0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, +0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, +0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, +0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, +0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, +0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, +0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, +0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, +0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, +0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, +0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, +0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, +0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, +0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, +0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, +0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, +0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, +0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, +0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, +0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, +0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, +0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, +0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, +0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, +0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, +0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, +0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, +0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, +0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, +0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, +0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, +0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, +0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, +0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, +0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, +0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, +0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, +0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, +0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, +0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, +0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, +0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, +0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, +0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, +0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, +0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, +0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, +0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, +0x4523ecf1 }; + +static const uint32 S3[256] = { +0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, +0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, +0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, +0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, +0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, +0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, +0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, +0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, +0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, +0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, +0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, +0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, +0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, +0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, +0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, +0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, +0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, +0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, +0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, +0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, +0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, +0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, +0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, +0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, +0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, +0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, +0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, +0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, +0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, +0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, +0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, +0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, +0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, +0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, +0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, +0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, +0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, +0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, +0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, +0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, +0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, +0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, +0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, +0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, +0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, +0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, +0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, +0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, +0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, +0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, +0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, +0xee353783 }; + +static const uint32 S4[256] = { +0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, +0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, +0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, +0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, +0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, +0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, +0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, +0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, +0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, +0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, +0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, +0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, +0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, +0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, +0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, +0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, +0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, +0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, +0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, +0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, +0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, +0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, +0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, +0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, +0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, +0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, +0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, +0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, +0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, +0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, +0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, +0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, +0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, +0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, +0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, +0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, +0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, +0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, +0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, +0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, +0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, +0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, +0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, +0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, +0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, +0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, +0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, +0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, +0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, +0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, +0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, +0x0aef7ed2 }; + +static const uint32 S5[256] = { +0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, +0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, +0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, +0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, +0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, +0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, +0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, +0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, +0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, +0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, +0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, +0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, +0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, +0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, +0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, +0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, +0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, +0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, +0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, +0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, +0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, +0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, +0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, +0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, +0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, +0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, +0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, +0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, +0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, +0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, +0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, +0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, +0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, +0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, +0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, +0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, +0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, +0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, +0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, +0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, +0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, +0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, +0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, +0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, +0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, +0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, +0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, +0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, +0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, +0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, +0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, +0xefe9e7d4 }; + +static const uint32 S6[256] = { +0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, +0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, +0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, +0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, +0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, +0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, +0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, +0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, +0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, +0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, +0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, +0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, +0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, +0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, +0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, +0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, +0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, +0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, +0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, +0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, +0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, +0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, +0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, +0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, +0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, +0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, +0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, +0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, +0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, +0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, +0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, +0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, +0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, +0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, +0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, +0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, +0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, +0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, +0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, +0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, +0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, +0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, +0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, +0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, +0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, +0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, +0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, +0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, +0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, +0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, +0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, +0xd675cf2f }; + +static const uint32 S7[256] = { +0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, +0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, +0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, +0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, +0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, +0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, +0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, +0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, +0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, +0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, +0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, +0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, +0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, +0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, +0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, +0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, +0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, +0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, +0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, +0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, +0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, +0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, +0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, +0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, +0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, +0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, +0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, +0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, +0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, +0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, +0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, +0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, +0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, +0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, +0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, +0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, +0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, +0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, +0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, +0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, +0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, +0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, +0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, +0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, +0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, +0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, +0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, +0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, +0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, +0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, +0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, +0x954b8aa3 }; + +static const uint32 S8[256] = { +0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, +0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, +0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, +0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, +0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, +0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, +0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, +0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, +0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, +0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, +0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, +0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, +0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, +0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, +0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, +0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, +0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, +0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, +0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, +0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, +0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, +0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, +0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, +0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, +0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, +0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, +0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, +0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, +0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, +0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, +0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, +0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, +0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, +0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, +0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, +0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, +0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, +0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, +0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, +0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, +0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, +0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, +0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, +0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, +0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, +0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, +0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, +0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, +0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, +0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, +0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, +0xea8bf59e }; + diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..36278c1 --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,162 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `aligned_alloc' function. */ +#undef HAVE_ALIGNED_ALLOC + +/* Define to 1 if you have the <cpuid.h> header file. */ +#undef HAVE_CPUID_H + +/* Define to 1 if you have the declaration of `mpz_powm', and to 0 if you + don't. */ +#undef HAVE_DECL_MPZ_POWM + +/* Define to 1 if you have the declaration of `mpz_powm_sec', and to 0 if you + don't. */ +#undef HAVE_DECL_MPZ_POWM_SEC + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `gmp' library (-lgmp). */ +#undef HAVE_LIBGMP + +/* Define to 1 if you have the `mpir' library (-lmpir). */ +#undef HAVE_LIBMPIR + +/* Define to 1 if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define if CC supports -maes */ +#undef HAVE_MAES + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `posix_memalign' function. */ +#undef HAVE_POSIX_MEMALIGN + +/* Define to 1 if you have the <stddef.h> header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/inttypes.h> header file. */ +#undef HAVE_SYS_INTTYPES_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the <wchar.h> header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if you have the <wmmintrin.h> header file. */ +#undef HAVE_WMMINTRIN_H + +/* Define to 1 if you have the `_aligned_malloc' function. */ +#undef HAVE__ALIGNED_MALLOC + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>, + <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>, + <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>, + <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef int16_t + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to the type of a signed integer type of width exactly 8 bits if such + a type exists and the standard includes do not define it. */ +#undef int8_t + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +#undef size_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t diff --git a/src/cpuid.c b/src/cpuid.c new file mode 100644 index 0000000..46ece7d --- /dev/null +++ b/src/cpuid.c @@ -0,0 +1,116 @@ +/* + * cpuid.c: check CPU capabilities + * + * Written in 2013 by Sebastian Ramacher <sebastian@ramacher.at> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ +#include "Python.h" +#include <stdint.h> +#include "config.h" + +#ifdef HAVE_CPUID_H +#include <cpuid.h> + +/* it's bit_AES with gcc */ +#ifndef bit_AES +/* but some versions of clang provide bit_AESNI instead */ +#ifdef bit_AESNI +#define bit_AES bit_AESNI +/* and others do not provide any define at all */ +#else +#define bit_AES 0x02000000 +#endif +#endif + +#endif + +#include "pycrypto_compat.h" + +/* + * The have_aes_ni Python function + */ + +static char have_aes_ni__doc__[] = +"have_aes_ni() -> bool\n" +"\n" +"Return whether AES-NI instructions are available.\n"; + +static PyObject * +have_aes_ni(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + +#ifndef HAVE_CPUID_H + Py_INCREF(Py_False); + return Py_False; +#else + uint32_t eax, ebx, ecx, edx; + /* call cpuid to check if AES-NI instructions are available */ + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + if (ecx & bit_AES) { + Py_INCREF(Py_True); + return Py_True; + } + } + Py_INCREF(Py_False); + return Py_False; +#endif +} + +/* + * Module-level method table and module initialization function + */ + +static PyMethodDef cpuid_methods[] = { + {"have_aes_ni", have_aes_ni, METH_VARARGS, have_aes_ni__doc__}, + {NULL, NULL, 0, NULL} /* end-of-list sentinel value */ +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "cpuid", + NULL, + -1, + cpuid_methods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +PyMODINIT_FUNC +#ifdef IS_PY3K +PyInit_cpuid(void) +#else +initcpuid(void) +#endif +{ + /* Initialize the module */ +#ifdef IS_PY3K + return PyModule_Create(&moduledef); +#else + Py_InitModule("cpuid", cpuid_methods); +#endif +} + +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/galois.c b/src/galois.c new file mode 100644 index 0000000..2660044 --- /dev/null +++ b/src/galois.c @@ -0,0 +1,426 @@ +/* + * galois.c: arithmetic in Galois Fields + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +#include "pycrypto_common.h" +#include <stddef.h> +#include <assert.h> +#include <string.h> + +/** Type for tables containing the expanded hash key **/ +typedef uint64_t t_key_tables[16][256][2]; + +typedef uint64_t t_v_tables[128][2]; + +/** + * Big Endian to word conversions + */ +static uint64_t be_to_word(const uint8_t fb[8]) +{ + uint64_t tmp; + int i; + tmp = 0; + for (i=0; i<8; i++) + tmp = tmp<<8 ^ *fb++; + return tmp; +} + +/** + * Word to Big Endian conversions + */ +static void word_to_be(uint8_t fb[8], uint64_t w) +{ + int i; + for (i=0; i<8; i++) { + fb[7-i] = (uint8_t) w; + w >>= 8; + } +} + +/** + * Compute H*x^i for i=0..127. Store the results in a new + * vector indexed by i. + */ +static const t_v_tables* make_v_tables(const uint8_t y[16]) +{ + t_v_tables *tables; + uint64_t *cur; + int i; + + tables = (t_v_tables*) calloc(128*2, sizeof(uint64_t)); + if (!tables) { + return NULL; + } + + cur = &((*tables)[0][0]); + + cur[0] = be_to_word(&y[0]); + cur[1] = be_to_word(&y[8]); + + for (i=1; i<128; i++) { + uint64_t c; + uint64_t *next; + + next = &((*tables)[i][0]); + + /** v = (v&1)*0xE1000000000000000000000000000000L ^ (v>>1) **/ + c = cur[1]&1 ? 0xE100000000000000 : 0; + next[1] = cur[1]>>1 | cur[0]<<63; + next[0] = cur[0]>>1 ^ c; + + cur = next; + } + + return (const t_v_tables*)tables; +} + +/** + * Multiply to elements of GF(2**128) using the reducing polynomial + * (x^128 + x^7 + x^2 + x + 1). + */ +static void gcm_mult(uint8_t out[16], const uint8_t x[16], const uint8_t y[16]) +{ + uint64_t z[2], v[2]; + int i; + + /** z, v = 0, y **/ + z[0] = z[1] = 0; + v[0] = be_to_word(&y[0]); + v[1] = be_to_word(&y[8]); + + for (i=0; i<16; i++) { + uint8_t j; + + for (j=0x80; j>0; j>>=1) { + uint64_t c; + + /** z ^= (x>>i&1)*v **/ + if (x[i] & j) { + + z[0] ^= v[0]; + z[1] ^= v[1]; + } + /** v = (v&1)*0xE1000000000000000000000000000000L ^ (v>>1) **/ + c = v[1]&1 ? 0xE100000000000000 : 0; + v[1] = v[1]>>1 | (v[0] << 63); + v[0] = v[0]>>1 ^ c; + } + } + word_to_be(out, z[0]); + word_to_be(out+8, z[1]); +} + +/** + * Multiply two elements of GF(2**128) using the reducing polynomial + * (x^128 + x^7 + x^2 + x + 1). + * + * The first element has been expanded into H tables. + */ +static void gcm_mult2(uint8_t out[16], const t_key_tables *key_tables, const uint8_t x[16]) +{ + int i; + uint64_t z[2]; + + z[0] = z[1] = 0; + for (i=0; i<16; i++) { + z[0] ^= (*key_tables)[i][x[i]][0]; + z[1] ^= (*key_tables)[i][x[i]][1]; + } + word_to_be(out, z[0]); + word_to_be(out+8, z[1]); +} + +/** + * Multiply two elements of GF(2**128) using the reducing polynomial + * (x^128 + x^7 + x^2 + x + 1). + * + * In first element, only the byte at position 'pos' is non-zero at has + * value 'x'. + * + * The second element, is expanded in V tables (128 elements, one per + * each bit position). + */ +static void gcm_mult3(uint64_t out[2], uint8_t x, uint8_t pos, const t_v_tables *v_tables) +{ + uint64_t z[2]; + int j; + const uint64_t (*v)[2]; + + /** z, v = 0, y **/ + z[0] = z[1] = 0; + + v = &((*v_tables)[pos*8]); + for (j=0x80; j!=0; j>>=1, v++) { + if (x & j) { + z[0] ^= (*v)[0]; + z[1] ^= (*v)[1]; + } + } + out[0] = z[0]; + out[1] = z[1]; +} + +/** + * Expand a hash key into a set of tables that will speed + * up GHASH. + * + * \param tables Pointer to allocated memory that will hold + * the tables. + * \param h The hash key. + */ +static int ghash_expand(t_key_tables *key_tables, const uint8_t h[16]) +{ + int i; + const t_v_tables *v_tables; + + v_tables = make_v_tables(h); + if (v_tables==NULL) { + return -1; + } + + for (i=0; i<16; i++) { + int j; + + for (j=0; j<256; j++) { + /** Z = H*j*P^{8i} **/ + gcm_mult3(&((*key_tables)[i][j][0]), j, i, v_tables); + } + } + + free(v_tables); + return 0; +} + +/** + * Compute the GHASH of a piece of an arbitrary data given an + * arbitrary Y_0, as specified in NIST SP 800 38D. + * + * \param y_out The resulting GHASH (16 bytes). + * \param block_data Pointer to the data to hash. + * \param len Length of the data to hash (multiple of 16). + * \param y_in The initial Y (Y_0, 16 bytes). + * \param key_tables The hash key, possibly expanded to 16*256*16 bytes. + * \param key_tables_len The length of the data pointed by key_table. + */ +static void ghash( + uint8_t y_out[16], + const uint8_t block_data[], + int len, + const uint8_t y_in[16], + const void *key_tables, + int key_tables_len + ) +{ + int i, j; + uint8_t x[16]; + const t_key_tables *key_tables_64 = NULL; + const uint8_t (*key)[16] = NULL; + + switch (key_tables_len) { + case sizeof(t_key_tables): + { + key_tables_64 = (const t_key_tables*) key_tables; + break; + } + case 16: + { + key = (const uint8_t (*)[16]) key_tables; + break; + } + default: + return; + } + + memcpy(y_out, y_in, 16); + + if (key_tables_64) { + for (i=0; i<len; i+=16) { + for (j=0; j<16; j++) { + x[j] = y_out[j] ^ block_data[i+j]; + } + gcm_mult2(y_out, key_tables_64, x); + } + } else { + for (i=0; i<len; i+=16) { + for (j=0; j<16; j++) { + x[j] = y_out[j] ^ block_data[i+j]; + } + gcm_mult(y_out, *key, x); + } + } +} + +static char ghash_expand__doc__[] = +"_ghash_expand(h:str) -> str\n" +"\n" +"Return an expanded hash key for GHASH.\n"; + +static PyObject * +ghash_expand_function(PyObject *self, PyObject *args) +{ + PyObject *h; + PyObject *retval = NULL; + Py_ssize_t len_h; + int err; + + if (!PyArg_ParseTuple(args, "S", &h)) { + goto out; + } + + len_h = PyBytes_GET_SIZE(h); + + if (len_h!=16) { + PyErr_SetString(PyExc_ValueError, "Length of h must be 16 bytes."); + goto out; + } + + /* Create return string */ + retval = PyBytes_FromStringAndSize(NULL, sizeof(t_key_tables)); + if (!retval) { + goto out; + } + + Py_BEGIN_ALLOW_THREADS; + + err = ghash_expand( + (t_key_tables*)PyBytes_AS_STRING(retval), + (uint8_t*)PyBytes_AS_STRING(h) + ); + + Py_END_ALLOW_THREADS; + + if (err!=0) { + Py_DECREF(retval); + retval = NULL; + } + +out: + return retval; +} + + +static char ghash__doc__[] = +"_ghash(data:str, y:str, exp_h:str) -> str\n" +"\n" +"Return a GHASH.\n"; + +static PyObject * +ghash_function(PyObject *self, PyObject *args) +{ + PyObject *data, *y, *exp_h; + PyObject *retval = NULL; + Py_ssize_t len_data, len_y, len_exp_h; + + if (!PyArg_ParseTuple(args, "SSS", &data, &y, &exp_h)) { + goto out; + } + + len_data = PyBytes_GET_SIZE(data); + len_y = PyBytes_GET_SIZE(y); + len_exp_h = PyBytes_GET_SIZE(exp_h); + + if (len_data%16!=0) { + PyErr_SetString(PyExc_ValueError, "Length of data must be a multiple of 16 bytes."); + goto out; + } + + if (len_y!=16) { + PyErr_SetString(PyExc_ValueError, "Length of y must be 16 bytes."); + goto out; + } + + if (len_exp_h!=sizeof(t_key_tables) && len_exp_h!=16) { + PyErr_SetString(PyExc_ValueError, "Length of expanded key is incorrect."); + goto out; + } + + /* Create return string */ + retval = PyBytes_FromStringAndSize(NULL, 16); + if (!retval) { + goto out; + } + + Py_BEGIN_ALLOW_THREADS; + +#define PyBytes_Buffer(a) (uint8_t*)PyBytes_AS_STRING(a) + + ghash( PyBytes_Buffer(retval), PyBytes_Buffer(data), len_data, + PyBytes_Buffer(y), + PyBytes_Buffer(exp_h), len_exp_h ); + +#undef PyBytes_Buffer + + Py_END_ALLOW_THREADS; + +out: + return retval; +} + +/* + * Module-level method table and module initialization function + */ + +static PyMethodDef galois_methods[] = { + {"_ghash_expand", ghash_expand_function, METH_VARARGS, ghash_expand__doc__}, + {"_ghash", ghash_function, METH_VARARGS, ghash__doc__}, + {NULL, NULL, 0, NULL} /* end-of-list sentinel value */ +}; + +#ifdef IS_PY3K + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "galois", + NULL, + -1, + galois_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit_galois(void) +{ + PyObject *m; + + /* Initialize the module */ + m = PyModule_Create(&moduledef); + if (m == NULL) + return NULL; + return m; +} + +#else + +PyMODINIT_FUNC +initgalois(void) +{ + PyObject *m; + + /* Initialize the module */ + m = Py_InitModule("galois", galois_methods); + if (m == NULL) + return; +} + +#endif diff --git a/src/hash_SHA2.h b/src/hash_SHA2.h new file mode 100644 index 0000000..a3b633d --- /dev/null +++ b/src/hash_SHA2.h @@ -0,0 +1,94 @@ +/* + * An generic header for the SHA-2 hash family. + * + * Written in 2010 by Lorenz Quack <don@amberfisharts.com> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#ifndef __HASH_SHA2_H +#define __HASH_SHA2_H + +#include "pycrypto_common.h" + +/* check if implementation set the correct macros */ +#ifndef MODULE_NAME +#error SHA2 Implementation must define MODULE_NAME before including this header +#endif + +#ifndef DIGEST_SIZE +#error SHA2 Implementation must define DIGEST_SIZE before including this header +#else +#define DIGEST_SIZE_BITS (DIGEST_SIZE*8) +#endif + +#ifndef BLOCK_SIZE +#error SHA2 Implementation must define BLOCK_SIZE before including this header +#else +#define BLOCK_SIZE_BITS (BLOCK_SIZE*8) +#endif + +#ifndef WORD_SIZE +#error SHA2 Implementation must define WORD_SIZE before including this header +#else +#if ((WORD_SIZE != 4) && (WORD_SIZE != 8)) +#error WORD_SIZE must be either 4 or 8 +#else +#define WORD_SIZE_BITS (WORD_SIZE*8) +#endif +#endif + +#ifndef SCHEDULE_SIZE +#error SHA2 Implementation must define SCHEDULE_SIZE before including this header +#endif + +/* define some helper macros */ +#define PADDING_SIZE (2 * WORD_SIZE) +#define LAST_BLOCK_SIZE (BLOCK_SIZE - PADDING_SIZE) + +/* define generic SHA-2 family functions */ +#define Ch(x,y,z) ((x & y) ^ (~x & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define ROTR(x, n) (((x)>>((n)&(WORD_SIZE_BITS-1)))|((x)<<(WORD_SIZE_BITS-((n)&(WORD_SIZE_BITS-1))))) +#define SHR(x, n) ((x)>>(n)) + +/* define fixed size types */ +typedef uint8_t U8; +typedef uint32_t U32; +typedef uint64_t U64; + +/* typedef a sha2_word_t type of appropriate size */ +#if (WORD_SIZE_BITS == 64) +typedef U64 sha2_word_t; +#elif (WORD_SIZE_BITS == 32) +typedef U32 sha2_word_t; +#else +#error According to the FIPS Standard WORD_SIZE_BITS must be either 32 or 64 +#endif + +/* define the hash_state structure */ +typedef struct{ + sha2_word_t state[8]; + int curlen; + sha2_word_t length_upper, length_lower; + unsigned char buf[BLOCK_SIZE]; +} hash_state; + +#endif /* __HASH_SHA2_H */ diff --git a/src/hash_SHA2_template.c b/src/hash_SHA2_template.c new file mode 100644 index 0000000..c7b8a13 --- /dev/null +++ b/src/hash_SHA2_template.c @@ -0,0 +1,198 @@ +/* + * An generic implementation of the SHA-2 hash family, this is endian neutral + * so should work just about anywhere. + * + * This code works much like the MD5 code provided by RSA. You sha_init() + * a "sha_state" then sha_process() the bytes you want and sha_done() to get + * the output. + * + * Originally written by Tom St Denis -- http://tomstdenis.home.dhs.org + * Adapted for PyCrypto by Jeethu Rao, Taylor Boon, and others. + * Turned into a generic template by Lorenz Quack <don@amberfisharts.com> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + * + */ + +#include "pycrypto_common.h" + +/* compress one block */ +static void sha_compress(hash_state * hs) +{ + sha2_word_t S[8], W[SCHEDULE_SIZE], T1, T2; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) + S[i] = hs->state[i]; + + /* copy the state into W[0..15] */ + for (i = 0; i < 16; i++){ + W[i] = ( + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+0]) << (WORD_SIZE_BITS- 8)) | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+1]) << (WORD_SIZE_BITS-16)) | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+2]) << (WORD_SIZE_BITS-24)) | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+3]) << (WORD_SIZE_BITS-32)) +#if (WORD_SIZE_BITS == 64) + | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+4]) << (WORD_SIZE_BITS-40)) | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+5]) << (WORD_SIZE_BITS-48)) | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+6]) << (WORD_SIZE_BITS-56)) | + (((sha2_word_t) hs->buf[(WORD_SIZE*i)+7])) +#endif + ); + } + + /* fill W[16..SCHEDULE_SIZE] */ + for (i = 16; i < SCHEDULE_SIZE; i++) + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + + /* Compress */ + for (i = 0; i < SCHEDULE_SIZE; i++) { + T1 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + T2 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + T1; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = T1 + T2; + } + + /* feedback */ + for (i = 0; i < 8; i++) + hs->state[i] += S[i]; +} + +/* adds *inc* to the length of the hash_state *hs* + * return 1 on success + * return 0 if the length overflows + */ +static int add_length(hash_state *hs, sha2_word_t inc) { + sha2_word_t overflow_detector; + overflow_detector = hs->length_lower; + hs->length_lower += inc; + if (overflow_detector > hs->length_lower) { + overflow_detector = hs->length_upper; + hs->length_upper++; + if (hs->length_upper > hs->length_upper) + return 0; + } + return 1; +} + +/* init the SHA state */ +static void sha_init(hash_state * hs) +{ + int i; + hs->curlen = hs->length_upper = hs->length_lower = 0; + for (i = 0; i < 8; ++i) + hs->state[i] = H[i]; +} + +static void sha_process(hash_state * hs, unsigned char *buf, int len) +{ + while (len--) { + /* copy byte */ + hs->buf[hs->curlen++] = *buf++; + + /* is a block full? */ + if (hs->curlen == BLOCK_SIZE) { + sha_compress(hs); + add_length(hs, BLOCK_SIZE_BITS); + hs->curlen = 0; + } + } +} + +static void sha_done(hash_state * hs, unsigned char *hash) +{ + int i; + + /* increase the length of the message */ + add_length(hs, hs->curlen * 8); + + /* append the '1' bit */ + hs->buf[hs->curlen++] = 0x80; + + /* if the length is currently above LAST_BLOCK_SIZE bytes we append + * zeros then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (hs->curlen > LAST_BLOCK_SIZE) { + for (; hs->curlen < BLOCK_SIZE;) + hs->buf[hs->curlen++] = 0; + sha_compress(hs); + hs->curlen = 0; + } + + /* pad upto LAST_BLOCK_SIZE bytes of zeroes */ + for (; hs->curlen < LAST_BLOCK_SIZE;) + hs->buf[hs->curlen++] = 0; + + /* append length */ + for (i = 0; i < WORD_SIZE; i++) + hs->buf[i + LAST_BLOCK_SIZE] = + (hs->length_upper >> ((WORD_SIZE - 1 - i) * 8)) & 0xFF; + for (i = 0; i < WORD_SIZE; i++) + hs->buf[i + LAST_BLOCK_SIZE + WORD_SIZE] = + (hs->length_lower >> ((WORD_SIZE - 1 - i) * 8)) & 0xFF; + sha_compress(hs); + + /* copy output */ + for (i = 0; i < DIGEST_SIZE; i++) + hash[i] = (hs->state[i / WORD_SIZE] >> + ((WORD_SIZE - 1 - (i % WORD_SIZE)) * 8)) & 0xFF; +} + +// Done +static void hash_init (hash_state *ptr) +{ + sha_init(ptr); +} + +// Done +static void +hash_update (hash_state *self, const U8 *buf, int len) +{ + sha_process(self,(unsigned char *)buf, len); +} + +// Done +static void +hash_copy(hash_state *src, hash_state *dest) +{ + memcpy(dest,src,sizeof(hash_state)); +} + +// Done +static PyObject * +hash_digest (const hash_state *self) +{ + unsigned char digest[DIGEST_SIZE]; + hash_state temp; + + hash_copy((hash_state*)self,&temp); + sha_done(&temp,digest); + return PyBytes_FromStringAndSize((char *)digest, DIGEST_SIZE); +} + +#include "hash_template.c" diff --git a/src/hash_template.c b/src/hash_template.c new file mode 100644 index 0000000..fa5a1b6 --- /dev/null +++ b/src/hash_template.c @@ -0,0 +1,401 @@ +/* + * hash_template.c : Generic framework for hash function extension modules + * + * Written by Andrew Kuchling and others + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +/* Basic object type */ + +#include "pycrypto_common.h" +#include <string.h> + +#define _STR(x) #x +#define _XSTR(x) _STR(x) +#define _PASTE(x,y) x##y +#define _PASTE2(x,y) _PASTE(x,y) +#ifdef IS_PY3K +#define _MODULE_NAME _PASTE2(PyInit_,MODULE_NAME) +#else +#define _MODULE_NAME _PASTE2(init,MODULE_NAME) +#endif +#define _MODULE_STRING _XSTR(MODULE_NAME) + +typedef struct { + PyObject_HEAD + hash_state st; +} ALGobject; + +/* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C. + * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize + */ +staticforward PyTypeObject ALGtype; + +static char ALG__doc__[] = +"Class that implements a " _MODULE_STRING " hash."; + +static ALGobject * +newALGobject(void) +{ + ALGobject *new; + + new = PyObject_New(ALGobject, &ALGtype); + return new; +} + +/* Internal methods for a hashing object */ + +static void +ALG_dealloc(PyObject *ptr) +{ + ALGobject *self = (ALGobject *)ptr; + + /* Overwrite the contents of the object */ + memset((char*)&(self->st), 0, sizeof(hash_state)); + PyObject_Del(ptr); +} + + +/* External methods for a hashing object */ + +static char ALG_copy__doc__[] = +"copy()\n" +"Return a copy (\"clone\") of the hash object.\n" +"\n" +"The copy will have the same internal state as the original hash\n" +"object.\n" +"This can be used to efficiently compute the digests of strings that\n" +"share a common initial substring.\n" +"\n" +":Return: A hash object of the same type\n"; + +static PyObject * +ALG_copy(ALGobject *self, PyObject *args) +{ + ALGobject *newobj; + + if (!PyArg_ParseTuple(args, "")) { + return NULL; + } + + if ( (newobj = newALGobject())==NULL) + return NULL; + + hash_copy(&(self->st), &(newobj->st)); + return((PyObject *)newobj); +} + +static char ALG_digest__doc__[] = +"digest()\n" +"Return the **binary** (non-printable) digest of the message that has been hashed so far.\n" +"\n" +"This method does not change the state of the hash object.\n" +"You can continue updating the object after calling this function.\n" +"\n" +":Return: A byte string of `digest_size` bytes. It may contain non-ASCII\n" +"characters, including null bytes.\n"; + +static PyObject * +ALG_digest(ALGobject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + return (PyObject *)hash_digest(&(self->st)); +} + +static char ALG_hexdigest__doc__[] = +"hexdigest()\n" +"Return the **printable** digest of the message that has been hashed so far.\n" +"\n" +"This method does not change the state of the hash object.\n" +"\n" +":Return: A string of 2* `digest_size` characters. It contains only\n" +"hexadecimal ASCII digits.\n"; + +static PyObject * +ALG_hexdigest(ALGobject *self, PyObject *args) +{ + PyObject *value, *retval; + unsigned char *raw_digest, *hex_digest; + int i, j, size; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + + /* Get the raw (binary) digest value */ + value = (PyObject *)hash_digest(&(self->st)); + size = PyBytes_Size(value); + raw_digest = (unsigned char *) PyBytes_AsString(value); + + /* Create a new string */ + retval = PyBytes_FromStringAndSize(NULL, size * 2 ); + hex_digest = (unsigned char *) PyBytes_AsString(retval); + + /* Make hex version of the digest */ + for(i=j=0; i<size; i++) + { + char c; + c = raw_digest[i] / 16; c = (c>9) ? c+'a'-10 : c + '0'; + hex_digest[j++] = c; + c = raw_digest[i] % 16; c = (c>9) ? c+'a'-10 : c + '0'; + hex_digest[j++] = c; + } +#ifdef IS_PY3K + /* Create a text string return value */ + retval = PyUnicode_FromEncodedObject(retval,"latin-1","strict"); +#endif + + Py_DECREF(value); + return retval; +} + +static char ALG_update__doc__[] = +"update(data)\n" +"Continue hashing of a message by consuming the next chunk of data.\n" +"\n" +"Repeated calls are equivalent to a single call with the concatenation\n" +"of all the arguments. In other words:\n" +"\n" +" >>> m.update(a); m.update(b)\n" +"\n" +"is equivalent to:\n" +"\n" +" >>> m.update(a+b)\n" +"\n" +":Parameters:\n" +" data : byte string\n" +" The next chunk of the message being hashed.\n"; + +static PyObject * +ALG_update(ALGobject *self, PyObject *args) +{ + unsigned char *cp; + int len; + + if (!PyArg_ParseTuple(args, "s#", &cp, &len)) + return NULL; + + Py_BEGIN_ALLOW_THREADS; + + hash_update(&(self->st), cp, len); + Py_END_ALLOW_THREADS; + + Py_INCREF(Py_None); + + return Py_None; +} + +/** Forward declaration for this module's new() method **/ +static char ALG_new__doc__[] = +"new(data=None)\n" +"Return a fresh instance of the hash object.\n" +"\n" +":Parameters:\n" +" data : byte string\n" +" The very first chunk of the message to hash.\n" +" It is equivalent to an early call to `" _MODULE_STRING ".update()`.\n" +" Optional.\n" +"\n" +":Return: A `" _MODULE_STRING "` object\n"; + +static PyObject *ALG_new(PyObject*, PyObject*); + +static PyMethodDef ALG_methods[] = { + {"copy", (PyCFunction)ALG_copy, METH_VARARGS, ALG_copy__doc__}, + {"digest", (PyCFunction)ALG_digest, METH_VARARGS, ALG_digest__doc__}, + {"hexdigest", (PyCFunction)ALG_hexdigest, METH_VARARGS, ALG_hexdigest__doc__}, + {"update", (PyCFunction)ALG_update, METH_VARARGS, ALG_update__doc__}, + {"new", (PyCFunction)ALG_new, METH_VARARGS, ALG_new__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +ALG_getattro(PyObject *self, PyObject *attr) +{ + if (!PyString_Check(attr)) + goto generic; + + if (PyString_CompareWithASCIIString(attr, "digest_size")==0) + return PyInt_FromLong(DIGEST_SIZE); + if (PyString_CompareWithASCIIString(attr, "name")==0) + return PyString_FromString(_MODULE_STRING); /* we should try to be compatible with hashlib here */ + + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr(self, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(ALG_methods, (PyObject *)self, PyString_AsString(attr)); +#endif +} + +static PyTypeObject ALGtype = { + PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + _MODULE_STRING, /*tp_name*/ + sizeof(ALGobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) ALG_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence */ + 0, /*tp_as_mapping */ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + ALG_getattro, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + ALG__doc__, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + ALG_methods, /*tp_methods*/ +#endif + }; + +/* The single module-level function: new() */ + +/** This method belong to both the module and the hash object **/ +static PyObject * +ALG_new(PyObject *self, PyObject *args) +{ + ALGobject *new; + unsigned char *cp = NULL; + int len; + + if ((new = newALGobject()) == NULL) + return NULL; + + if (!PyArg_ParseTuple(args, "|s#", + &cp, &len)) { + Py_DECREF(new); + return NULL; + } + + hash_init(&(new->st)); + + if (PyErr_Occurred()) { + Py_DECREF(new); + return NULL; + } + if (cp) { + Py_BEGIN_ALLOW_THREADS; + hash_update(&(new->st), cp, len); + Py_END_ALLOW_THREADS; + } + + return (PyObject *)new; +} + +/* List of functions exported by this module */ + +static struct PyMethodDef ALG_functions[] = { + {"new", (PyCFunction)ALG_new, METH_VARARGS, ALG_new__doc__}, + {NULL, NULL} /* Sentinel */ +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "Crypto.Hash." _MODULE_STRING, /* m_name */ + MODULE__doc__, /* m_doc */ + -1, /* m_size */ + ALG_functions, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif + +/* Initialize this module. */ + +PyMODINIT_FUNC +_MODULE_NAME (void) +{ + PyObject *m = NULL; + PyObject *__all__ = NULL; + + if (PyType_Ready(&ALGtype) < 0) + goto errout; + + /* Create the module and add the functions */ +#ifdef IS_PY3K + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("Crypto.Hash." _MODULE_STRING, ALG_functions, MODULE__doc__); +#endif + if (m == NULL) + goto errout; + + /* Add the type object to the module (using the name of the module itself), + * so that its methods docstrings are discoverable by introspection tools. */ + PyObject_SetAttrString(m, _MODULE_STRING, (PyObject *)&ALGtype); + + /* Add some symbolic constants to the module */ + PyModule_AddIntConstant(m, "digest_size", DIGEST_SIZE); + PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); + + /* Create __all__ (to help generate documentation) */ + __all__ = PyList_New(4); + if (__all__ == NULL) + goto errout; + PyList_SetItem(__all__, 0, PyString_FromString(_MODULE_STRING)); /* This is the ALGType object */ + PyList_SetItem(__all__, 1, PyString_FromString("new")); + PyList_SetItem(__all__, 2, PyString_FromString("digest_size")); + PyList_SetItem(__all__, 3, PyString_FromString("block_size")); + PyObject_SetAttrString(m, "__all__", __all__); + +out: + /* Final error check, then return */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + Py_CLEAR(__all__); + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + goto out; +} diff --git a/src/inc-msvc/config.h b/src/inc-msvc/config.h new file mode 100644 index 0000000..2485df9 --- /dev/null +++ b/src/inc-msvc/config.h @@ -0,0 +1,23 @@ +/* Define to 1 if you have the declaration of `mpz_powm', and to 0 if you + don't. */ +#undef HAVE_DECL_MPZ_POWM + +/* Define to 1 if you have the declaration of `mpz_powm_sec', and to 0 if you + don't. */ +#undef HAVE_DECL_MPZ_POWM_SEC + +/* Define to 1 if you have the `gmp' library (-lgmp). */ +#undef HAVE_LIBGMP + +/* Define to 1 if you have the `mpir' library (-lmpir). */ +#undef HAVE_LIBMPIR + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to `__inline__' or `__inline' if that's what the C compiler + * calls it, or to nothing if 'inline' is not supported under any name. */ +#define inline __inline diff --git a/src/inc-msvc/stdint.h b/src/inc-msvc/stdint.h new file mode 100644 index 0000000..f4a8eb7 --- /dev/null +++ b/src/inc-msvc/stdint.h @@ -0,0 +1,42 @@ +/* + * inc-msvc/stdint.h: Partial stdint.h for MSVC compiler + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ +#ifndef PYCRYPTO_MSVC_STDINT_H +#define PYCRYPTO_MSVC_STDINT_H + +typedef signed __int8 int8_t; +typedef signed __int16 int16_t; +typedef signed __int32 int32_t; +typedef signed __int64 int64_t; + +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +#ifndef inline +# define inline __inline +#endif /* inline */ + +#endif /* PYCRYPTO_MSVC_STDINT_H */ +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/pycrypto_common.h b/src/pycrypto_common.h new file mode 100644 index 0000000..3182ec1 --- /dev/null +++ b/src/pycrypto_common.h @@ -0,0 +1,41 @@ +/* + * pycrypto_compat.h: Common header file for PyCrypto + * + * Written in 2013 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ +#ifndef PYCRYPTO_COMMON_H +#define PYCRYPTO_COMMON_H + +#include "Python.h" +#include "pycrypto_compat.h" +#include "config.h" +#if HAVE_STDINT_H +# include <stdint.h> +#elif HAVE_INTTYPES_H +# include <inttypes.h> +#elif HAVE_SYS_INTTYPES_H +# include <sys/inttypes.h> +#else +# error "stdint.h and inttypes.h not found" +#endif + + +#endif /* PYCRYPTO_COMMON_H */ diff --git a/src/pycrypto_compat.h b/src/pycrypto_compat.h new file mode 100644 index 0000000..3f890b4 --- /dev/null +++ b/src/pycrypto_compat.h @@ -0,0 +1,107 @@ +/* + * pycrypto_compat.h: Compatibility with older versions of Python + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ +#ifndef PYCRYPTO_COMPAT_H +#define PYCRYPTO_COMPAT_H +#include "Python.h" + +/* + * Python 3.x defines, for conditional compiles + */ + +#if PY_MAJOR_VERSION >= 3 +# define IS_PY3K +# define PyInt_AS_LONG PyLong_AS_LONG +# define PyInt_CheckExact PyLong_CheckExact +# define PyInt_FromLong PyLong_FromLong +# define PyString_Check PyUnicode_Check +# define PyString_CompareWithASCIIString PyUnicode_CompareWithASCIIString +# define PyString_FromString PyUnicode_FromString +# define staticforward static +#else +# define PyBytes_GET_SIZE PyString_GET_SIZE +# define PyBytes_FromStringAndSize PyString_FromStringAndSize +# define PyBytes_AS_STRING PyString_AS_STRING +# define PyBytes_Check PyString_Check +# define PyBytes_Size PyString_Size +# define PyBytes_AsString PyString_AsString +# define PyBytesObject PyStringObject +# define PyString_CompareWithASCIIString(o,s) \ + (PyString_Check(o) ? strcmp(PyString_AsString(o),(s)) : -1) /* NB: only compares up to the first NUL byte */ +# if PY_MINOR_VERSION <= 5 /* Python 2.5 and earlier */ +# define Py_TYPE(v) ((v)->ob_type) +# define PyLong_MASK MASK +# define PyLong_SHIFT SHIFT +# define PyVarObject_HEAD_INIT(a,b) PyObject_HEAD_INIT(a) 0, +# endif +# if PY_MINOR_VERSION <= 1 /* Python 2.1 only */ +# define METH_O METH_OLDARGS /* METH_O is a subset of what METH_OLDARGS provides */ +# define PyInt_CheckExact PyInt_Check +# define PyString_CheckExact PyString_Check +# define PyType_Ready(t) (((t)->ob_type = &PyType_Type) ? 0 : 0) +# endif +#endif + +/* Python 2.1 doesn't have PyModule_AddIntConstant */ +#if PYTHON_API_VERSION < 1011 +#define PyModule_AddIntConstant(m,n,v) \ + do { \ + PyObject *o=PyInt_FromLong(v); \ + if (o!=NULL) { \ + PyObject_SetAttrString((m),(n),o); \ + Py_DECREF(o); \ + } \ + } while(0) +#endif + +/* + * Py_CLEAR for Python < 2.4 + * See http://docs.python.org/api/countingRefs.html + */ +#if PY_VERSION_HEX < 0x02040000 && !defined(Py_CLEAR) +#define Py_CLEAR(obj) \ + do {\ + PyObject *tmp = (PyObject *)(obj);\ + (obj) = NULL;\ + Py_XDECREF(tmp);\ + } while(0) +#endif + +/* + * Compatibility code for Python < 2.5 (see PEP 353) + * PEP 353 has been placed into the public domain, so we can use this code + * without restriction. + */ +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + +/* Compatibility code for Python < 2.3 */ +#if PY_VERSION_HEX < 0x02030000 +typedef void PyMODINIT_FUNC; +#endif + +#endif /* PYCRYPTO_COMPAT_H */ +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/stream_template.c b/src/stream_template.c new file mode 100644 index 0000000..c0aa42c --- /dev/null +++ b/src/stream_template.c @@ -0,0 +1,337 @@ +/* -*- C -*- */ + +/* + * stream_template.c : Generic framework for stream ciphers + * + * Written by Andrew Kuchling and others + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +#include "pycrypto_common.h" +#include "modsupport.h" + +#define _STR(x) #x +#define _XSTR(x) _STR(x) +#define _PASTE(x,y) x##y +#define _PASTE2(x,y) _PASTE(x,y) +#ifdef IS_PY3K +#define _MODULE_NAME _PASTE2(PyInit_,MODULE_NAME) +#else +#define _MODULE_NAME _PASTE2(init,MODULE_NAME) +#endif +#define _MODULE_STRING _XSTR(MODULE_NAME) + + /* + * + * Python interface + * + */ + +typedef struct +{ + PyObject_HEAD + stream_state st; +} ALGobject; + +/* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C. + * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize + */ +staticforward PyTypeObject ALGtype; + +static ALGobject * +newALGobject(void) +{ + ALGobject * new; + new = PyObject_New(ALGobject, &ALGtype); + return new; +} + +static void +ALGdealloc(PyObject *ptr) +{ + ALGobject *self = (ALGobject *)ptr; + + /* Overwrite the contents of the object */ + memset((char*)&(self->st), 0, sizeof(stream_state)); + PyObject_Del(ptr); +} + +static char ALGnew__doc__[] = +"Return a new " _MODULE_STRING " encryption object."; + +static char *kwlist[] = {"key", NULL}; + +static ALGobject * +ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) +{ + unsigned char *key; + ALGobject * new; + int keylen; + + new = newALGobject(); + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#", kwlist, + &key, &keylen)) + { + Py_DECREF(new); + return NULL; + } + + if (KEY_SIZE!=0 && keylen != KEY_SIZE) + { + PyErr_SetString(PyExc_ValueError, + _MODULE_STRING " key must be " + "KEY_SIZE bytes long"); + return NULL; + } + if (KEY_SIZE== 0 && keylen == 0) + { + PyErr_SetString(PyExc_ValueError, + _MODULE_STRING " key cannot be " + "the null string (0 bytes long)"); + return NULL; + } + stream_init(&(new->st), key, keylen); + if (PyErr_Occurred()) + { + Py_DECREF(new); + return NULL; + } + return new; +} + +static char ALG_Encrypt__doc__[] = +"Decrypt the provided string of binary data."; + +static PyObject * +ALG_Encrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + int len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len == 0) /* Handle empty string */ + { + return PyBytes_FromStringAndSize(NULL, 0); + } + buffer = malloc(len); + if (buffer == NULL) + { + PyErr_SetString(PyExc_MemoryError, "No memory available in " + _MODULE_STRING " encrypt"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS; + memcpy(buffer, str, len); + stream_encrypt(&(self->st), buffer, len); + Py_END_ALLOW_THREADS; + result = PyBytes_FromStringAndSize((char *)buffer, len); + free(buffer); + return (result); +} + +static char ALG_Decrypt__doc__[] = +"decrypt(string): Decrypt the provided string of binary data."; + +static PyObject * +ALG_Decrypt(ALGobject *self, PyObject *args) +{ + unsigned char *buffer, *str; + int len; + PyObject *result; + + if (!PyArg_Parse(args, "s#", &str, &len)) + return NULL; + if (len == 0) /* Handle empty string */ + { + return PyBytes_FromStringAndSize(NULL, 0); + } + buffer = malloc(len); + if (buffer == NULL) + { + PyErr_SetString(PyExc_MemoryError, "No memory available in " + _MODULE_STRING " decrypt"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS; + memcpy(buffer, str, len); + stream_decrypt(&(self->st), buffer, len); + Py_END_ALLOW_THREADS; + result = PyBytes_FromStringAndSize((char *)buffer, len); + free(buffer); + return (result); +} + +/* ALGobject methods */ +static PyMethodDef ALGmethods[] = + { + {"encrypt", (PyCFunction) ALG_Encrypt, METH_O, ALG_Encrypt__doc__}, + {"decrypt", (PyCFunction) ALG_Decrypt, METH_O, ALG_Decrypt__doc__}, + {NULL, NULL} /* sentinel */ + }; + +static PyObject * +ALGgetattro(PyObject *self, PyObject *attr) +{ + if (!PyString_Check(attr)) + goto generic; + + if (PyString_CompareWithASCIIString(attr, "block_size") == 0) + { + return PyInt_FromLong(BLOCK_SIZE); + } + if (PyString_CompareWithASCIIString(attr, "key_size") == 0) + { + return PyInt_FromLong(KEY_SIZE); + } + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr(self, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(ALGmethods, (PyObject *)self, PyString_AsString(attr)); +#endif +} + +/* List of functions defined in the module */ + +static struct PyMethodDef modulemethods[] = +{ + {"new", (PyCFunction) ALGnew, + METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject ALGtype = + { + PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + _MODULE_STRING, /*tp_name*/ + sizeof(ALGobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) ALGdealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + ALGgetattro, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + ALGmethods, /*tp_methods*/ +#endif + }; + +#ifdef IS_PY3K + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "Crypto.Cipher." _MODULE_STRING, + NULL, + -1, + modulemethods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +/* Initialization function for the module */ + +PyMODINIT_FUNC +_MODULE_NAME (void) +{ + PyObject *m = NULL; + PyObject *__all__ = NULL; + + if (PyType_Ready(&ALGtype) < 0) + goto errout; + +#ifdef IS_PY3K + /* Create the module and add the functions */ + m = PyModule_Create(&moduledef); +#else + /* Create the module and add the functions */ + m = Py_InitModule("Crypto.Cipher." _MODULE_STRING, modulemethods); +#endif + if (m == NULL) + goto errout; + + /* Add the type object to the module (using the name of the module itself), + * so that its methods docstrings are discoverable by introspection tools. */ + PyObject_SetAttrString(m, _MODULE_STRING, (PyObject *)&ALGtype); + + /* Add some symbolic constants to the module */ + PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); + PyModule_AddIntConstant(m, "key_size", KEY_SIZE); + + /* Create __all__ (to help generate documentation) */ + __all__ = PyList_New(4); + if (__all__ == NULL) + goto errout; + PyList_SetItem(__all__, 0, PyString_FromString(_MODULE_STRING)); /* This is the ALGType object */ + PyList_SetItem(__all__, 1, PyString_FromString("new")); + PyList_SetItem(__all__, 2, PyString_FromString("block_size")); + PyList_SetItem(__all__, 3, PyString_FromString("key_size")); + PyObject_SetAttrString(m, "__all__", __all__); + +out: + /* Final error check */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + Py_CLEAR(__all__); + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + goto out; +} + +/* vim:set ts=4 sw=4 sts=0 noexpandtab: */ diff --git a/src/strxor.c b/src/strxor.c new file mode 100644 index 0000000..55d8067 --- /dev/null +++ b/src/strxor.c @@ -0,0 +1,271 @@ +/* + * strxor.c: string XOR functions + * + * Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> + * + * =================================================================== + * The contents of this file are dedicated to the public domain. To + * the extent that dedication to the public domain is not available, + * everyone is granted a worldwide, perpetual, royalty-free, + * non-exclusive license to exercise all rights associated with the + * contents of this file for any purpose whatsoever. + * No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * =================================================================== + */ + +#include "pycrypto_common.h" +#include <stddef.h> +#include <assert.h> +#include <string.h> + +static const char rcsid[] = "$Id$"; + +/* + * xor_strings - XOR two strings together to produce a third string + * + * dest[0..n-1] := src_a[0..n-1] ^ src_b[0..n-1] + * + */ +static void +xor_strings(char *dest, const char *src_a, const char *src_b, size_t n) +{ + size_t i; + + /* assert no pointer overflow */ + assert(src_a + n > src_a); + assert(src_b + n > src_b); + assert(dest + n > dest); + + for (i = 0; i < n; i++) { + dest[i] = src_a[i] ^ src_b[i]; + } +} + +/* + * xor_string_with_char - XOR a string with a char to produce another string + * + * dest[0..n-1] := src[0..n-1] ^ c + * + */ +static void +xor_string_with_char(char *dest, const char *src, char c, size_t n) +{ + size_t i; + + /* assert no pointer overflow */ + assert(src + n > src); + assert(dest + n > dest); + + for (i = 0; i < n; i++) { + dest[i] = src[i] ^ c; + } +} + +/* + * "Import assertions" + * + * These runtime checks are performed when this module is first initialized + * + */ + +#define IMP_ASSERT(exp) do {\ + if (!(exp)) {\ + PyErr_Format(PyExc_AssertionError, "%s:%d: assertion failure: '%s'", __FILE__, __LINE__, #exp);\ + return;\ + }\ +} while(0) + +static void +runtime_test(void) +{ + /* size_t should be able to represent the length of any size buffer */ + IMP_ASSERT(sizeof(size_t) == sizeof(void *)); + + /* we must be able to perform the assignment (Py_ssize_t) -> (size_t) + * as long as the value is non-negative. */ + IMP_ASSERT(sizeof(size_t) >= sizeof(Py_ssize_t)); + + /* char must be one octet */ + IMP_ASSERT(sizeof(char) == 1); + + /* Perform a basic test of the xor_strings function, including a test for + * an off-by-one bug. */ + { + char x[7] = "\x00hello"; /* NUL + "hello" + NUL */ + char y[7] = "\xffworld"; /* 0xff + "world" + NUL */ + char z[9] = "[ABCDEFG]"; /* "[ABCDEFG]" + NUL */ + + xor_strings(z+1, x, y, 7); + IMP_ASSERT(!memcmp(z, "[\xff\x1f\x0a\x1e\x00\x0b\x00]", 9)); + } + + /* Perform a basic test of the xor_string_with_char function, including a test for + * an off-by-one bug. */ + { + char x[7] = "\x00hello"; /* NUL + "hello" + NUL */ + char y = 170; /* 0xaa */ + char z[9] = "[ABCDEFG]"; /* "[ABCDEFG]" + NUL */ + + xor_string_with_char(z+1, x, y, 7); + IMP_ASSERT(!memcmp(z, "[\xaa\xc2\xcf\xc6\xc6\xc5\xaa]", 9)); + } +} + +/* + * The strxor Python function + */ + +static char strxor__doc__[] = +"strxor(a:str, b:str) -> str\n" +"\n" +"Return a XOR b. Both a and b must have the same length.\n"; + +static PyObject * +strxor_function(PyObject *self, PyObject *args) +{ + PyObject *a, *b, *retval; + Py_ssize_t len_a, len_b; + + if (!PyArg_ParseTuple(args, "SS", &a, &b)) + return NULL; + + len_a = PyBytes_GET_SIZE(a); + len_b = PyBytes_GET_SIZE(b); + + assert(len_a >= 0); + assert(len_b >= 0); + + if (len_a != len_b) { + PyErr_SetString(PyExc_ValueError, "length of both strings must be equal"); + return NULL; + } + + /* Create return string */ + retval = PyBytes_FromStringAndSize(NULL, len_a); + if (!retval) { + return NULL; + } + + /* retval := a ^ b */ + xor_strings(PyBytes_AS_STRING(retval), PyBytes_AS_STRING(a), PyBytes_AS_STRING(b), len_a); + + return retval; +} + +/* + * The strxor_c Python function + */ + +static char strxor_c__doc__[] = +"strxor_c(s:str, c:int) -> str\n" +"\n" +"Return s XOR chr(c). c must be in range(256).\n"; + +static PyObject * +strxor_c_function(PyObject *self, PyObject *args) +{ + PyObject *s, *retval; + int c; + Py_ssize_t length; + + if (!PyArg_ParseTuple(args, "Si", &s, &c)) + return NULL; + + if ((c < 0) || (c > 255)) { + PyErr_SetString(PyExc_ValueError, "c must be in range(256)"); + return NULL; + } + + length = PyBytes_GET_SIZE(s); + assert(length >= 0); + + /* Create return string */ + retval = PyBytes_FromStringAndSize(NULL, length); + if (!retval) { + return NULL; + } + + /* retval := a ^ chr(c)*length */ + xor_string_with_char(PyBytes_AS_STRING(retval), PyBytes_AS_STRING(s), (char) c, length); + + return retval; +} + +/* + * Module-level method table and module initialization function + */ + +static PyMethodDef strxor_methods[] = { + {"strxor", strxor_function, METH_VARARGS, strxor__doc__}, + {"strxor_c", strxor_c_function, METH_VARARGS, strxor_c__doc__}, + + {NULL, NULL, 0, NULL} /* end-of-list sentinel value */ +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "strxor", + NULL, + -1, + strxor_methods, + NULL, + NULL, + NULL, + NULL +}; +#endif + +PyMODINIT_FUNC +#ifdef IS_PY3K +PyInit_strxor(void) +#else +initstrxor(void) +#endif +{ + PyObject *m = NULL; + + /* Initialize the module */ +#ifdef IS_PY3K + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("strxor", strxor_methods); +#endif + if (m == NULL) + goto errout; + + /* Perform runtime tests */ + runtime_test(); + +out: + /* Final error check */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + goto out; +} + +/* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/winrand.c b/src/winrand.c new file mode 100644 index 0000000..4200fbc --- /dev/null +++ b/src/winrand.c @@ -0,0 +1,467 @@ +/* -*- C -*- */ +/* + * Uses Windows CryptoAPI CryptGenRandom to get random bytes. + * The "new" method returns an object, whose "get_bytes" method + * can be called repeatedly to get random bytes, seeded by the + * OS. See the description in the comment at the end. + * + * If you have the Intel Security Driver header files (icsp4ms.h) + * for their hardware random number generator in the 810 and 820 chipsets, + * then define HAVE_INTEL_RNG. + * + * ======================================================================= + * The contents of this file are dedicated to the public domain. To the + * extent that dedication to the public domain is not available, everyone + * is granted a worldwide, perpetual, royalty-free, non-exclusive license + * to exercise all rights associated with the contents of this file for + * any purpose whatsoever. No rights are reserved. + * + * 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 AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * ======================================================================= + * + */ + +/* Author: Mark Moraes */ + +#include "pycrypto_common.h" + +#ifdef MS_WIN32 + +#define _WIN32_WINNT 0x400 +#define WINSOCK + +#include <windows.h> +#include <wincrypt.h> + +#ifdef HAVE_INTEL_RNG +# include "icsp4ms.h" +#else +# define PROV_INTEL_SEC 22 +# define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider" +#endif + +/* To-Do: store provider name and type for print/repr? */ + +typedef struct +{ + PyObject_HEAD + HCRYPTPROV hcp; +} WRobject; + +/* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C. + * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize + */ +#define is_WRobject(v) (Py_TYPE(v) == &WRtype) +staticforward PyTypeObject WRtype; + +static void +WRdealloc(PyObject *ptr) +{ + WRobject *o = (WRobject *)ptr; + + if (! is_WRobject(ptr)) { + PyErr_Format(PyExc_TypeError, + "WinRandom trying to dealloc non-WinRandom object"); + return; + } + if (! CryptReleaseContext(o->hcp, 0)) { + PyErr_Format(PyExc_SystemError, + "CryptReleaseContext failed, error 0x%x", + (unsigned int) GetLastError()); + return; + } + /* Overwrite the contents of the object */ + o->hcp = 0; + PyObject_Del(ptr); +} + +static char winrandom__doc__[] = +"new([provider], [provtype]): Returns an object handle to Windows\n\ +CryptoAPI that can be used to access a cryptographically strong\n\ +pseudo-random generator that uses OS-gathered entropy.\n\ +Provider is a string that specifies the Cryptographic Service Provider\n\ +to use, default is the default OS CSP.\n\ +provtype is an integer specifying the provider type to use, default\n\ +is 1 (PROV_RSA_FULL)"; + +static char WR_get_bytes__doc__[] = +"get_bytes(nbytes, [userdata]]): Returns nbytes of random data\n\ +from Windows CryptGenRandom.\n\ +userdata is a string with any additional entropic data that the\n\ +user wishes to provide."; + +static WRobject * +winrandom_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + HCRYPTPROV hcp = 0; + WRobject *res; + char *provname = NULL; + int provtype = PROV_RSA_FULL; + static char *kwlist[] = { "provider", "provtype", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|si", kwlist, + &provname, &provtype)) { + return NULL; + } + if (! CryptAcquireContext(&hcp, NULL, (LPCTSTR) provname, + (DWORD) provtype, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { + PyErr_Format(PyExc_SystemError, + "CryptAcquireContext for provider \"%s\" type %i failed, error 0x%x", + provname? provname : "(null)", provtype, + (unsigned int) GetLastError()); + return NULL; + } + res = PyObject_New(WRobject, &WRtype); + res->hcp = hcp; + return res; +} + +static PyObject * +WR_get_bytes(WRobject *self, PyObject *args) +{ + int n, nbytes, len = 0; + PyObject *res; + char *buf, *str = NULL; + + if (! is_WRobject(self)) { + PyErr_Format(PyExc_TypeError, + "WinRandom trying to get_bytes with non-WinRandom object"); + return NULL; + } + if (!PyArg_ParseTuple(args, "i|s#", &n, &str, &len)) { + return NULL; + } + if (n <= 0) { + PyErr_SetString(PyExc_ValueError, "nbytes must be positive number"); + return NULL; + } + /* Just in case char != BYTE, or userdata > desired result */ + nbytes = (((n > len) ? n : len) * sizeof(char)) / sizeof(BYTE) + 1; + if ((buf = (char *) PyMem_Malloc(nbytes)) == NULL) + return PyErr_NoMemory(); + if (len > 0) + memcpy(buf, str, len); + /* + * if userdata > desired result, we end up getting + * more bytes than we really needed to return. No + * easy way to avoid that: we prefer that + * CryptGenRandom does the distillation of userdata + * down to entropy, rather than trying to do it + * ourselves. Since the extra bytes presumably come + * from an RC4 stream, they should be relatively + * cheap. + */ + + if (! CryptGenRandom(self->hcp, (DWORD) nbytes, (BYTE *) buf)) { + PyErr_Format(PyExc_SystemError, + "CryptGenRandom failed, error 0x%x", + (unsigned int) GetLastError()); + PyMem_Free(buf); + return NULL; + } + + res = PyBytes_FromStringAndSize(buf, n); + PyMem_Free(buf); + return res; +} + +/* WinRandom object methods */ + +static PyMethodDef WRmethods[] = +{ + {"get_bytes", (PyCFunction) WR_get_bytes, METH_VARARGS, + WR_get_bytes__doc__}, + {NULL, NULL} /* sentinel */ +}; + +/* winrandom module methods */ + +static PyMethodDef WR_mod_methods[] = { + {"new", (PyCFunction) winrandom_new, METH_VARARGS|METH_KEYWORDS, + winrandom__doc__}, + {NULL, NULL} /* Sentinel */ +}; + +static PyObject * +WRgetattro(PyObject *s, PyObject *attr) +{ + WRobject *self = (WRobject*)s; + if (! is_WRobject(self)) { + PyErr_Format(PyExc_TypeError, + "WinRandom trying to getattr with non-WinRandom object"); + return NULL; + } + if (!PyString_Check(attr)) + goto generic; + if (PyString_CompareWithASCIIString(attr, "hcp") == 0) + return PyInt_FromLong((long) self->hcp); + generic: +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + return PyObject_GenericGetAttr(s, attr); +#else + if (PyString_Check(attr) < 0) { + PyErr_SetObject(PyExc_AttributeError, attr); + return NULL; + } + return Py_FindMethod(WRmethods, (PyObject *)self, PyString_AsString(attr)); +#endif +} + +static PyTypeObject WRtype = + { + PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ + "winrandom.WinRandom", /*tp_name*/ + sizeof(WRobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) WRdealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number */ + 0, /*tp_as_sequence */ + 0, /*tp_as_mapping */ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + WRgetattro, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ +#if PYTHON_API_VERSION >= 1011 /* Python 2.2 and later */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + WRmethods, /*tp_methods*/ +#endif +}; + +#ifdef IS_PY3K +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "winrandom", + NULL, + -1, + WR_mod_methods, + NULL, + NULL, + NULL, + NULL + }; +#endif + +PyMODINIT_FUNC +#ifdef IS_PY3K +PyInit_winrandom() +#else +initwinrandom() +#endif +{ + PyObject *m = NULL; + + if (PyType_Ready(&WRtype) < 0) + goto errout; + + /* Initialize the module */ +#ifdef IS_PY3K + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule("winrandom", WR_mod_methods); +#endif + if (m == NULL) + goto errout; + + /* define Windows CSP Provider Types */ +#ifdef PROV_RSA_FULL + PyModule_AddIntConstant(m, "PROV_RSA_FULL", PROV_RSA_FULL); +#endif +#ifdef PROV_RSA_SIG + PyModule_AddIntConstant(m, "PROV_RSA_SIG", PROV_RSA_SIG); +#endif +#ifdef PROV_DSS + PyModule_AddIntConstant(m, "PROV_DSS", PROV_DSS); +#endif +#ifdef PROV_FORTEZZA + PyModule_AddIntConstant(m, "PROV_FORTEZZA", PROV_FORTEZZA); +#endif +#ifdef PROV_MS_EXCHANGE + PyModule_AddIntConstant(m, "PROV_MS_EXCHANGE", PROV_MS_EXCHANGE); +#endif +#ifdef PROV_SSL + PyModule_AddIntConstant(m, "PROV_SSL", PROV_SSL); +#endif +#ifdef PROV_RSA_SCHANNEL + PyModule_AddIntConstant(m, "PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL); +#endif +#ifdef PROV_DSS_DH + PyModule_AddIntConstant(m, "PROV_DSS_DH", PROV_DSS_DH); +#endif +#ifdef PROV_EC_ECDSA_SIG + PyModule_AddIntConstant(m, "PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG); +#endif +#ifdef PROV_EC_ECNRA_SIG + PyModule_AddIntConstant(m, "PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG); +#endif +#ifdef PROV_EC_ECDSA_FULL + PyModule_AddIntConstant(m, "PROV_EC_ECDSA_FULL", PROV_EC_ECDSA_FULL); +#endif +#ifdef PROV_EC_ECNRA_FULL + PyModule_AddIntConstant(m, "PROV_EC_ECNRA_FULL", PROV_EC_ECNRA_FULL); +#endif +#ifdef PROV_SPYRUS_LYNKS + PyModule_AddIntConstant(m, "PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS); +#endif +#ifdef PROV_INTEL_SEC + PyModule_AddIntConstant(m, "PROV_INTEL_SEC", PROV_INTEL_SEC); +#endif + + /* Define Windows CSP Provider Names */ +#ifdef MS_DEF_PROV + PyModule_AddStringConstant(m, "MS_DEF_PROV", MS_DEF_PROV); +#endif +#ifdef MS_ENHANCED_PROV + PyModule_AddStringConstant(m, "MS_ENHANCED_PROV", MS_ENHANCED_PROV); +#endif +#ifdef MS_DEF_RSA_SIG_PROV + PyModule_AddStringConstant(m, "MS_DEF_RSA_SIG_PROV", + MS_DEF_RSA_SIG_PROV); +#endif +#ifdef MS_DEF_RSA_SCHANNEL_PROV + PyModule_AddStringConstant(m, "MS_DEF_RSA_SCHANNEL_PROV", + MS_DEF_RSA_SCHANNEL_PROV); +#endif +#ifdef MS_ENHANCED_RSA_SCHANNEL_PROV + PyModule_AddStringConstant(m, "MS_ENHANCED_RSA_SCHANNEL_PROV", + MS_ENHANCED_RSA_SCHANNEL_PROV); +#endif +#ifdef MS_DEF_DSS_PROV + PyModule_AddStringConstant(m, "MS_DEF_DSS_PROV", MS_DEF_DSS_PROV); +#endif +#ifdef MS_DEF_DSS_DH_PROV + PyModule_AddStringConstant(m, "MS_DEF_DSS_DH_PROV", + MS_DEF_DSS_DH_PROV); +#endif +#ifdef INTEL_DEF_PROV + PyModule_AddStringConstant(m, "INTEL_DEF_PROV", INTEL_DEF_PROV); +#endif + +out: + /* Final error check */ + if (m == NULL && !PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "can't initialize module"); + goto errout; + } + + /* Free local objects here */ + + /* Return */ +#ifdef IS_PY3K + return m; +#else + return; +#endif + +errout: + /* Free the module and other global objects here */ + Py_CLEAR(m); + goto out; +} +/* + +CryptGenRandom usage is described in +http://msdn.microsoft.com/library/en-us/security/security/cryptgenrandom.asp +and many associated pages on Windows Cryptographic Service +Providers, which say: + + With Microsoft CSPs, CryptGenRandom uses the same + random number generator used by other security + components. This allows numerous processes to + contribute to a system-wide seed. CryptoAPI stores + an intermediate random seed with every user. To form + the seed for the random number generator, a calling + application supplies bits it might havefor instance, + mouse or keyboard timing inputthat are then added to + both the stored seed and various system data and + user data such as the process ID and thread ID, the + system clock, the system time, the system counter, + memory status, free disk clusters, the hashed user + environment block. This result is SHA-1 hashed, and + the output is used to seed an RC4 stream, which is + then used as the random stream and used to update + the stored seed. + +The only other detailed description I've found of the +sources of randomness for CryptGenRandom is this excerpt +from a posting +http://www.der-keiler.de/Newsgroups/comp.security.ssh/2002-06/0169.html + +From: Jon McClelland (dowot69@hotmail.com) +Date: 06/12/02 +... + +Windows, call a function such as CryptGenRandom, which has two of +the properties of a good random number generator, unpredictability and +even value distribution. This function, declared in Wincrypt.h, is +available on just about every Windows platform, including Windows 95 +with Internet Explorer 3.02 or later, Windows 98, Windows Me, Windows +CE v3, Windows NT 4, Windows 2000, and Windows XP. + +CryptGenRandom gets its randomness, also known as entropy, from many +sources in Windows 2000, including the following: +The current process ID (GetCurrentProcessID). +The current thread ID (GetCurrentThreadID). +The ticks since boot (GetTickCount). +The current time (GetLocalTime). +Various high-precision performance counters (QueryPerformanceCounter). +A Message Digest 4 (MD4) hash of the user's environment block, which +includes username, computer name, and search path. + +High-precision internal CPU counters, such as RDTSC, RDMSR, RDPMC (x86 +only-more information about these counters is at +developer.intel.com/software/idap/resources/technical_collateral/pentiumii/RDTSCPM1.HTM +<http://developer.intel.com>). + +Low-level system information, such as idle time, kernel time, +interrupt times, commit limit, page read count, cache read count, +nonpaged pool allocations, alignment fixup count, operating system +lookaside information. + +Such information is added to a buffer, which is hashed using MD4 and +used as the key to modify a buffer, using RC4, provided by the user. +(Refer to the CryptGenRandom documentation in the Platform SDK for +more information about the user-provided buffer.) Hence, if the user +provides additional data in the buffer, this is used as an element in +the witches brew to generate the random data. The result is a +cryptographically random number generator. +Also, note that if you plan to sell your software to the United States +federal government, you'll need to use FIPS 140-1-approved algorithms. +The default versions of CryptGenRandom in Microsoft Windows CE v3, +Windows 95, Windows 98, Windows Me, Windows 2000, and Windows XP are +FIPS-approved. Obviously FIPS-140 compliance is necessary but not +sufficient to provide a properly secure source of random data. + +*/ +/* +[Update: 2007-11-13] +CryptGenRandom does not necessarily provide forward secrecy or reverse +secrecy. See the paper by Leo Dorrendorf and Zvi Gutterman and Benny +Pinkas, _Cryptanalysis of the Random Number Generator of the Windows +Operating System_, Cryptology ePrint Archive, Report 2007/419, +http://eprint.iacr.org/2007/419 +*/ + +#endif /* MS_WIN32 */ diff --git a/tools/create-pythons.sh b/tools/create-pythons.sh new file mode 100755 index 0000000..52c7fe9 --- /dev/null +++ b/tools/create-pythons.sh @@ -0,0 +1,244 @@ +#!/bin/bash +# Experimental script used to install multiple versions of Python for testing PyCrypto. +# Edit it to suit your needs. +# by Dwayne Litzenberger +# +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +set -e + +apply_multiarch_hack_patch() { +patch -p1 <<'EOF' +--- a/setup.py 2008-10-16 11:58:19.000000000 -0700 ++++ b/setup.py 2013-02-02 19:05:15.398794396 -0800 +@@ -246,6 +246,7 @@ + # Ensure that /usr/local is always used + add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') + add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') ++ add_dir_to_list(self.compiler.library_dirs, os.getenv("EXTRA_LIBDIR")) + + # Add paths specified in the environment variables LDFLAGS and + # CPPFLAGS for header and library files. +EOF +} + +apply_plat_linux3_patch() { +patch -p1 <<'EOF' +diff -ru Python-2.2.3.orig/configure Python-2.2.3/configure +--- Python-2.2.3.orig/configure 2003-03-29 14:25:14.000000000 -0800 ++++ Python-2.2.3/configure 2014-02-22 14:37:36.540457776 -0800 +@@ -641,6 +641,8 @@ + MACHDEP="$ac_md_system$ac_md_release" + + case $MACHDEP in ++ linux1) MACHDEP="linux1";; ++ linux*) MACHDEP="linux2";; + cygwin*) MACHDEP="cygwin";; + darwin*) MACHDEP="darwin";; + '') MACHDEP="unknown";; +diff -ru Python-2.2.3.orig/configure.in Python-2.2.3/configure.in +--- Python-2.2.3.orig/configure.in 2003-03-29 14:25:17.000000000 -0800 ++++ Python-2.2.3/configure.in 2014-02-22 14:37:29.668562217 -0800 +@@ -68,6 +68,8 @@ + MACHDEP="$ac_md_system$ac_md_release" + + case $MACHDEP in ++ linux1) MACHDEP="linux1";; ++ linux*) MACHDEP="linux2";; + cygwin*) MACHDEP="cygwin";; + darwin*) MACHDEP="darwin";; + '') MACHDEP="unknown";; +EOF +} + +PREFIX=${PREFIX:-$(dirname "$(readlink -f "$0")")/py} +CONCURRENCY_LEVEL=${CONCURRENCY_LEVEL:-5} + +# Unexport vars +export -n PREFIX CONCURRENCY_LEVEL + +# +# Download +# + +mkdir -p "$PREFIX/src" "$PREFIX/archives" "$PREFIX/build" "$PREFIX/pythons" +cd "$PREFIX/archives" + +wget -c -i- <<-'EOF' +http://www.python.org/ftp/python/2.1.3/Python-2.1.3.tgz +http://www.python.org/ftp/python/2.2.3/Python-2.2.3.tgz +http://www.python.org/ftp/python/2.3.7/Python-2.3.7.tar.bz2 +http://www.python.org/ftp/python/2.4.6/Python-2.4.6.tar.bz2 +http://www.python.org/ftp/python/2.5.6/Python-2.5.6.tar.bz2 +http://www.python.org/ftp/python/2.6.8/Python-2.6.8.tar.bz2 +http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tar.bz2 +http://www.python.org/ftp/python/3.0.1/Python-3.0.1.tar.bz2 +http://www.python.org/ftp/python/3.1.5/Python-3.1.5.tar.bz2 +http://www.python.org/ftp/python/3.2.3/Python-3.2.3.tar.bz2 +http://www.python.org/ftp/python/3.3.0/Python-3.3.0.tar.bz2 +http://www.python.org/ftp/python/3.4.0/Python-3.4.0rc1.tgz +EOF + +# HACK - "wget -c" doesn't properly handle sites like this that don't support the Range header +wget -nc -i- <<-'EOF' +https://gist.github.com/raw/1929293/18b5c29262ea04d0802e998da368e14b73112bda/fix-python-2.5.6-svnversion-issue.patch +EOF + +# Check MD5 checksums (mostly transcribed from www.python.org, up to v3.3) +md5sum -c <<-'EOF' +a8b04cdc822a6fc833ed9b99c7fba589 *Python-2.1.3.tgz +169f89f318e252dac0c54dd1b165d229 *Python-2.2.3.tgz +fa73476c5214c57d0751fae527f991e1 *Python-2.3.7.tar.bz2 +76083277f6c7e4d78992f36d7ad9018d *Python-2.4.6.tar.bz2 +5d45979c5f30fb2dd5f067c6b06b88e4 *Python-2.5.6.tar.bz2 +c6e0420a21d8b23dee8b0195c9b9a125 *Python-2.6.8.tar.bz2 +c57477edd6d18bd9eeca2f21add73919 *Python-2.7.3.tar.bz2 +7291eac6a9a7a3642e309c78b8d744e5 *Python-3.0.1.tar.bz2 +dc8a7a96c12880d2e61e9f4add9d3dc7 *Python-3.1.5.tar.bz2 +cea34079aeb2e21e7b60ee82a0ac286b *Python-3.2.3.tar.bz2 +b3b2524f72409d919a4137826a870a8f *Python-3.3.0.tar.bz2 +8f75b4e8e907bc17d9e4478da1bd0f0f *Python-3.4.0rc1.tgz +871fac364185ba4b94a74f6245f08f34 *fix-python-2.5.6-svnversion-issue.patch +EOF +#1d00e2fb19418e486c30b850df625aa3 *Python-2.5.5.tar.bz2 +#cf4e6881bb84a7ce6089e4a307f71f14 *Python-2.6.6.tar.bz2 +#aa27bc25725137ba155910bd8e5ddc4f *Python-2.7.1.tar.bz2 +#ad5e5f1c07e829321e0a015f8cafe245 *Python-3.1.3.tar.bz2 +#9d763097a13a59ff53428c9e4d098a05 *Python-3.2.2.tar.bz2 +#45ab5ff5edfb73ec277b1c763f3d5a42 *Python-3.2b2.tar.bz2 + +# Check SHA256 checksums (originally generated by me) +if which sha256sum >/dev/null ; then + sha256sum -c <<-'EOF' +1bcb5bb587948bc38f36db60e15c376009c56c66570e563a08a82bf7f227afb9 *Python-2.1.3.tgz +a8f92e6b89d47359fff0d1fbfe47f104afc77fd1cd5143e7332758b7bc100188 *Python-2.2.3.tgz +4bd3aebaa1fe8e30afee9f0f968e699509b73ed5cff270b608216293515359f0 *Python-2.3.7.tar.bz2 +da104139ad3f4534482942ac02cf8f8ed9badd370ffa14f06b07c44914423e08 *Python-2.4.6.tar.bz2 +57e04484de051decd4741fb4a4a3f543becc9a219af8b8063b5541e270f26dcc *Python-2.5.6.tar.bz2 +c34036718ee1f091736677f543bc7960861cf9fcbea77d49572b59f7f1ab3c3f *Python-2.6.8.tar.bz2 +726457e11cb153adc3f428aaf1901fc561a374c30e5e7da6742c0742a338663c *Python-2.7.3.tar.bz2 +91afb6ac16d3d22bc6bfbc80726dc85ede32bf838f660cc67016c7d0a7079add *Python-3.0.1.tar.bz2 +3a72a21528f0751e89151744350dd12004131d312d47b935ce8041b070c90361 *Python-3.1.5.tar.bz2 +5648ec81f93870fde2f0aa4ed45c8718692b15ce6fd9ed309bfb827ae12010aa *Python-3.2.3.tar.bz2 +15c113fd6c058712f05d31b4eff149d4d823b8e39ef5e37228dc5dc4f8716df9 *Python-3.3.0.tar.bz2 +95fae4e71ffd4b442527a379f1a7d8ca7ac1ca3c60f3c740fe06d8562814722f *Python-3.4.0rc1.tgz +46c40e269b073155f7b5c2e2aa7abdac55b0756d6239def317fff81f7d5088d7 *fix-python-2.5.6-svnversion-issue.patch + EOF +#2623a04d40123950eb2a459aa39805f48f6254c21b4c0fcfa430d5eca8a0389b *Python-2.5.5.tar.bz2 +#134c5e0736bae2e5570d0b915693374f11108ded63c35a23a35d282737d2ce83 *Python-2.6.6.tar.bz2 +#80e387bcf57eae8ce26726753584fd63e060ec11682d1145af921e85fd612292 *Python-2.7.1.tar.bz2 +#77f6f41a51be4ca85d83670405c8281dd1237bb00d8be8a7560cb3ccdf5558cb *Python-3.1.3.tar.bz2 +#0bead812d9fbd56826f90b30150d8eb75ce56520b05f6a3a0dc474ef7aa927a3 *Python-3.2b2.tar.bz2 +#11426a3c6e4a33e343f100b092049d0a3e09de1c7a2fbf5f0086a8282db59dee *Python-3.2.2.tar.bz2 +else + echo >&2 "$0: warning: No sha256sum command; skipping check." +fi + +# +# Extract +# +for filename in \ + Python-2.1.3.tgz Python-2.2.3.tgz \ + Python-2.3.7.tar.bz2 Python-2.4.6.tar.bz2 Python-2.5.6.tar.bz2 \ + Python-2.6.8.tar.bz2 Python-2.7.3.tar.bz2 Python-3.0.1.tar.bz2 \ + Python-3.1.5.tar.bz2 Python-3.2.3.tar.bz2 Python-3.3.0.tar.bz2 \ + Python-3.4.0rc1.tgz +do + dir="`basename "$filename"`" + dir=${dir%%.tgz} + dir=${dir%%.tar.bz2} + + name=`echo "$dir" | tr 'A-Z' 'a-z' | sed -e 's/-//g'` + name=${name%%.[0-9]} + + echo "#########################" + echo "### Building $dir ($name)" + echo "### in $PREFIX/build/$dir" + echo "#########################" + + # Extract + if [ -d "$PREFIX/src/$dir" ] ; then + echo "$name: Skipping $filename ($dir exists)" + else + echo "$name: Extracting $filename ..." + mkdir -p "$PREFIX/src/tmp" + cd "$PREFIX/src/tmp" + case "$filename" in + *.tgz) + tar xzf "$PREFIX/archives/$filename" + ;; + *.tar.bz2) + tar xjf "$PREFIX/archives/$filename" + ;; + *) + echo >&2 "Don't know how to handle $filename" + exit 1 + esac + mv "$dir" "$PREFIX/src/" + fi + + # Apply patches + cd "$PREFIX/src/$dir" + if ! [ -e .fix-python-2.5.6-svnversion-issue.patch.applied ] && [ "$dir" = "Python-2.5.6" -o "$dir" = "Python-3.0.1" ] ; then + patch -p1 < "$PREFIX/archives/fix-python-2.5.6-svnversion-issue.patch" + touch .fix-python-2.5.6-svnversion-issue.patch.applied + fi + if ! [ -e .ssl-fix.applied ] && [ "$dir" = "Python-2.5.6" ] ; then + echo "_ssl _ssl.c -lssl -lcrypto" >> Modules/Setup.dist + touch .ssl-fix.applied + fi + if ! [ -e .multiarch-hack.applied ] && [ "$dir" = "Python-2.5.6" -o "$dir" = "Python-2.6.8" -o "$dir" = "Python-3.0.1" ] && gcc -print-multiarch >/dev/null ; then + # This is a glorious hack to get sqlite & hashlib to build properly on Debian/Ubuntu multiarch. + apply_multiarch_hack_patch + touch .multiarch-hack.applied + export EXTRA_LIBDIR=/usr/lib/`gcc -print-multiarch` + fi + if ! [ -e .plat-linux3.applied ] ; then + # sys.platform should return "linux2" on Linux, even if the system + # was compiled on Linux 3.x or later. + case "$dir" in + Python-2.[23456]*) + apply_plat_linux3_patch + touch .plat-linux3.applied + ;; + esac + fi + + # Set some special configure parameters + if [ `uname -m` = "x86_64" ] && [ "$name" = "python2.3" ] ; then + # Workaround for bug in Ubuntu 10.10 amd64 gcc-4.4 + # See http://orip.org/2008/10/building-python-235-on-ubuntu-intrepid.html + # and Ubuntu Bug #286334 + extra_config_params=BASECFLAGS=-U_FORTIFY_SOURCE + else + extra_config_params= + fi + + # Profiling support? + if [ "$PROFILING" -eq 1 ] ; then + extra_config_params="$extra_config_params --enable-profiling" + fi + + # Create build directory, configure, and build + set -x + mkdir -p "$PREFIX/build/$dir" "$PREFIX/pythons/$name" + cd "$PREFIX/build/$dir" + "$PREFIX/src/$dir/configure" $extra_config_params --prefix="$PREFIX/pythons/$name" --enable-unicode=ucs4 + make -s -j"$CONCURRENCY_LEVEL" + make -s install + set +x +done diff --git a/tools/test-all.sh b/tools/test-all.sh new file mode 100755 index 0000000..ae3c88c --- /dev/null +++ b/tools/test-all.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Script used to build PyCrypto under all Python versions +# Edit it to suit your needs. +# by Dwayne Litzenberger +# +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# 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 AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +set -e +PREFIX=${PREFIX:-$(dirname "$(readlink -f "$0")")/py} + +export -n PREFIX # unexport + +find "$PREFIX"/pythons/python* -maxdepth 0 -type d -print0 | sort -z | while IFS= read -d '' -r pythondir +do + echo "=== `basename $pythondir` ===" + "$pythondir"/bin/python?.? setup.py -q build + "$pythondir"/bin/python?.? setup.py -q test +done |