diff options
Diffstat (limited to 'src')
75 files changed, 912 insertions, 813 deletions
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) |