aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rwxr-xr-xconfigure.py7
-rw-r--r--doc/news.rst28
-rw-r--r--doc/os.rst1
-rw-r--r--doc/todo.rst1
-rw-r--r--readme.rst48
-rw-r--r--src/build-data/buildh.in71
-rw-r--r--src/build-data/os/aix.txt1
-rw-r--r--src/build-data/os/cygwin.txt1
-rw-r--r--src/build-data/os/darwin.txt1
-rw-r--r--src/build-data/os/freebsd.txt1
-rw-r--r--src/build-data/os/haiku.txt1
-rw-r--r--src/build-data/os/hpux.txt1
-rw-r--r--src/build-data/os/irix.txt1
-rw-r--r--src/build-data/os/linux.txt1
-rw-r--r--src/build-data/os/netbsd.txt1
-rw-r--r--src/build-data/os/qnx.txt1
-rw-r--r--src/build-data/os/solaris.txt1
-rw-r--r--src/cmd/rng.cpp2
-rw-r--r--src/lib/asn1/oid_lookup/default.cpp6
-rw-r--r--src/lib/block/aes/aes.cpp561
-rw-r--r--src/lib/entropy/beos_stats/es_beos.cpp14
-rw-r--r--src/lib/entropy/beos_stats/es_beos.h4
-rw-r--r--src/lib/entropy/cryptoapi_rng/es_capi.cpp6
-rw-r--r--src/lib/entropy/cryptoapi_rng/es_capi.h5
-rw-r--r--src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp8
-rw-r--r--src/lib/entropy/darwin_secrandom/darwin_secrandom.h7
-rw-r--r--src/lib/entropy/dev_random/dev_random.cpp17
-rw-r--r--src/lib/entropy/dev_random/dev_random.h6
-rw-r--r--src/lib/entropy/egd/es_egd.cpp8
-rw-r--r--src/lib/entropy/egd/es_egd.h5
-rw-r--r--src/lib/entropy/entropy_src.h35
-rw-r--r--src/lib/entropy/entropy_srcs.cpp144
-rw-r--r--src/lib/entropy/hres_timer/hres_timer.cpp19
-rw-r--r--src/lib/entropy/hres_timer/hres_timer.h4
-rw-r--r--src/lib/entropy/info.txt2
-rw-r--r--src/lib/entropy/proc_walk/proc_walk.cpp3
-rw-r--r--src/lib/entropy/proc_walk/proc_walk.h4
-rw-r--r--src/lib/entropy/rdrand/rdrand.h4
-rw-r--r--src/lib/entropy/unix_procs/unix_procs.cpp22
-rw-r--r--src/lib/entropy/unix_procs/unix_procs.h8
-rw-r--r--src/lib/entropy/win32_stats/es_win32.cpp51
-rw-r--r--src/lib/entropy/win32_stats/es_win32.h4
-rw-r--r--src/lib/filters/comp_filter.cpp7
-rw-r--r--src/lib/math/mp/mp_generic/mp_madd.h7
-rw-r--r--src/lib/pubkey/dh/dh.cpp2
-rw-r--r--src/lib/pubkey/dl_group/dl_group.cpp2
-rw-r--r--src/lib/pubkey/ec_group/named.cpp46
-rw-r--r--src/lib/pubkey/elgamal/elgamal.cpp4
-rw-r--r--src/lib/pubkey/if_algo/if_algo.cpp2
-rw-r--r--src/lib/pubkey/pubkey.h20
-rw-r--r--src/lib/pubkey/workfactor.cpp56
-rw-r--r--src/lib/pubkey/workfactor.h19
-rw-r--r--src/lib/rng/auto_rng/auto_rng.h7
-rw-r--r--src/lib/rng/hmac_drbg/hmac_drbg.cpp10
-rw-r--r--src/lib/rng/hmac_drbg/hmac_drbg.h4
-rw-r--r--src/lib/rng/hmac_rng/hmac_rng.cpp40
-rw-r--r--src/lib/rng/hmac_rng/hmac_rng.h6
-rw-r--r--src/lib/rng/rng.cpp15
-rw-r--r--src/lib/rng/rng.h40
-rw-r--r--src/lib/rng/system_rng/system_rng.cpp24
-rw-r--r--src/lib/rng/system_rng/system_rng.h7
-rw-r--r--src/lib/rng/x931_rng/x931_rng.cpp7
-rw-r--r--src/lib/rng/x931_rng/x931_rng.h5
-rw-r--r--src/lib/utils/cpuid.cpp2
-rw-r--r--src/lib/utils/cpuid.h19
-rw-r--r--src/lib/utils/simd/simd_altivec/simd_altivec.h4
-rwxr-xr-xsrc/scripts/ci/travis/build.sh2
-rw-r--r--src/tests/main.cpp (renamed from src/tests/test_main.cpp)25
-rw-r--r--src/tests/test_block.cpp8
-rw-r--r--src/tests/test_entropy.cpp153
-rw-r--r--src/tests/test_hash.cpp2
-rw-r--r--src/tests/test_mac.cpp2
-rw-r--r--src/tests/test_rng.h4
-rw-r--r--src/tests/test_stream.cpp2
-rw-r--r--src/tests/test_utils.cpp8
-rw-r--r--src/tests/tests.cpp53
-rw-r--r--src/tests/tests.h61
-rw-r--r--src/tests/unit_ecc.cpp6
-rw-r--r--src/tests/unit_ecdsa.cpp6
-rw-r--r--src/tests/unit_tls.cpp7
81 files changed, 965 insertions, 847 deletions
diff --git a/.gitignore b/.gitignore
index 998a8a173..27b84e513 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,4 +47,4 @@ cachegrind.*
callgrind.*
# Test output
-src/tests/outdata/*.pem
+src/tests/outdata
diff --git a/configure.py b/configure.py
index 122e493f3..85e441666 100755
--- a/configure.py
+++ b/configure.py
@@ -584,7 +584,14 @@ class ModuleInfo(object):
# Coerce to more useful types
def convert_lib_list(l):
+ if len(l) % 3 != 0:
+ raise Exception("Bad <libs> in module %s" % (self.basename))
result = {}
+
+ for sep in l[1::3]:
+ if(sep != '->'):
+ raise Exception("Bad <libs> in module %s" % (self.basename))
+
for (targetlist, vallist) in zip(l[::3], l[2::3]):
vals = vallist.split(',')
for target in targetlist.split(','):
diff --git a/doc/news.rst b/doc/news.rst
index 2622c66bd..cce298ffd 100644
--- a/doc/news.rst
+++ b/doc/news.rst
@@ -9,28 +9,36 @@ Version 1.11.25, Not Yet Released
adopted over time, each of which was insufficient on its own for testing the
entire library. These have been fully converged on a new framework which
suffices for all of the tests. There should be no user-visible change as a
- result of this.
+ result of this, except that the output format of `botan-test` has changed.
+
+* Improved side channel countermeasures for the table based AES implementation,
+ by ensuring the table is loaded into memory at start and computing the table
+ at runtime to avoid flush+reload based attacks due to shared VMM mappings.
+
+* Support for the insecure ECC groups secp112r1, secp112r2, secp128r1, and
+ secp128r2 has been removed.
* The OpenSSL implementation of RC4 would return the wrong value from `name` if
leading bytes of the keystream had been skipped in the output.
-* Fixed the signature of botan_pubkey_destroy which took the wrong type and was
- not usable.
+* Fixed the signature of the FFI function botan_pubkey_destroy, which took the
+ wrong type and was not usable.
-* The TLS client would erronously reject any server key exchange
- packet smaller than 6 bytes. This prevented negotiating a plain PSK
- TLS ciphersuite with an empty identity hint. ECDHE_PSK and DHE_PSK
- suites were not affected.
+* The TLS client would erronously reject any server key exchange packet smaller
+ than 6 bytes. This prevented negotiating a plain PSK TLS ciphersuite with an
+ empty identity hint. ECDHE_PSK and DHE_PSK suites were not affected.
-* Fixed a bug that would cause the TLS client to occasionally reject a
- valid server key exchange message as having an invalid signature.
- This only affected DHE ciphersuites.
+* Fixed a bug that would cause the TLS client to occasionally reject a valid
+ server key exchange message as having an invalid signature. This only affected
+ DHE and SRP ciphersuites.
* Support for negotiating use of SHA-224 in TLS has been disabled in the
default policy.
* Added `remove_all` function to the `TLS::Session_Manager` interface
+* Avoid GCC warning in pedantic mode when including bigint.h GH #330
+
Version 1.11.24, 2015-11-04
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/os.rst b/doc/os.rst
index 9e1ee641e..83fee9351 100644
--- a/doc/os.rst
+++ b/doc/os.rst
@@ -33,7 +33,6 @@ A summary of OS features as defined in ``src/build-data/os``.
"clock_gettime", " ", "X", " ", " ", "X", "X", " ", " ", " ", " ", "X", " ", " ", "X", "X", "X", " ", " "
"cryptgenrandom", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", "X"
"dlopen", " ", "X", " ", "X", " ", "X", " ", " ", " ", " ", "X", " ", " ", "X", "X", "X", " ", " "
- "getsid", "X", " ", "X", "X", " ", "X", "X", "X", " ", "X", "X", " ", " ", "X", " ", "X", "X", " "
"gettimeofday", "X", "X", "X", "X", "X", "X", "X", "X", " ", "X", "X", " ", "X", "X", "X", "X", "X", " "
"gmtime_r", " ", "X", " ", "X", " ", "X", "X", " ", " ", " ", "X", " ", " ", "X", "X", "X", " ", " "
"gmtime_s", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X"
diff --git a/doc/todo.rst b/doc/todo.rst
index 11bfc8836..5ea142464 100644
--- a/doc/todo.rst
+++ b/doc/todo.rst
@@ -57,6 +57,7 @@ Symmetric Algorithms, Hashes, ...
----------------------------------------
* Bitsliced AES or Camellia
+* Compressed tables for AES
* Camellia with AES-NI
* Serpent using AVX2
* Serpent using SSSE3 pshufb for sboxes
diff --git a/readme.rst b/readme.rst
index 1a0ec1e4a..144364bb4 100644
--- a/readme.rst
+++ b/readme.rst
@@ -1,15 +1,14 @@
Botan: Crypto and TLS for C++11
========================================
-Botan (Japanese for peony) is a C++ cryptography library released
-under the permissive `Simplified BSD
+Botan (Japanese for peony) is a cryptography library written in C++11
+and released under the permissive `Simplified BSD
<http://botan.randombit.net/license.txt>`_ license.
-It provides TLS, X.509 certificates, OCSP, ECDSA, AES, GCM,
-ChaCha20Poly1305, McEliece, bcrypt, and quite a few other things. It
-also provides a `botan` command line tool for various cryptographic
-operations, the source for which also helps demonstrate usage of the
-library.
+It provides TLS, X.509 certificates, OCSP, ECDSA, AES, GCM, ChaCha20Poly1305,
+McEliece, bcrypt, and quite a few other things. It also provides a `botan`
+command line tool for various cryptographic operations, the source for which
+also helps demonstrate usage of the library.
Development is coordinated on `GitHub <https://github.com/randombit/botan>`_
and contributions are welcome. Read `doc/hacking.rst` for more
@@ -47,9 +46,9 @@ may also prove useful resources.
In addition to C++, botan has a C89 API specifically designed to be easy
to call from other languages. A Python binding using ctypes is included,
-there are also bindings for
+there are also partial bindings for
`Node.js <https://github.com/justinfreitag/node-botan>`_ and
-`OCaml <https://github.com/randombit/botan-ocaml>`_
+`OCaml <https://github.com/randombit/botan-ocaml>`_ among others.
There is also a third party open source implementation of
`SSHv2 <https://github.com/cdesjardins/cppssh>`_ using the library.
@@ -151,27 +150,27 @@ the very least ask for review/input on a mailing list such as the
crypto lists. And (if possible) pay a professional cryptographer or
security company to review your design and code.
-Supported Algorithms/Protocols/RFCs
+Find Enclosed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TLS/Public Key Infrastructure
----------------------------------------
-* TLS/DTLS (v1.0 to v1.2), including using preshared keys (TLS-PSK)
- or passwords (TLS-SRP) and most important extensions (including
- secure renegotiation, session tickets, SNI, and ALPN)
-* X.509 certificates (including generating new self-signed and CA
- certs) and CRLs
-* PKIX certificate path validation, OCSP requests, PKCS #10 CSRs
+* TLS and DTLS (v1.0 to v1.2), including using preshared keys
+ (TLS-PSK) and passwords (TLS-SRP) and most important extensions,
+ such as session tickets, SNI, and ALPN.
+* X.509v3 certificates and CRLs
+* PKIX certificate path validation with multiple test suites for same
+* OCSP requests
+* PKCS #10 certificate requests
Public Key Cryptography
----------------------------------------
-* Encryption algorithms RSA and ElGamal (with OAEP or PKCS #1 v1.5)
-* Signature algorithms RSA, DSA, ECDSA, GOST 34.10-2001, Nyberg-Rueppel,
- Rabin-Williams (with PSS, PKCS #1 v1.5, or X9.31)
-* Diffie-Hellman, ECDH using NIST/Brainpool prime groups, Curve25519
-* McEliece code based encryption providing a KEM scheme
+* Encryption with RSA and ElGamal
+* Signatures with RSA, DSA, ECDSA, GOST 34.10-2001, Nyberg-Rueppel, Rabin-Williams
+* Key agreement with Diffie-Hellman, ECDH, Curve25519, and McEliece
+* Padding schemes OAEP, PSS, PKCS #1 v1.5, X9.31
Ciphers and cipher modes
----------------------------------------
@@ -204,8 +203,12 @@ Other Useful Things
----------------------------------------
* Key derivation functions for passwords, including PBKDF2
-* Password hashing functions, including bcrypt
+* Password hashing functions, including bcrypt and a PBKDF based scheme
* General key derivation functions KDF1 and KDF2 from IEEE 1363
+* Format preserving encryption scheme FE1
+* Threshold secret sharing
+* RFC 3394 keywrapping
+* Rivest's all or nothing transform
Recommended Algorithms
----------------------------------------
@@ -228,3 +231,4 @@ currently recommend using:
or ECDSA with P-256/SHA-256 or P-384/SHA-384
* Key Agreement: ECDH P-256 or Curve25519, with KDF2(SHA-256)
+ Or McEliece if you are concerned about attacks by quantum computers.
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index 31277ff0c..8b950177f 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -101,10 +101,66 @@
* RNGs will automatically poll the system for additional seed material
* after producing this many bytes of output.
*/
-#define BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED 512
+#define BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED 4096
#define BOTAN_RNG_RESEED_POLL_BITS 128
#define BOTAN_RNG_AUTO_RESEED_TIMEOUT std::chrono::milliseconds(10)
-#define BOTAN_RNG_RESEED_DEFAULT_TIMEOUT std::chrono::milliseconds(100)
+#define BOTAN_RNG_RESEED_DEFAULT_TIMEOUT std::chrono::milliseconds(50)
+
+/*
+* Specifies (in order) the list of entropy sources that will be used
+* to seed an in-memory RNG. The first few in the default list
+* ("timer", "proc_info", etc) do not count as contributing any entropy
+* but are included as they are fast and help protect against a
+* seriously broken system RNG.
+*/
+#define BOTAN_ENTROPY_DEFAULT_SOURCES \
+ { "timestamp", "rdrand", "proc_info", \
+ "darwin_secrandom", "dev_random", "win32_cryptoapi", "egd", \
+ "proc_walk", "system_stats", "unix_procs" }
+
+/*
+* These control the RNG used by the system RNG interface
+*/
+#define BOTAN_SYSTEM_RNG_DEVICE "/dev/urandom"
+#define BOTAN_SYSTEM_RNG_CRYPTOAPI_PROV_TYPE PROV_RSA_FULL
+
+/*
+* These paramaters control how many bytes to read from the system
+* PRNG, and how long to block if applicable.
+*
+* Timeout is ignored on Windows as CryptGenRandom doesn't block
+*/
+#define BOTAN_SYSTEM_RNG_POLL_DEVICES { "/dev/urandom", "/dev/random", "/dev/srandom" }
+
+#define BOTAN_SYSTEM_RNG_POLL_REQUEST 64
+#define BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS 20
+
+#define BOTAN_ENTROPY_EGD_PATHS { "/var/run/egd-pool", "/dev/egd-pool" }
+#define BOTAN_ENTROPY_PROC_FS_PATH "/proc"
+#define BOTAN_ENTROPY_SAFE_PATHS { "/bin", "/sbin", "/usr/bin", "/usr/sbin" }
+
+/*
+* Defines the static entropy estimates which each type of source uses.
+* These values are expressed as the bits of entropy per byte of
+* output (in double format) and should be conservative. These are used
+* unless an entropy source has some more specific opinion on the entropy
+* of the underlying source.
+*/
+
+// We include some high resolution timestamps because it can't hurt
+#define BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS 0
+
+// Data which is system or process specific, but otherwise static
+#define BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA 0
+
+// Binary system data of some kind
+#define BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA 0.5
+
+// Human readable text which has entropy
+#define BOTAN_ENTROPY_ESTIMATE_SYSTEM_TEXT (1.0 / 64)
+
+// The output of a PRNG we are trusting to be strong
+#define BOTAN_ENTROPY_ESTIMATE_STRONG_RNG 7.0
/* Should we use GCC-style inline assembler? */
#if !defined(BOTAN_USE_GCC_INLINE_ASM) && defined(__GNUG__)
@@ -128,6 +184,17 @@
#define BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS
#endif
+/*
+* If no way of dynamically determining the cache line size for the
+* system exists, this value is used as the default. Used by the side
+* channel countermeasures rather than for alignment purposes, so it is
+* better to be on the smaller side if the exact value cannot be
+* determined. Typically 32 or 64 bytes on modern CPUs.
+*/
+#if !defined(BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE)
+ #define BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE 32
+#endif
+
%{target_compiler_defines}
#if defined(_MSC_VER)
diff --git a/src/build-data/os/aix.txt b/src/build-data/os/aix.txt
index 546fbf9ad..369b720c4 100644
--- a/src/build-data/os/aix.txt
+++ b/src/build-data/os/aix.txt
@@ -2,5 +2,4 @@ os_type unix
<target_features>
gettimeofday
-getsid
</target_features>
diff --git a/src/build-data/os/cygwin.txt b/src/build-data/os/cygwin.txt
index 7788cd3ca..ee934f787 100644
--- a/src/build-data/os/cygwin.txt
+++ b/src/build-data/os/cygwin.txt
@@ -12,6 +12,5 @@ doc_dir docs
<target_features>
gettimeofday
-getsid
timegm
</target_features>
diff --git a/src/build-data/os/darwin.txt b/src/build-data/os/darwin.txt
index 56285ccf7..b1f2363dc 100644
--- a/src/build-data/os/darwin.txt
+++ b/src/build-data/os/darwin.txt
@@ -16,7 +16,6 @@ gettimeofday
gmtime_r
memset_s
readdir
-getsid
timegm
</target_features>
diff --git a/src/build-data/os/freebsd.txt b/src/build-data/os/freebsd.txt
index 32767cb1f..510a7accd 100644
--- a/src/build-data/os/freebsd.txt
+++ b/src/build-data/os/freebsd.txt
@@ -7,6 +7,5 @@ posix_mlock
gmtime_r
dlopen
readdir
-getsid
timegm
</target_features>
diff --git a/src/build-data/os/haiku.txt b/src/build-data/os/haiku.txt
index 981ce6795..8e35e76eb 100644
--- a/src/build-data/os/haiku.txt
+++ b/src/build-data/os/haiku.txt
@@ -8,7 +8,6 @@ doc_dir system/documentation
<target_features>
gettimeofday
gmtime_r
-getsid
</target_features>
<aliases>
diff --git a/src/build-data/os/hpux.txt b/src/build-data/os/hpux.txt
index 726b0b960..22d51ef0a 100644
--- a/src/build-data/os/hpux.txt
+++ b/src/build-data/os/hpux.txt
@@ -2,7 +2,6 @@ os_type unix
<target_features>
gettimeofday
-getsid
</target_features>
<aliases>
diff --git a/src/build-data/os/irix.txt b/src/build-data/os/irix.txt
index 546fbf9ad..369b720c4 100644
--- a/src/build-data/os/irix.txt
+++ b/src/build-data/os/irix.txt
@@ -2,5 +2,4 @@ os_type unix
<target_features>
gettimeofday
-getsid
</target_features>
diff --git a/src/build-data/os/linux.txt b/src/build-data/os/linux.txt
index c83e57afa..bb65055e4 100644
--- a/src/build-data/os/linux.txt
+++ b/src/build-data/os/linux.txt
@@ -11,7 +11,6 @@ posix_mlock
gmtime_r
dlopen
readdir
-getsid
timegm
</target_features>
diff --git a/src/build-data/os/netbsd.txt b/src/build-data/os/netbsd.txt
index 32767cb1f..510a7accd 100644
--- a/src/build-data/os/netbsd.txt
+++ b/src/build-data/os/netbsd.txt
@@ -7,6 +7,5 @@ posix_mlock
gmtime_r
dlopen
readdir
-getsid
timegm
</target_features>
diff --git a/src/build-data/os/qnx.txt b/src/build-data/os/qnx.txt
index 71c85eb3c..4c0965764 100644
--- a/src/build-data/os/qnx.txt
+++ b/src/build-data/os/qnx.txt
@@ -6,5 +6,4 @@ gettimeofday
posix_mlock
gmtime_r
dlopen
-getsid
</target_features>
diff --git a/src/build-data/os/solaris.txt b/src/build-data/os/solaris.txt
index 52749e397..0ed785036 100644
--- a/src/build-data/os/solaris.txt
+++ b/src/build-data/os/solaris.txt
@@ -6,7 +6,6 @@ install_cmd_exec '/usr/ucb/install -m 755'
<target_features>
posix_mlock
gettimeofday
-getsid
</target_features>
<aliases>
diff --git a/src/cmd/rng.cpp b/src/cmd/rng.cpp
index 901607bea..b89376b4c 100644
--- a/src/cmd/rng.cpp
+++ b/src/cmd/rng.cpp
@@ -49,7 +49,7 @@ int rng(int argc, char* argv[])
return total_collected >= amt;
});
- EntropySource::poll_available_sources(accum);
+ Entropy_Sources::global_sources().poll(accum);
}
}
catch(std::exception& e)
diff --git a/src/lib/asn1/oid_lookup/default.cpp b/src/lib/asn1/oid_lookup/default.cpp
index 0e23b18a2..2034ab25c 100644
--- a/src/lib/asn1/oid_lookup/default.cpp
+++ b/src/lib/asn1/oid_lookup/default.cpp
@@ -202,13 +202,9 @@ const char* default_oid_list()
"1.3.6.1.5.5.7.48.1.1 = PKIX.OCSP.BasicResponse" "\n"
// ECC param sets
- "1.3.132.0.6 = secp112r1" "\n"
- "1.3.132.0.7 = secp112r2" "\n"
"1.3.132.0.8 = secp160r1" "\n"
"1.3.132.0.9 = secp160k1" "\n"
"1.3.132.0.10 = secp256k1" "\n"
- "1.3.132.0.28 = secp128r1" "\n"
- "1.3.132.0.29 = secp128r2" "\n"
"1.3.132.0.30 = secp160r2" "\n"
"1.3.132.0.31 = secp192k1" "\n"
"1.3.132.0.32 = secp224k1" "\n"
@@ -232,6 +228,8 @@ const char* default_oid_list()
"1.3.36.3.3.2.8.1.1.11 = brainpool384r1" "\n"
"1.3.36.3.3.2.8.1.1.13 = brainpool512r1" "\n"
+ "1.3.6.1.4.1.8301.3.1.2.9.0.38 = secp521r1" "\n"
+
"1.2.643.2.2.35.1 = gost_256A" "\n"
"1.2.643.2.2.36.0 = gost_256A" "\n"
diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp
index 61cc9d777..0da4ff0a0 100644
--- a/src/lib/block/aes/aes.cpp
+++ b/src/lib/block/aes/aes.cpp
@@ -1,14 +1,47 @@
/*
* AES
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2010,2015 Jack Lloyd
*
-* Based on the public domain reference implemenation
+* Based on the public domain reference implementation by Paulo Baretto
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#include <botan/aes.h>
#include <botan/loadstor.h>
+#include <botan/cpuid.h>
+#include <botan/internal/bit_ops.h>
+
+/*
+* This implementation is based on table lookups which are known to be
+* vulnerable to timing and cache based side channel attacks. Some
+* countermeasures are used which may be helpful in some situations:
+*
+* - Small tables are used in the first and last rounds.
+*
+* - The TE and TD tables are computed at runtime to avoid flush+reload
+* attacks using clflush. As different processes will not share the
+* same underlying table data, an attacker can't manipulate another
+* processes cache lines via their shared reference to the library
+* read only segment.
+*
+* - Each cache line of the lookup tables is accessed at the beginning
+* of each call to encrypt or decrypt. (See the Z variable below)
+*
+* If available SSSE3 or AES-NI are used instead of this version, as both
+* are faster and immune to side channel attacks.
+*
+* Some AES cache timing papers for reference:
+*
+* "Software mitigations to hedge AES against cache-based software side
+* channel vulnerabilities" https://eprint.iacr.org/2006/052.pdf
+*
+* "Cache Games - Bringing Access-Based Cache Attacks on AES to Practice"
+* http://www.ieee-security.org/TC/SP2011/PAPERS/2011/paper031.pdf
+*
+* "Cache-Collision Timing Attacks Against AES" Bonneau, Mironov
+* http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.88.4753
+*/
namespace Botan {
@@ -62,351 +95,56 @@ const byte SD[256] = {
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
0x55, 0x21, 0x0C, 0x7D };
-const u32bit TE[1024] = {
- 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD,
- 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D,
- 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D,
- 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
- 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7,
- 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A,
- 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4,
- 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
- 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1,
- 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D,
- 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E,
- 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
- 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E,
- 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C,
- 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46,
- 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
- 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7,
- 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81,
- 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE,
- 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
- 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A,
- 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F,
- 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2,
- 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
- 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E,
- 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C,
- 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256,
- 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
- 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4,
- 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7,
- 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA,
- 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
- 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1,
- 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21,
- 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42,
- 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
- 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158,
- 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133,
- 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22,
- 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
- 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,
- 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11,
- 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A, 0xA5C66363, 0x84F87C7C,
- 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5,
- 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7,
- 0xE64DABAB, 0x9AEC7676, 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D,
- 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, 0xEC41ADAD, 0x67B3D4D4,
- 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0,
- 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F,
- 0x02F5F7F7, 0x4F83CCCC, 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1,
- 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515, 0x0C080404, 0x5295C7C7,
- 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A,
- 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727,
- 0xCD7FB2B2, 0x9FEA7575, 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A,
- 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0, 0xF6A45252, 0x4D763B3B,
- 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484,
- 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC,
- 0xC879B1B1, 0xEDB65B5B, 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939,
- 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF, 0x6BBBD0D0, 0x2AC5EFEF,
- 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585,
- 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C,
- 0xBA259F9F, 0xE34BA8A8, 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F,
- 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, 0xDF63BCBC, 0xC177B6B6,
- 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2,
- 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797,
- 0xCC884444, 0x392E1717, 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D,
- 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, 0xA0C06060, 0x98198181,
- 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888,
- 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E,
- 0x1D160B0B, 0x76ADDBDB, 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A,
- 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C, 0x5D9FC2C2, 0x6EBDD3D3,
- 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979,
- 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5,
- 0xD29C4E4E, 0xE049A9A9, 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA,
- 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808, 0xD56FBABA, 0x88F07878,
- 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6,
- 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD,
- 0x860D8B8B, 0x850F8A8A, 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666,
- 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E, 0xA3C26161, 0x5F6A3535,
- 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E,
- 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9,
- 0x89078E8E, 0xA7339494, 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9,
- 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, 0x8F038C8C, 0xF859A1A1,
- 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868,
- 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454,
- 0xD66DBBBB, 0x3A2C1616, 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B,
- 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, 0x30506030, 0x01030201,
- 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76,
- 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259,
- 0x47C98E47, 0xF00BFBF0, 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF,
- 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0, 0xB7C275B7, 0xFD1CE1FD,
- 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC,
- 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8,
- 0x31536231, 0x153F2A15, 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3,
- 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A, 0x07090E07, 0x12362412,
- 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75,
- 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E,
- 0x5AEEB45A, 0xA0FB5BA0, 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3,
- 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, 0x53F5A653, 0xD168B9D1,
- 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B,
- 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C,
- 0x58E8B058, 0xCF4A85CF, 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB,
- 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, 0x45CF8A45, 0xF910E9F9,
- 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8,
- 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D,
- 0x38487038, 0xF504F1F5, 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221,
- 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, 0xCD4C81CD, 0x0C14180C,
- 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17,
- 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D,
- 0x192B3219, 0x7395E673, 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC,
- 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88, 0x46CA8C46, 0xEE29C7EE,
- 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB,
- 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06,
- 0x246C4824, 0x5CE4B85C, 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462,
- 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279, 0xE732D5E7, 0xC8438BC8,
- 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9,
- 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A,
- 0xAEE947AE, 0x08181008, 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E,
- 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, 0xE823CBE8, 0xDD7CA1DD,
- 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A,
- 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603,
- 0xF601F7F6, 0x0E121C0E, 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9,
- 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, 0xE138D9E1, 0xF813EBF8,
- 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394,
- 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55,
- 0x28785028, 0xDF7AA5DF, 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D,
- 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068, 0x41C38241, 0x99B02999,
- 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16,
- 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6,
- 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56,
- 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 0xCACA458F, 0x82829D1F,
- 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
- 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753,
- 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C,
- 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 0x34345C68, 0xA5A5F451,
- 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
- 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137,
- 0x05050F0A, 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF,
- 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, 0x83839E1D,
- 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
- 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD,
- 0x2F2F715E, 0x84849713, 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1,
- 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D,
- 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
- 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A,
- 0x33335566, 0x85859411, 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE,
- 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D,
- 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
- 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5,
- 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3,
- 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 0xC4C45793, 0xA7A7F255,
- 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
- 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54,
- 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28,
- 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 0xE0E03BDB, 0x32325664,
- 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
- 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431,
- 0xE4E437D3, 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA,
- 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, 0x5656FAAC,
- 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
- 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157,
- 0xB4B4C773, 0xC6C65197, 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E,
- 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C,
- 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
- 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899,
- 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322,
- 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C,
- 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
- 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7,
- 0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E,
- 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C };
-
-const u32bit TD[1024] = {
- 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1,
- 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25,
- 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, 0xDEB15A49, 0x25BA1B67,
- 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6,
- 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3,
- 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD,
- 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, 0x63DF4A18, 0xE51A3182,
- 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94,
- 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2,
- 0xE31F8F57, 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5,
- 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, 0xA779B492,
- 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A,
- 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA,
- 0x5E719F06, 0xBD6E1051, 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46,
- 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997,
- 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB,
- 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48,
- 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927,
- 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F,
- 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16,
- 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD,
- 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD,
- 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, 0x8B432976, 0xCB23C6DC,
- 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120,
- 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3,
- 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422,
- 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, 0x87494EC7, 0xD938D1C1,
- 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4,
- 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8,
- 0x2E39F75E, 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3,
- 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, 0x6E5918F4,
- 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6,
- 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331,
- 0xC6A59430, 0x35A266C0, 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815,
- 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D,
- 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F,
- 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252,
- 0xE9105633, 0x6DD64713, 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89,
- 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F,
- 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86,
- 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C,
- 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190,
- 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742, 0x5051F4A7, 0x537E4165,
- 0xC31A17A4, 0x963A275E, 0xCB3BAB6B, 0xF11F9D45, 0xABACFA58, 0x934BE303,
- 0x552030FA, 0xF6AD766D, 0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB,
- 0x80263544, 0x8FB562A3, 0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0,
- 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9, 0xE7038F5F, 0x9515929C,
- 0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421, 0x2949E069, 0x448EC9C8,
- 0x6A75C289, 0x78F48E79, 0x6B99583E, 0xDD27B971, 0xB6BEE14F, 0x17F088AD,
- 0x66C920AC, 0xB47DCE3A, 0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F,
- 0xE0B16477, 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B, 0x58704868, 0x198F45FD,
- 0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02, 0x57E31F8F, 0x2A6655AB,
- 0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, 0xF2302887, 0xB223BFA5,
- 0xBA02036A, 0x5CED1682, 0x2B8ACF1C, 0x92A779B4, 0xF0F307F2, 0xA14E69E2,
- 0xCD65DAF4, 0xD50605BE, 0x1FD13462, 0x8AC4A6FE, 0x9D342E53, 0xA0A2F355,
- 0x32058AE1, 0x75A4F6EB, 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10,
- 0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, 0xB591548D, 0x0571C45D,
- 0x6F0406D4, 0xFF605015, 0x241998FB, 0x97D6BDE9, 0xCC894043, 0x7767D99E,
- 0xBDB0E842, 0x8807898B, 0x38E7195B, 0xDB79C8EE, 0x47A17C0A, 0xE97C420F,
- 0xC9F8841E, 0x00000000, 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72,
- 0xFBFD0EFF, 0x560F8538, 0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6,
- 0xD19B5B54, 0x3A24362E, 0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, 0x9E1B9B91,
- 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A, 0x0AE293BA, 0xE5C0A02A,
- 0x433C22E0, 0x1D121B17, 0x0B0E090D, 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9,
- 0x8557F119, 0x4CAF7507, 0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5,
- 0xC544663B, 0x345BFB7E, 0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1,
- 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611, 0x7D854A24, 0xF8D2BB3D,
- 0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230, 0xEC0D8652, 0xD077C1E3,
- 0x6C2BB316, 0x99A970B9, 0xFA119448, 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F,
- 0xD8567D2C, 0xEF223390, 0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B,
- 0xCFA6F581, 0x28A57ADE, 0x26DAB78E, 0xA43FADBF, 0xE42C3A9D, 0x0D507892,
- 0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, 0xF582C3AF,
- 0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, 0x3BC8AC99, 0xA710187D,
- 0x6EE89C63, 0x7BDB3BBB, 0x09CD2678, 0xF46E5918, 0x01EC9AB7, 0xA8834F9A,
- 0x65E6956E, 0x7EAAFFE6, 0x0821BCCF, 0xE6EF15E8, 0xD9BAE79B, 0xCE4A6F36,
- 0xD4EA9F09, 0xD629B07C, 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266,
- 0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, 0x4AF10498, 0xF741ECDA,
- 0x0E7FCD50, 0x2F1791F6, 0x8D764DD6, 0x4D43EFB0, 0x54CCAA4D, 0xDFE49604,
- 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, 0x7F466551, 0x049D5EEA, 0x5D018C35,
- 0x73FA8774, 0x2EFB0B41, 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647,
- 0x8C9AD761, 0x7A37A10C, 0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9,
- 0xEDE11CE5, 0x3C7A47B1, 0x599CD2DF, 0x3F55F273, 0x791814CE, 0xBF73C737,
- 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB, 0x81CAAFF3, 0x3EB968C4,
- 0x2C382434, 0x5FC2A340, 0x72161DC3, 0x0CBCE225, 0x8B283C49, 0x41FF0D95,
- 0x7139A801, 0xDE080CB3, 0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6,
- 0x74486C5C, 0x42D0B857, 0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27,
- 0x6BCB3BAB, 0x45F11F9D, 0x58ABACFA, 0x03934BE3, 0xFA552030, 0x6DF6AD76,
- 0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, 0xA38FB562,
- 0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, 0x7502C32F, 0xF012814C,
- 0x97A38D46, 0xF9C66BD3, 0x5FE7038F, 0x9C951592, 0x7AEBBF6D, 0x59DA9552,
- 0x832DD4BE, 0x21D35874, 0x692949E0, 0xC8448EC9, 0x896A75C2, 0x7978F48E,
- 0x3E6B9958, 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE,
- 0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, 0x77E0B164, 0xAE84BB6B,
- 0xA01CFE81, 0x2B94F908, 0x68587048, 0xFD198F45, 0x6C8794DE, 0xF8B7527B,
- 0xD323AB73, 0x02E2724B, 0x8F57E31F, 0xAB2A6655, 0x2807B2EB, 0xC2032FB5,
- 0x7B9A86C5, 0x08A5D337, 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16,
- 0x1C2B8ACF, 0xB492A779, 0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605,
- 0x621FD134, 0xFE8AC4A6, 0x539D342E, 0x55A0A2F3, 0xE132058A, 0xEB75A4F6,
- 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E, 0x8AF93E21, 0x063D96DD,
- 0x05AEDD3E, 0xBD464DE6, 0x8DB59154, 0x5D0571C4, 0xD46F0406, 0x15FF6050,
- 0xFB241998, 0xE997D6BD, 0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789,
- 0x5B38E719, 0xEEDB79C8, 0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000,
- 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A, 0xFFFBFD0E, 0x38560F85,
- 0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C, 0x54D19B5B, 0x2E3A2436,
- 0x67B10C0A, 0xE70F9357, 0x96D2B4EE, 0x919E1B9B, 0xC54F80C0, 0x20A261DC,
- 0x4B695A77, 0x1A161C12, 0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B,
- 0x0D0B0E09, 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E, 0x198557F1, 0x074CAF75,
- 0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72, 0x3BC54466, 0x7E345BFB,
- 0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, 0xDCCAD731, 0x85104263,
- 0x22401397, 0x112084C6, 0x247D854A, 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729,
- 0x2F4B1D9E, 0x30F3DCB2, 0x52EC0D86, 0xE3D077C1, 0x166C2BB3, 0xB999A970,
- 0x48FA1194, 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233,
- 0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, 0xDE28A57A,
- 0x8E26DAB7, 0xBFA43FAD, 0x9DE42C3A, 0x920D5078, 0xCC9B6A5F, 0x4662547E,
- 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, 0xAFF582C3, 0x80BE9F5D, 0x937C69D0,
- 0x2DA96FD5, 0x12B3CF25, 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B,
- 0x7809CD26, 0x18F46E59, 0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF,
- 0xCF0821BC, 0xE8E6EF15, 0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, 0x7CD629B0,
- 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2, 0xBC37744E, 0xCAA6FC82,
- 0xD0B0E090, 0xD81533A7, 0x984AF104, 0xDAF741EC, 0x500E7FCD, 0xF62F1791,
- 0xD68D764D, 0xB04D43EF, 0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A,
- 0x1FB8C12C, 0x517F4665, 0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B,
- 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6, 0x618C9AD7, 0x0C7A37A1,
- 0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761, 0xE5EDE11C, 0xB13C7A47,
- 0xDF599CD2, 0x733F55F2, 0xCE791814, 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD,
- 0x6F14DF3D, 0xDB867844, 0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3,
- 0xC372161D, 0x250CBCE2, 0x498B283C, 0x9541FF0D, 0x017139A8, 0xB3DE080C,
- 0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532, 0x5C74486C, 0x5742D0B8,
- 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F,
- 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5,
- 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 0xB15A49DE, 0xBA1B6725,
- 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
- 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358,
- 0xE0692949, 0xC9C8448E, 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27,
- 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 0xDF4A1863, 0x1A3182E5,
- 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
- 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272,
- 0x1F8F57E3, 0x55AB2A66, 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3,
- 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 0xCF1C2B8A, 0x79B492A7,
- 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
- 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40,
- 0x719F065E, 0x6E1051BD, 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D,
- 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 0x98FB2419, 0xBDE997D6,
- 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
- 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832,
- 0x1170AC1E, 0x5A724E6C, 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736,
- 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 0x0A67B10C, 0x57E70F93,
- 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
- 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2,
- 0xB6A8B92D, 0x1EA9C814, 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3,
- 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 0x4329768B, 0x23C6DCCB,
- 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
- 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC,
- 0x8652EC0D, 0xC1E3D077, 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247,
- 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 0x494EC787, 0x38D1C1D9,
- 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
- 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890,
- 0x39F75E2E, 0xC3AFF582, 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF,
- 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 0x267809CD, 0x5918F46E,
- 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
- 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A,
- 0xA59430C6, 0xA266C035, 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533,
- 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 0x4DD68D76, 0xEFB04D43,
- 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
- 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292,
- 0x105633E9, 0xD647136D, 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB,
- 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 0xD2DF599C, 0xF2733F55,
- 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
- 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC,
- 0x3C498B28, 0x0D9541FF, 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064,
- 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 };
+inline byte xtime(byte s) { return (s << 1) ^ ((s >> 7) * 0x1B); }
+inline byte xtime4(byte s) { return xtime(xtime(s)); }
+inline byte xtime8(byte s) { return xtime(xtime(xtime(s))); }
+
+inline byte xtime3(byte s) { return xtime(s) ^ s; }
+inline byte xtime9(byte s) { return xtime8(s) ^ s; }
+inline byte xtime11(byte s) { return xtime8(s) ^ xtime(s) ^ s; }
+inline byte xtime13(byte s) { return xtime8(s) ^ xtime4(s) ^ s; }
+inline byte xtime14(byte s) { return xtime8(s) ^ xtime4(s) ^ xtime(s); }
+
+const std::vector<u32bit>& AES_TE()
+ {
+ auto compute_TE = []() {
+ std::vector<u32bit> TE(1024);
+ for(size_t i = 0; i != 256; ++i)
+ {
+ const byte s = SE[i];
+ const u32bit x = make_u32bit(xtime(s), s, s, xtime3(s));
+
+ TE[i] = x;
+ TE[i+256] = rotate_right(x, 8);
+ TE[i+512] = rotate_right(x, 16);
+ TE[i+768] = rotate_right(x, 24);
+ }
+ return TE;
+ };
+
+ static std::vector<u32bit> TE = compute_TE();
+ return TE;
+ }
+
+const std::vector<u32bit>& AES_TD()
+ {
+ auto compute_TD = []() {
+ std::vector<u32bit> TD(1024);
+ for(size_t i = 0; i != 256; ++i)
+ {
+ const byte s = SD[i];
+ const u32bit x = make_u32bit(xtime14(s), xtime9(s), xtime13(s), xtime11(s));
+
+ TD[i] = x;
+ TD[i+256] = rotate_right(x, 8);
+ TD[i+512] = rotate_right(x, 16);
+ TD[i+768] = rotate_right(x, 24);
+ }
+ return TD;
+ };
+ static std::vector<u32bit> TD = compute_TD();
+ return TD;
+ }
/*
* AES Encryption
@@ -418,12 +156,17 @@ void aes_encrypt_n(const byte in[], byte out[],
{
BOTAN_ASSERT(EK.size() && ME.size() == 16, "Key was set");
- const size_t BLOCK_SIZE = 16;
+ const size_t cache_line_size = CPUID::cache_line_size();
- const u32bit* TE0 = TE;
- const u32bit* TE1 = TE + 256;
- const u32bit* TE2 = TE + 512;
- const u32bit* TE3 = TE + 768;
+ const std::vector<u32bit>& TE = AES_TE();
+
+ // Hit every cache line of TE
+ u32bit Z = 0;
+ for(size_t i = 0; i < TE.size(); i += cache_line_size / sizeof(u32bit))
+ {
+ Z |= TE[i];
+ }
+ Z &= TE[82]; // this is zero, which hopefully the compiler cannot deduce
for(size_t i = 0; i != blocks; ++i)
{
@@ -432,6 +175,8 @@ void aes_encrypt_n(const byte in[], byte out[],
u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2];
u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3];
+ T0 ^= Z;
+
/* Use only the first 256 entries of the TE table and do the
* rotations directly in the code. This reduces the number of
* cache lines potentially used in the first round from 64 to 16
@@ -462,44 +207,25 @@ void aes_encrypt_n(const byte in[], byte out[],
for(size_t r = 2*4; r < EK.size(); r += 2*4)
{
- T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^
- TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ EK[r];
- T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^
- TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ EK[r+1];
- T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^
- TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ EK[r+2];
- T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^
- TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ EK[r+3];
-
- B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^
- TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[r+4];
- B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^
- TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[r+5];
- B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^
- TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[r+6];
- B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^
- TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[r+7];
+ T0 = EK[r ] ^ TE[get_byte(0, B0) ] ^ TE[get_byte(1, B1) + 256] ^
+ TE[get_byte(2, B2) + 512] ^ TE[get_byte(3, B3) + 768];
+ T1 = EK[r+1] ^ TE[get_byte(0, B1) ] ^ TE[get_byte(1, B2) + 256] ^
+ TE[get_byte(2, B3) + 512] ^ TE[get_byte(3, B0) + 768];
+ T2 = EK[r+2] ^ TE[get_byte(0, B2) ] ^ TE[get_byte(1, B3) + 256] ^
+ TE[get_byte(2, B0) + 512] ^ TE[get_byte(3, B1) + 768];
+ T3 = EK[r+3] ^ TE[get_byte(0, B3) ] ^ TE[get_byte(1, B0) + 256] ^
+ TE[get_byte(2, B1) + 512] ^ TE[get_byte(3, B2) + 768];
+
+ B0 = EK[r+4] ^ TE[get_byte(0, T0) ] ^ TE[get_byte(1, T1) + 256] ^
+ TE[get_byte(2, T2) + 512] ^ TE[get_byte(3, T3) + 768];
+ B1 = EK[r+5] ^ TE[get_byte(0, T1) ] ^ TE[get_byte(1, T2) + 256] ^
+ TE[get_byte(2, T3) + 512] ^ TE[get_byte(3, T0) + 768];
+ B2 = EK[r+6] ^ TE[get_byte(0, T2) ] ^ TE[get_byte(1, T3) + 256] ^
+ TE[get_byte(2, T0) + 512] ^ TE[get_byte(3, T1) + 768];
+ B3 = EK[r+7] ^ TE[get_byte(0, T3) ] ^ TE[get_byte(1, T0) + 256] ^
+ TE[get_byte(2, T1) + 512] ^ TE[get_byte(3, T2) + 768];
}
- /*
- Joseph Bonneau and Ilya Mironov's paper "Cache-Collision Timing
- Attacks Against AES" describes an attack that can recover AES
- keys with as few as 2**13 samples.
-
- http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.88.4753
-
- They recommend using a byte-wide table, which still allows an attack
- but increases the samples required from 2**13 to 2**25:
-
- """In addition to OpenSSL v. 0.9.8.(a), which was used in our
- experiments, the AES implementations of Crypto++ 5.2.1 and
- LibTomCrypt 1.09 use the original Rijndael C implementation with
- very few changes and are highly vulnerable. The AES implementations
- in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but
- use a smaller byte-wide final table which lessens the effectiveness
- of the attacks."""
- */
-
out[ 0] = SE[get_byte(0, B0)] ^ ME[0];
out[ 1] = SE[get_byte(1, B1)] ^ ME[1];
out[ 2] = SE[get_byte(2, B2)] ^ ME[2];
@@ -517,8 +243,8 @@ void aes_encrypt_n(const byte in[], byte out[],
out[14] = SE[get_byte(2, B1)] ^ ME[14];
out[15] = SE[get_byte(3, B2)] ^ ME[15];
- in += BLOCK_SIZE;
- out += BLOCK_SIZE;
+ in += 16;
+ out += 16;
}
}
@@ -531,12 +257,15 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
{
BOTAN_ASSERT(DK.size() && MD.size() == 16, "Key was set");
- const size_t BLOCK_SIZE = 16;
+ const size_t cache_line_size = CPUID::cache_line_size();
+ const std::vector<u32bit>& TD = AES_TD();
- const u32bit* TD0 = TD;
- const u32bit* TD1 = TD + 256;
- const u32bit* TD2 = TD + 512;
- const u32bit* TD3 = TD + 768;
+ u32bit Z = 0;
+ for(size_t i = 0; i < TD.size(); i += cache_line_size / sizeof(u32bit))
+ {
+ Z |= TD[i];
+ }
+ Z &= TD[99]; // this is zero, which hopefully the compiler cannot deduce
for(size_t i = 0; i != blocks; ++i)
{
@@ -545,6 +274,8 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2];
u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3];
+ T0 ^= Z;
+
u32bit B0 = TD[get_byte(0, T0)] ^
rotate_right(TD[get_byte(1, T3)], 8) ^
rotate_right(TD[get_byte(2, T2)], 16) ^
@@ -567,23 +298,23 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
for(size_t r = 2*4; r < DK.size(); r += 2*4)
{
- T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^
- TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ DK[r];
- T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^
- TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ DK[r+1];
- T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^
- TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ DK[r+2];
- T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^
- TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ DK[r+3];
-
- B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^
- TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[r+4];
- B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^
- TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[r+5];
- B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^
- TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[r+6];
- B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^
- TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[r+7];
+ T0 = DK[r ] ^ TD[get_byte(0, B0) ] ^ TD[get_byte(1, B3) + 256] ^
+ TD[get_byte(2, B2) + 512] ^ TD[get_byte(3, B1) + 768];
+ T1 = DK[r+1] ^ TD[get_byte(0, B1) ] ^ TD[get_byte(1, B0) + 256] ^
+ TD[get_byte(2, B3) + 512] ^ TD[get_byte(3, B2) + 768];
+ T2 = DK[r+2] ^ TD[get_byte(0, B2) ] ^ TD[get_byte(1, B1) + 256] ^
+ TD[get_byte(2, B0) + 512] ^ TD[get_byte(3, B3) + 768];
+ T3 = DK[r+3] ^ TD[get_byte(0, B3) ] ^ TD[get_byte(1, B2) + 256] ^
+ TD[get_byte(2, B1) + 512] ^ TD[get_byte(3, B0) + 768];
+
+ B0 = DK[r+4] ^ TD[get_byte(0, T0) ] ^ TD[get_byte(1, T3) + 256] ^
+ TD[get_byte(2, T2) + 512] ^ TD[get_byte(3, T1) + 768];
+ B1 = DK[r+5] ^ TD[get_byte(0, T1) ] ^ TD[get_byte(1, T0) + 256] ^
+ TD[get_byte(2, T3) + 512] ^ TD[get_byte(3, T2) + 768];
+ B2 = DK[r+6] ^ TD[get_byte(0, T2) ] ^ TD[get_byte(1, T1) + 256] ^
+ TD[get_byte(2, T0) + 512] ^ TD[get_byte(3, T3) + 768];
+ B3 = DK[r+7] ^ TD[get_byte(0, T3) ] ^ TD[get_byte(1, T2) + 256] ^
+ TD[get_byte(2, T1) + 512] ^ TD[get_byte(3, T0) + 768];
}
out[ 0] = SD[get_byte(0, B0)] ^ MD[0];
@@ -603,8 +334,8 @@ void aes_decrypt_n(const byte in[], byte out[], size_t blocks,
out[14] = SD[get_byte(2, B1)] ^ MD[14];
out[15] = SD[get_byte(3, B0)] ^ MD[15];
- in += BLOCK_SIZE;
- out += BLOCK_SIZE;
+ in += 16;
+ out += 16;
}
}
@@ -648,6 +379,8 @@ void aes_key_schedule(const byte key[], size_t length,
}
}
+ const std::vector<u32bit>& TD = AES_TD();
+
for(size_t i = 0; i != 4*(rounds+1); i += 4)
{
XDK[i ] = XEK[4*rounds-i ];
diff --git a/src/lib/entropy/beos_stats/es_beos.cpp b/src/lib/entropy/beos_stats/es_beos.cpp
index c0dfdd89b..aa0e257a9 100644
--- a/src/lib/entropy/beos_stats/es_beos.cpp
+++ b/src/lib/entropy/beos_stats/es_beos.cpp
@@ -20,40 +20,40 @@ void BeOS_EntropySource::poll(Entropy_Accumulator& accum)
{
system_info info_sys;
get_system_info(&info_sys);
- accum.add(info_sys, 2);
+ accum.add(info_sys, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
key_info info_key; // current state of the keyboard
get_key_info(&info_key);
- accum.add(info_key, 0);
+ accum.add(info_key, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
team_info info_team;
int32 cookie_team = 0;
while(get_next_team_info(&cookie_team, &info_team) == B_OK)
{
- accum.add(info_team, 2);
+ accum.add(info_team, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
team_id id = info_team.team;
int32 cookie = 0;
thread_info info_thr;
while(get_next_thread_info(id, &cookie, &info_thr) == B_OK)
- accum.add(info_thr, 1);
+ accum.add(info_thr, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
cookie = 0;
image_info info_img;
while(get_next_image_info(id, &cookie, &info_img) == B_OK)
- accum.add(info_img, 1);
+ accum.add(info_img, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
cookie = 0;
sem_info info_sem;
while(get_next_sem_info(id, &cookie, &info_sem) == B_OK)
- accum.add(info_sem, 1);
+ accum.add(info_sem, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
cookie = 0;
area_info info_area;
while(get_next_area_info(id, &cookie, &info_area) == B_OK)
- accum.add(info_area, 2);
+ accum.add(info_area, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
if(accum.polling_finished())
break;
diff --git a/src/lib/entropy/beos_stats/es_beos.h b/src/lib/entropy/beos_stats/es_beos.h
index 2565b9180..db5824f6f 100644
--- a/src/lib/entropy/beos_stats/es_beos.h
+++ b/src/lib/entropy/beos_stats/es_beos.h
@@ -15,10 +15,10 @@ namespace Botan {
/**
* BeOS Entropy Source
*/
-class BeOS_EntropySource : public EntropySource
+class BeOS_EntropySource : public Entropy_Source
{
private:
- std::string name() const override { return "BeOS Statistics"; }
+ std::string name() const override { return "system_stats"; }
void poll(Entropy_Accumulator& accum) override;
};
diff --git a/src/lib/entropy/cryptoapi_rng/es_capi.cpp b/src/lib/entropy/cryptoapi_rng/es_capi.cpp
index 019b55a10..88c8488ad 100644
--- a/src/lib/entropy/cryptoapi_rng/es_capi.cpp
+++ b/src/lib/entropy/cryptoapi_rng/es_capi.cpp
@@ -57,15 +57,15 @@ class CSP_Handle
*/
void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum)
{
- m_buf.resize(32);
+ secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
for(size_t i = 0; i != prov_types.size(); ++i)
{
CSP_Handle csp(prov_types[i]);
- if(size_t got = csp.gen_random(m_buf.data(), m_buf.size()))
+ if(size_t got = csp.gen_random(buf.data(), buf.size()))
{
- accum.add(m_buf.data(), got, 6);
+ accum.add(buf.data(), got, BOTAN_ENTROPY_ESTIMATE_STRONG_RNG);
break;
}
}
diff --git a/src/lib/entropy/cryptoapi_rng/es_capi.h b/src/lib/entropy/cryptoapi_rng/es_capi.h
index 81a5003b2..eb63183e9 100644
--- a/src/lib/entropy/cryptoapi_rng/es_capi.h
+++ b/src/lib/entropy/cryptoapi_rng/es_capi.h
@@ -16,10 +16,10 @@ namespace Botan {
/**
* Win32 CAPI Entropy Source
*/
-class Win32_CAPI_EntropySource : public EntropySource
+class Win32_CAPI_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "Win32 CryptoGenRandom"; }
+ std::string name() const override { return "win32_cryptoapi"; }
void poll(Entropy_Accumulator& accum) override;
@@ -30,7 +30,6 @@ class Win32_CAPI_EntropySource : public EntropySource
Win32_CAPI_EntropySource(const std::string& provs = "");
private:
std::vector<u64bit> prov_types;
- secure_vector<byte> m_buf;
};
}
diff --git a/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp b/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp
index f04b75a12..4f1ed87bd 100644
--- a/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp
+++ b/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp
@@ -15,13 +15,11 @@ namespace Botan {
*/
void Darwin_SecRandom::poll(Entropy_Accumulator& accum)
{
- const size_t ENTROPY_BITS_PER_BYTE = 8;
- const size_t BUF_SIZE = 256;
+ secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
- m_buf.resize(BUF_SIZE);
- if (0 == SecRandomCopyBytes(kSecRandomDefault, m_buf.size(), m_buf.data()))
+ if(0 == SecRandomCopyBytes(kSecRandomDefault, buf.size(), buf.data()))
{
- accum.add(m_buf.data(), m_buf.size(), ENTROPY_BITS_PER_BYTE);
+ accum.add(buf.data(), buf.size(), BOTAN_ENTROPY_ESTIMATE_STRONG_RNG);
}
}
diff --git a/src/lib/entropy/darwin_secrandom/darwin_secrandom.h b/src/lib/entropy/darwin_secrandom/darwin_secrandom.h
index 504d5cc64..970cd7941 100644
--- a/src/lib/entropy/darwin_secrandom/darwin_secrandom.h
+++ b/src/lib/entropy/darwin_secrandom/darwin_secrandom.h
@@ -15,15 +15,12 @@ namespace Botan {
/**
* Entropy source using SecRandomCopyBytes from Darwin's Security.framework
*/
-class Darwin_SecRandom : public EntropySource
+class Darwin_SecRandom : public Entropy_Source
{
public:
- std::string name() const override { return "Darwin SecRandomCopyBytes"; }
+ std::string name() const override { return "darwin_secrandom"; }
void poll(Entropy_Accumulator& accum) override;
-
- private:
- secure_vector<byte> m_buf;
};
}
diff --git a/src/lib/entropy/dev_random/dev_random.cpp b/src/lib/entropy/dev_random/dev_random.cpp
index 526835fea..aca161d64 100644
--- a/src/lib/entropy/dev_random/dev_random.cpp
+++ b/src/lib/entropy/dev_random/dev_random.cpp
@@ -6,7 +6,6 @@
*/
#include <botan/internal/dev_random.h>
-#include <botan/internal/rounding.h>
#include <sys/types.h>
#include <sys/select.h>
@@ -60,11 +59,7 @@ void Device_EntropySource::poll(Entropy_Accumulator& accum)
if(m_devices.empty())
return;
- const size_t ENTROPY_BITS_PER_BYTE = 8;
- const size_t MS_WAIT_TIME = 32;
- const size_t READ_ATTEMPT = 32;
-
- int max_fd = m_devices[0];
+ fd_type max_fd = m_devices[0];
fd_set read_set;
FD_ZERO(&read_set);
for(size_t i = 0; i != m_devices.size(); ++i)
@@ -75,21 +70,21 @@ void Device_EntropySource::poll(Entropy_Accumulator& accum)
struct ::timeval timeout;
- timeout.tv_sec = (MS_WAIT_TIME / 1000);
- timeout.tv_usec = (MS_WAIT_TIME % 1000) * 1000;
+ timeout.tv_sec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS / 1000);
+ timeout.tv_usec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS % 1000) * 1000;
if(::select(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0)
return;
- m_buf.resize(READ_ATTEMPT);
+ secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
for(size_t i = 0; i != m_devices.size(); ++i)
{
if(FD_ISSET(m_devices[i], &read_set))
{
- const ssize_t got = ::read(m_devices[i], m_buf.data(), m_buf.size());
+ const ssize_t got = ::read(m_devices[i], buf.data(), buf.size());
if(got > 0)
- accum.add(m_buf.data(), got, ENTROPY_BITS_PER_BYTE);
+ accum.add(buf.data(), got, BOTAN_ENTROPY_ESTIMATE_STRONG_RNG);
}
}
}
diff --git a/src/lib/entropy/dev_random/dev_random.h b/src/lib/entropy/dev_random/dev_random.h
index 0d0c2df60..f634cf16c 100644
--- a/src/lib/entropy/dev_random/dev_random.h
+++ b/src/lib/entropy/dev_random/dev_random.h
@@ -17,10 +17,10 @@ namespace Botan {
/**
* Entropy source reading from kernel devices like /dev/random
*/
-class Device_EntropySource : public EntropySource
+class Device_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "RNG Device Reader"; }
+ std::string name() const override { return "dev_random"; }
void poll(Entropy_Accumulator& accum) override;
@@ -28,8 +28,6 @@ class Device_EntropySource : public EntropySource
~Device_EntropySource();
private:
typedef int fd_type;
-
- secure_vector<byte> m_buf;
std::vector<fd_type> m_devices;
};
diff --git a/src/lib/entropy/egd/es_egd.cpp b/src/lib/entropy/egd/es_egd.cpp
index d64b87ba1..c3b75e8f5 100644
--- a/src/lib/entropy/egd/es_egd.cpp
+++ b/src/lib/entropy/egd/es_egd.cpp
@@ -137,19 +137,17 @@ EGD_EntropySource::~EGD_EntropySource()
*/
void EGD_EntropySource::poll(Entropy_Accumulator& accum)
{
- const size_t READ_ATTEMPT = 32;
-
std::lock_guard<std::mutex> lock(m_mutex);
- m_buf.resize(READ_ATTEMPT);
+ secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
for(size_t i = 0; i != sockets.size(); ++i)
{
- size_t got = sockets[i].read(m_buf.data(), m_buf.size());
+ size_t got = sockets[i].read(buf.data(), buf.size());
if(got)
{
- accum.add(m_buf.data(), got, 6);
+ accum.add(buf.data(), got, BOTAN_ENTROPY_ESTIMATE_STRONG_RNG);
break;
}
}
diff --git a/src/lib/entropy/egd/es_egd.h b/src/lib/entropy/egd/es_egd.h
index 7f7df1133..0b497a8bd 100644
--- a/src/lib/entropy/egd/es_egd.h
+++ b/src/lib/entropy/egd/es_egd.h
@@ -18,10 +18,10 @@ namespace Botan {
/**
* EGD Entropy Source
*/
-class EGD_EntropySource : public EntropySource
+class EGD_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "EGD/PRNGD"; }
+ std::string name() const override { return "egd"; }
void poll(Entropy_Accumulator& accum) override;
@@ -44,7 +44,6 @@ class EGD_EntropySource : public EntropySource
std::mutex m_mutex;
std::vector<EGD_Socket> sockets;
- secure_vector<byte> m_buf;
};
}
diff --git a/src/lib/entropy/entropy_src.h b/src/lib/entropy/entropy_src.h
index c635b8756..0f4c38358 100644
--- a/src/lib/entropy/entropy_src.h
+++ b/src/lib/entropy/entropy_src.h
@@ -66,18 +66,27 @@ class BOTAN_DLL Entropy_Accumulator
{
add(&v, sizeof(T), entropy_bits_per_byte);
}
+
+ secure_vector<byte>& get_io_buf(size_t sz) { m_io_buf.resize(sz); return m_io_buf; }
private:
std::function<bool (const byte[], size_t, double)> m_accum_fn;
+ secure_vector<byte> m_io_buf;
bool m_done = false;
};
/**
* Abstract interface to a source of entropy
*/
-class BOTAN_DLL EntropySource
+class BOTAN_DLL Entropy_Source
{
public:
- static void poll_available_sources(class Entropy_Accumulator& accum);
+ /*
+ * Return a new entropy source of a particular type, or null
+ * Each entropy source may require substantial resources (eg, a file handle
+ * or socket instance), so try to share them among multiple RNGs, or just
+ * use the preconfigured global list accessed by global_entropy_sources()
+ */
+ static std::unique_ptr<Entropy_Source> create(const std::string& type);
/**
* @return name identifying this entropy source
@@ -90,7 +99,27 @@ class BOTAN_DLL EntropySource
*/
virtual void poll(Entropy_Accumulator& accum) = 0;
- virtual ~EntropySource() {}
+ virtual ~Entropy_Source() {}
+ };
+
+class BOTAN_DLL Entropy_Sources
+ {
+ public:
+ static Entropy_Sources& global_sources();
+
+ void add_source(std::unique_ptr<Entropy_Source> src);
+
+ std::vector<std::string> enabled_sources() const;
+
+ void poll(Entropy_Accumulator& accum);
+ bool poll_just(Entropy_Accumulator& accum, const std::string& src);
+
+ Entropy_Sources() {}
+ Entropy_Sources(const std::vector<std::string>& sources);
+
+ ~Entropy_Sources();
+ private:
+ std::vector<Entropy_Source*> m_srcs;
};
}
diff --git a/src/lib/entropy/entropy_srcs.cpp b/src/lib/entropy/entropy_srcs.cpp
index d57160c88..cbf13d488 100644
--- a/src/lib/entropy/entropy_srcs.cpp
+++ b/src/lib/entropy/entropy_srcs.cpp
@@ -49,83 +49,147 @@
namespace Botan {
-namespace {
-
-std::vector<std::unique_ptr<EntropySource>> get_default_entropy_sources()
+std::unique_ptr<Entropy_Source> Entropy_Source::create(const std::string& name)
{
- std::vector<std::unique_ptr<EntropySource>> sources;
-
+ if(name == "timestamp")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER)
- sources.push_back(std::unique_ptr<EntropySource>(new High_Resolution_Timestamp));
+ return std::unique_ptr<Entropy_Source>(new High_Resolution_Timestamp);
#endif
+ }
+ if(name == "rdrand")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
- sources.push_back(std::unique_ptr<EntropySource>(new Intel_Rdrand));
+ return std::unique_ptr<Entropy_Source>(new Intel_Rdrand);
#endif
+ }
+ if(name == "proc_info")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER)
- sources.push_back(std::unique_ptr<EntropySource>(new UnixProcessInfo_EntropySource));
+ return std::unique_ptr<Entropy_Source>(new UnixProcessInfo_EntropySource);
#endif
+ }
-#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
- sources.push_back(std::unique_ptr<EntropySource>(new Device_EntropySource(
- { "/dev/random", "/dev/srandom", "/dev/urandom" }
- )));
+ if(name == "darwin_secrandom")
+ {
+#if defined(BOTAN_HAS_ENTROPY_SRC_DARWIN_SECRANDOM)
+ return std::unique_ptr<Entropy_Source>(new Darwin_SecRandom);
#endif
+ }
-#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
- sources.push_back(std::unique_ptr<EntropySource>(new Win32_CAPI_EntropySource));
+ if(name == "dev_random")
+ {
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
+ return std::unique_ptr<Entropy_Source>(new Device_EntropySource(BOTAN_SYSTEM_RNG_POLL_DEVICES));
+ }
+
+ if(name == "win32_cryptoapi")
+ {
+#elif defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ return std::unique_ptr<Entropy_Source>(new Win32_CAPI_EntropySource);
#endif
+ }
+ if(name == "proc_walk")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER)
- sources.push_back(std::unique_ptr<EntropySource>(new ProcWalking_EntropySource("/proc")));
+ return std::unique_ptr<Entropy_Source>(new ProcWalking_EntropySource("/proc"));
#endif
+ }
+ if(name == "system_stats")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
- sources.push_back(std::unique_ptr<EntropySource>(new Win32_EntropySource));
-#endif
-
-#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
- sources.push_back(std::unique_ptr<EntropySource>(new BeOS_EntropySource));
+ return std::unique_ptr<Entropy_Source>(new Win32_EntropySource);
+#elif defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ return std::unique_ptr<Entropy_Source>(new BeOS_EntropySource);
#endif
+ }
+ if(name == "unix_procs")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER)
- sources.push_back(std::unique_ptr<EntropySource>(new Unix_EntropySource(
- { "/bin", "/sbin", "/usr/bin", "/usr/sbin" }
- )));
+ return std::unique_ptr<Entropy_Source>(new Unix_EntropySource(BOTAN_ENTROPY_SAFE_PATHS));
#endif
+ }
+ if(name == "egd")
+ {
#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
- sources.push_back(std::unique_ptr<EntropySource>(
- new EGD_EntropySource({ "/var/run/egd-pool", "/dev/egd-pool" })
- ));
+ return std::unique_ptr<Entropy_Source>(new EGD_EntropySource(BOTAN_ENTROPY_EGD_PATHS));
#endif
+ }
-#if defined(BOTAN_HAS_ENTROPY_SRC_DARWIN_SECRANDOM)
- sources.push_back(std::unique_ptr<EntropySource>(new Darwin_SecRandom));
-#endif
+ return std::unique_ptr<Entropy_Source>();
+ }
+void Entropy_Sources::add_source(std::unique_ptr<Entropy_Source> src)
+ {
+ if(src.get())
+ {
+ m_srcs.push_back(src.release());
+ }
+ }
+
+std::vector<std::string> Entropy_Sources::enabled_sources() const
+ {
+ std::vector<std::string> sources;
+ for(size_t i = 0; i != m_srcs.size(); ++i)
+ {
+ sources.push_back(m_srcs[i]->name());
+ }
return sources;
}
-}
+void Entropy_Sources::poll(Entropy_Accumulator& accum)
+ {
+ for(size_t i = 0; i != m_srcs.size(); ++i)
+ {
+ m_srcs[i]->poll(accum);
+ if(accum.polling_goal_achieved())
+ break;
+ }
+ }
-//static
-void EntropySource::poll_available_sources(class Entropy_Accumulator& accum)
+bool Entropy_Sources::poll_just(Entropy_Accumulator& accum, const std::string& the_src)
{
- static std::vector<std::unique_ptr<EntropySource>> g_sources(get_default_entropy_sources());
+ for(size_t i = 0; i != m_srcs.size(); ++i)
+ {
+ if(m_srcs[i]->name() == the_src)
+ {
+ m_srcs[i]->poll(accum);
+ return true;
+ }
+ }
- if(g_sources.empty())
- throw std::runtime_error("No entropy sources enabled at build time, RNG poll failed");
+ return false;
+ }
- size_t poll_attempt = 0;
+Entropy_Sources::Entropy_Sources(const std::vector<std::string>& sources)
+ {
+ for(auto&& src_name : sources)
+ {
+ add_source(Entropy_Source::create(src_name));
+ }
+ }
- while(!accum.polling_finished() && poll_attempt < 16)
+Entropy_Sources::~Entropy_Sources()
+ {
+ for(size_t i = 0; i != m_srcs.size(); ++i)
{
- const size_t src_idx = poll_attempt % g_sources.size();
- g_sources[src_idx]->poll(accum);
- ++poll_attempt;
+ delete m_srcs[i];
+ m_srcs[i] = nullptr;
}
+ m_srcs.clear();
+ }
+
+Entropy_Sources& Entropy_Sources::global_sources()
+ {
+ static Entropy_Sources global_entropy_sources(BOTAN_ENTROPY_DEFAULT_SOURCES);
+
+ return global_entropy_sources;
}
}
diff --git a/src/lib/entropy/hres_timer/hres_timer.cpp b/src/lib/entropy/hres_timer/hres_timer.cpp
index 6efa3b188..0b39c935a 100644
--- a/src/lib/entropy/hres_timer/hres_timer.cpp
+++ b/src/lib/entropy/hres_timer/hres_timer.cpp
@@ -26,16 +26,13 @@ namespace Botan {
*/
void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
{
- // Don't count any timestamps as contributing any entropy
- const double ESTIMATED_ENTROPY_PER_BYTE = 0.0;
-
#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
-#define CLOCK_GETTIME_POLL(src) \
- do { \
- struct timespec ts; \
- ::clock_gettime(src, &ts); \
- accum.add(&ts, sizeof(ts), ESTIMATED_ENTROPY_PER_BYTE); \
+#define CLOCK_GETTIME_POLL(src) \
+ do { \
+ struct timespec ts; \
+ ::clock_gettime(src, &ts); \
+ accum.add(&ts, sizeof(ts), BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); \
} while(0)
#if defined(CLOCK_REALTIME)
@@ -65,7 +62,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
#define STD_CHRONO_POLL(clock) \
do { \
auto timestamp = clock::now().time_since_epoch().count(); \
- accum.add(timestamp, ESTIMATED_ENTROPY_PER_BYTE); \
+ accum.add(timestamp, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); \
} while(0)
STD_CHRONO_POLL(std::chrono::high_resolution_clock);
@@ -109,7 +106,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
#endif
- accum.add(rtc, ESTIMATED_ENTROPY_PER_BYTE);
+ accum.add(rtc, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS);
#endif
@@ -117,7 +114,7 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum)
{
LARGE_INTEGER tv;
::QueryPerformanceCounter(&tv);
- accum.add(tv.QuadPart, ESTIMATED_ENTROPY_PER_BYTE);
+ accum.add(tv.QuadPart, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS);
}
#endif
}
diff --git a/src/lib/entropy/hres_timer/hres_timer.h b/src/lib/entropy/hres_timer/hres_timer.h
index b5b92fd97..93ced283a 100644
--- a/src/lib/entropy/hres_timer/hres_timer.h
+++ b/src/lib/entropy/hres_timer/hres_timer.h
@@ -18,10 +18,10 @@ namespace Botan {
* @note Any results from timers are marked as not contributing entropy
* to the poll, as a local attacker could observe them directly.
*/
-class High_Resolution_Timestamp : public EntropySource
+class High_Resolution_Timestamp : public Entropy_Source
{
public:
- std::string name() const override { return "High Resolution Timestamp"; }
+ std::string name() const override { return "timestamp"; }
void poll(Entropy_Accumulator& accum) override;
};
diff --git a/src/lib/entropy/info.txt b/src/lib/entropy/info.txt
index 77c2669e9..ba5a4044d 100644
--- a/src/lib/entropy/info.txt
+++ b/src/lib/entropy/info.txt
@@ -1 +1 @@
-define ENTROPY_SOURCE 20150201
+define ENTROPY_SOURCE 20151120
diff --git a/src/lib/entropy/proc_walk/proc_walk.cpp b/src/lib/entropy/proc_walk/proc_walk.cpp
index 3d63e5d5a..7ef6a8e26 100644
--- a/src/lib/entropy/proc_walk/proc_walk.cpp
+++ b/src/lib/entropy/proc_walk/proc_walk.cpp
@@ -113,7 +113,6 @@ int Directory_Walker::next_fd()
void ProcWalking_EntropySource::poll(Entropy_Accumulator& accum)
{
const size_t MAX_FILES_READ_PER_POLL = 2048;
- const double ENTROPY_ESTIMATE = 1.0 / (8*1024);
std::lock_guard<std::mutex> lock(m_mutex);
@@ -137,7 +136,7 @@ void ProcWalking_EntropySource::poll(Entropy_Accumulator& accum)
::close(fd);
if(got > 0)
- accum.add(m_buf.data(), got, ENTROPY_ESTIMATE);
+ accum.add(m_buf.data(), got, BOTAN_ENTROPY_ESTIMATE_SYSTEM_TEXT);
if(accum.polling_finished())
break;
diff --git a/src/lib/entropy/proc_walk/proc_walk.h b/src/lib/entropy/proc_walk/proc_walk.h
index ec56f9e2d..b67f71111 100644
--- a/src/lib/entropy/proc_walk/proc_walk.h
+++ b/src/lib/entropy/proc_walk/proc_walk.h
@@ -23,10 +23,10 @@ class File_Descriptor_Source
/**
* File Tree Walking Entropy Source
*/
-class ProcWalking_EntropySource : public EntropySource
+class ProcWalking_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "Proc Walker"; }
+ std::string name() const override { return "proc_walk"; }
void poll(Entropy_Accumulator& accum) override;
diff --git a/src/lib/entropy/rdrand/rdrand.h b/src/lib/entropy/rdrand/rdrand.h
index 9ff6e557f..1fa928641 100644
--- a/src/lib/entropy/rdrand/rdrand.h
+++ b/src/lib/entropy/rdrand/rdrand.h
@@ -16,10 +16,10 @@ namespace Botan {
* Entropy source using the rdrand instruction first introduced on
* Intel's Ivy Bridge architecture.
*/
-class Intel_Rdrand : public EntropySource
+class Intel_Rdrand : public Entropy_Source
{
public:
- std::string name() const override { return "Intel Rdrand"; }
+ std::string name() const override { return "rdrand"; }
void poll(Entropy_Accumulator& accum) override;
};
diff --git a/src/lib/entropy/unix_procs/unix_procs.cpp b/src/lib/entropy/unix_procs/unix_procs.cpp
index c6ad6a700..44d9772e5 100644
--- a/src/lib/entropy/unix_procs/unix_procs.cpp
+++ b/src/lib/entropy/unix_procs/unix_procs.cpp
@@ -43,8 +43,8 @@ size_t concurrent_processes(size_t user_request)
const size_t DEFAULT_CONCURRENT = 2;
const size_t MAX_CONCURRENT = 8;
- if(user_request > 0 && user_request < MAX_CONCURRENT)
- return user_request;
+ if(user_request > 0)
+ return std::min(user_request, MAX_CONCURRENT);
const long online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
@@ -68,18 +68,15 @@ Unix_EntropySource::Unix_EntropySource(const std::vector<std::string>& trusted_p
void UnixProcessInfo_EntropySource::poll(Entropy_Accumulator& accum)
{
- accum.add(::getpid(), 0.0);
- accum.add(::getppid(), 0.0);
- accum.add(::getuid(), 0.0);
- accum.add(::getgid(), 0.0);
-#if defined(BOTAN_TARGET_OS_HAS_GETSID)
- accum.add(::getsid(0), 0.0);
-#endif
- accum.add(::getpgrp(), 0.0);
+ accum.add(::getpid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
+ accum.add(::getppid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
+ accum.add(::getuid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
+ accum.add(::getgid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
+ accum.add(::getpgrp(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
struct ::rusage usage;
::getrusage(RUSAGE_SELF, &usage);
- accum.add(usage, 0.0);
+ accum.add(usage, BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
}
void Unix_EntropySource::Unix_Process::spawn(const std::vector<std::string>& args)
@@ -197,7 +194,6 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum)
return; // still empty, really nothing to try
const size_t MS_WAIT_TIME = 32;
- const double ENTROPY_ESTIMATE = 1.0 / 1024;
m_buf.resize(4096);
@@ -241,7 +237,7 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum)
{
const ssize_t got = ::read(fd, m_buf.data(), m_buf.size());
if(got > 0)
- accum.add(m_buf.data(), got, ENTROPY_ESTIMATE);
+ accum.add(m_buf.data(), got, BOTAN_ENTROPY_ESTIMATE_SYSTEM_TEXT);
else
proc.spawn(next_source());
}
diff --git a/src/lib/entropy/unix_procs/unix_procs.h b/src/lib/entropy/unix_procs/unix_procs.h
index 808d34221..bc2fd87d1 100644
--- a/src/lib/entropy/unix_procs/unix_procs.h
+++ b/src/lib/entropy/unix_procs/unix_procs.h
@@ -20,10 +20,10 @@ namespace Botan {
* effective against local attackers as they can sample from the same
* distribution.
*/
-class Unix_EntropySource : public EntropySource
+class Unix_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "Unix Process Runner"; }
+ std::string name() const override { return "unix_procs"; }
void poll(Entropy_Accumulator& accum) override;
@@ -78,10 +78,10 @@ class Unix_EntropySource : public EntropySource
secure_vector<byte> m_buf;
};
-class UnixProcessInfo_EntropySource : public EntropySource
+class UnixProcessInfo_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "Unix Process Info"; }
+ std::string name() const override { return "proc_info"; }
void poll(Entropy_Accumulator& accum) override;
};
diff --git a/src/lib/entropy/win32_stats/es_win32.cpp b/src/lib/entropy/win32_stats/es_win32.cpp
index 04e441570..52bb24136 100644
--- a/src/lib/entropy/win32_stats/es_win32.cpp
+++ b/src/lib/entropy/win32_stats/es_win32.cpp
@@ -20,31 +20,32 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum)
First query a bunch of basic statistical stuff, though
don't count it for much in terms of contributed entropy.
*/
- accum.add(GetTickCount(), 0);
- accum.add(GetMessagePos(), 0);
- accum.add(GetMessageTime(), 0);
- accum.add(GetInputState(), 0);
- accum.add(GetCurrentProcessId(), 0);
- accum.add(GetCurrentThreadId(), 0);
+ accum.add(GetTickCount(), BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
+ accum.add(GetMessagePos(), BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
+ accum.add(GetMessageTime(), BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
+ accum.add(GetInputState(), BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
+
+ accum.add(GetCurrentProcessId(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
+ accum.add(GetCurrentThreadId(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
- accum.add(sys_info, 1);
+ accum.add(sys_info, BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA);
MEMORYSTATUS mem_info;
GlobalMemoryStatus(&mem_info);
- accum.add(mem_info, 1);
+ accum.add(mem_info, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
POINT point;
GetCursorPos(&point);
- accum.add(point, 1);
+ accum.add(point, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
GetCaretPos(&point);
- accum.add(point, 1);
+ accum.add(point, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
LARGE_INTEGER perf_counter;
QueryPerformanceCounter(&perf_counter);
- accum.add(perf_counter, 0);
+ accum.add(perf_counter, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS);
/*
Now use the Tooltip library to iterate throug various objects on
@@ -53,18 +54,18 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum)
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
-#define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \
- if(!accum.polling_finished()) \
- { \
- DATA_TYPE info; \
- info.dwSize = sizeof(DATA_TYPE); \
- if(FUNC_FIRST(snapshot, &info)) \
- { \
- do \
- { \
- accum.add(info, 1); \
- } while(FUNC_NEXT(snapshot, &info)); \
- } \
+#define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \
+ if(!accum.polling_finished()) \
+ { \
+ DATA_TYPE info; \
+ info.dwSize = sizeof(DATA_TYPE); \
+ if(FUNC_FIRST(snapshot, &info)) \
+ { \
+ do \
+ { \
+ accum.add(info, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); \
+ } while(FUNC_NEXT(snapshot, &info)); \
+ } \
}
TOOLHELP32_ITER(MODULEENTRY32, Module32First, Module32Next);
@@ -86,7 +87,7 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum)
{
do
{
- accum.add(heap_list, 1);
+ accum.add(heap_list, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
if(++heap_lists_found > HEAP_LISTS_MAX)
break;
@@ -101,7 +102,7 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum)
{
if(heap_objs_found++ > HEAP_OBJS_PER_LIST)
break;
- accum.add(heap_entry, 1);
+ accum.add(heap_entry, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA);
} while(Heap32Next(&heap_entry));
}
diff --git a/src/lib/entropy/win32_stats/es_win32.h b/src/lib/entropy/win32_stats/es_win32.h
index 98bfb0e36..958a79e19 100644
--- a/src/lib/entropy/win32_stats/es_win32.h
+++ b/src/lib/entropy/win32_stats/es_win32.h
@@ -15,10 +15,10 @@ namespace Botan {
/**
* Win32 Entropy Source
*/
-class Win32_EntropySource : public EntropySource
+class Win32_EntropySource : public Entropy_Source
{
public:
- std::string name() const override { return "Win32 Statistics"; }
+ std::string name() const override { return "system_stats"; }
void poll(Entropy_Accumulator& accum) override;
};
diff --git a/src/lib/filters/comp_filter.cpp b/src/lib/filters/comp_filter.cpp
index 61ac16f38..f909db4a7 100644
--- a/src/lib/filters/comp_filter.cpp
+++ b/src/lib/filters/comp_filter.cpp
@@ -1,6 +1,7 @@
/*
* Filter interface for compression
* (C) 2014,2015 Jack Lloyd
+* (C) 2015 Matej Kenda
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -23,9 +24,15 @@ Decompression_Filter::Decompression_Filter(const std::string& type, size_t bs) :
Compression_Decompression_Filter::Compression_Decompression_Filter(Transform* transform, size_t bs) :
m_buffersize(std::max<size_t>(256, bs)), m_buffer(m_buffersize)
{
+ if (!transform)
+ {
+ throw std::invalid_argument("Transform is null");
+ }
m_transform.reset(dynamic_cast<Compressor_Transform*>(transform));
if(!m_transform)
+ {
throw std::invalid_argument("Transform " + transform->name() + " is not a compressor");
+ }
}
std::string Compression_Decompression_Filter::name() const
diff --git a/src/lib/math/mp/mp_generic/mp_madd.h b/src/lib/math/mp/mp_generic/mp_madd.h
index 3b0487356..95a1069a4 100644
--- a/src/lib/math/mp/mp_generic/mp_madd.h
+++ b/src/lib/math/mp/mp_generic/mp_madd.h
@@ -10,6 +10,7 @@
#define BOTAN_MP_WORD_MULADD_H__
#include <botan/mp_types.h>
+#include <botan/mul128.h>
namespace Botan {
@@ -23,13 +24,13 @@ namespace Botan {
typedef u64bit dword;
#define BOTAN_HAS_MP_DWORD
#elif (BOTAN_MP_WORD_BITS == 64)
-
- #include <botan/mul128.h>
-
#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
typedef uint128_t dword;
#define BOTAN_HAS_MP_DWORD
+ #else
+ // No native 128 bit integer type; use mul64x64_128 instead
#endif
+
#else
#error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
#endif
diff --git a/src/lib/pubkey/dh/dh.cpp b/src/lib/pubkey/dh/dh.cpp
index f182a7792..3888166bb 100644
--- a/src/lib/pubkey/dh/dh.cpp
+++ b/src/lib/pubkey/dh/dh.cpp
@@ -43,7 +43,7 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
if(x == 0)
{
const BigInt& p = group_p();
- x.randomize(rng, 2 * dl_work_factor(p.bits()));
+ x.randomize(rng, dl_exponent_size(p.bits()));
}
if(y == 0)
diff --git a/src/lib/pubkey/dl_group/dl_group.cpp b/src/lib/pubkey/dl_group/dl_group.cpp
index fbaa67eaa..8e9c35f2a 100644
--- a/src/lib/pubkey/dl_group/dl_group.cpp
+++ b/src/lib/pubkey/dl_group/dl_group.cpp
@@ -55,7 +55,7 @@ DL_Group::DL_Group(RandomNumberGenerator& rng,
else if(type == Prime_Subgroup)
{
if(!qbits)
- qbits = 2 * dl_work_factor(pbits);
+ qbits = dl_exponent_size(pbits);
q = random_prime(rng, qbits);
BigInt X;
diff --git a/src/lib/pubkey/ec_group/named.cpp b/src/lib/pubkey/ec_group/named.cpp
index 9a2497c27..3ee791053 100644
--- a/src/lib/pubkey/ec_group/named.cpp
+++ b/src/lib/pubkey/ec_group/named.cpp
@@ -11,38 +11,6 @@ namespace Botan {
const char* EC_Group::PEM_for_named_group(const std::string& name)
{
- if(name == "secp112r1")
- return
- "-----BEGIN EC PARAMETERS-----"
- "MHQCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDtt8Kr9i415mgHa+"
- "rSCIBA5lnvi6BDkW7t6JEXArIgQdBAlIcjmZWl7na1X5wvCYqJzlr4ckwKI+Dg/3"
- "dQACDwDbfCq/YuNedijfrGVhxQIBAQ=="
- "-----END EC PARAMETERS-----";
-
- if(name == "secp112r2")
- return
- "-----BEGIN EC PARAMETERS-----"
- "MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZc"
- "DvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826V"
- "bpcCDjbfCq/YuNdZfKEFINBLAgEB"
- "-----END EC PARAMETERS-----";
-
- if(name == "secp128r1")
- return
- "-----BEGIN EC PARAMETERS-----"
- "MIGAAgEBMBwGByqGSM49AQECEQD////9////////////////MCQEEP////3/////"
- "//////////wEEOh1ecEQefQ92CSZPCzuXtMEIQQWH/dSi4mbLQwoYHylLFuGz1rI"
- "OVuv6xPALaKS3e16gwIRAP////4AAAAAdaMNG5A4oRUCAQE="
- "-----END EC PARAMETERS-----";
-
- if(name == "secp128r2")
- return
- "-----BEGIN EC PARAMETERS-----"
- "MH8CAQEwHAYHKoZIzj0BAQIRAP////3///////////////8wJAQQ1gMZmNGzu/6/"
- "Wcybv/mu4QQQXu78o4DQKRncLGVYu22KXQQhBHtqpdheVymD5vsyp83rwUAntpFq"
- "iU067nEG/oBfw0tEAhA/////f////74AJHIGE7WjAgEE"
- "-----END EC PARAMETERS-----";
-
if(name == "secp160k1")
return
"-----BEGIN EC PARAMETERS-----"
@@ -154,20 +122,6 @@ const char* EC_Group::PEM_for_named_group(const std::string& name)
"////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB"
"-----END EC PARAMETERS-----";
- if(name == "1.3.6.1.4.1.8301.3.1.2.9.0.38")
- return
- "-----BEGIN EC PARAMETERS-----"
- "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////"
- "//////////////////////////////////////////////////8wgYgEQgH/////"
- "////////////////////////////////////////////////////////////////"
- "/////////////////ARCAFGVPrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ"
- "4VYZOVHsfpN7FlLAvTuxvwc1c9+IPSw08e9FH9RrUD8ABIGFBADGhY4GtwQE6c2e"
- "PstmI5W0QpxkgTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0izwYVqQpv5"
- "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm"
- "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////"
- "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB"
- "-----END EC PARAMETERS-----";
-
if(name == "brainpool160r1")
return
"-----BEGIN EC PARAMETERS-----"
diff --git a/src/lib/pubkey/elgamal/elgamal.cpp b/src/lib/pubkey/elgamal/elgamal.cpp
index 5bcdd5689..4ff3cc47a 100644
--- a/src/lib/pubkey/elgamal/elgamal.cpp
+++ b/src/lib/pubkey/elgamal/elgamal.cpp
@@ -34,7 +34,7 @@ ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng,
x = x_arg;
if(x == 0)
- x.randomize(rng, 2 * dl_work_factor(group_p().bits()));
+ x.randomize(rng, dl_exponent_size(group_p().bits()));
y = power_mod(group_g(), x, group_p());
@@ -112,7 +112,7 @@ ElGamal_Encryption_Operation::raw_encrypt(const byte msg[], size_t msg_len,
if(m >= p)
throw Invalid_Argument("ElGamal encryption: Input is too large");
- BigInt k(rng, 2 * dl_work_factor(p.bits()));
+ BigInt k(rng, dl_exponent_size(p.bits()));
BigInt a = powermod_g_p(k);
BigInt b = mod_p.multiply(m, powermod_y_p(k));
diff --git a/src/lib/pubkey/if_algo/if_algo.cpp b/src/lib/pubkey/if_algo/if_algo.cpp
index d8430b40c..9c49b8dd4 100644
--- a/src/lib/pubkey/if_algo/if_algo.cpp
+++ b/src/lib/pubkey/if_algo/if_algo.cpp
@@ -15,7 +15,7 @@ namespace Botan {
size_t IF_Scheme_PublicKey::estimated_strength() const
{
- return dl_work_factor(n.bits());
+ return if_work_factor(n.bits());
}
AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const
diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h
index 67116a9ec..637e522e4 100644
--- a/src/lib/pubkey/pubkey.h
+++ b/src/lib/pubkey/pubkey.h
@@ -134,7 +134,7 @@ class BOTAN_DLL PK_Signer
const std::string& provider = "");
/**
- * Sign a message.
+ * Sign a message all in one go
* @param in the message to sign as a byte array
* @param length the length of the above byte array
* @param rng the rng to use
@@ -181,6 +181,15 @@ class BOTAN_DLL PK_Signer
void update(const std::vector<byte>& in) { update(in.data(), in.size()); }
/**
+ * Add a message part.
+ * @param in the message part to add
+ */
+ void update(const std::string& in)
+ {
+ update(reinterpret_cast<const byte*>(in.data()), in.size());
+ }
+
+ /**
* Get the signature of the so far processed message (provided by the
* calls to update()).
* @param rng the rng to use
@@ -265,6 +274,15 @@ class BOTAN_DLL PK_Verifier
{ update(in.data(), in.size()); }
/**
+ * Add a message part of the message corresponding to the
+ * signature to be verified.
+ */
+ void update(const std::string& in)
+ {
+ update(reinterpret_cast<const byte*>(in.data()), in.size());
+ }
+
+ /**
* Check the signature of the buffered message, i.e. the one build
* by successive calls to update.
* @param sig the signature to be verified as a byte array
diff --git a/src/lib/pubkey/workfactor.cpp b/src/lib/pubkey/workfactor.cpp
index 46a7be507..5cbd17f09 100644
--- a/src/lib/pubkey/workfactor.cpp
+++ b/src/lib/pubkey/workfactor.cpp
@@ -16,40 +16,42 @@ size_t ecp_work_factor(size_t bits)
return bits / 2;
}
+size_t if_work_factor(size_t bits)
+ {
+ // RFC 3766: k * e^((1.92 + o(1)) * cubrt(ln(n) * (ln(ln(n)))^2))
+ // It estimates k at .02 and o(1) to be effectively zero for sizes of interest
+ const double k = .02;
+
+ // approximates natural logarithm of p
+ const double log2_e = std::log2(std::exp(1));
+ const double log_p = bits / log2_e;
+
+ const double est = 1.92 * std::pow(log_p * std::log(log_p) * std::log(log_p), 1.0/3.0);
+
+ return static_cast<size_t>(std::log2(k) + log2_e * est);
+ }
+
size_t dl_work_factor(size_t bits)
{
+ // Lacking better estimates...
+ return if_work_factor(bits);
+ }
+
+size_t dl_exponent_size(size_t bits)
+ {
/*
- Based on GNFS work factors. Constant is 1.43 times the asymptotic
- value; I'm not sure but I believe that came from a paper on 'real
- world' runtimes, but I don't remember where now.
-
- Sample return values:
- |512| -> 64
- |1024| -> 86
- |1536| -> 102
- |2048| -> 116
- |3072| -> 138
- |4096| -> 155
- |8192| -> 206
-
- For DL algos, we use an exponent of twice the size of the result;
- the assumption is that an arbitrary discrete log on a group of size
- bits would take about 2^n effort, and thus using an exponent of
- size 2^(2*n) implies that all available attacks are about as easy
- (as e.g Pollard's kangaroo algorithm can compute the DL in sqrt(x)
- operations) while minimizing the exponent size for performance
- reasons.
+ This uses a slightly tweaked version of the standard work factor
+ function above. It assumes k is 1 (thus overestimating the strength
+ of the prime group by 5-6 bits), and always returns at least 128 bits
+ (this only matters for very small primes).
*/
-
const size_t MIN_WORKFACTOR = 64;
+ const double log2_e = std::log2(std::exp(1));
+ const double log_p = bits / log2_e;
- // approximates natural logarithm of p
- const double log_p = bits / 1.4426;
-
- const double strength =
- 2.76 * std::pow(log_p, 1.0/3.0) * std::pow(std::log(log_p), 2.0/3.0);
+ const double strength = 1.92 * std::pow(log_p, 1.0/3.0) * std::pow(std::log(log_p), 2.0/3.0);
- return std::max(static_cast<size_t>(strength), MIN_WORKFACTOR);
+ return 2 * std::max<size_t>(MIN_WORKFACTOR, log2_e * strength);
}
}
diff --git a/src/lib/pubkey/workfactor.h b/src/lib/pubkey/workfactor.h
index ab7f6b051..eb86b6d88 100644
--- a/src/lib/pubkey/workfactor.h
+++ b/src/lib/pubkey/workfactor.h
@@ -20,6 +20,25 @@ namespace Botan {
size_t dl_work_factor(size_t prime_group_size);
/**
+* Return the appropriate exponent size to use for a particular prime
+* group. This is twice the size of the estimated cost of breaking the
+* key using an index calculus attack; the assumption is that if an
+* arbitrary discrete log on a group of size bits would take about 2^n
+* effort, and thus using an exponent of size 2^(2*n) implies that all
+* available attacks are about as easy (as e.g Pollard's kangaroo
+* algorithm can compute the DL in sqrt(x) operations) while minimizing
+* the exponent size for performance reasons.
+*/
+size_t dl_exponent_size(size_t prime_group_size);
+
+/**
+* Estimate work factor for integer factorization
+* @param n_bits size of modulus in bits
+* @return estimated security level for this modulus
+*/
+size_t if_work_factor(size_t n_bits);
+
+/**
* Estimate work factor for EC discrete logarithm
* @param prime_group_size size of the group in bits
* @return estimated security level for this group
diff --git a/src/lib/rng/auto_rng/auto_rng.h b/src/lib/rng/auto_rng/auto_rng.h
index a7b28af92..ce0c5a7d2 100644
--- a/src/lib/rng/auto_rng/auto_rng.h
+++ b/src/lib/rng/auto_rng/auto_rng.h
@@ -25,7 +25,12 @@ class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
std::string name() const override { return m_rng->name(); }
- void reseed(size_t poll_bits = 256) override { m_rng->reseed(poll_bits); }
+ size_t reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout) override
+ {
+ return m_rng->reseed_with_sources(srcs, poll_bits, poll_timeout);
+ }
void add_entropy(const byte in[], size_t len) override
{ m_rng->add_entropy(in, len); }
diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.cpp b/src/lib/rng/hmac_drbg/hmac_drbg.cpp
index ad731b6b3..67325ee1b 100644
--- a/src/lib/rng/hmac_drbg/hmac_drbg.cpp
+++ b/src/lib/rng/hmac_drbg/hmac_drbg.cpp
@@ -78,11 +78,13 @@ void HMAC_DRBG::update(const byte input[], size_t input_len)
}
}
-void HMAC_DRBG::reseed(size_t poll_bits)
+size_t HMAC_DRBG::reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout)
{
if(m_prng)
{
- m_prng->reseed(poll_bits);
+ size_t bits = m_prng->reseed_with_sources(srcs, poll_bits, poll_timeout);
if(m_prng->is_seeded())
{
@@ -90,7 +92,11 @@ void HMAC_DRBG::reseed(size_t poll_bits)
update(input.data(), input.size());
m_reseed_counter = 1;
}
+
+ return bits;
}
+
+ return 0;
}
void HMAC_DRBG::add_entropy(const byte input[], size_t length)
diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.h b/src/lib/rng/hmac_drbg/hmac_drbg.h
index c9d0e3d20..bd2d18d47 100644
--- a/src/lib/rng/hmac_drbg/hmac_drbg.h
+++ b/src/lib/rng/hmac_drbg/hmac_drbg.h
@@ -24,7 +24,9 @@ class BOTAN_DLL HMAC_DRBG : public RandomNumberGenerator
void clear() override;
std::string name() const override;
- void reseed(size_t poll_bits) override;
+ size_t reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout) override;
void add_entropy(const byte input[], size_t input_len) override;
diff --git a/src/lib/rng/hmac_rng/hmac_rng.cpp b/src/lib/rng/hmac_rng/hmac_rng.cpp
index 5456b3bac..f5a782526 100644
--- a/src/lib/rng/hmac_rng/hmac_rng.cpp
+++ b/src/lib/rng/hmac_rng/hmac_rng.cpp
@@ -95,7 +95,11 @@ void HMAC_RNG::randomize(byte out[], size_t length)
m_output_since_reseed += length;
if(m_output_since_reseed >= BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED)
- reseed_with_timeout(BOTAN_RNG_RESEED_POLL_BITS, BOTAN_RNG_AUTO_RESEED_TIMEOUT);
+ {
+ reseed_with_sources(Entropy_Sources::global_sources(),
+ BOTAN_RNG_RESEED_POLL_BITS,
+ BOTAN_RNG_AUTO_RESEED_TIMEOUT);
+ }
/*
HMAC KDF as described in E-t-E, using a CTXinfo of "rng"
@@ -112,15 +116,9 @@ void HMAC_RNG::randomize(byte out[], size_t length)
}
}
-/*
-* Poll for entropy and reset the internal keys
-*/
-void HMAC_RNG::reseed(size_t poll_bits)
- {
- reseed_with_timeout(poll_bits, BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
- }
-
-void HMAC_RNG::reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds timeout)
+size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds timeout)
{
/*
Using the terminology of E-t-E, XTR is the MAC function (normally
@@ -130,20 +128,18 @@ void HMAC_RNG::reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds t
a bad poll doesn't wipe us out.
*/
- double bits_collected = 0;
-
- typedef std::chrono::high_resolution_clock clock;
+ typedef std::chrono::system_clock clock;
auto deadline = clock::now() + timeout;
- Entropy_Accumulator accum(
- [&](const byte in[], size_t in_len, double entropy_estimate)
- {
+ double bits_collected = 0;
+
+ Entropy_Accumulator accum([&](const byte in[], size_t in_len, double entropy_estimate) {
m_extractor->update(in, in_len);
bits_collected += entropy_estimate;
return (bits_collected >= poll_bits || clock::now() > deadline);
});
- EntropySource::poll_available_sources(accum);
+ srcs.poll(accum);
/*
* It is necessary to feed forward poll data. Otherwise, a good poll
@@ -172,6 +168,8 @@ void HMAC_RNG::reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds t
m_extractor->output_length() * 8);
m_output_since_reseed = 0;
+
+ return static_cast<size_t>(bits_collected);
}
bool HMAC_RNG::is_seeded() const
@@ -180,12 +178,16 @@ bool HMAC_RNG::is_seeded() const
}
/*
-* Add user-supplied entropy to the extractor input
+* Add user-supplied entropy to the extractor input then reseed
+* to incorporate it into the state
*/
void HMAC_RNG::add_entropy(const byte input[], size_t length)
{
m_extractor->update(input, length);
- reseed_with_timeout(BOTAN_RNG_RESEED_POLL_BITS, BOTAN_RNG_AUTO_RESEED_TIMEOUT);
+
+ reseed_with_sources(Entropy_Sources::global_sources(),
+ BOTAN_RNG_RESEED_POLL_BITS,
+ BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
}
/*
diff --git a/src/lib/rng/hmac_rng/hmac_rng.h b/src/lib/rng/hmac_rng/hmac_rng.h
index ba12e665d..1e38daa08 100644
--- a/src/lib/rng/hmac_rng/hmac_rng.h
+++ b/src/lib/rng/hmac_rng/hmac_rng.h
@@ -32,9 +32,9 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
void clear() override;
std::string name() const override;
- void reseed(size_t poll_bits) override;
-
- void reseed_with_timeout(size_t poll_bits, std::chrono::milliseconds ms);
+ size_t reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout) override;
void add_entropy(const byte[], size_t) override;
diff --git a/src/lib/rng/rng.cpp b/src/lib/rng/rng.cpp
index d4fd5fb10..c17f23dd0 100644
--- a/src/lib/rng/rng.cpp
+++ b/src/lib/rng/rng.cpp
@@ -7,9 +7,24 @@
#include <botan/rng.h>
#include <botan/hmac_rng.h>
+#include <botan/entropy_src.h>
namespace Botan {
+size_t RandomNumberGenerator::reseed(size_t bits_to_collect)
+ {
+ return this->reseed_with_timeout(bits_to_collect,
+ BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
+ }
+
+size_t RandomNumberGenerator::reseed_with_timeout(size_t bits_to_collect,
+ std::chrono::milliseconds timeout)
+ {
+ return this->reseed_with_sources(Entropy_Sources::global_sources(),
+ bits_to_collect,
+ timeout);
+ }
+
RandomNumberGenerator* RandomNumberGenerator::make_rng()
{
std::unique_ptr<MessageAuthenticationCode> h1(MessageAuthenticationCode::create("HMAC(SHA-512)"));
diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h
index a28a676a6..1ce0d5153 100644
--- a/src/lib/rng/rng.h
+++ b/src/lib/rng/rng.h
@@ -8,13 +8,16 @@
#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__
#define BOTAN_RANDOM_NUMBER_GENERATOR_H__
-#include <botan/entropy_src.h>
+#include <botan/secmem.h>
#include <botan/exceptn.h>
+#include <chrono>
#include <string>
#include <mutex>
namespace Botan {
+class Entropy_Sources;
+
/**
* This class represents a random number (RNG) generator object.
*/
@@ -100,11 +103,29 @@ class BOTAN_DLL RandomNumberGenerator
virtual std::string name() const = 0;
/**
- * Seed this RNG using the entropy sources it contains.
+ * Seed this RNG using the global entropy sources and default timeout
+ * @param bits_to_collect is the number of bits of entropy to
+ attempt to gather from the entropy sources
+ */
+ size_t reseed(size_t bits_to_collect);
+
+ /**
+ * Seed this RNG using the global entropy sources
* @param bits_to_collect is the number of bits of entropy to
attempt to gather from the entropy sources
+ * @param poll_timeout try not to run longer than this, no matter what
*/
- virtual void reseed(size_t bits_to_collect) = 0;
+ size_t reseed_with_timeout(size_t bits_to_collect,
+ std::chrono::milliseconds poll_timeout);
+
+ /**
+ * Poll provided sources for up to poll_bits bits of entropy
+ * or until the timeout expires. Returns estimate of the number
+ * of bits collected.
+ */
+ virtual size_t reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout) = 0;
/**
* Add entropy to this RNG.
@@ -135,7 +156,12 @@ class BOTAN_DLL Null_RNG : public RandomNumberGenerator
std::string name() const override { return "Null_RNG"; }
- void reseed(size_t) override {}
+ size_t reseed_with_sources(Entropy_Sources&, size_t,
+ std::chrono::milliseconds) override
+ {
+ return 0;
+ }
+
bool is_seeded() const override { return false; }
void add_entropy(const byte[], size_t) override {}
};
@@ -170,10 +196,12 @@ class BOTAN_DLL Serialized_RNG : public RandomNumberGenerator
return m_rng->name();
}
- void reseed(size_t poll_bits) override
+ size_t reseed_with_sources(Entropy_Sources& src,
+ size_t bits,
+ std::chrono::milliseconds msec) override
{
std::lock_guard<std::mutex> lock(m_mutex);
- m_rng->reseed(poll_bits);
+ return m_rng->reseed_with_sources(src, bits, msec);
}
void add_entropy(const byte in[], size_t len) override
diff --git a/src/lib/rng/system_rng/system_rng.cpp b/src/lib/rng/system_rng/system_rng.cpp
index 8b949d071..50ec696a0 100644
--- a/src/lib/rng/system_rng/system_rng.cpp
+++ b/src/lib/rng/system_rng/system_rng.cpp
@@ -40,8 +40,18 @@ class System_RNG_Impl : public RandomNumberGenerator
void clear() override {}
std::string name() const override { return "system"; }
- void reseed(size_t) override {}
- void add_entropy(const byte[], size_t) override {}
+ size_t reseed_with_sources(Entropy_Sources&,
+ size_t /*poll_bits*/,
+ std::chrono::milliseconds /*timeout*/) override
+ {
+ // We ignore it and assert the PRNG is seeded.
+ // TODO: could poll and write it to /dev/urandom to help seed it
+ return 0;
+ }
+
+ void add_entropy(const byte[], size_t) override
+ {
+ }
private:
#if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM)
@@ -55,14 +65,18 @@ System_RNG_Impl::System_RNG_Impl()
{
#if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM)
- if(!CryptAcquireContext(&m_prov, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ if(!CryptAcquireContext(&m_prov, 0, 0, BOTAN_SYSTEM_RNG_CRYPTOAPI_PROV_TYPE, CRYPT_VERIFYCONTEXT))
throw std::runtime_error("System_RNG failed to acquire crypto provider");
#else
- m_fd = ::open("/dev/urandom", O_RDONLY);
+#ifndef O_NOCTTY
+ #define O_NOCTTY 0
+#endif
+
+ m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDONLY | O_NOCTTY);
if(m_fd < 0)
- throw std::runtime_error("System_RNG failed to open /dev/urandom");
+ throw std::runtime_error("System_RNG failed to open RNG device");
#endif
}
diff --git a/src/lib/rng/system_rng/system_rng.h b/src/lib/rng/system_rng/system_rng.h
index 0f4b94725..6290b8769 100644
--- a/src/lib/rng/system_rng/system_rng.h
+++ b/src/lib/rng/system_rng/system_rng.h
@@ -35,7 +35,12 @@ class BOTAN_DLL System_RNG : public RandomNumberGenerator
std::string name() const override { return m_rng.name(); }
- void reseed(size_t poll_bits = 256) override { m_rng.reseed(poll_bits); }
+ size_t reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout) override
+ {
+ return m_rng.reseed_with_sources(srcs, poll_bits, poll_timeout);
+ }
void add_entropy(const byte in[], size_t len) override { m_rng.add_entropy(in, len); }
private:
diff --git a/src/lib/rng/x931_rng/x931_rng.cpp b/src/lib/rng/x931_rng/x931_rng.cpp
index d531cf4a9..020d9a5a5 100644
--- a/src/lib/rng/x931_rng/x931_rng.cpp
+++ b/src/lib/rng/x931_rng/x931_rng.cpp
@@ -72,10 +72,13 @@ void ANSI_X931_RNG::rekey()
}
}
-void ANSI_X931_RNG::reseed(size_t poll_bits)
+size_t ANSI_X931_RNG::reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout)
{
- m_prng->reseed(poll_bits);
+ size_t bits = m_prng->reseed_with_sources(srcs, poll_bits, poll_timeout);
rekey();
+ return bits;
}
void ANSI_X931_RNG::add_entropy(const byte input[], size_t length)
diff --git a/src/lib/rng/x931_rng/x931_rng.h b/src/lib/rng/x931_rng/x931_rng.h
index 899fed956..ed7124a08 100644
--- a/src/lib/rng/x931_rng/x931_rng.h
+++ b/src/lib/rng/x931_rng/x931_rng.h
@@ -24,7 +24,10 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
void clear() override;
std::string name() const override;
- void reseed(size_t poll_bits) override;
+ size_t reseed_with_sources(Entropy_Sources& srcs,
+ size_t poll_bits,
+ std::chrono::milliseconds poll_timeout) override;
+
void add_entropy(const byte[], size_t) override;
/**
diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp
index c98829789..695a28550 100644
--- a/src/lib/utils/cpuid.cpp
+++ b/src/lib/utils/cpuid.cpp
@@ -74,7 +74,7 @@
namespace Botan {
u64bit CPUID::g_x86_processor_flags[2] = { 0, 0 };
-size_t CPUID::g_cache_line_size = 0;
+size_t CPUID::g_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
bool CPUID::g_altivec_capable = false;
bool CPUID::g_initialized = false;
diff --git a/src/lib/utils/cpuid.h b/src/lib/utils/cpuid.h
index 36c301c2f..3781b6f8e 100644
--- a/src/lib/utils/cpuid.h
+++ b/src/lib/utils/cpuid.h
@@ -27,12 +27,27 @@ class BOTAN_DLL CPUID
/**
* Return a best guess of the cache line size
*/
- static size_t cache_line_size() { initialize(); return g_cache_line_size; }
+ static size_t cache_line_size()
+ {
+ if(!g_initialized)
+ {
+ initialize();
+ }
+ return g_cache_line_size;
+ }
/**
* Check if the processor supports AltiVec/VMX
*/
- static bool has_altivec() { initialize(); return g_altivec_capable; }
+ static bool has_altivec()
+ {
+ if(!g_initialized)
+ {
+ initialize();
+ }
+
+ return g_altivec_capable;
+ }
/**
* Check if the processor supports RDTSC
diff --git a/src/lib/utils/simd/simd_altivec/simd_altivec.h b/src/lib/utils/simd/simd_altivec/simd_altivec.h
index 0a77d60fa..3963f2817 100644
--- a/src/lib/utils/simd/simd_altivec/simd_altivec.h
+++ b/src/lib/utils/simd/simd_altivec/simd_altivec.h
@@ -69,7 +69,7 @@ class SIMD_Altivec
void store_le(byte out[]) const
{
- __vector unsigned char perm = vec_lvsl(0, (u32bit*)0);
+ __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr));
perm = vec_xor(perm, vec_splat_u8(3));
@@ -179,7 +179,7 @@ class SIMD_Altivec
SIMD_Altivec bswap() const
{
- __vector unsigned char perm = vec_lvsl(0, (u32bit*)0);
+ __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr));
perm = vec_xor(perm, vec_splat_u8(3));
diff --git a/src/scripts/ci/travis/build.sh b/src/scripts/ci/travis/build.sh
index 092e9cbe6..06d3bfb04 100755
--- a/src/scripts/ci/travis/build.sh
+++ b/src/scripts/ci/travis/build.sh
@@ -9,7 +9,7 @@ elif [ "$BUILD_MODE" = "shared" ]; then
elif [ "$BUILD_MODE" = "coverage" ]; then
CFG_FLAGS=(--with-coverage)
elif [ "$BUILD_MODE" = "sanitizer" ]; then
- CFG_FLAGS=(--with-sanitizer)
+ CFG_FLAGS=(--with-sanitizers)
fi
if [ "$MODULES" = "min" ]; then
diff --git a/src/tests/test_main.cpp b/src/tests/main.cpp
index 009073ae1..41d29d542 100644
--- a/src/tests/test_main.cpp
+++ b/src/tests/main.cpp
@@ -29,21 +29,20 @@ namespace {
using Botan_Tests::Test;
-int help(std::ostream& out, char* argv0)
+int help(std::ostream& out, const std::string binary_name)
{
std::ostringstream err;
err << "Usage:\n"
- << argv0 << " test1 test2 ...\n"
+ << binary_name << " test1 test2 ...\n"
<< "Available tests: ";
for(auto&& test : Test::registered_tests())
{
err << test << " ";
}
- err << "\n";
- out << err.str();
+ out << err.str() << std::endl;
return 1;
}
@@ -191,15 +190,13 @@ setup_tests(std::ostream& out, size_t threads, size_t soak_level, bool log_succe
return rng;
}
-}
-
-int main(int argc, char* argv[])
+int cpp_main(const std::vector<std::string> args)
{
try
{
- if(argc == 2 && (std::string(argv[1]) == "--help" || std::string(argv[1])== "help"))
+ if(args.size() == 2 && (args[1] == "--help" || args[1] == "help"))
{
- return help(std::cout, argv[0]);
+ return help(std::cout, args[0]);
}
size_t threads = 0;//std::thread::hardware_concurrency();
@@ -207,7 +204,7 @@ int main(int argc, char* argv[])
const std::string drbg_seed = "";
bool log_success = false;
- std::vector<std::string> req(argv + 1, argv + argc);
+ std::vector<std::string> req(args.begin()+1, args.end());
if(req.empty())
{
@@ -242,3 +239,11 @@ int main(int argc, char* argv[])
return 3;
}
}
+
+}
+
+int main(int argc, char* argv[])
+ {
+ std::vector<std::string> args(argv, argv + argc);
+ return cpp_main(args);
+ }
diff --git a/src/tests/test_block.cpp b/src/tests/test_block.cpp
index 224735e22..7831b99a3 100644
--- a/src/tests/test_block.cpp
+++ b/src/tests/test_block.cpp
@@ -40,10 +40,10 @@ class Block_Cipher_Tests : public Text_Based_Test
continue;
}
- result.test_eq(provider.c_str(), cipher->name(), algo);
- result.test_gte(provider.c_str(), cipher->parallelism(), 1);
- result.test_gte(provider.c_str(), cipher->block_size(), 8);
- result.test_gte(provider.c_str(), cipher->parallel_bytes(), cipher->block_size() * cipher->parallelism());
+ result.test_eq(provider, cipher->name(), algo);
+ result.test_gte(provider, cipher->parallelism(), 1);
+ result.test_gte(provider, cipher->block_size(), 8);
+ result.test_gte(provider, cipher->parallel_bytes(), cipher->block_size() * cipher->parallelism());
cipher->set_key(key);
std::vector<uint8_t> buf = input;
diff --git a/src/tests/test_entropy.cpp b/src/tests/test_entropy.cpp
new file mode 100644
index 000000000..0ffee8491
--- /dev/null
+++ b/src/tests/test_entropy.cpp
@@ -0,0 +1,153 @@
+/*
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "tests.h"
+#include <botan/entropy_src.h>
+
+#if defined(BOTAN_HAS_COMPRESSION)
+ #include <botan/compression.h>
+#endif
+
+namespace Botan_Tests {
+
+namespace {
+
+class Entropy_Source_Tests : public Test
+ {
+ public:
+ std::vector<Test::Result> run() override
+ {
+ static const size_t MAX_ENTROPY = 512;
+ static const size_t MAX_SAMPLES = 256;
+ static const size_t MAX_ENTROPY_BYTES = 256*1024;
+
+ Botan::Entropy_Sources& srcs = Botan::Entropy_Sources::global_sources();
+
+ std::vector<std::string> src_names = srcs.enabled_sources();
+
+ std::vector<Test::Result> results;
+
+ for(auto&& src_name : src_names)
+ {
+ Test::Result result("Entropy source " + src_name);
+
+ result.start_timer();
+
+ try
+ {
+ std::vector<uint8_t> entropy;
+ size_t samples = 0;
+ size_t entropy_estimate = 0;
+
+ Botan::Entropy_Accumulator accum(
+ [&](const uint8_t buf[], size_t buf_len, size_t buf_entropy) -> bool {
+ entropy.insert(entropy.end(), buf, buf + buf_len);
+ entropy_estimate += buf_entropy;
+ ++samples;
+
+ result.test_note("sample " + std::to_string(samples) + " " +
+ Botan::hex_encode(buf, buf_len) + " " + std::to_string(buf_entropy));
+
+ result.test_gte("impossible entropy", buf_len * 8, buf_entropy);
+
+ return (entropy_estimate > MAX_ENTROPY ||
+ samples > MAX_SAMPLES ||
+ entropy.size() > MAX_ENTROPY_BYTES);
+ });
+
+ result.confirm("polled source", srcs.poll_just(accum, src_name));
+
+ result.test_note("saw " + std::to_string(samples) +
+ " samples with total estimated entropy " +
+ std::to_string(entropy_estimate));
+ result.test_note("poll result", entropy);
+
+#if defined(BOTAN_HAS_COMPRESSION)
+ if(!entropy.empty())
+ {
+ for(const std::string comp_algo : { "zlib", "bzip2", "lzma" })
+ {
+ std::unique_ptr<Botan::Compressor_Transform> comp(Botan::make_compressor(comp_algo, 9));
+
+ if(comp)
+ {
+ size_t comp1_size = 0;
+
+ try
+ {
+ Botan::secure_vector<byte> compressed;
+ compressed.assign(entropy.begin(), entropy.end());
+ comp->start();
+ comp->finish(compressed);
+
+ comp1_size = compressed.size();
+
+ result.test_gte(comp_algo + " compressed entropy better than advertised",
+ compressed.size() * 8, entropy_estimate);
+ }
+ catch(std::exception& e)
+ {
+ result.test_failure(comp_algo + " exception while compressing", e.what());
+ }
+
+ std::vector<uint8_t> entropy2;
+ size_t entropy_estimate2 = 0;
+ Botan::Entropy_Accumulator accum2(
+ [&](const uint8_t buf[], size_t buf_len, size_t buf_entropy) -> bool {
+ entropy2.insert(entropy2.end(), buf, buf + buf_len);
+ entropy_estimate2 += buf_entropy;
+ return entropy2.size() >= entropy.size();
+ });
+
+ result.confirm("polled source", srcs.poll_just(accum2, src_name));
+ result.test_note("poll 2 result", entropy2);
+
+ try
+ {
+ Botan::secure_vector<byte> compressed;
+ compressed.insert(compressed.end(), entropy.begin(), entropy.end());
+ compressed.insert(compressed.end(), entropy2.begin(), entropy2.end());
+
+ comp->start();
+ comp->finish(compressed);
+
+ size_t comp2_size = compressed.size();
+
+ result.test_lt("Two blocks of entropy are larger than one",
+ comp1_size, comp2_size);
+
+ size_t comp_diff = comp2_size - comp1_size;
+
+ result.test_gte(comp_algo + " diff compressed entropy better than advertised",
+ comp_diff*8, entropy_estimate2);
+ }
+ catch(std::exception& e)
+ {
+ result.test_failure(comp_algo + " exception while compressing", e.what());
+ }
+ }
+ }
+ }
+#endif
+ }
+ catch(std::exception& e)
+ {
+ result.test_failure("during entropy collection test", e.what());
+ }
+
+ result.end_timer();
+ results.push_back(result);
+ }
+
+ return results;
+ }
+ };
+
+BOTAN_REGISTER_TEST("entropy", Entropy_Source_Tests);
+
+}
+
+}
diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp
index 6c0dfb1c6..bdfe70a6a 100644
--- a/src/tests/test_hash.cpp
+++ b/src/tests/test_hash.cpp
@@ -42,7 +42,7 @@ class Hash_Function_Tests : public Text_Based_Test
continue;
}
- result.test_eq(provider.c_str(), hash->name(), algo);
+ result.test_eq(provider, hash->name(), algo);
hash->update(input);
diff --git a/src/tests/test_mac.cpp b/src/tests/test_mac.cpp
index a5b2b49ca..e7341f443 100644
--- a/src/tests/test_mac.cpp
+++ b/src/tests/test_mac.cpp
@@ -48,7 +48,7 @@ class Message_Auth_Tests : public Text_Based_Test
continue;
}
- result.test_eq(provider.c_str(), mac->name(), algo);
+ result.test_eq(provider, mac->name(), algo);
mac->set_key(key);
diff --git a/src/tests/test_rng.h b/src/tests/test_rng.h
index f1d40f7f1..7d30fd6cc 100644
--- a/src/tests/test_rng.h
+++ b/src/tests/test_rng.h
@@ -30,7 +30,9 @@ class Fixed_Output_RNG : public Botan::RandomNumberGenerator
return out;
}
- void reseed(size_t) override {}
+ size_t reseed_with_sources(Botan::Entropy_Sources&,
+ size_t,
+ std::chrono::milliseconds) { return 0; }
void randomize(byte out[], size_t len) override
{
diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp
index ed86b3d84..618d34755 100644
--- a/src/tests/test_stream.cpp
+++ b/src/tests/test_stream.cpp
@@ -46,7 +46,7 @@ class Stream_Cipher_Tests : public Text_Based_Test
continue;
}
- result.test_eq(provider.c_str(), cipher->name(), algo);
+ result.test_eq(provider, cipher->name(), algo);
cipher->set_key(key);
if(nonce.size())
diff --git a/src/tests/test_utils.cpp b/src/tests/test_utils.cpp
index dfe0b19d3..9ee799519 100644
--- a/src/tests/test_utils.cpp
+++ b/src/tests/test_utils.cpp
@@ -34,7 +34,7 @@ class Utility_Function_Tests : public Text_Based_Test
const size_t x = get_req_sz(vars, "In1");
const size_t to = get_req_sz(vars, "In2");
- result.test_eq(algo.c_str(), Botan::round_up(x, to), get_req_sz(vars, "Out"));
+ result.test_eq(algo, Botan::round_up(x, to), get_req_sz(vars, "Out"));
try
{
@@ -48,8 +48,8 @@ class Utility_Function_Tests : public Text_Based_Test
const size_t x = get_req_sz(vars, "In1");
const size_t to = get_req_sz(vars, "In2");
- result.test_eq(algo.c_str(), Botan::round_down<size_t>(x, to), get_req_sz(vars, "Out"));
- result.test_eq(algo.c_str(), Botan::round_down<size_t>(x, 0), x);
+ result.test_eq(algo, Botan::round_down<size_t>(x, to), get_req_sz(vars, "Out"));
+ result.test_eq(algo, Botan::round_down<size_t>(x, 0), x);
}
return result;
@@ -313,7 +313,7 @@ class Base64_Tests : public Text_Based_Test
}
catch(std::exception& e)
{
- result.test_failure(b64_ws.c_str(), e.what());
+ result.test_failure(b64_ws, e.what());
}
}
}
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index e421d245c..4db24dcc7 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -106,12 +106,12 @@ bool Test::Result::test_success(const std::string& note)
return true;
}
-bool Test::Result::test_failure(const char* what, const char* error)
+bool Test::Result::test_failure(const std::string& what, const std::string& error)
{
return test_failure(who() + " " + what + " with error " + error);
}
-void Test::Result::test_failure(const char* what, const uint8_t buf[], size_t buf_len)
+void Test::Result::test_failure(const std::string& what, const uint8_t buf[], size_t buf_len)
{
test_failure(who() + ": " + what +
" buf len " + std::to_string(buf_len) +
@@ -124,7 +124,7 @@ bool Test::Result::test_failure(const std::string& err)
return false;
}
-bool Test::Result::test_ne(const char* what,
+bool Test::Result::test_ne(const std::string& what,
const uint8_t produced[], size_t produced_len,
const uint8_t expected[], size_t expected_len)
{
@@ -133,7 +133,7 @@ bool Test::Result::test_ne(const char* what,
return test_success();
}
-bool Test::Result::test_eq(const char* producer, const char* what,
+bool Test::Result::test_eq(const char* producer, const std::string& what,
const uint8_t produced[], size_t produced_size,
const uint8_t expected[], size_t expected_size)
{
@@ -149,12 +149,7 @@ bool Test::Result::test_eq(const char* producer, const char* what,
err << " producer '" << producer << "'";
}
- err << " unexpected result";
-
- if(what)
- {
- err << " for " << what;
- }
+ err << " unexpected result for " << what;
if(produced_size != expected_size)
{
@@ -182,29 +177,27 @@ bool Test::Result::test_eq(const char* producer, const char* what,
return test_failure(err.str());
}
-bool Test::Result::test_eq(const char* what, const std::string& produced, const std::string& expected)
+bool Test::Result::test_eq(const std::string& what, const std::string& produced, const std::string& expected)
{
return test_is_eq(what, produced, expected);
}
-bool Test::Result::test_eq(const char* what, const char* produced, const char* expected)
+bool Test::Result::test_eq(const std::string& what, const char* produced, const char* expected)
{
return test_is_eq(what, std::string(produced), std::string(expected));
}
-bool Test::Result::test_eq(const char* what, size_t produced, size_t expected)
+bool Test::Result::test_eq(const std::string& what, size_t produced, size_t expected)
{
return test_is_eq(what, produced, expected);
}
-bool Test::Result::test_lt(const char* what, size_t produced, size_t expected)
+bool Test::Result::test_lt(const std::string& what, size_t produced, size_t expected)
{
if(produced >= expected)
{
std::ostringstream err;
- err << m_who;
- if(what)
- err << " " << what;
+ err << m_who << " " << what;
err << " unexpected result " << produced << " >= " << expected;
return test_failure(err.str());
}
@@ -212,14 +205,13 @@ bool Test::Result::test_lt(const char* what, size_t produced, size_t expected)
return test_success();
}
-bool Test::Result::test_gte(const char* what, size_t produced, size_t expected)
+bool Test::Result::test_gte(const std::string& what, size_t produced, size_t expected)
{
if(produced < expected)
{
std::ostringstream err;
err << m_who;
- if(what)
- err << " " << what;
+ err << " " << what;
err << " unexpected result " << produced << " < " << expected;
return test_failure(err.str());
}
@@ -228,12 +220,12 @@ bool Test::Result::test_gte(const char* what, size_t produced, size_t expected)
}
#if defined(BOTAN_HAS_BIGINT)
-bool Test::Result::test_eq(const char* what, const BigInt& produced, const BigInt& expected)
+bool Test::Result::test_eq(const std::string& what, const BigInt& produced, const BigInt& expected)
{
return test_is_eq(what, produced, expected);
}
-bool Test::Result::test_ne(const char* what, const BigInt& produced, const BigInt& expected)
+bool Test::Result::test_ne(const std::string& what, const BigInt& produced, const BigInt& expected)
{
if(produced != expected)
return test_success();
@@ -245,7 +237,7 @@ bool Test::Result::test_ne(const char* what, const BigInt& produced, const BigIn
#endif
#if defined(BOTAN_HAS_EC_CURVE_GFP)
-bool Test::Result::test_eq(const char* what, const Botan::PointGFp& a, const Botan::PointGFp& b)
+bool Test::Result::test_eq(const std::string& what, const Botan::PointGFp& a, const Botan::PointGFp& b)
{
//return test_is_eq(what, a, b);
if(a == b)
@@ -258,19 +250,18 @@ bool Test::Result::test_eq(const char* what, const Botan::PointGFp& a, const Bot
}
#endif
-bool Test::Result::test_eq(const char* what, bool produced, bool expected)
+bool Test::Result::test_eq(const std::string& what, bool produced, bool expected)
{
return test_is_eq(what, produced, expected);
}
-bool Test::Result::test_rc_ok(const char* what, int rc)
+bool Test::Result::test_rc_ok(const std::string& what, int rc)
{
if(rc != 0)
{
std::ostringstream err;
err << m_who;
- if(what)
- err << " " << what;
+ err << " " << what;
err << " unexpectedly failed with error code " << rc;
return test_failure(err.str());
}
@@ -278,16 +269,14 @@ bool Test::Result::test_rc_ok(const char* what, int rc)
return test_success();
}
-bool Test::Result::test_rc_fail(const char* func, const char* why, int rc)
+bool Test::Result::test_rc_fail(const std::string& func, const std::string& why, int rc)
{
if(rc == 0)
{
std::ostringstream err;
err << m_who;
- if(func)
- err << " call to " << func << " unexpectedly succeeded";
- if(why)
- err << " expecting failure because " << why;
+ err << " call to " << func << " unexpectedly succeeded";
+ err << " expecting failure because " << why;
return test_failure(err.str());
}
diff --git a/src/tests/tests.h b/src/tests/tests.h
index 9f511c4fb..fddf44aaf 100644
--- a/src/tests/tests.h
+++ b/src/tests/tests.h
@@ -99,7 +99,7 @@ class Test
else
{
Result r(result.who());
- r.test_note("Got expected failure " + result.result_string());
+ r.test_note("Got expected failure");
return r;
}
}
@@ -108,23 +108,30 @@ class Test
void test_note(const std::string& note, const char* extra = nullptr);
+ template<typename Alloc>
+ void test_note(const std::string& who, const std::vector<uint8_t, Alloc>& vec)
+ {
+ const std::string hex = Botan::hex_encode(vec);
+ return test_note(who, hex.c_str());
+ }
+
void note_missing(const std::string& thing);
bool test_success(const std::string& note = "");
bool test_failure(const std::string& err);
- bool test_failure(const char* what, const char* error);
+ bool test_failure(const std::string& what, const std::string& error);
- void test_failure(const char* what, const uint8_t buf[], size_t buf_len);
+ void test_failure(const std::string& what, const uint8_t buf[], size_t buf_len);
template<typename Alloc>
- void test_failure(const char* what, const std::vector<uint8_t, Alloc>& buf)
+ void test_failure(const std::string& what, const std::vector<uint8_t, Alloc>& buf)
{
test_failure(what, buf.data(), buf.size());
}
- bool confirm(const char* what, bool expr)
+ bool confirm(const std::string& what, bool expr)
{
return test_eq(what, expr, true);
}
@@ -132,18 +139,14 @@ class Test
template<typename T>
bool test_is_eq(const T& produced, const T& expected)
{
- return test_is_eq(nullptr, produced, expected);
+ return test_is_eq("comparison", produced, expected);
}
template<typename T>
- bool test_is_eq(const char* what, const T& produced, const T& expected)
+ bool test_is_eq(const std::string& what, const T& produced, const T& expected)
{
std::ostringstream out;
- out << m_who;
- if(what)
- {
- out << " " << what;
- }
+ out << m_who << " " << what;
if(produced == expected)
{
@@ -157,36 +160,36 @@ class Test
}
}
- bool test_eq(const char* what, const char* produced, const char* expected);
- bool test_eq(const char* what, const std::string& produced, const std::string& expected);
- bool test_eq(const char* what, bool produced, bool expected);
+ bool test_eq(const std::string& what, const char* produced, const char* expected);
+ bool test_eq(const std::string& what, const std::string& produced, const std::string& expected);
+ bool test_eq(const std::string& what, bool produced, bool expected);
- bool test_eq(const char* what, size_t produced, size_t expected);
- bool test_lt(const char* what, size_t produced, size_t expected);
- bool test_gte(const char* what, size_t produced, size_t expected);
+ bool test_eq(const std::string& what, size_t produced, size_t expected);
+ bool test_lt(const std::string& what, size_t produced, size_t expected);
+ bool test_gte(const std::string& what, size_t produced, size_t expected);
- bool test_rc_ok(const char* func, int rc);
- bool test_rc_fail(const char* func, const char* why, int rc);
+ bool test_rc_ok(const std::string& func, int rc);
+ bool test_rc_fail(const std::string& func, const std::string& why, int rc);
#if defined(BOTAN_HAS_BIGINT)
- bool test_eq(const char* what, const BigInt& produced, const BigInt& expected);
- bool test_ne(const char* what, const BigInt& produced, const BigInt& expected);
+ bool test_eq(const std::string& what, const BigInt& produced, const BigInt& expected);
+ bool test_ne(const std::string& what, const BigInt& produced, const BigInt& expected);
#endif
#if defined(BOTAN_HAS_EC_CURVE_GFP)
- bool test_eq(const char* what, const Botan::PointGFp& a, const Botan::PointGFp& b);
+ bool test_eq(const std::string& what, const Botan::PointGFp& a, const Botan::PointGFp& b);
#endif
- bool test_eq(const char* producer, const char* what,
+ bool test_eq(const char* producer, const std::string& what,
const uint8_t produced[], size_t produced_len,
const uint8_t expected[], size_t expected_len);
- bool test_ne(const char* what,
+ bool test_ne(const std::string& what,
const uint8_t produced[], size_t produced_len,
const uint8_t expected[], size_t expected_len);
template<typename Alloc1, typename Alloc2>
- bool test_eq(const char* what,
+ bool test_eq(const std::string& what,
const std::vector<uint8_t, Alloc1>& produced,
const std::vector<uint8_t, Alloc2>& expected)
{
@@ -196,7 +199,7 @@ class Test
}
template<typename Alloc1, typename Alloc2>
- bool test_eq(const std::string& producer, const char* what,
+ bool test_eq(const std::string& producer, const std::string& what,
const std::vector<uint8_t, Alloc1>& produced,
const std::vector<uint8_t, Alloc2>& expected)
{
@@ -206,7 +209,7 @@ class Test
}
template<typename Alloc>
- bool test_eq(const char* what,
+ bool test_eq(const std::string& what,
const std::vector<uint8_t, Alloc>& produced,
const char* expected_hex)
{
@@ -217,7 +220,7 @@ class Test
}
template<typename Alloc1, typename Alloc2>
- bool test_ne(const char* what,
+ bool test_ne(const std::string& what,
const std::vector<uint8_t, Alloc1>& produced,
const std::vector<uint8_t, Alloc2>& expected)
{
diff --git a/src/tests/unit_ecc.cpp b/src/tests/unit_ecc.cpp
index 65187a428..92dee8ba4 100644
--- a/src/tests/unit_ecc.cpp
+++ b/src/tests/unit_ecc.cpp
@@ -33,10 +33,6 @@ const std::vector<std::string> ec_groups = {
"brainpool384r1",
"brainpool512r1",
"gost_256A",
- "secp112r1",
- "secp112r2",
- "secp128r1",
- "secp128r2",
"secp160k1",
"secp160r1",
"secp160r2",
@@ -183,7 +179,7 @@ std::vector<Test::Result> ECC_Randomized_Tests::run()
}
catch(std::exception& e)
{
- result.test_failure(group_name.c_str(), e.what());
+ result.test_failure(group_name, e.what());
}
results.push_back(result);
}
diff --git a/src/tests/unit_ecdsa.cpp b/src/tests/unit_ecdsa.cpp
index ed9096083..169819e32 100644
--- a/src/tests/unit_ecdsa.cpp
+++ b/src/tests/unit_ecdsa.cpp
@@ -280,10 +280,6 @@ Test::Result test_curve_registry()
"1.2.840.10045.3.1.5",
"1.2.840.10045.3.1.6",
"1.2.840.10045.3.1.7",
- "1.3.132.0.6",
- "1.3.132.0.7",
- "1.3.132.0.28",
- "1.3.132.0.29",
"1.3.132.0.9",
"1.3.132.0.30",
"1.3.132.0.31",
@@ -416,9 +412,11 @@ class ECDSA_Unit_Tests : public Test
{
std::vector<Test::Result> results;
results.push_back(test_hash_larger_than_n());
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
results.push_back(test_decode_ecdsa_X509());
results.push_back(test_decode_ver_link_SHA256());
results.push_back(test_decode_ver_link_SHA1());
+#endif
results.push_back(test_sign_then_ver());
results.push_back(test_ec_sign());
results.push_back(test_create_pkcs8());
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp
index 8e53fc3db..ec585ed6f 100644
--- a/src/tests/unit_tls.cpp
+++ b/src/tests/unit_tls.cpp
@@ -276,8 +276,8 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
server.send(server_sent);
}
- const bool corrupt_client_data = (r == 3 && (rng.next_byte() <= 128 || rounds > 2));
- const bool corrupt_server_data = (r == 4 && (rng.next_byte() <= 128 || rounds > 2));
+ const bool corrupt_client_data = (r == 3);
+ const bool corrupt_server_data = (r == 4);
if(c2s_traffic.size() > 0)
{
@@ -332,7 +332,6 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
input.resize(needed);
Test::rng().randomize(input.data(), input.size());
needed = client.received_data(input.data(), input.size());
- result.test_eq("no more data needed now", needed, 0);
total_consumed += needed;
}
}
@@ -529,7 +528,6 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
input.resize(needed);
Test::rng().randomize(input.data(), input.size());
needed = client.received_data(input.data(), input.size());
- result.test_eq("no more data needed now", needed, 0);
}
}
catch(std::exception& e)
@@ -570,7 +568,6 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
input.resize(needed);
Test::rng().randomize(input.data(), input.size());
needed = client.received_data(input.data(), input.size());
- result.test_eq("no more data needed now", needed, 0);
}
}
catch(std::exception& e)