diff options
Diffstat (limited to 'src/lib')
98 files changed, 2512 insertions, 4121 deletions
diff --git a/src/lib/asn1/oid_lookup/default.cpp b/src/lib/asn1/oid_lookup/default.cpp index 0d64a8bef..6527b3b25 100644 --- a/src/lib/asn1/oid_lookup/default.cpp +++ b/src/lib/asn1/oid_lookup/default.cpp @@ -21,8 +21,6 @@ const char* default_oid_list() "1.2.840.10040.4.1 = DSA" "\n" "1.2.840.10046.2.1 = DH" "\n" "1.3.6.1.4.1.3029.1.2.1 = ElGamal" "\n" - "1.3.6.1.4.1.25258.1.1 = RW" "\n" - "1.3.6.1.4.1.25258.1.2 = NR" "\n" "1.3.6.1.4.1.25258.1.3 = McEliece" "\n" "1.3.6.1.4.1.25258.1.4 = Curve25519" "\n" @@ -93,7 +91,6 @@ const char* default_oid_list() "1.2.840.113549.1.9.16.3.8 = Compression.Zlib" "\n" "1.2.840.113549.1.1.1 = RSA/EME-PKCS1-v1_5" "\n" - "1.2.840.113549.1.1.2 = RSA/EMSA3(MD2)" "\n" "1.2.840.113549.1.1.4 = RSA/EMSA3(MD5)" "\n" "1.2.840.113549.1.1.5 = RSA/EMSA3(SHA-160)" "\n" "1.2.840.113549.1.1.11 = RSA/EMSA3(SHA-256)" "\n" @@ -124,27 +121,6 @@ const char* default_oid_list() "1.2.643.2.2.3 = GOST-34.10/EMSA1(GOST-R-34.11-94)" "\n" - "1.3.6.1.4.1.25258.2.1.1.1 = RW/EMSA2(RIPEMD-160)" "\n" - "1.3.6.1.4.1.25258.2.1.1.2 = RW/EMSA2(SHA-160)" "\n" - "1.3.6.1.4.1.25258.2.1.1.3 = RW/EMSA2(SHA-224)" "\n" - "1.3.6.1.4.1.25258.2.1.1.4 = RW/EMSA2(SHA-256)" "\n" - "1.3.6.1.4.1.25258.2.1.1.5 = RW/EMSA2(SHA-384)" "\n" - "1.3.6.1.4.1.25258.2.1.1.6 = RW/EMSA2(SHA-512)" "\n" - - "1.3.6.1.4.1.25258.2.1.2.1 = RW/EMSA4(RIPEMD-160)" "\n" - "1.3.6.1.4.1.25258.2.1.2.2 = RW/EMSA4(SHA-160)" "\n" - "1.3.6.1.4.1.25258.2.1.2.3 = RW/EMSA4(SHA-224)" "\n" - "1.3.6.1.4.1.25258.2.1.2.4 = RW/EMSA4(SHA-256)" "\n" - "1.3.6.1.4.1.25258.2.1.2.5 = RW/EMSA4(SHA-384)" "\n" - "1.3.6.1.4.1.25258.2.1.2.6 = RW/EMSA4(SHA-512)" "\n" - - "1.3.6.1.4.1.25258.2.2.1.1 = NR/EMSA2(RIPEMD-160)" "\n" - "1.3.6.1.4.1.25258.2.2.1.2 = NR/EMSA2(SHA-160)" "\n" - "1.3.6.1.4.1.25258.2.2.1.3 = NR/EMSA2(SHA-224)" "\n" - "1.3.6.1.4.1.25258.2.2.1.4 = NR/EMSA2(SHA-256)" "\n" - "1.3.6.1.4.1.25258.2.2.1.5 = NR/EMSA2(SHA-384)" "\n" - "1.3.6.1.4.1.25258.2.2.1.6 = NR/EMSA2(SHA-512)" "\n" - "2.5.4.3 = X520.CommonName" "\n" "2.5.4.4 = X520.Surname" "\n" "2.5.4.5 = X520.SerialNumber" "\n" diff --git a/src/lib/block/block_cipher.cpp b/src/lib/block/block_cipher.cpp index c70ba229d..230d9e3a0 100644 --- a/src/lib/block/block_cipher.cpp +++ b/src/lib/block/block_cipher.cpp @@ -63,14 +63,6 @@ #include <botan/lion.h> #endif -#if defined(BOTAN_HAS_LUBY_RACKOFF) - #include <botan/lubyrack.h> -#endif - -#if defined(BOTAN_HAS_MARS) - #include <botan/mars.h> -#endif - #if defined(BOTAN_HAS_MISTY1) #include <botan/misty1.h> #endif @@ -83,22 +75,6 @@ #include <botan/noekeon_simd.h> #endif -#if defined(BOTAN_HAS_RC2) - #include <botan/rc2.h> -#endif - -#if defined(BOTAN_HAS_RC5) - #include <botan/rc5.h> -#endif - -#if defined(BOTAN_HAS_RC6) - #include <botan/rc6.h> -#endif - -#if defined(BOTAN_HAS_SAFER) - #include <botan/safer_sk.h> -#endif - #if defined(BOTAN_HAS_SEED) #include <botan/seed.h> #endif @@ -111,18 +87,6 @@ #include <botan/serp_simd.h> #endif -#if defined(BOTAN_HAS_SKIPJACK) - #include <botan/skipjack.h> -#endif - -#if defined(BOTAN_HAS_SQUARE) - #include <botan/square.h> -#endif - -#if defined(BOTAN_HAS_TEA) - #include <botan/tea.h> -#endif - #if defined(BOTAN_HAS_TWOFISH) #include <botan/twofish.h> #endif @@ -232,10 +196,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_sse2(), IDEA_SSE2, "IDEA", BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(KASUMI); #endif -#if defined(BOTAN_HAS_MARS) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(MARS); -#endif - #if defined(BOTAN_HAS_MISTY1) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(MISTY1); #endif @@ -249,22 +209,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_simd_32(), Noekeon_SIMD, "Noeke "simd32", BOTAN_SIMD_ALGORITHM_PRIO); #endif -#if defined(BOTAN_HAS_RC2) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(RC2); -#endif - -#if defined(BOTAN_HAS_RC5) -BOTAN_REGISTER_BLOCK_CIPHER_1LEN(RC5, 12); -#endif - -#if defined(BOTAN_HAS_RC6) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(RC6); -#endif - -#if defined(BOTAN_HAS_SAFER) -BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1LEN(SAFER_SK, "SAFER-SK", 10); -#endif - #if defined(BOTAN_HAS_SEED) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(SEED); #endif @@ -278,10 +222,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_simd_32(), Serpent_SIMD, "Serpe "simd32", BOTAN_SIMD_ALGORITHM_PRIO); #endif -#if defined(BOTAN_HAS_TEA) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(TEA); -#endif - #if defined(BOTAN_HAS_TWOFISH) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Twofish); #endif diff --git a/src/lib/block/mars/info.txt b/src/lib/block/mars/info.txt deleted file mode 100644 index 0af3d7955..000000000 --- a/src/lib/block/mars/info.txt +++ /dev/null @@ -1 +0,0 @@ -define MARS 20131128 diff --git a/src/lib/block/mars/mars.cpp b/src/lib/block/mars/mars.cpp deleted file mode 100644 index 4605be415..000000000 --- a/src/lib/block/mars/mars.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* -* MARS -* (C) 1999-2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/mars.h> -#include <botan/loadstor.h> - -namespace Botan { - -namespace { - -/** -* The MARS sbox -*/ -const u32bit SBOX[512] = { - 0x09D0C479, 0x28C8FFE0, 0x84AA6C39, 0x9DAD7287, 0x7DFF9BE3, 0xD4268361, - 0xC96DA1D4, 0x7974CC93, 0x85D0582E, 0x2A4B5705, 0x1CA16A62, 0xC3BD279D, - 0x0F1F25E5, 0x5160372F, 0xC695C1FB, 0x4D7FF1E4, 0xAE5F6BF4, 0x0D72EE46, - 0xFF23DE8A, 0xB1CF8E83, 0xF14902E2, 0x3E981E42, 0x8BF53EB6, 0x7F4BF8AC, - 0x83631F83, 0x25970205, 0x76AFE784, 0x3A7931D4, 0x4F846450, 0x5C64C3F6, - 0x210A5F18, 0xC6986A26, 0x28F4E826, 0x3A60A81C, 0xD340A664, 0x7EA820C4, - 0x526687C5, 0x7EDDD12B, 0x32A11D1D, 0x9C9EF086, 0x80F6E831, 0xAB6F04AD, - 0x56FB9B53, 0x8B2E095C, 0xB68556AE, 0xD2250B0D, 0x294A7721, 0xE21FB253, - 0xAE136749, 0xE82AAE86, 0x93365104, 0x99404A66, 0x78A784DC, 0xB69BA84B, - 0x04046793, 0x23DB5C1E, 0x46CAE1D6, 0x2FE28134, 0x5A223942, 0x1863CD5B, - 0xC190C6E3, 0x07DFB846, 0x6EB88816, 0x2D0DCC4A, 0xA4CCAE59, 0x3798670D, - 0xCBFA9493, 0x4F481D45, 0xEAFC8CA8, 0xDB1129D6, 0xB0449E20, 0x0F5407FB, - 0x6167D9A8, 0xD1F45763, 0x4DAA96C3, 0x3BEC5958, 0xABABA014, 0xB6CCD201, - 0x38D6279F, 0x02682215, 0x8F376CD5, 0x092C237E, 0xBFC56593, 0x32889D2C, - 0x854B3E95, 0x05BB9B43, 0x7DCD5DCD, 0xA02E926C, 0xFAE527E5, 0x36A1C330, - 0x3412E1AE, 0xF257F462, 0x3C4F1D71, 0x30A2E809, 0x68E5F551, 0x9C61BA44, - 0x5DED0AB8, 0x75CE09C8, 0x9654F93E, 0x698C0CCA, 0x243CB3E4, 0x2B062B97, - 0x0F3B8D9E, 0x00E050DF, 0xFC5D6166, 0xE35F9288, 0xC079550D, 0x0591AEE8, - 0x8E531E74, 0x75FE3578, 0x2F6D829A, 0xF60B21AE, 0x95E8EB8D, 0x6699486B, - 0x901D7D9B, 0xFD6D6E31, 0x1090ACEF, 0xE0670DD8, 0xDAB2E692, 0xCD6D4365, - 0xE5393514, 0x3AF345F0, 0x6241FC4D, 0x460DA3A3, 0x7BCF3729, 0x8BF1D1E0, - 0x14AAC070, 0x1587ED55, 0x3AFD7D3E, 0xD2F29E01, 0x29A9D1F6, 0xEFB10C53, - 0xCF3B870F, 0xB414935C, 0x664465ED, 0x024ACAC7, 0x59A744C1, 0x1D2936A7, - 0xDC580AA6, 0xCF574CA8, 0x040A7A10, 0x6CD81807, 0x8A98BE4C, 0xACCEA063, - 0xC33E92B5, 0xD1E0E03D, 0xB322517E, 0x2092BD13, 0x386B2C4A, 0x52E8DD58, - 0x58656DFB, 0x50820371, 0x41811896, 0xE337EF7E, 0xD39FB119, 0xC97F0DF6, - 0x68FEA01B, 0xA150A6E5, 0x55258962, 0xEB6FF41B, 0xD7C9CD7A, 0xA619CD9E, - 0xBCF09576, 0x2672C073, 0xF003FB3C, 0x4AB7A50B, 0x1484126A, 0x487BA9B1, - 0xA64FC9C6, 0xF6957D49, 0x38B06A75, 0xDD805FCD, 0x63D094CF, 0xF51C999E, - 0x1AA4D343, 0xB8495294, 0xCE9F8E99, 0xBFFCD770, 0xC7C275CC, 0x378453A7, - 0x7B21BE33, 0x397F41BD, 0x4E94D131, 0x92CC1F98, 0x5915EA51, 0x99F861B7, - 0xC9980A88, 0x1D74FD5F, 0xB0A495F8, 0x614DEED0, 0xB5778EEA, 0x5941792D, - 0xFA90C1F8, 0x33F824B4, 0xC4965372, 0x3FF6D550, 0x4CA5FEC0, 0x8630E964, - 0x5B3FBBD6, 0x7DA26A48, 0xB203231A, 0x04297514, 0x2D639306, 0x2EB13149, - 0x16A45272, 0x532459A0, 0x8E5F4872, 0xF966C7D9, 0x07128DC0, 0x0D44DB62, - 0xAFC8D52D, 0x06316131, 0xD838E7CE, 0x1BC41D00, 0x3A2E8C0F, 0xEA83837E, - 0xB984737D, 0x13BA4891, 0xC4F8B949, 0xA6D6ACB3, 0xA215CDCE, 0x8359838B, - 0x6BD1AA31, 0xF579DD52, 0x21B93F93, 0xF5176781, 0x187DFDDE, 0xE94AEB76, - 0x2B38FD54, 0x431DE1DA, 0xAB394825, 0x9AD3048F, 0xDFEA32AA, 0x659473E3, - 0x623F7863, 0xF3346C59, 0xAB3AB685, 0x3346A90B, 0x6B56443E, 0xC6DE01F8, - 0x8D421FC0, 0x9B0ED10C, 0x88F1A1E9, 0x54C1F029, 0x7DEAD57B, 0x8D7BA426, - 0x4CF5178A, 0x551A7CCA, 0x1A9A5F08, 0xFCD651B9, 0x25605182, 0xE11FC6C3, - 0xB6FD9676, 0x337B3027, 0xB7C8EB14, 0x9E5FD030, 0x6B57E354, 0xAD913CF7, - 0x7E16688D, 0x58872A69, 0x2C2FC7DF, 0xE389CCC6, 0x30738DF1, 0x0824A734, - 0xE1797A8B, 0xA4A8D57B, 0x5B5D193B, 0xC8A8309B, 0x73F9A978, 0x73398D32, - 0x0F59573E, 0xE9DF2B03, 0xE8A5B6C8, 0x848D0704, 0x98DF93C2, 0x720A1DC3, - 0x684F259A, 0x943BA848, 0xA6370152, 0x863B5EA3, 0xD17B978B, 0x6D9B58EF, - 0x0A700DD4, 0xA73D36BF, 0x8E6A0829, 0x8695BC14, 0xE35B3447, 0x933AC568, - 0x8894B022, 0x2F511C27, 0xDDFBCC3C, 0x006662B6, 0x117C83FE, 0x4E12B414, - 0xC2BCA766, 0x3A2FEC10, 0xF4562420, 0x55792E2A, 0x46F5D857, 0xCEDA25CE, - 0xC3601D3B, 0x6C00AB46, 0xEFAC9C28, 0xB3C35047, 0x611DFEE3, 0x257C3207, - 0xFDD58482, 0x3B14D84F, 0x23BECB64, 0xA075F3A3, 0x088F8EAD, 0x07ADF158, - 0x7796943C, 0xFACABF3D, 0xC09730CD, 0xF7679969, 0xDA44E9ED, 0x2C854C12, - 0x35935FA3, 0x2F057D9F, 0x690624F8, 0x1CB0BAFD, 0x7B0DBDC6, 0x810F23BB, - 0xFA929A1A, 0x6D969A17, 0x6742979B, 0x74AC7D05, 0x010E65C4, 0x86A3D963, - 0xF907B5A0, 0xD0042BD3, 0x158D7D03, 0x287A8255, 0xBBA8366F, 0x096EDC33, - 0x21916A7B, 0x77B56B86, 0x951622F9, 0xA6C5E650, 0x8CEA17D1, 0xCD8C62BC, - 0xA3D63433, 0x358A68FD, 0x0F9B9D3C, 0xD6AA295B, 0xFE33384A, 0xC000738E, - 0xCD67EB2F, 0xE2EB6DC2, 0x97338B02, 0x06C9F246, 0x419CF1AD, 0x2B83C045, - 0x3723F18A, 0xCB5B3089, 0x160BEAD7, 0x5D494656, 0x35F8A74B, 0x1E4E6C9E, - 0x000399BD, 0x67466880, 0xB4174831, 0xACF423B2, 0xCA815AB3, 0x5A6395E7, - 0x302A67C5, 0x8BDB446B, 0x108F8FA4, 0x10223EDA, 0x92B8B48B, 0x7F38D0EE, - 0xAB2701D4, 0x0262D415, 0xAF224A30, 0xB3D88ABA, 0xF8B2C3AF, 0xDAF7EF70, - 0xCC97D3B7, 0xE9614B6C, 0x2BAEBFF4, 0x70F687CF, 0x386C9156, 0xCE092EE5, - 0x01E87DA6, 0x6CE91E6A, 0xBB7BCC84, 0xC7922C20, 0x9D3B71FD, 0x060E41C6, - 0xD7590F15, 0x4E03BB47, 0x183C198E, 0x63EEB240, 0x2DDBF49A, 0x6D5CBA54, - 0x923750AF, 0xF9E14236, 0x7838162B, 0x59726C72, 0x81B66760, 0xBB2926C1, - 0x48A0CE0D, 0xA6C0496D, 0xAD43507B, 0x718D496A, 0x9DF057AF, 0x44B1BDE6, - 0x054356DC, 0xDE7CED35, 0xD51A138B, 0x62088CC9, 0x35830311, 0xC96EFCA2, - 0x686F86EC, 0x8E77CB68, 0x63E1D6B8, 0xC80F9778, 0x79C491FD, 0x1B4C67F2, - 0x72698D7D, 0x5E368C31, 0xF7D95E2E, 0xA1D3493F, 0xDCD9433E, 0x896F1552, - 0x4BC4CA7A, 0xA6D1BAF4, 0xA5A96DCC, 0x0BEF8B46, 0xA169FDA7, 0x74DF40B7, - 0x4E208804, 0x9A756607, 0x038E87C8, 0x20211E44, 0x8B7AD4BF, 0xC6403F35, - 0x1848E36D, 0x80BDB038, 0x1E62891C, 0x643D2107, 0xBF04D6F8, 0x21092C8C, - 0xF644F389, 0x0778404E, 0x7B78ADB8, 0xA2C52D53, 0x42157ABE, 0xA2253E2E, - 0x7BF3F4AE, 0x80F594F9, 0x953194E7, 0x77EB92ED, 0xB3816930, 0xDA8D9336, - 0xBF447469, 0xF26D9483, 0xEE6FAED5, 0x71371235, 0xDE425F73, 0xB4E59F43, - 0x7DBE2D4E, 0x2D37B185, 0x49DC9A63, 0x98C39D98, 0x1301C9A2, 0x389B1BBF, - 0x0C18588D, 0xA421C1BA, 0x7AA3865C, 0x71E08558, 0x3C5CFCAA, 0x7D239CA4, - 0x0297D9DD, 0xD7DC2830, 0x4B37802B, 0x7428AB54, 0xAEEE0347, 0x4B3FBB85, - 0x692F2F08, 0x134E578E, 0x36D9E0BF, 0xAE8B5FCF, 0xEDB93ECF, 0x2B27248E, - 0x170EB1EF, 0x7DC57FD6, 0x1E760F16, 0xB1136601, 0x864E1B9B, 0xD7EA7319, - 0x3AB871BD, 0xCFA4D76F, 0xE31BD782, 0x0DBEB469, 0xABB96061, 0x5370F85D, - 0xFFB07E37, 0xDA30D0FB, 0xEBC977B6, 0x0B98B40F, 0x3A4D0FE6, 0xDF4FC26B, - 0x159CF22A, 0xC298D6E2, 0x2B78EF6A, 0x61A94AC0, 0xAB561187, 0x14EEA0F0, - 0xDF0D4164, 0x19AF70EE }; - -/* -* MARS Encryption Round -*/ -inline void encrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D, - u32bit EK1, u32bit EK2) - { - const u32bit X = A + EK1; - A = rotate_left(A, 13); - u32bit Y = A * EK2; - u32bit Z = SBOX[X % 512]; - - Y = rotate_left(Y, 5); - Z ^= Y; - C += rotate_left(X, Y % 32); - Y = rotate_left(Y, 5); - Z ^= Y; - D ^= Y; - B += rotate_left(Z, Y % 32); - } - -/* -* MARS Decryption Round -*/ -inline void decrypt_round(u32bit& A, u32bit& B, u32bit& C, u32bit& D, - u32bit EK1, u32bit EK2) - { - u32bit Y = A * EK1; - A = rotate_right(A, 13); - const u32bit X = A + EK2; - u32bit Z = SBOX[X % 512]; - - Y = rotate_left(Y, 5); - Z ^= Y; - C -= rotate_left(X, Y % 32); - Y = rotate_left(Y, 5); - Z ^= Y; - D ^= Y; - B -= rotate_left(Z, Y % 32); - } - -/* -* MARS Forward Mixing Operation -*/ -void forward_mix(u32bit& A, u32bit& B, u32bit& C, u32bit& D) - { - for(size_t j = 0; j != 2; ++j) - { - B ^= SBOX[get_byte(3, A)]; B += SBOX[get_byte(2, A) + 256]; - C += SBOX[get_byte(1, A)]; D ^= SBOX[get_byte(0, A) + 256]; - A = rotate_right(A, 24) + D; - - C ^= SBOX[get_byte(3, B)]; C += SBOX[get_byte(2, B) + 256]; - D += SBOX[get_byte(1, B)]; A ^= SBOX[get_byte(0, B) + 256]; - B = rotate_right(B, 24) + C; - - D ^= SBOX[get_byte(3, C)]; D += SBOX[get_byte(2, C) + 256]; - A += SBOX[get_byte(1, C)]; B ^= SBOX[get_byte(0, C) + 256]; - C = rotate_right(C, 24); - - A ^= SBOX[get_byte(3, D)]; A += SBOX[get_byte(2, D) + 256]; - B += SBOX[get_byte(1, D)]; C ^= SBOX[get_byte(0, D) + 256]; - D = rotate_right(D, 24); - } - } - -/* -* MARS Reverse Mixing Operation -*/ -void reverse_mix(u32bit& A, u32bit& B, u32bit& C, u32bit& D) - { - for(size_t j = 0; j != 2; ++j) - { - B ^= SBOX[get_byte(3, A) + 256]; C -= SBOX[get_byte(0, A)]; - D -= SBOX[get_byte(1, A) + 256]; D ^= SBOX[get_byte(2, A)]; - A = rotate_left(A, 24); - - C ^= SBOX[get_byte(3, B) + 256]; D -= SBOX[get_byte(0, B)]; - A -= SBOX[get_byte(1, B) + 256]; A ^= SBOX[get_byte(2, B)]; - C -= (B = rotate_left(B, 24)); - - D ^= SBOX[get_byte(3, C) + 256]; A -= SBOX[get_byte(0, C)]; - B -= SBOX[get_byte(1, C) + 256]; B ^= SBOX[get_byte(2, C)]; - C = rotate_left(C, 24); - D -= A; - - A ^= SBOX[get_byte(3, D) + 256]; B -= SBOX[get_byte(0, D)]; - C -= SBOX[get_byte(1, D) + 256]; C ^= SBOX[get_byte(2, D)]; - D = rotate_left(D, 24); - } - } - -/* -* Generate a mask for runs of bits -*/ -u32bit gen_mask(u32bit input) - { - u32bit mask = 0; - - for(u32bit j = 2; j != 31; ++j) - { - const u32bit region = (input >> (j-1)) & 0x07; - - if(region == 0x00 || region == 0x07) - { - const u32bit low = (j < 9) ? 0 : (j - 9); - const u32bit high = (j < 23) ? j : 23; - - for(u32bit k = low; k != high; ++k) - { - const u32bit value = (input >> k) & 0x3FF; - - if(value == 0 || value == 0x3FF) - { - mask |= static_cast<u32bit>(1) << j; - break; - } - } - } - } - - return mask; - } - -} - -/* -* MARS Encryption -*/ -void MARS::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit A = load_le<u32bit>(in, 0) + m_EK[0]; - u32bit B = load_le<u32bit>(in, 1) + m_EK[1]; - u32bit C = load_le<u32bit>(in, 2) + m_EK[2]; - u32bit D = load_le<u32bit>(in, 3) + m_EK[3]; - - forward_mix(A, B, C, D); - - encrypt_round(A, B, C, D, m_EK[ 4], m_EK[ 5]); - encrypt_round(B, C, D, A, m_EK[ 6], m_EK[ 7]); - encrypt_round(C, D, A, B, m_EK[ 8], m_EK[ 9]); - encrypt_round(D, A, B, C, m_EK[10], m_EK[11]); - encrypt_round(A, B, C, D, m_EK[12], m_EK[13]); - encrypt_round(B, C, D, A, m_EK[14], m_EK[15]); - encrypt_round(C, D, A, B, m_EK[16], m_EK[17]); - encrypt_round(D, A, B, C, m_EK[18], m_EK[19]); - - encrypt_round(A, D, C, B, m_EK[20], m_EK[21]); - encrypt_round(B, A, D, C, m_EK[22], m_EK[23]); - encrypt_round(C, B, A, D, m_EK[24], m_EK[25]); - encrypt_round(D, C, B, A, m_EK[26], m_EK[27]); - encrypt_round(A, D, C, B, m_EK[28], m_EK[29]); - encrypt_round(B, A, D, C, m_EK[30], m_EK[31]); - encrypt_round(C, B, A, D, m_EK[32], m_EK[33]); - encrypt_round(D, C, B, A, m_EK[34], m_EK[35]); - - reverse_mix(A, B, C, D); - - A -= m_EK[36]; B -= m_EK[37]; C -= m_EK[38]; D -= m_EK[39]; - - store_le(out, A, B, C, D); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* MARS Decryption -*/ -void MARS::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit A = load_le<u32bit>(in, 3) + m_EK[39]; - u32bit B = load_le<u32bit>(in, 2) + m_EK[38]; - u32bit C = load_le<u32bit>(in, 1) + m_EK[37]; - u32bit D = load_le<u32bit>(in, 0) + m_EK[36]; - - forward_mix(A, B, C, D); - - decrypt_round(A, B, C, D, m_EK[35], m_EK[34]); - decrypt_round(B, C, D, A, m_EK[33], m_EK[32]); - decrypt_round(C, D, A, B, m_EK[31], m_EK[30]); - decrypt_round(D, A, B, C, m_EK[29], m_EK[28]); - decrypt_round(A, B, C, D, m_EK[27], m_EK[26]); - decrypt_round(B, C, D, A, m_EK[25], m_EK[24]); - decrypt_round(C, D, A, B, m_EK[23], m_EK[22]); - decrypt_round(D, A, B, C, m_EK[21], m_EK[20]); - - decrypt_round(A, D, C, B, m_EK[19], m_EK[18]); - decrypt_round(B, A, D, C, m_EK[17], m_EK[16]); - decrypt_round(C, B, A, D, m_EK[15], m_EK[14]); - decrypt_round(D, C, B, A, m_EK[13], m_EK[12]); - decrypt_round(A, D, C, B, m_EK[11], m_EK[10]); - decrypt_round(B, A, D, C, m_EK[ 9], m_EK[ 8]); - decrypt_round(C, B, A, D, m_EK[ 7], m_EK[ 6]); - decrypt_round(D, C, B, A, m_EK[ 5], m_EK[ 4]); - - reverse_mix(A, B, C, D); - - A -= m_EK[3]; B -= m_EK[2]; C -= m_EK[1]; D -= m_EK[0]; - - store_le(out, D, C, B, A); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* MARS Key Schedule -*/ -void MARS::key_schedule(const byte key[], size_t length) - { - secure_vector<u32bit> T(15); - for(size_t i = 0; i != length / 4; ++i) - T[i] = load_le<u32bit>(key, i); - - T[length / 4] = static_cast<u32bit>(length) / 4; - - m_EK.resize(40); - - for(u32bit i = 0; i != 4; ++i) - { - T[ 0] ^= rotate_left(T[ 8] ^ T[13], 3) ^ (i ); - T[ 1] ^= rotate_left(T[ 9] ^ T[14], 3) ^ (i + 4); - T[ 2] ^= rotate_left(T[10] ^ T[ 0], 3) ^ (i + 8); - T[ 3] ^= rotate_left(T[11] ^ T[ 1], 3) ^ (i + 12); - T[ 4] ^= rotate_left(T[12] ^ T[ 2], 3) ^ (i + 16); - T[ 5] ^= rotate_left(T[13] ^ T[ 3], 3) ^ (i + 20); - T[ 6] ^= rotate_left(T[14] ^ T[ 4], 3) ^ (i + 24); - T[ 7] ^= rotate_left(T[ 0] ^ T[ 5], 3) ^ (i + 28); - T[ 8] ^= rotate_left(T[ 1] ^ T[ 6], 3) ^ (i + 32); - T[ 9] ^= rotate_left(T[ 2] ^ T[ 7], 3) ^ (i + 36); - T[10] ^= rotate_left(T[ 3] ^ T[ 8], 3) ^ (i + 40); - T[11] ^= rotate_left(T[ 4] ^ T[ 9], 3) ^ (i + 44); - T[12] ^= rotate_left(T[ 5] ^ T[10], 3) ^ (i + 48); - T[13] ^= rotate_left(T[ 6] ^ T[11], 3) ^ (i + 52); - T[14] ^= rotate_left(T[ 7] ^ T[12], 3) ^ (i + 56); - - for(size_t j = 0; j != 4; ++j) - { - T[ 0] = rotate_left(T[ 0] + SBOX[T[14] % 512], 9); - T[ 1] = rotate_left(T[ 1] + SBOX[T[ 0] % 512], 9); - T[ 2] = rotate_left(T[ 2] + SBOX[T[ 1] % 512], 9); - T[ 3] = rotate_left(T[ 3] + SBOX[T[ 2] % 512], 9); - T[ 4] = rotate_left(T[ 4] + SBOX[T[ 3] % 512], 9); - T[ 5] = rotate_left(T[ 5] + SBOX[T[ 4] % 512], 9); - T[ 6] = rotate_left(T[ 6] + SBOX[T[ 5] % 512], 9); - T[ 7] = rotate_left(T[ 7] + SBOX[T[ 6] % 512], 9); - T[ 8] = rotate_left(T[ 8] + SBOX[T[ 7] % 512], 9); - T[ 9] = rotate_left(T[ 9] + SBOX[T[ 8] % 512], 9); - T[10] = rotate_left(T[10] + SBOX[T[ 9] % 512], 9); - T[11] = rotate_left(T[11] + SBOX[T[10] % 512], 9); - T[12] = rotate_left(T[12] + SBOX[T[11] % 512], 9); - T[13] = rotate_left(T[13] + SBOX[T[12] % 512], 9); - T[14] = rotate_left(T[14] + SBOX[T[13] % 512], 9); - } - - m_EK[10*i + 0] = T[ 0]; - m_EK[10*i + 1] = T[ 4]; - m_EK[10*i + 2] = T[ 8]; - m_EK[10*i + 3] = T[12]; - m_EK[10*i + 4] = T[ 1]; - m_EK[10*i + 5] = T[ 5]; - m_EK[10*i + 6] = T[ 9]; - m_EK[10*i + 7] = T[13]; - m_EK[10*i + 8] = T[ 2]; - m_EK[10*i + 9] = T[ 6]; - } - - for(size_t i = 5; i != 37; i += 2) - { - const u32bit key3 = m_EK[i] & 3; - m_EK[i] |= 3; - m_EK[i] ^= rotate_left(SBOX[265 + key3], m_EK[i-1] % 32) & gen_mask(m_EK[i]); - } - } - -void MARS::clear() - { - zap(m_EK); - } - -} diff --git a/src/lib/block/mars/mars.h b/src/lib/block/mars/mars.h deleted file mode 100644 index a4d7a07d6..000000000 --- a/src/lib/block/mars/mars.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* MARS -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_MARS_H__ -#define BOTAN_MARS_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* MARS, IBM's candidate for AES -*/ -class BOTAN_DLL MARS final : public Block_Cipher_Fixed_Params<16, 16, 32, 4> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "MARS"; } - BlockCipher* clone() const override { return new MARS; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK; - }; - -} - -#endif diff --git a/src/lib/block/rc2/info.txt b/src/lib/block/rc2/info.txt deleted file mode 100644 index fae09cf23..000000000 --- a/src/lib/block/rc2/info.txt +++ /dev/null @@ -1 +0,0 @@ -define RC2 20131128 diff --git a/src/lib/block/rc2/rc2.cpp b/src/lib/block/rc2/rc2.cpp deleted file mode 100644 index 112c6561d..000000000 --- a/src/lib/block/rc2/rc2.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* -* RC2 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/rc2.h> -#include <botan/loadstor.h> - -namespace Botan { - -/* -* RC2 Encryption -*/ -void RC2::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(size_t j = 0; j != 16; ++j) - { - R0 += (R1 & ~R3) + (R2 & R3) + m_K[4*j]; - R0 = rotate_left(R0, 1); - - R1 += (R2 & ~R0) + (R3 & R0) + m_K[4*j + 1]; - R1 = rotate_left(R1, 2); - - R2 += (R3 & ~R1) + (R0 & R1) + m_K[4*j + 2]; - R2 = rotate_left(R2, 3); - - R3 += (R0 & ~R2) + (R1 & R2) + m_K[4*j + 3]; - R3 = rotate_left(R3, 5); - - if(j == 4 || j == 10) - { - R0 += m_K[R3 % 64]; - R1 += m_K[R0 % 64]; - R2 += m_K[R1 % 64]; - R3 += m_K[R2 % 64]; - } - } - - store_le(out, R0, R1, R2, R3); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* RC2 Decryption -*/ -void RC2::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(size_t j = 0; j != 16; ++j) - { - R3 = rotate_right(R3, 5); - R3 -= (R0 & ~R2) + (R1 & R2) + m_K[63 - (4*j + 0)]; - - R2 = rotate_right(R2, 3); - R2 -= (R3 & ~R1) + (R0 & R1) + m_K[63 - (4*j + 1)]; - - R1 = rotate_right(R1, 2); - R1 -= (R2 & ~R0) + (R3 & R0) + m_K[63 - (4*j + 2)]; - - R0 = rotate_right(R0, 1); - R0 -= (R1 & ~R3) + (R2 & R3) + m_K[63 - (4*j + 3)]; - - if(j == 4 || j == 10) - { - R3 -= m_K[R2 % 64]; - R2 -= m_K[R1 % 64]; - R1 -= m_K[R0 % 64]; - R0 -= m_K[R3 % 64]; - } - } - - store_le(out, R0, R1, R2, R3); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* RC2 Key Schedule -*/ -void RC2::key_schedule(const byte key[], size_t length) - { - static const byte TABLE[256] = { - 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, 0x28, 0xE9, 0xFD, 0x79, - 0x4A, 0xA0, 0xD8, 0x9D, 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, - 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, 0x17, 0x9A, 0x59, 0xF5, - 0x87, 0xB3, 0x4F, 0x13, 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, - 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, 0xF0, 0x95, 0x21, 0x22, - 0x5C, 0x6B, 0x4E, 0x82, 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, - 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, 0x12, 0x75, 0xCA, 0x1F, - 0x3B, 0xBE, 0xE4, 0xD1, 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, - 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, 0x27, 0xF2, 0x1D, 0x9B, - 0xBC, 0x94, 0x43, 0x03, 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, - 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, 0x08, 0xE8, 0xEA, 0xDE, - 0x80, 0x52, 0xEE, 0xF7, 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, - 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, 0x4B, 0x9F, 0xD0, 0x5E, - 0x04, 0x18, 0xA4, 0xEC, 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, - 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, 0x99, 0x7C, 0x3A, 0x85, - 0x23, 0xB8, 0xB4, 0x7A, 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, - 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, 0x05, 0xDF, 0x29, 0x10, - 0x67, 0x6C, 0xBA, 0xC9, 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, - 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, 0x0D, 0x38, 0x34, 0x1B, - 0xAB, 0x33, 0xFF, 0xB0, 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, - 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, - 0xFE, 0x7F, 0xC1, 0xAD }; - - secure_vector<byte> L(128); - copy_mem(L.data(), key, length); - - for(size_t i = length; i != 128; ++i) - L[i] = TABLE[(L[i-1] + L[i-length]) % 256]; - - L[128-length] = TABLE[L[128-length]]; - - for(s32bit i = 127-length; i >= 0; --i) - L[i] = TABLE[L[i+1] ^ L[i+length]]; - - m_K.resize(64); - load_le<u16bit>(m_K.data(), L.data(), 64); - } - -void RC2::clear() - { - zap(m_K); - } - -/* -* Return the code of the effective key bits -*/ -byte RC2::EKB_code(size_t ekb) - { - const byte EKB[256] = { - 0xBD, 0x56, 0xEA, 0xF2, 0xA2, 0xF1, 0xAC, 0x2A, 0xB0, 0x93, 0xD1, 0x9C, - 0x1B, 0x33, 0xFD, 0xD0, 0x30, 0x04, 0xB6, 0xDC, 0x7D, 0xDF, 0x32, 0x4B, - 0xF7, 0xCB, 0x45, 0x9B, 0x31, 0xBB, 0x21, 0x5A, 0x41, 0x9F, 0xE1, 0xD9, - 0x4A, 0x4D, 0x9E, 0xDA, 0xA0, 0x68, 0x2C, 0xC3, 0x27, 0x5F, 0x80, 0x36, - 0x3E, 0xEE, 0xFB, 0x95, 0x1A, 0xFE, 0xCE, 0xA8, 0x34, 0xA9, 0x13, 0xF0, - 0xA6, 0x3F, 0xD8, 0x0C, 0x78, 0x24, 0xAF, 0x23, 0x52, 0xC1, 0x67, 0x17, - 0xF5, 0x66, 0x90, 0xE7, 0xE8, 0x07, 0xB8, 0x60, 0x48, 0xE6, 0x1E, 0x53, - 0xF3, 0x92, 0xA4, 0x72, 0x8C, 0x08, 0x15, 0x6E, 0x86, 0x00, 0x84, 0xFA, - 0xF4, 0x7F, 0x8A, 0x42, 0x19, 0xF6, 0xDB, 0xCD, 0x14, 0x8D, 0x50, 0x12, - 0xBA, 0x3C, 0x06, 0x4E, 0xEC, 0xB3, 0x35, 0x11, 0xA1, 0x88, 0x8E, 0x2B, - 0x94, 0x99, 0xB7, 0x71, 0x74, 0xD3, 0xE4, 0xBF, 0x3A, 0xDE, 0x96, 0x0E, - 0xBC, 0x0A, 0xED, 0x77, 0xFC, 0x37, 0x6B, 0x03, 0x79, 0x89, 0x62, 0xC6, - 0xD7, 0xC0, 0xD2, 0x7C, 0x6A, 0x8B, 0x22, 0xA3, 0x5B, 0x05, 0x5D, 0x02, - 0x75, 0xD5, 0x61, 0xE3, 0x18, 0x8F, 0x55, 0x51, 0xAD, 0x1F, 0x0B, 0x5E, - 0x85, 0xE5, 0xC2, 0x57, 0x63, 0xCA, 0x3D, 0x6C, 0xB4, 0xC5, 0xCC, 0x70, - 0xB2, 0x91, 0x59, 0x0D, 0x47, 0x20, 0xC8, 0x4F, 0x58, 0xE0, 0x01, 0xE2, - 0x16, 0x38, 0xC4, 0x6F, 0x3B, 0x0F, 0x65, 0x46, 0xBE, 0x7E, 0x2D, 0x7B, - 0x82, 0xF9, 0x40, 0xB5, 0x1D, 0x73, 0xF8, 0xEB, 0x26, 0xC7, 0x87, 0x97, - 0x25, 0x54, 0xB1, 0x28, 0xAA, 0x98, 0x9D, 0xA5, 0x64, 0x6D, 0x7A, 0xD4, - 0x10, 0x81, 0x44, 0xEF, 0x49, 0xD6, 0xAE, 0x2E, 0xDD, 0x76, 0x5C, 0x2F, - 0xA7, 0x1C, 0xC9, 0x09, 0x69, 0x9A, 0x83, 0xCF, 0x29, 0x39, 0xB9, 0xE9, - 0x4C, 0xFF, 0x43, 0xAB }; - - if(ekb < 256) - return EKB[ekb]; - else - throw Encoding_Error("RC2::EKB_code: EKB is too large"); - } - -} diff --git a/src/lib/block/rc2/rc2.h b/src/lib/block/rc2/rc2.h deleted file mode 100644 index 9ec9b9557..000000000 --- a/src/lib/block/rc2/rc2.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -* RC2 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_RC2_H__ -#define BOTAN_RC2_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* RC2 -*/ -class BOTAN_DLL RC2 final : public Block_Cipher_Fixed_Params<8, 1, 32> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - /** - * Return the code of the effective key bits - * @param bits key length - * @return EKB code - */ - static byte EKB_code(size_t bits); - - void clear() override; - std::string name() const override { return "RC2"; } - BlockCipher* clone() const override { return new RC2; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u16bit> m_K; - }; - -} - -#endif diff --git a/src/lib/block/rc5/info.txt b/src/lib/block/rc5/info.txt deleted file mode 100644 index 2c2c613ba..000000000 --- a/src/lib/block/rc5/info.txt +++ /dev/null @@ -1 +0,0 @@ -define RC5 20131128 diff --git a/src/lib/block/rc5/rc5.cpp b/src/lib/block/rc5/rc5.cpp deleted file mode 100644 index a02a45e9f..000000000 --- a/src/lib/block/rc5/rc5.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -* RC5 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/rc5.h> -#include <botan/loadstor.h> -#include <botan/parsing.h> - -namespace Botan { - -/* -* RC5 Encryption -*/ -void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - - A += m_S[0]; B += m_S[1]; - for(size_t j = 0; j != m_rounds; j += 4) - { - A = rotate_left(A ^ B, B % 32) + m_S[2*j+2]; - B = rotate_left(B ^ A, A % 32) + m_S[2*j+3]; - - A = rotate_left(A ^ B, B % 32) + m_S[2*j+4]; - B = rotate_left(B ^ A, A % 32) + m_S[2*j+5]; - - A = rotate_left(A ^ B, B % 32) + m_S[2*j+6]; - B = rotate_left(B ^ A, A % 32) + m_S[2*j+7]; - - A = rotate_left(A ^ B, B % 32) + m_S[2*j+8]; - B = rotate_left(B ^ A, A % 32) + m_S[2*j+9]; - } - - store_le(out, A, B); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* RC5 Decryption -*/ -void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - - for(size_t j = m_rounds; j != 0; j -= 4) - { - B = rotate_right(B - m_S[2*j+1], A % 32) ^ A; - A = rotate_right(A - m_S[2*j ], B % 32) ^ B; - - B = rotate_right(B - m_S[2*j-1], A % 32) ^ A; - A = rotate_right(A - m_S[2*j-2], B % 32) ^ B; - - B = rotate_right(B - m_S[2*j-3], A % 32) ^ A; - A = rotate_right(A - m_S[2*j-4], B % 32) ^ B; - - B = rotate_right(B - m_S[2*j-5], A % 32) ^ A; - A = rotate_right(A - m_S[2*j-6], B % 32) ^ B; - } - B -= m_S[1]; A -= m_S[0]; - - store_le(out, A, B); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* RC5 Key Schedule -*/ -void RC5::key_schedule(const byte key[], size_t length) - { - m_S.resize(2*m_rounds + 2); - - const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); - const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, m_S.size()); - - m_S[0] = 0xB7E15163; - for(size_t i = 1; i != m_S.size(); ++i) - m_S[i] = m_S[i-1] + 0x9E3779B9; - - secure_vector<u32bit> K(8); - - for(s32bit i = length-1; i >= 0; --i) - K[i/4] = (K[i/4] << 8) + key[i]; - - u32bit A = 0, B = 0; - - for(size_t i = 0; i != MIX_ROUNDS; ++i) - { - A = rotate_left(m_S[i % m_S.size()] + A + B, 3); - B = rotate_left(K[i % WORD_KEYLENGTH] + A + B, (A + B) % 32); - m_S[i % m_S.size()] = A; - K[i % WORD_KEYLENGTH] = B; - } - } - -void RC5::clear() - { - zap(m_S); - } - -/* -* Return the name of this type -*/ -std::string RC5::name() const - { - return "RC5(" + std::to_string(m_rounds) + ")"; - } - -/* -* RC5 Constructor -*/ -RC5::RC5(size_t r) : m_rounds(r) - { - if(m_rounds < 8 || m_rounds > 32 || (m_rounds % 4 != 0)) - throw Invalid_Argument("RC5: Invalid number of rounds " + - std::to_string(m_rounds)); - } - -} diff --git a/src/lib/block/rc5/rc5.h b/src/lib/block/rc5/rc5.h deleted file mode 100644 index 4d9232326..000000000 --- a/src/lib/block/rc5/rc5.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -* RC5 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_RC5_H__ -#define BOTAN_RC5_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* RC5 -*/ -class BOTAN_DLL RC5 final : public Block_Cipher_Fixed_Params<8, 1, 32> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override; - BlockCipher* clone() const override { return new RC5(m_rounds); } - - /** - * @param rounds the number of RC5 rounds to run. Must be between - * 8 and 32 and a multiple of 4. - */ - explicit RC5(size_t rounds); - private: - void key_schedule(const byte[], size_t) override; - - size_t m_rounds; - secure_vector<u32bit> m_S; - }; - -} - -#endif diff --git a/src/lib/block/rc6/info.txt b/src/lib/block/rc6/info.txt deleted file mode 100644 index e54379f65..000000000 --- a/src/lib/block/rc6/info.txt +++ /dev/null @@ -1 +0,0 @@ -define RC6 20131128 diff --git a/src/lib/block/rc6/rc6.cpp b/src/lib/block/rc6/rc6.cpp deleted file mode 100644 index 426b86ebd..000000000 --- a/src/lib/block/rc6/rc6.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* -* RC6 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/rc6.h> -#include <botan/loadstor.h> - -namespace Botan { - -/* -* RC6 Encryption -*/ -void RC6::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); - - B += m_S[0]; D += m_S[1]; - - for(size_t j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - A = rotate_left(A ^ T1, T2 % 32) + m_S[2*j+2]; - C = rotate_left(C ^ T2, T1 % 32) + m_S[2*j+3]; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - B = rotate_left(B ^ T1, T2 % 32) + m_S[2*j+4]; - D = rotate_left(D ^ T2, T1 % 32) + m_S[2*j+5]; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - C = rotate_left(C ^ T1, T2 % 32) + m_S[2*j+6]; - A = rotate_left(A ^ T2, T1 % 32) + m_S[2*j+7]; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - D = rotate_left(D ^ T1, T2 % 32) + m_S[2*j+8]; - B = rotate_left(B ^ T2, T1 % 32) + m_S[2*j+9]; - } - - A += m_S[42]; C += m_S[43]; - - store_le(out, A, B, C, D); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* RC6 Decryption -*/ -void RC6::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); - - C -= m_S[43]; A -= m_S[42]; - - for(size_t j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - B = rotate_right(B - m_S[41 - 2*j], T1 % 32) ^ T2; - D = rotate_right(D - m_S[40 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - A = rotate_right(A - m_S[39 - 2*j], T1 % 32) ^ T2; - C = rotate_right(C - m_S[38 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - D = rotate_right(D - m_S[37 - 2*j], T1 % 32) ^ T2; - B = rotate_right(B - m_S[36 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - C = rotate_right(C - m_S[35 - 2*j], T1 % 32) ^ T2; - A = rotate_right(A - m_S[34 - 2*j], T2 % 32) ^ T1; - } - - D -= m_S[1]; B -= m_S[0]; - - store_le(out, A, B, C, D); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* RC6 Key Schedule -*/ -void RC6::key_schedule(const byte key[], size_t length) - { - m_S.resize(44); - - const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); - const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, m_S.size()); - - m_S[0] = 0xB7E15163; - for(size_t i = 1; i != m_S.size(); ++i) - m_S[i] = m_S[i-1] + 0x9E3779B9; - - secure_vector<u32bit> K(8); - - for(s32bit i = length-1; i >= 0; --i) - K[i/4] = (K[i/4] << 8) + key[i]; - - u32bit A = 0, B = 0; - for(size_t i = 0; i != MIX_ROUNDS; ++i) - { - A = rotate_left(m_S[i % m_S.size()] + A + B, 3); - B = rotate_left(K[i % WORD_KEYLENGTH] + A + B, (A + B) % 32); - m_S[i % m_S.size()] = A; - K[i % WORD_KEYLENGTH] = B; - } - } - -void RC6::clear() - { - zap(m_S); - } - -} diff --git a/src/lib/block/rc6/rc6.h b/src/lib/block/rc6/rc6.h deleted file mode 100644 index 3f9bb0af1..000000000 --- a/src/lib/block/rc6/rc6.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* RC6 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_RC6_H__ -#define BOTAN_RC6_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* RC6, Ron Rivest's AES candidate -*/ -class BOTAN_DLL RC6 final : public Block_Cipher_Fixed_Params<16, 1, 32> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "RC6"; } - BlockCipher* clone() const override { return new RC6; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_S; - }; - -} - -#endif diff --git a/src/lib/block/safer/info.txt b/src/lib/block/safer/info.txt deleted file mode 100644 index ad7841dab..000000000 --- a/src/lib/block/safer/info.txt +++ /dev/null @@ -1 +0,0 @@ -define SAFER 20131128 diff --git a/src/lib/block/safer/safer_sk.cpp b/src/lib/block/safer/safer_sk.cpp deleted file mode 100644 index 8dec0b897..000000000 --- a/src/lib/block/safer/safer_sk.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* -* SAFER-SK -* (C) 1999-2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/safer_sk.h> -#include <botan/rotate.h> -#include <botan/parsing.h> - -namespace Botan { - -namespace { - -const byte EXP[256] = { - 0x01, 0x2D, 0xE2, 0x93, 0xBE, 0x45, 0x15, 0xAE, 0x78, 0x03, 0x87, 0xA4, - 0xB8, 0x38, 0xCF, 0x3F, 0x08, 0x67, 0x09, 0x94, 0xEB, 0x26, 0xA8, 0x6B, - 0xBD, 0x18, 0x34, 0x1B, 0xBB, 0xBF, 0x72, 0xF7, 0x40, 0x35, 0x48, 0x9C, - 0x51, 0x2F, 0x3B, 0x55, 0xE3, 0xC0, 0x9F, 0xD8, 0xD3, 0xF3, 0x8D, 0xB1, - 0xFF, 0xA7, 0x3E, 0xDC, 0x86, 0x77, 0xD7, 0xA6, 0x11, 0xFB, 0xF4, 0xBA, - 0x92, 0x91, 0x64, 0x83, 0xF1, 0x33, 0xEF, 0xDA, 0x2C, 0xB5, 0xB2, 0x2B, - 0x88, 0xD1, 0x99, 0xCB, 0x8C, 0x84, 0x1D, 0x14, 0x81, 0x97, 0x71, 0xCA, - 0x5F, 0xA3, 0x8B, 0x57, 0x3C, 0x82, 0xC4, 0x52, 0x5C, 0x1C, 0xE8, 0xA0, - 0x04, 0xB4, 0x85, 0x4A, 0xF6, 0x13, 0x54, 0xB6, 0xDF, 0x0C, 0x1A, 0x8E, - 0xDE, 0xE0, 0x39, 0xFC, 0x20, 0x9B, 0x24, 0x4E, 0xA9, 0x98, 0x9E, 0xAB, - 0xF2, 0x60, 0xD0, 0x6C, 0xEA, 0xFA, 0xC7, 0xD9, 0x00, 0xD4, 0x1F, 0x6E, - 0x43, 0xBC, 0xEC, 0x53, 0x89, 0xFE, 0x7A, 0x5D, 0x49, 0xC9, 0x32, 0xC2, - 0xF9, 0x9A, 0xF8, 0x6D, 0x16, 0xDB, 0x59, 0x96, 0x44, 0xE9, 0xCD, 0xE6, - 0x46, 0x42, 0x8F, 0x0A, 0xC1, 0xCC, 0xB9, 0x65, 0xB0, 0xD2, 0xC6, 0xAC, - 0x1E, 0x41, 0x62, 0x29, 0x2E, 0x0E, 0x74, 0x50, 0x02, 0x5A, 0xC3, 0x25, - 0x7B, 0x8A, 0x2A, 0x5B, 0xF0, 0x06, 0x0D, 0x47, 0x6F, 0x70, 0x9D, 0x7E, - 0x10, 0xCE, 0x12, 0x27, 0xD5, 0x4C, 0x4F, 0xD6, 0x79, 0x30, 0x68, 0x36, - 0x75, 0x7D, 0xE4, 0xED, 0x80, 0x6A, 0x90, 0x37, 0xA2, 0x5E, 0x76, 0xAA, - 0xC5, 0x7F, 0x3D, 0xAF, 0xA5, 0xE5, 0x19, 0x61, 0xFD, 0x4D, 0x7C, 0xB7, - 0x0B, 0xEE, 0xAD, 0x4B, 0x22, 0xF5, 0xE7, 0x73, 0x23, 0x21, 0xC8, 0x05, - 0xE1, 0x66, 0xDD, 0xB3, 0x58, 0x69, 0x63, 0x56, 0x0F, 0xA1, 0x31, 0x95, - 0x17, 0x07, 0x3A, 0x28 }; - -const byte LOG[512] = { - 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, 0x10, 0x12, 0x9F, 0xE4, - 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, 0x4F, 0x06, 0x94, 0xFC, - 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, 0x70, 0xED, 0xE8, 0xEC, - 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, 0x44, 0x01, 0xAC, 0x25, - 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, 0x0D, 0x6E, 0xFE, 0x26, - 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, 0x98, 0x05, 0x9C, 0xBB, - 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, 0xAF, 0x24, 0x5B, 0x87, - 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, 0x5C, 0x8B, 0xD5, 0x54, - 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, 0xCA, 0xF5, 0xD1, 0x17, - 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, 0xAE, 0xCC, 0xD6, 0x35, - 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, 0xD0, 0x50, 0x59, 0x3F, - 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, 0x4C, 0x2E, 0x6B, 0x9E, - 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, 0x75, 0x4A, 0x91, 0x71, - 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, 0x0B, 0xDC, 0x37, 0x31, - 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, 0xA4, 0x2F, 0x46, 0xF3, - 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, 0x85, 0x18, 0x04, 0x1D, - 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, 0xEE, 0x8D, 0x53, 0x4B, - 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, 0x81, 0xC4, 0xC7, 0x36, - 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, 0x6D, 0xF0, 0x02, 0x28, - 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, 0x86, 0xCF, 0xE5, 0x42, - 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, 0x92, 0x90, 0x7D, 0x39, - 0x6F, 0xE0, 0x89, 0x30, 0x80, 0x00, 0xB0, 0x09, 0x60, 0xEF, 0xB9, 0xFD, - 0x10, 0x12, 0x9F, 0xE4, 0x69, 0xBA, 0xAD, 0xF8, 0xC0, 0x38, 0xC2, 0x65, - 0x4F, 0x06, 0x94, 0xFC, 0x19, 0xDE, 0x6A, 0x1B, 0x5D, 0x4E, 0xA8, 0x82, - 0x70, 0xED, 0xE8, 0xEC, 0x72, 0xB3, 0x15, 0xC3, 0xFF, 0xAB, 0xB6, 0x47, - 0x44, 0x01, 0xAC, 0x25, 0xC9, 0xFA, 0x8E, 0x41, 0x1A, 0x21, 0xCB, 0xD3, - 0x0D, 0x6E, 0xFE, 0x26, 0x58, 0xDA, 0x32, 0x0F, 0x20, 0xA9, 0x9D, 0x84, - 0x98, 0x05, 0x9C, 0xBB, 0x22, 0x8C, 0x63, 0xE7, 0xC5, 0xE1, 0x73, 0xC6, - 0xAF, 0x24, 0x5B, 0x87, 0x66, 0x27, 0xF7, 0x57, 0xF4, 0x96, 0xB1, 0xB7, - 0x5C, 0x8B, 0xD5, 0x54, 0x79, 0xDF, 0xAA, 0xF6, 0x3E, 0xA3, 0xF1, 0x11, - 0xCA, 0xF5, 0xD1, 0x17, 0x7B, 0x93, 0x83, 0xBC, 0xBD, 0x52, 0x1E, 0xEB, - 0xAE, 0xCC, 0xD6, 0x35, 0x08, 0xC8, 0x8A, 0xB4, 0xE2, 0xCD, 0xBF, 0xD9, - 0xD0, 0x50, 0x59, 0x3F, 0x4D, 0x62, 0x34, 0x0A, 0x48, 0x88, 0xB5, 0x56, - 0x4C, 0x2E, 0x6B, 0x9E, 0xD2, 0x3D, 0x3C, 0x03, 0x13, 0xFB, 0x97, 0x51, - 0x75, 0x4A, 0x91, 0x71, 0x23, 0xBE, 0x76, 0x2A, 0x5F, 0xF9, 0xD4, 0x55, - 0x0B, 0xDC, 0x37, 0x31, 0x16, 0x74, 0xD7, 0x77, 0xA7, 0xE6, 0x07, 0xDB, - 0xA4, 0x2F, 0x46, 0xF3, 0x61, 0x45, 0x67, 0xE3, 0x0C, 0xA2, 0x3B, 0x1C, - 0x85, 0x18, 0x04, 0x1D, 0x29, 0xA0, 0x8F, 0xB2, 0x5A, 0xD8, 0xA6, 0x7E, - 0xEE, 0x8D, 0x53, 0x4B, 0xA1, 0x9A, 0xC1, 0x0E, 0x7A, 0x49, 0xA5, 0x2C, - 0x81, 0xC4, 0xC7, 0x36, 0x2B, 0x7F, 0x43, 0x95, 0x33, 0xF2, 0x6C, 0x68, - 0x6D, 0xF0, 0x02, 0x28, 0xCE, 0xDD, 0x9B, 0xEA, 0x5E, 0x99, 0x7C, 0x14, - 0x86, 0xCF, 0xE5, 0x42, 0xB8, 0x40, 0x78, 0x2D, 0x3A, 0xE9, 0x64, 0x1F, - 0x92, 0x90, 0x7D, 0x39, 0x6F, 0xE0, 0x89, 0x30 }; - -} - -/* -* SAFER-SK Encryption -*/ -void SAFER_SK::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7], X, Y; - - for(size_t j = 0; j != 16*m_rounds; j += 16) - { - A = EXP[A ^ m_EK[j ]]; B = LOG[B + m_EK[j+1]]; - C = LOG[C + m_EK[j+2]]; D = EXP[D ^ m_EK[j+3]]; - E = EXP[E ^ m_EK[j+4]]; F = LOG[F + m_EK[j+5]]; - G = LOG[G + m_EK[j+6]]; H = EXP[H ^ m_EK[j+7]]; - - A += m_EK[j+ 8]; B ^= m_EK[j+ 9]; C ^= m_EK[j+10]; D += m_EK[j+11]; - E += m_EK[j+12]; F ^= m_EK[j+13]; G ^= m_EK[j+14]; H += m_EK[j+15]; - - B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; - C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; - H += D; Y = D + H; D = B + F; X = B + D; B = A + E; - A += B; F = C + G; E = C + F; C = X; G = Y; - } - - out[0] = A ^ m_EK[16*m_rounds+0]; out[1] = B + m_EK[16*m_rounds+1]; - out[2] = C + m_EK[16*m_rounds+2]; out[3] = D ^ m_EK[16*m_rounds+3]; - out[4] = E ^ m_EK[16*m_rounds+4]; out[5] = F + m_EK[16*m_rounds+5]; - out[6] = G + m_EK[16*m_rounds+6]; out[7] = H ^ m_EK[16*m_rounds+7]; - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* SAFER-SK Decryption -*/ -void SAFER_SK::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7]; - - A ^= m_EK[16*m_rounds+0]; B -= m_EK[16*m_rounds+1]; C -= m_EK[16*m_rounds+2]; - D ^= m_EK[16*m_rounds+3]; E ^= m_EK[16*m_rounds+4]; F -= m_EK[16*m_rounds+5]; - G -= m_EK[16*m_rounds+6]; H ^= m_EK[16*m_rounds+7]; - - for(s32bit j = 16*(m_rounds-1); j >= 0; j -= 16) - { - byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; - A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; - A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; - A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; - - A = LOG[A - m_EK[j+8 ] + 256]; B = EXP[B ^ m_EK[j+9 ]]; - C = EXP[C ^ m_EK[j+10]]; D = LOG[D - m_EK[j+11] + 256]; - E = LOG[E - m_EK[j+12] + 256]; F = EXP[F ^ m_EK[j+13]]; - G = EXP[G ^ m_EK[j+14]]; H = LOG[H - m_EK[j+15] + 256]; - - A ^= m_EK[j+0]; B -= m_EK[j+1]; C -= m_EK[j+2]; D ^= m_EK[j+3]; - E ^= m_EK[j+4]; F -= m_EK[j+5]; G -= m_EK[j+6]; H ^= m_EK[j+7]; - } - - out[0] = A; out[1] = B; out[2] = C; out[3] = D; - out[4] = E; out[5] = F; out[6] = G; out[7] = H; - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* SAFER-SK Key Schedule -*/ -void SAFER_SK::key_schedule(const byte key[], size_t) - { - const byte BIAS[208] = { - 0x16, 0x73, 0x3B, 0x1E, 0x8E, 0x70, 0xBD, 0x86, 0x47, 0x7E, 0x24, 0x56, - 0xF1, 0x77, 0x88, 0x46, 0xB1, 0xBA, 0xA3, 0xB7, 0x10, 0x0A, 0xC5, 0x37, - 0xC9, 0x5A, 0x28, 0xAC, 0x64, 0xA5, 0xEC, 0xAB, 0xC6, 0x67, 0x95, 0x58, - 0x0D, 0xF8, 0x9A, 0xF6, 0x66, 0xDC, 0x05, 0x3D, 0xD3, 0x8A, 0xC3, 0xD8, - 0x6A, 0xE9, 0x36, 0x49, 0x43, 0xBF, 0xEB, 0xD4, 0x9B, 0x68, 0xA0, 0x65, - 0x5D, 0x57, 0x92, 0x1F, 0x71, 0x5C, 0xBB, 0x22, 0xC1, 0xBE, 0x7B, 0xBC, - 0x63, 0x94, 0x5F, 0x2A, 0x61, 0xB8, 0x34, 0x32, 0xFD, 0xFB, 0x17, 0x40, - 0xE6, 0x51, 0x1D, 0x41, 0x8F, 0x29, 0xDD, 0x04, 0x80, 0xDE, 0xE7, 0x31, - 0x7F, 0x01, 0xA2, 0xF7, 0x39, 0xDA, 0x6F, 0x23, 0xFE, 0x3A, 0xD0, 0x1C, - 0xD1, 0x30, 0x3E, 0x12, 0xCD, 0x0F, 0xE0, 0xA8, 0xAF, 0x82, 0x59, 0x2C, - 0x7D, 0xAD, 0xB2, 0xEF, 0xC2, 0x87, 0xCE, 0x75, 0x13, 0x02, 0x90, 0x4F, - 0x2E, 0x72, 0x33, 0x85, 0x8D, 0xCF, 0xA9, 0x81, 0xE2, 0xC4, 0x27, 0x2F, - 0x7A, 0x9F, 0x52, 0xE1, 0x15, 0x38, 0x2B, 0xFC, 0x42, 0xC7, 0x08, 0xE4, - 0x09, 0x55, 0x5E, 0x8C, 0x76, 0x60, 0xFF, 0xDF, 0xD7, 0x98, 0xFA, 0x0B, - 0x00, 0x1A, 0xF9, 0xA6, 0xB9, 0xE8, 0x9E, 0x62, 0xD9, 0x91, 0x50, 0xD2, - 0xEE, 0x18, 0xB4, 0x07, 0xEA, 0x5B, 0xA4, 0xC8, 0x0E, 0xCB, 0x48, 0x69, - 0x4E, 0x9C, 0x35, 0x79, 0x45, 0x4D, 0x54, 0xE5, 0x3C, 0x0C, 0x4A, 0x8B, - 0x3F, 0xCC, 0xA7, 0xDB }; - - const byte KEY_INDEX[208] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E, - 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, - 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, - 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x0E, 0x0F, 0x10, 0x11, - 0x09, 0x0A, 0x0B, 0x0C, 0x06, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, - 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x08, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0D, 0x0E, - 0x0F, 0x10, 0x11, 0x09, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x01, - 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x05, 0x06, 0x07, 0x08, - 0x00, 0x01, 0x02, 0x03, 0x0F, 0x10, 0x11, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F }; - - m_EK.resize(16 * m_rounds + 8); - - secure_vector<byte> KB(18); - - for(size_t i = 0; i != 8; ++i) - { - KB[ 8] ^= KB[i] = rotate_left(key[i], 5); - KB[17] ^= KB[i+9] = m_EK[i] = key[i+8]; - } - - for(size_t i = 0; i != m_rounds; ++i) - { - for(size_t j = 0; j != 18; ++j) - KB[j] = rotate_left(KB[j], 6); - for(size_t j = 0; j != 16; ++j) - m_EK[16*i+j+8] = KB[KEY_INDEX[16*i+j]] + BIAS[16*i+j]; - } - } - -void SAFER_SK::clear() - { - zap(m_EK); - } - -/* -* Return the name of this type -*/ -std::string SAFER_SK::name() const - { - return "SAFER-SK(" + std::to_string(m_rounds) + ")"; - } - -/* -* Return a clone of this object -*/ -BlockCipher* SAFER_SK::clone() const - { - return new SAFER_SK(m_rounds); - } - -/* -* SAFER-SK Constructor -*/ -SAFER_SK::SAFER_SK(size_t r) : m_rounds(r) - { - if(m_rounds > 13 || m_rounds == 0) - throw Invalid_Argument(name() + ": Invalid number of rounds"); - } - -} diff --git a/src/lib/block/safer/safer_sk.h b/src/lib/block/safer/safer_sk.h deleted file mode 100644 index af944b36c..000000000 --- a/src/lib/block/safer/safer_sk.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -* SAFER-SK -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_SAFER_SK_H__ -#define BOTAN_SAFER_SK_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* SAFER-SK -*/ -class BOTAN_DLL SAFER_SK final : public Block_Cipher_Fixed_Params<8, 16> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override; - BlockCipher* clone() const override; - - /** - * @param rounds the number of rounds to use - must be between 1 - * and 13 - */ - explicit SAFER_SK(size_t rounds); - private: - void key_schedule(const byte[], size_t) override; - - size_t m_rounds; - secure_vector<byte> m_EK; - }; - -} - -#endif diff --git a/src/lib/block/tea/info.txt b/src/lib/block/tea/info.txt deleted file mode 100644 index 14edfdb03..000000000 --- a/src/lib/block/tea/info.txt +++ /dev/null @@ -1 +0,0 @@ -define TEA 20131128 diff --git a/src/lib/block/tea/tea.cpp b/src/lib/block/tea/tea.cpp deleted file mode 100644 index 457171e1d..000000000 --- a/src/lib/block/tea/tea.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* -* TEA -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/tea.h> -#include <botan/loadstor.h> - -namespace Botan { - -/* -* TEA Encryption -*/ -void TEA::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - u32bit S = 0; - for(size_t j = 0; j != 32; ++j) - { - S += 0x9E3779B9; - L += ((R << 4) + m_K[0]) ^ (R + S) ^ ((R >> 5) + m_K[1]); - R += ((L << 4) + m_K[2]) ^ (L + S) ^ ((L >> 5) + m_K[3]); - } - - store_be(out, L, R); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* TEA Decryption -*/ -void TEA::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - for(size_t i = 0; i != blocks; ++i) - { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - u32bit S = 0xC6EF3720; - for(size_t j = 0; j != 32; ++j) - { - R -= ((L << 4) + m_K[2]) ^ (L + S) ^ ((L >> 5) + m_K[3]); - L -= ((R << 4) + m_K[0]) ^ (R + S) ^ ((R >> 5) + m_K[1]); - S -= 0x9E3779B9; - } - - store_be(out, L, R); - - in += BLOCK_SIZE; - out += BLOCK_SIZE; - } - } - -/* -* TEA Key Schedule -*/ -void TEA::key_schedule(const byte key[], size_t) - { - m_K.resize(4); - for(size_t i = 0; i != 4; ++i) - m_K[i] = load_be<u32bit>(key, i); - } - -void TEA::clear() - { - zap(m_K); - } - -} diff --git a/src/lib/block/tea/tea.h b/src/lib/block/tea/tea.h deleted file mode 100644 index 6b6308381..000000000 --- a/src/lib/block/tea/tea.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* TEA -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_TEA_H__ -#define BOTAN_TEA_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* TEA -*/ -class BOTAN_DLL TEA final : public Block_Cipher_Fixed_Params<8, 16> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "TEA"; } - BlockCipher* clone() const override { return new TEA; } - private: - void key_schedule(const byte[], size_t) override; - secure_vector<u32bit> m_K; - }; - -} - -#endif diff --git a/src/lib/block/xtea_simd/info.txt b/src/lib/block/xtea_simd/info.txt deleted file mode 100644 index 01fb4110d..000000000 --- a/src/lib/block/xtea_simd/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define XTEA_SIMD 20131128 - -<requires> -xtea -simd -</requires> diff --git a/src/lib/block/xtea_simd/xtea_simd.cpp b/src/lib/block/xtea_simd/xtea_simd.cpp deleted file mode 100644 index 6e50f4ff7..000000000 --- a/src/lib/block/xtea_simd/xtea_simd.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -* XTEA in SIMD -* (C) 2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/xtea_simd.h> -#include <botan/internal/simd_32.h> - -namespace Botan { - -namespace { - -void xtea_encrypt_8(const byte in[64], byte out[64], const u32bit EK[64]) - { - SIMD_32 L0 = SIMD_32::load_be(in ); - SIMD_32 R0 = SIMD_32::load_be(in + 16); - SIMD_32 L1 = SIMD_32::load_be(in + 32); - SIMD_32 R1 = SIMD_32::load_be(in + 48); - - SIMD_32::transpose(L0, R0, L1, R1); - - for(size_t i = 0; i != 32; i += 2) - { - SIMD_32 K0(EK[2*i ]); - SIMD_32 K1(EK[2*i+1]); - SIMD_32 K2(EK[2*i+2]); - SIMD_32 K3(EK[2*i+3]); - - L0 += (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K0; - L1 += (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K0; - - R0 += (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K1; - R1 += (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K1; - - L0 += (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K2; - L1 += (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K2; - - R0 += (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K3; - R1 += (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K3; - } - - SIMD_32::transpose(L0, R0, L1, R1); - - L0.store_be(out); - R0.store_be(out + 16); - L1.store_be(out + 32); - R1.store_be(out + 48); - } - -void xtea_decrypt_8(const byte in[64], byte out[64], const u32bit EK[64]) - { - SIMD_32 L0 = SIMD_32::load_be(in ); - SIMD_32 R0 = SIMD_32::load_be(in + 16); - SIMD_32 L1 = SIMD_32::load_be(in + 32); - SIMD_32 R1 = SIMD_32::load_be(in + 48); - - SIMD_32::transpose(L0, R0, L1, R1); - - for(size_t i = 0; i != 32; i += 2) - { - SIMD_32 K0(EK[63 - 2*i]); - SIMD_32 K1(EK[62 - 2*i]); - SIMD_32 K2(EK[61 - 2*i]); - SIMD_32 K3(EK[60 - 2*i]); - - R0 -= (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K0; - R1 -= (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K0; - - L0 -= (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K1; - L1 -= (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K1; - - R0 -= (((L0 << 4) ^ (L0 >> 5)) + L0) ^ K2; - R1 -= (((L1 << 4) ^ (L1 >> 5)) + L1) ^ K2; - - L0 -= (((R0 << 4) ^ (R0 >> 5)) + R0) ^ K3; - L1 -= (((R1 << 4) ^ (R1 >> 5)) + R1) ^ K3; - } - - SIMD_32::transpose(L0, R0, L1, R1); - - L0.store_be(out); - R0.store_be(out + 16); - L1.store_be(out + 32); - R1.store_be(out + 48); - } - -} - -/* -* XTEA Encryption -*/ -void XTEA_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - const u32bit* KS = &(this->get_EK()[0]); - - while(blocks >= 8) - { - xtea_encrypt_8(in, out, KS); - in += 8 * BLOCK_SIZE; - out += 8 * BLOCK_SIZE; - blocks -= 8; - } - - if(blocks) - XTEA::encrypt_n(in, out, blocks); - } - -/* -* XTEA Decryption -*/ -void XTEA_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - const u32bit* KS = &(this->get_EK()[0]); - - while(blocks >= 8) - { - xtea_decrypt_8(in, out, KS); - in += 8 * BLOCK_SIZE; - out += 8 * BLOCK_SIZE; - blocks -= 8; - } - - if(blocks) - XTEA::decrypt_n(in, out, blocks); - } - -} diff --git a/src/lib/block/xtea_simd/xtea_simd.h b/src/lib/block/xtea_simd/xtea_simd.h deleted file mode 100644 index 0b0558032..000000000 --- a/src/lib/block/xtea_simd/xtea_simd.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -* XTEA in SIMD -* (C) 2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_XTEA_SIMD_H__ -#define BOTAN_XTEA_SIMD_H__ - -#include <botan/xtea.h> - -namespace Botan { - -/** -* XTEA implemented using SIMD operations -*/ -class BOTAN_DLL XTEA_SIMD final : public XTEA - { - public: - size_t parallelism() const override { return 8; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - BlockCipher* clone() const override { return new XTEA_SIMD; } - }; - -} - -#endif diff --git a/src/lib/cert/x509/key_constraint.cpp b/src/lib/cert/x509/key_constraint.cpp index a90af013c..30d1cb3b8 100644 --- a/src/lib/cert/x509/key_constraint.cpp +++ b/src/lib/cert/x509/key_constraint.cpp @@ -31,8 +31,7 @@ void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key, permitted |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; } - if(name == "RSA" || name == "RW" || name == "NR" || - name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA") + if(name == "RSA" || name == "DSA" || name == "ECDSA" || name == "ECGDSA" || name == "ECKCDSA") { permitted |= DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_CERT_SIGN | CRL_SIGN; } diff --git a/src/lib/cert/x509/x509_ca.h b/src/lib/cert/x509/x509_ca.h index 6ea51cd06..ba3724f5e 100644 --- a/src/lib/cert/x509/x509_ca.h +++ b/src/lib/cert/x509/x509_ca.h @@ -22,7 +22,6 @@ namespace Botan { class BOTAN_DLL X509_CA { public: - /** * Sign a PKCS#10 Request. * @param req the request to sign diff --git a/src/lib/cert/x509/x509cert.cpp b/src/lib/cert/x509/x509cert.cpp index cb9b644bc..8166e43ef 100644 --- a/src/lib/cert/x509/x509cert.cpp +++ b/src/lib/cert/x509/x509cert.cpp @@ -72,32 +72,6 @@ X509_Certificate::X509_Certificate(const std::vector<byte>& in) : do_decode(); } -X509_Certificate::X509_Certificate(const X509_Certificate& other) : - X509_Object(other) - { - m_subject = other.m_subject; - m_issuer = other.m_issuer; - m_self_signed = other.m_self_signed; - m_v3_extensions = other.m_v3_extensions; - } - -X509_Certificate& X509_Certificate::operator=(const X509_Certificate& other) - { - if(&other == this) - { - return *this; - } - else - { - m_subject = other.m_subject; - m_issuer = other.m_issuer; - m_self_signed = other.m_self_signed; - m_v3_extensions = other.m_v3_extensions; - } - return *this; - } - - /* * Decode the TBSCertificate data */ @@ -276,16 +250,18 @@ bool X509_Certificate::allowed_extended_usage(const std::string& usage) const bool X509_Certificate::allowed_usage(Usage_Type usage) const { + // These follow suggestions in RFC 5280 4.2.1.12 + switch(usage) { case Usage_Type::UNSPECIFIED: return true; case Usage_Type::TLS_SERVER_AUTH: - return (allowed_usage(DATA_ENCIPHERMENT) || allowed_usage(KEY_ENCIPHERMENT) || allowed_usage(DIGITAL_SIGNATURE)) && allowed_extended_usage("PKIX.ServerAuth"); + return (allowed_usage(KEY_AGREEMENT) || allowed_usage(KEY_ENCIPHERMENT) || allowed_usage(DIGITAL_SIGNATURE)) && allowed_extended_usage("PKIX.ServerAuth"); case Usage_Type::TLS_CLIENT_AUTH: - return (allowed_usage(DIGITAL_SIGNATURE) || allowed_usage(NON_REPUDIATION)) && allowed_extended_usage("PKIX.ClientAuth"); + return (allowed_usage(DIGITAL_SIGNATURE) || allowed_usage(KEY_AGREEMENT)) && allowed_extended_usage("PKIX.ClientAuth"); case Usage_Type::OCSP_RESPONDER: return (allowed_usage(DIGITAL_SIGNATURE) || allowed_usage(NON_REPUDIATION)) && allowed_extended_usage("PKIX.OCSPSigning"); diff --git a/src/lib/cert/x509/x509cert.h b/src/lib/cert/x509/x509cert.h index eb98f9c3d..d64d8fd2b 100644 --- a/src/lib/cert/x509/x509cert.h +++ b/src/lib/cert/x509/x509cert.h @@ -274,9 +274,9 @@ class BOTAN_DLL X509_Certificate : public X509_Object explicit X509_Certificate(const std::vector<byte>& in); - X509_Certificate(const X509_Certificate& other); + X509_Certificate(const X509_Certificate& other) = default; - X509_Certificate& operator=(const X509_Certificate& other); + X509_Certificate& operator=(const X509_Certificate& other) = default; private: void force_decode() override; diff --git a/src/lib/hash/has160/has160.cpp b/src/lib/hash/has160/has160.cpp deleted file mode 100644 index 114b5f8b5..000000000 --- a/src/lib/hash/has160/has160.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* -* HAS-160 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/has160.h> - -namespace Botan { - -namespace HAS_160_F { - -/* -* HAS-160 F1 Function -*/ -inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, - u32bit msg, u32bit rot) - { - E += rotate_left(A, rot) + (D ^ (B & (C ^ D))) + msg; - B = rotate_left(B, 10); - } - -/* -* HAS-160 F2 Function -*/ -inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, - u32bit msg, u32bit rot) - { - E += rotate_left(A, rot) + (B ^ C ^ D) + msg + 0x5A827999; - B = rotate_left(B, 17); - } - -/* -* HAS-160 F3 Function -*/ -inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, - u32bit msg, u32bit rot) - { - E += rotate_left(A, rot) + (C ^ (B | ~D)) + msg + 0x6ED9EBA1; - B = rotate_left(B, 25); - } - -/* -* HAS-160 F4 Function -*/ -inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, - u32bit msg, u32bit rot) - { - E += rotate_left(A, rot) + (B ^ C ^ D) + msg + 0x8F1BBCDC; - B = rotate_left(B, 30); - } - -} - -/* -* HAS-160 Compression Function -*/ -void HAS_160::compress_n(const byte input[], size_t blocks) - { - using namespace HAS_160_F; - - u32bit A = m_digest[0], B = m_digest[1], C = m_digest[2], - D = m_digest[3], E = m_digest[4]; - - for(size_t i = 0; i != blocks; ++i) - { - load_le(m_X.data(), input, 16); - - m_X[16] = m_X[ 0] ^ m_X[ 1] ^ m_X[ 2] ^ m_X[ 3]; - m_X[17] = m_X[ 4] ^ m_X[ 5] ^ m_X[ 6] ^ m_X[ 7]; - m_X[18] = m_X[ 8] ^ m_X[ 9] ^ m_X[10] ^ m_X[11]; - m_X[19] = m_X[12] ^ m_X[13] ^ m_X[14] ^ m_X[15]; - F1(A,B,C,D,E,m_X[18], 5); F1(E,A,B,C,D,m_X[ 0],11); - F1(D,E,A,B,C,m_X[ 1], 7); F1(C,D,E,A,B,m_X[ 2],15); - F1(B,C,D,E,A,m_X[ 3], 6); F1(A,B,C,D,E,m_X[19],13); - F1(E,A,B,C,D,m_X[ 4], 8); F1(D,E,A,B,C,m_X[ 5],14); - F1(C,D,E,A,B,m_X[ 6], 7); F1(B,C,D,E,A,m_X[ 7],12); - F1(A,B,C,D,E,m_X[16], 9); F1(E,A,B,C,D,m_X[ 8],11); - F1(D,E,A,B,C,m_X[ 9], 8); F1(C,D,E,A,B,m_X[10],15); - F1(B,C,D,E,A,m_X[11], 6); F1(A,B,C,D,E,m_X[17],12); - F1(E,A,B,C,D,m_X[12], 9); F1(D,E,A,B,C,m_X[13],14); - F1(C,D,E,A,B,m_X[14], 5); F1(B,C,D,E,A,m_X[15],13); - - m_X[16] = m_X[ 3] ^ m_X[ 6] ^ m_X[ 9] ^ m_X[12]; - m_X[17] = m_X[ 2] ^ m_X[ 5] ^ m_X[ 8] ^ m_X[15]; - m_X[18] = m_X[ 1] ^ m_X[ 4] ^ m_X[11] ^ m_X[14]; - m_X[19] = m_X[ 0] ^ m_X[ 7] ^ m_X[10] ^ m_X[13]; - F2(A,B,C,D,E,m_X[18], 5); F2(E,A,B,C,D,m_X[ 3],11); - F2(D,E,A,B,C,m_X[ 6], 7); F2(C,D,E,A,B,m_X[ 9],15); - F2(B,C,D,E,A,m_X[12], 6); F2(A,B,C,D,E,m_X[19],13); - F2(E,A,B,C,D,m_X[15], 8); F2(D,E,A,B,C,m_X[ 2],14); - F2(C,D,E,A,B,m_X[ 5], 7); F2(B,C,D,E,A,m_X[ 8],12); - F2(A,B,C,D,E,m_X[16], 9); F2(E,A,B,C,D,m_X[11],11); - F2(D,E,A,B,C,m_X[14], 8); F2(C,D,E,A,B,m_X[ 1],15); - F2(B,C,D,E,A,m_X[ 4], 6); F2(A,B,C,D,E,m_X[17],12); - F2(E,A,B,C,D,m_X[ 7], 9); F2(D,E,A,B,C,m_X[10],14); - F2(C,D,E,A,B,m_X[13], 5); F2(B,C,D,E,A,m_X[ 0],13); - - m_X[16] = m_X[ 5] ^ m_X[ 7] ^ m_X[12] ^ m_X[14]; - m_X[17] = m_X[ 0] ^ m_X[ 2] ^ m_X[ 9] ^ m_X[11]; - m_X[18] = m_X[ 4] ^ m_X[ 6] ^ m_X[13] ^ m_X[15]; - m_X[19] = m_X[ 1] ^ m_X[ 3] ^ m_X[ 8] ^ m_X[10]; - F3(A,B,C,D,E,m_X[18], 5); F3(E,A,B,C,D,m_X[12],11); - F3(D,E,A,B,C,m_X[ 5], 7); F3(C,D,E,A,B,m_X[14],15); - F3(B,C,D,E,A,m_X[ 7], 6); F3(A,B,C,D,E,m_X[19],13); - F3(E,A,B,C,D,m_X[ 0], 8); F3(D,E,A,B,C,m_X[ 9],14); - F3(C,D,E,A,B,m_X[ 2], 7); F3(B,C,D,E,A,m_X[11],12); - F3(A,B,C,D,E,m_X[16], 9); F3(E,A,B,C,D,m_X[ 4],11); - F3(D,E,A,B,C,m_X[13], 8); F3(C,D,E,A,B,m_X[ 6],15); - F3(B,C,D,E,A,m_X[15], 6); F3(A,B,C,D,E,m_X[17],12); - F3(E,A,B,C,D,m_X[ 8], 9); F3(D,E,A,B,C,m_X[ 1],14); - F3(C,D,E,A,B,m_X[10], 5); F3(B,C,D,E,A,m_X[ 3],13); - - m_X[16] = m_X[ 2] ^ m_X[ 7] ^ m_X[ 8] ^ m_X[13]; - m_X[17] = m_X[ 3] ^ m_X[ 4] ^ m_X[ 9] ^ m_X[14]; - m_X[18] = m_X[ 0] ^ m_X[ 5] ^ m_X[10] ^ m_X[15]; - m_X[19] = m_X[ 1] ^ m_X[ 6] ^ m_X[11] ^ m_X[12]; - F4(A,B,C,D,E,m_X[18], 5); F4(E,A,B,C,D,m_X[ 7],11); - F4(D,E,A,B,C,m_X[ 2], 7); F4(C,D,E,A,B,m_X[13],15); - F4(B,C,D,E,A,m_X[ 8], 6); F4(A,B,C,D,E,m_X[19],13); - F4(E,A,B,C,D,m_X[ 3], 8); F4(D,E,A,B,C,m_X[14],14); - F4(C,D,E,A,B,m_X[ 9], 7); F4(B,C,D,E,A,m_X[ 4],12); - F4(A,B,C,D,E,m_X[16], 9); F4(E,A,B,C,D,m_X[15],11); - F4(D,E,A,B,C,m_X[10], 8); F4(C,D,E,A,B,m_X[ 5],15); - F4(B,C,D,E,A,m_X[ 0], 6); F4(A,B,C,D,E,m_X[17],12); - F4(E,A,B,C,D,m_X[11], 9); F4(D,E,A,B,C,m_X[ 6],14); - F4(C,D,E,A,B,m_X[ 1], 5); F4(B,C,D,E,A,m_X[12],13); - - A = (m_digest[0] += A); - B = (m_digest[1] += B); - C = (m_digest[2] += C); - D = (m_digest[3] += D); - E = (m_digest[4] += E); - - input += hash_block_size(); - } - } - -/* -* Copy out the digest -*/ -void HAS_160::copy_out(byte output[]) - { - copy_out_vec_le(output, output_length(), m_digest); - } - -/* -* Clear memory of sensitive data -*/ -void HAS_160::clear() - { - MDx_HashFunction::clear(); - zeroise(m_X); - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - } - -} diff --git a/src/lib/hash/has160/has160.h b/src/lib/hash/has160/has160.h deleted file mode 100644 index 7ef090eb7..000000000 --- a/src/lib/hash/has160/has160.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* HAS-160 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_HAS_160_H__ -#define BOTAN_HAS_160_H__ - -#include <botan/mdx_hash.h> - -namespace Botan { - -/** -* HAS-160, a Korean hash function standardized in -* TTAS.KO-12.0011/R1. Used in conjunction with KCDSA -*/ -class BOTAN_DLL HAS_160 final : public MDx_HashFunction - { - public: - std::string name() const override { return "HAS-160"; } - size_t output_length() const override { return 20; } - HashFunction* clone() const override { return new HAS_160; } - - void clear() override; - - HAS_160() : MDx_HashFunction(64, false, true), m_X(20), m_digest(5) - { clear(); } - private: - void compress_n(const byte[], size_t blocks) override; - void copy_out(byte[]) override; - - secure_vector<u32bit> m_X, m_digest; - }; - -} - -#endif diff --git a/src/lib/hash/has160/info.txt b/src/lib/hash/has160/info.txt deleted file mode 100644 index cf403dad5..000000000 --- a/src/lib/hash/has160/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define HAS_160 20131128 - -<requires> -mdx_hash -</requires> diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp index 9a15c7998..42a7666b6 100644 --- a/src/lib/hash/hash.cpp +++ b/src/lib/hash/hash.cpp @@ -25,18 +25,10 @@ #include <botan/gost_3411.h> #endif -#if defined(BOTAN_HAS_HAS_160) - #include <botan/has160.h> -#endif - #if defined(BOTAN_HAS_KECCAK) #include <botan/keccak.h> #endif -#if defined(BOTAN_HAS_MD2) - #include <botan/md2.h> -#endif - #if defined(BOTAN_HAS_MD4) #include <botan/md4.h> #endif @@ -45,10 +37,6 @@ #include <botan/md5.h> #endif -#if defined(BOTAN_HAS_RIPEMD_128) - #include <botan/rmd128.h> -#endif - #if defined(BOTAN_HAS_RIPEMD_160) #include <botan/rmd160.h> #endif @@ -147,18 +135,10 @@ BOTAN_REGISTER_NAMED_T(HashFunction, "Parallel", Parallel, Parallel::make); BOTAN_REGISTER_HASH_NAMED_NOARGS(GOST_34_11, "GOST-R-34.11-94"); #endif -#if defined(BOTAN_HAS_HAS_160) -BOTAN_REGISTER_HASH_NAMED_NOARGS(HAS_160, "HAS-160"); -#endif - #if defined(BOTAN_HAS_KECCAK) BOTAN_REGISTER_HASH_NAMED_1LEN(Keccak_1600, "Keccak-1600", 512); #endif -#if defined(BOTAN_HAS_MD2) -BOTAN_REGISTER_HASH_NOARGS(MD2); -#endif - #if defined(BOTAN_HAS_MD4) BOTAN_REGISTER_HASH_NOARGS(MD4); #endif @@ -167,10 +147,6 @@ BOTAN_REGISTER_HASH_NOARGS(MD4); BOTAN_REGISTER_HASH_NOARGS(MD5); #endif -#if defined(BOTAN_HAS_RIPEMD_128) -BOTAN_REGISTER_HASH_NAMED_NOARGS(RIPEMD_128, "RIPEMD-128"); -#endif - #if defined(BOTAN_HAS_RIPEMD_160) BOTAN_REGISTER_HASH_NAMED_NOARGS(RIPEMD_160, "RIPEMD-160"); #endif diff --git a/src/lib/hash/md2/info.txt b/src/lib/hash/md2/info.txt deleted file mode 100644 index 8ea7dc393..000000000 --- a/src/lib/hash/md2/info.txt +++ /dev/null @@ -1 +0,0 @@ -define MD2 20131128 diff --git a/src/lib/hash/md2/md2.cpp b/src/lib/hash/md2/md2.cpp deleted file mode 100644 index f5e222610..000000000 --- a/src/lib/hash/md2/md2.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -* MD2 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/md2.h> - -namespace Botan { - -/** -* MD2 Compression Function -*/ -void MD2::hash(const byte input[]) - { - static const byte SBOX[256] = { - 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, - 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, - 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, - 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, - 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, - 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, - 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 0x80, 0x7F, 0x5D, 0x9A, - 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, - 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, - 0xAC, 0x56, 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, - 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 0x70, 0x59, - 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, - 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, - 0x34, 0x40, 0x7E, 0x0F, 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, - 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, - 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, - 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, - 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, - 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, - 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, - 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, - 0x9F, 0x11, 0x83, 0x14 }; - - buffer_insert(m_X, 16, input, hash_block_size()); - xor_buf(&m_X[32], m_X.data(), &m_X[16], hash_block_size()); - byte T = 0; - - for(size_t i = 0; i != 18; ++i) - { - for(size_t k = 0; k != 48; k += 8) - { - T = m_X[k ] ^= SBOX[T]; T = m_X[k+1] ^= SBOX[T]; - T = m_X[k+2] ^= SBOX[T]; T = m_X[k+3] ^= SBOX[T]; - T = m_X[k+4] ^= SBOX[T]; T = m_X[k+5] ^= SBOX[T]; - T = m_X[k+6] ^= SBOX[T]; T = m_X[k+7] ^= SBOX[T]; - } - - T += static_cast<byte>(i); - } - - T = m_checksum[15]; - for(size_t i = 0; i != hash_block_size(); ++i) - T = m_checksum[i] ^= SBOX[input[i] ^ T]; - } - -/** -* Update the hash -*/ -void MD2::add_data(const byte input[], size_t length) - { - buffer_insert(m_buffer, m_position, input, length); - - if(m_position + length >= hash_block_size()) - { - hash(m_buffer.data()); - input += (hash_block_size() - m_position); - length -= (hash_block_size() - m_position); - while(length >= hash_block_size()) - { - hash(input); - input += hash_block_size(); - length -= hash_block_size(); - } - copy_mem(m_buffer.data(), input, length); - m_position = 0; - } - m_position += length; - } - -/** -* Finalize a MD2 Hash -*/ -void MD2::final_result(byte output[]) - { - for(size_t i = m_position; i != hash_block_size(); ++i) - m_buffer[i] = static_cast<byte>(hash_block_size() - m_position); - - hash(m_buffer.data()); - hash(m_checksum.data()); - copy_mem(output, m_X.data(), output_length()); - clear(); - } - -/** -* Clear memory of sensitive data -*/ -void MD2::clear() - { - zeroise(m_X); - zeroise(m_checksum); - zeroise(m_buffer); - m_position = 0; - } - -} diff --git a/src/lib/hash/md2/md2.h b/src/lib/hash/md2/md2.h deleted file mode 100644 index 58629495a..000000000 --- a/src/lib/hash/md2/md2.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -* MD2 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_MD2_H__ -#define BOTAN_MD2_H__ - -#include <botan/hash.h> - -namespace Botan { - -/** -* MD2 -*/ -class BOTAN_DLL MD2 final : public HashFunction - { - public: - std::string name() const override { return "MD2"; } - size_t output_length() const override { return 16; } - size_t hash_block_size() const override { return 16; } - HashFunction* clone() const override { return new MD2; } - - void clear() override; - - MD2() : m_X(48), m_checksum(16), m_buffer(16), m_position(0) - { clear(); } - private: - void add_data(const byte[], size_t) override; - void hash(const byte[]); - void final_result(byte[]) override; - - secure_vector<byte> m_X, m_checksum, m_buffer; - size_t m_position; - }; - -} - -#endif diff --git a/src/lib/hash/rmd128/info.txt b/src/lib/hash/rmd128/info.txt deleted file mode 100644 index 7d2a4eacd..000000000 --- a/src/lib/hash/rmd128/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define RIPEMD_128 20131128 - -<requires> -mdx_hash -</requires> diff --git a/src/lib/hash/rmd128/rmd128.cpp b/src/lib/hash/rmd128/rmd128.cpp deleted file mode 100644 index e520fa0c3..000000000 --- a/src/lib/hash/rmd128/rmd128.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -* RIPEMD-128 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/rmd128.h> - -namespace Botan { - -namespace RIPEMD_128_F { - -/* -* RIPEMD-128 F1 Function -*/ -inline void F1(u32bit& A, u32bit B, u32bit C, u32bit D, - u32bit msg, u32bit shift) - { - A += (B ^ C ^ D) + msg; - A = rotate_left(A, shift); - } - -/* -* RIPEMD-128 F2 Function -*/ -inline void F2(u32bit& A, u32bit B, u32bit C, u32bit D, - u32bit msg, u32bit shift, u32bit magic) - { - A += (D ^ (B & (C ^ D))) + msg + magic; - A = rotate_left(A, shift); - } - -/* -* RIPEMD-128 F3 Function -*/ -inline void F3(u32bit& A, u32bit B, u32bit C, u32bit D, - u32bit msg, u32bit shift, u32bit magic) - { - A += (D ^ (B | ~C)) + msg + magic; - A = rotate_left(A, shift); - } - -/* -* RIPEMD-128 F4 Function -*/ -inline void F4(u32bit& A, u32bit B, u32bit C, u32bit D, - u32bit msg, u32bit shift, u32bit magic) - { - A += (C ^ (D & (B ^ C))) + msg + magic; - A = rotate_left(A, shift); - } - -} - -/* -* RIPEMD-128 Compression Function -*/ -void RIPEMD_128::compress_n(const byte input[], size_t blocks) - { - using namespace RIPEMD_128_F; - - const u32bit MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1, - MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0x50A28BE6, - MAGIC6 = 0x5C4DD124, MAGIC7 = 0x6D703EF3; - - for(size_t i = 0; i != blocks; ++i) - { - load_le(m_M.data(), input, m_M.size()); - - u32bit A1 = m_digest[0], A2 = A1, B1 = m_digest[1], B2 = B1, - C1 = m_digest[2], C2 = C1, D1 = m_digest[3], D2 = D1; - - F1(A1,B1,C1,D1,m_M[ 0],11 ); F4(A2,B2,C2,D2,m_M[ 5], 8,MAGIC5); - F1(D1,A1,B1,C1,m_M[ 1],14 ); F4(D2,A2,B2,C2,m_M[14], 9,MAGIC5); - F1(C1,D1,A1,B1,m_M[ 2],15 ); F4(C2,D2,A2,B2,m_M[ 7], 9,MAGIC5); - F1(B1,C1,D1,A1,m_M[ 3],12 ); F4(B2,C2,D2,A2,m_M[ 0],11,MAGIC5); - F1(A1,B1,C1,D1,m_M[ 4], 5 ); F4(A2,B2,C2,D2,m_M[ 9],13,MAGIC5); - F1(D1,A1,B1,C1,m_M[ 5], 8 ); F4(D2,A2,B2,C2,m_M[ 2],15,MAGIC5); - F1(C1,D1,A1,B1,m_M[ 6], 7 ); F4(C2,D2,A2,B2,m_M[11],15,MAGIC5); - F1(B1,C1,D1,A1,m_M[ 7], 9 ); F4(B2,C2,D2,A2,m_M[ 4], 5,MAGIC5); - F1(A1,B1,C1,D1,m_M[ 8],11 ); F4(A2,B2,C2,D2,m_M[13], 7,MAGIC5); - F1(D1,A1,B1,C1,m_M[ 9],13 ); F4(D2,A2,B2,C2,m_M[ 6], 7,MAGIC5); - F1(C1,D1,A1,B1,m_M[10],14 ); F4(C2,D2,A2,B2,m_M[15], 8,MAGIC5); - F1(B1,C1,D1,A1,m_M[11],15 ); F4(B2,C2,D2,A2,m_M[ 8],11,MAGIC5); - F1(A1,B1,C1,D1,m_M[12], 6 ); F4(A2,B2,C2,D2,m_M[ 1],14,MAGIC5); - F1(D1,A1,B1,C1,m_M[13], 7 ); F4(D2,A2,B2,C2,m_M[10],14,MAGIC5); - F1(C1,D1,A1,B1,m_M[14], 9 ); F4(C2,D2,A2,B2,m_M[ 3],12,MAGIC5); - F1(B1,C1,D1,A1,m_M[15], 8 ); F4(B2,C2,D2,A2,m_M[12], 6,MAGIC5); - - F2(A1,B1,C1,D1,m_M[ 7], 7,MAGIC2); F3(A2,B2,C2,D2,m_M[ 6], 9,MAGIC6); - F2(D1,A1,B1,C1,m_M[ 4], 6,MAGIC2); F3(D2,A2,B2,C2,m_M[11],13,MAGIC6); - F2(C1,D1,A1,B1,m_M[13], 8,MAGIC2); F3(C2,D2,A2,B2,m_M[ 3],15,MAGIC6); - F2(B1,C1,D1,A1,m_M[ 1],13,MAGIC2); F3(B2,C2,D2,A2,m_M[ 7], 7,MAGIC6); - F2(A1,B1,C1,D1,m_M[10],11,MAGIC2); F3(A2,B2,C2,D2,m_M[ 0],12,MAGIC6); - F2(D1,A1,B1,C1,m_M[ 6], 9,MAGIC2); F3(D2,A2,B2,C2,m_M[13], 8,MAGIC6); - F2(C1,D1,A1,B1,m_M[15], 7,MAGIC2); F3(C2,D2,A2,B2,m_M[ 5], 9,MAGIC6); - F2(B1,C1,D1,A1,m_M[ 3],15,MAGIC2); F3(B2,C2,D2,A2,m_M[10],11,MAGIC6); - F2(A1,B1,C1,D1,m_M[12], 7,MAGIC2); F3(A2,B2,C2,D2,m_M[14], 7,MAGIC6); - F2(D1,A1,B1,C1,m_M[ 0],12,MAGIC2); F3(D2,A2,B2,C2,m_M[15], 7,MAGIC6); - F2(C1,D1,A1,B1,m_M[ 9],15,MAGIC2); F3(C2,D2,A2,B2,m_M[ 8],12,MAGIC6); - F2(B1,C1,D1,A1,m_M[ 5], 9,MAGIC2); F3(B2,C2,D2,A2,m_M[12], 7,MAGIC6); - F2(A1,B1,C1,D1,m_M[ 2],11,MAGIC2); F3(A2,B2,C2,D2,m_M[ 4], 6,MAGIC6); - F2(D1,A1,B1,C1,m_M[14], 7,MAGIC2); F3(D2,A2,B2,C2,m_M[ 9],15,MAGIC6); - F2(C1,D1,A1,B1,m_M[11],13,MAGIC2); F3(C2,D2,A2,B2,m_M[ 1],13,MAGIC6); - F2(B1,C1,D1,A1,m_M[ 8],12,MAGIC2); F3(B2,C2,D2,A2,m_M[ 2],11,MAGIC6); - - F3(A1,B1,C1,D1,m_M[ 3],11,MAGIC3); F2(A2,B2,C2,D2,m_M[15], 9,MAGIC7); - F3(D1,A1,B1,C1,m_M[10],13,MAGIC3); F2(D2,A2,B2,C2,m_M[ 5], 7,MAGIC7); - F3(C1,D1,A1,B1,m_M[14], 6,MAGIC3); F2(C2,D2,A2,B2,m_M[ 1],15,MAGIC7); - F3(B1,C1,D1,A1,m_M[ 4], 7,MAGIC3); F2(B2,C2,D2,A2,m_M[ 3],11,MAGIC7); - F3(A1,B1,C1,D1,m_M[ 9],14,MAGIC3); F2(A2,B2,C2,D2,m_M[ 7], 8,MAGIC7); - F3(D1,A1,B1,C1,m_M[15], 9,MAGIC3); F2(D2,A2,B2,C2,m_M[14], 6,MAGIC7); - F3(C1,D1,A1,B1,m_M[ 8],13,MAGIC3); F2(C2,D2,A2,B2,m_M[ 6], 6,MAGIC7); - F3(B1,C1,D1,A1,m_M[ 1],15,MAGIC3); F2(B2,C2,D2,A2,m_M[ 9],14,MAGIC7); - F3(A1,B1,C1,D1,m_M[ 2],14,MAGIC3); F2(A2,B2,C2,D2,m_M[11],12,MAGIC7); - F3(D1,A1,B1,C1,m_M[ 7], 8,MAGIC3); F2(D2,A2,B2,C2,m_M[ 8],13,MAGIC7); - F3(C1,D1,A1,B1,m_M[ 0],13,MAGIC3); F2(C2,D2,A2,B2,m_M[12], 5,MAGIC7); - F3(B1,C1,D1,A1,m_M[ 6], 6,MAGIC3); F2(B2,C2,D2,A2,m_M[ 2],14,MAGIC7); - F3(A1,B1,C1,D1,m_M[13], 5,MAGIC3); F2(A2,B2,C2,D2,m_M[10],13,MAGIC7); - F3(D1,A1,B1,C1,m_M[11],12,MAGIC3); F2(D2,A2,B2,C2,m_M[ 0],13,MAGIC7); - F3(C1,D1,A1,B1,m_M[ 5], 7,MAGIC3); F2(C2,D2,A2,B2,m_M[ 4], 7,MAGIC7); - F3(B1,C1,D1,A1,m_M[12], 5,MAGIC3); F2(B2,C2,D2,A2,m_M[13], 5,MAGIC7); - - F4(A1,B1,C1,D1,m_M[ 1],11,MAGIC4); F1(A2,B2,C2,D2,m_M[ 8],15 ); - F4(D1,A1,B1,C1,m_M[ 9],12,MAGIC4); F1(D2,A2,B2,C2,m_M[ 6], 5 ); - F4(C1,D1,A1,B1,m_M[11],14,MAGIC4); F1(C2,D2,A2,B2,m_M[ 4], 8 ); - F4(B1,C1,D1,A1,m_M[10],15,MAGIC4); F1(B2,C2,D2,A2,m_M[ 1],11 ); - F4(A1,B1,C1,D1,m_M[ 0],14,MAGIC4); F1(A2,B2,C2,D2,m_M[ 3],14 ); - F4(D1,A1,B1,C1,m_M[ 8],15,MAGIC4); F1(D2,A2,B2,C2,m_M[11],14 ); - F4(C1,D1,A1,B1,m_M[12], 9,MAGIC4); F1(C2,D2,A2,B2,m_M[15], 6 ); - F4(B1,C1,D1,A1,m_M[ 4], 8,MAGIC4); F1(B2,C2,D2,A2,m_M[ 0],14 ); - F4(A1,B1,C1,D1,m_M[13], 9,MAGIC4); F1(A2,B2,C2,D2,m_M[ 5], 6 ); - F4(D1,A1,B1,C1,m_M[ 3],14,MAGIC4); F1(D2,A2,B2,C2,m_M[12], 9 ); - F4(C1,D1,A1,B1,m_M[ 7], 5,MAGIC4); F1(C2,D2,A2,B2,m_M[ 2],12 ); - F4(B1,C1,D1,A1,m_M[15], 6,MAGIC4); F1(B2,C2,D2,A2,m_M[13], 9 ); - F4(A1,B1,C1,D1,m_M[14], 8,MAGIC4); F1(A2,B2,C2,D2,m_M[ 9],12 ); - F4(D1,A1,B1,C1,m_M[ 5], 6,MAGIC4); F1(D2,A2,B2,C2,m_M[ 7], 5 ); - F4(C1,D1,A1,B1,m_M[ 6], 5,MAGIC4); F1(C2,D2,A2,B2,m_M[10],15 ); - F4(B1,C1,D1,A1,m_M[ 2],12,MAGIC4); F1(B2,C2,D2,A2,m_M[14], 8 ); - - D2 = m_digest[1] + C1 + D2; - m_digest[1] = m_digest[2] + D1 + A2; - m_digest[2] = m_digest[3] + A1 + B2; - m_digest[3] = m_digest[0] + B1 + C2; - m_digest[0] = D2; - - input += hash_block_size(); - } - } - -/* -* Copy out the digest -*/ -void RIPEMD_128::copy_out(byte output[]) - { - copy_out_vec_le(output, output_length(), m_digest); - } - -/* -* Clear memory of sensitive data -*/ -void RIPEMD_128::clear() - { - MDx_HashFunction::clear(); - zeroise(m_M); - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - } - -} diff --git a/src/lib/hash/rmd128/rmd128.h b/src/lib/hash/rmd128/rmd128.h deleted file mode 100644 index ba36ab902..000000000 --- a/src/lib/hash/rmd128/rmd128.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -* RIPEMD-128 -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_RIPEMD_128_H__ -#define BOTAN_RIPEMD_128_H__ - -#include <botan/mdx_hash.h> - -namespace Botan { - -/** -* RIPEMD-128 -*/ -class BOTAN_DLL RIPEMD_128 final : public MDx_HashFunction - { - public: - std::string name() const override { return "RIPEMD-128"; } - size_t output_length() const override { return 16; } - HashFunction* clone() const override { return new RIPEMD_128; } - - void clear() override; - - RIPEMD_128() : MDx_HashFunction(64, false, true), m_M(16), m_digest(4) - { clear(); } - private: - void compress_n(const byte[], size_t blocks) override; - void copy_out(byte[]) override; - - secure_vector<u32bit> m_M, m_digest; - }; - -} - -#endif diff --git a/src/lib/math/bigint/big_ops2.cpp b/src/lib/math/bigint/big_ops2.cpp index 9a3408247..6e234f036 100644 --- a/src/lib/math/bigint/big_ops2.cpp +++ b/src/lib/math/bigint/big_ops2.cpp @@ -1,6 +1,7 @@ /* * BigInt Assignment Operators * (C) 1999-2007 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -118,10 +119,7 @@ BigInt& BigInt::operator*=(const BigInt& y) secure_vector<word> z(data(), data() + x_sw); secure_vector<word> workspace(size()); - - bigint_mul(mutable_data(), size(), workspace.data(), - z.data(), z.size(), x_sw, - y.data(), y.size(), y_sw); + bigint_mul(*this, BigInt(*this), y, workspace.data()); } return (*this); diff --git a/src/lib/math/bigint/big_ops3.cpp b/src/lib/math/bigint/big_ops3.cpp index 6cf837020..24927b4fc 100644 --- a/src/lib/math/bigint/big_ops3.cpp +++ b/src/lib/math/bigint/big_ops3.cpp @@ -1,6 +1,7 @@ /* * BigInt Binary Operators * (C) 1999-2007 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -93,9 +94,7 @@ BigInt operator*(const BigInt& x, const BigInt& y) else if(x_sw && y_sw) { secure_vector<word> workspace(z.size()); - bigint_mul(z.mutable_data(), z.size(), workspace.data(), - x.data(), x.size(), x_sw, - y.data(), y.size(), y_sw); + bigint_mul(z, x, y, workspace.data()); } if(x_sw && y_sw && x.sign() != y.sign()) diff --git a/src/lib/math/ec_gfp/curve_gfp.cpp b/src/lib/math/ec_gfp/curve_gfp.cpp index 9bf2191c6..96593e601 100644 --- a/src/lib/math/ec_gfp/curve_gfp.cpp +++ b/src/lib/math/ec_gfp/curve_gfp.cpp @@ -1,6 +1,7 @@ /* * Elliptic curves over GF(p) Montgomery Representation * (C) 2014,2015 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -80,20 +81,14 @@ void CurveGFp_Montgomery::curve_mul(BigInt& z, const BigInt& x, const BigInt& y, return; } - const size_t x_sw = x.sig_words(); - const size_t y_sw = y.sig_words(); - const size_t output_size = 2*m_p_words + 1; ws.resize(2*(m_p_words+2)); z.grow_to(output_size); z.clear(); - bigint_monty_mul(z.mutable_data(), output_size, - x.data(), x.size(), x_sw, - y.data(), y.size(), y_sw, - m_p.data(), m_p_words, m_p_dash, - ws.data()); + bigint_monty_mul(z, x, y, m_p.data(), m_p_words, m_p_dash, ws.data()); + } void CurveGFp_Montgomery::curve_sqr(BigInt& z, const BigInt& x, @@ -115,9 +110,7 @@ void CurveGFp_Montgomery::curve_sqr(BigInt& z, const BigInt& x, z.grow_to(output_size); z.clear(); - bigint_monty_sqr(z.mutable_data(), output_size, - x.data(), x.size(), x_sw, - m_p.data(), m_p_words, m_p_dash, + bigint_monty_sqr(z, x, m_p.data(), m_p_words, m_p_dash, ws.data()); } @@ -174,9 +167,7 @@ void CurveGFp_NIST::curve_mul(BigInt& z, const BigInt& x, const BigInt& y, z.grow_to(output_size); z.clear(); - bigint_mul(z.mutable_data(), output_size, ws.data(), - x.data(), x.size(), x.sig_words(), - y.data(), y.size(), y.sig_words()); + bigint_mul(z, x, y, ws.data()); this->redc(z, ws); } diff --git a/src/lib/math/mp/mp_core.h b/src/lib/math/mp/mp_core.h index 73f13742c..c4ce005ba 100644 --- a/src/lib/math/mp/mp_core.h +++ b/src/lib/math/mp/mp_core.h @@ -2,6 +2,7 @@ * MPI Algorithms * (C) 1999-2010 Jack Lloyd * 2006 Luca Piccarreta +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -9,6 +10,7 @@ #ifndef BOTAN_MP_CORE_OPS_H__ #define BOTAN_MP_CORE_OPS_H__ +#include <botan/bigint.h> #include <botan/mp_types.h> namespace Botan { @@ -134,17 +136,14 @@ void bigint_monty_redc(word z[], /* * Montgomery Multiplication */ -void bigint_monty_mul(word z[], size_t z_size, - const word x[], size_t x_size, size_t x_sw, - const word y[], size_t y_size, size_t y_sw, +void bigint_monty_mul(BigInt& z, const BigInt& x, const BigInt& y, const word p[], size_t p_size, word p_dash, word workspace[]); /* * Montgomery Squaring */ -void bigint_monty_sqr(word z[], size_t z_size, - const word x[], size_t x_size, size_t x_sw, +void bigint_monty_sqr(BigInt& z, const BigInt& x, const word p[], size_t p_size, word p_dash, word workspace[]); @@ -182,9 +181,7 @@ void bigint_comba_sqr16(word out[32], const word in[16]); /* * High Level Multiplication/Squaring Interfaces */ -void bigint_mul(word z[], size_t z_size, word workspace[], - const word x[], size_t x_size, size_t x_sw, - const word y[], size_t y_size, size_t y_sw); +void bigint_mul(BigInt& z, const BigInt& x, const BigInt& y, word workspace[]); void bigint_sqr(word z[], size_t z_size, word workspace[], const word x[], size_t x_size, size_t x_sw); diff --git a/src/lib/math/mp/mp_karat.cpp b/src/lib/math/mp/mp_karat.cpp index 9135fdd6a..7a763e2a9 100644 --- a/src/lib/math/mp/mp_karat.cpp +++ b/src/lib/math/mp/mp_karat.cpp @@ -1,6 +1,7 @@ /* * Multiplication and Squaring * (C) 1999-2010 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -252,60 +253,55 @@ size_t karatsuba_size(size_t z_size, size_t x_size, size_t x_sw) /* * Multiplication Algorithm Dispatcher */ -void bigint_mul(word z[], size_t z_size, word workspace[], - const word x[], size_t x_size, size_t x_sw, - const word y[], size_t y_size, size_t y_sw) +void bigint_mul(BigInt& z, const BigInt& x, const BigInt& y, word workspace[]) { - // checking that z_size >= x_sw + y_sw without overflow - BOTAN_ASSERT(z_size > x_sw && z_size > y_sw && z_size-x_sw >= y_sw, "Output size is sufficient"); - - if(x_sw == 1) + if(x.sig_words() == 1) { - bigint_linmul3(z, y, y_sw, x[0]); + bigint_linmul3(z.mutable_data(), y.data(), y.sig_words(), x.data()[0]); } - else if(y_sw == 1) + else if(y.sig_words() == 1) { - bigint_linmul3(z, x, x_sw, y[0]); + bigint_linmul3(z.mutable_data(), x.data(), x.sig_words(), y.data()[0]); } - else if(x_sw <= 4 && x_size >= 4 && - y_sw <= 4 && y_size >= 4 && z_size >= 8) + else if(x.sig_words() <= 4 && x.size() >= 4 && + y.sig_words() <= 4 && y.size() >= 4 && z.size() >= 8) { - bigint_comba_mul4(z, x, y); + bigint_comba_mul4(z.mutable_data(), x.data(), y.data()); } - else if(x_sw <= 6 && x_size >= 6 && - y_sw <= 6 && y_size >= 6 && z_size >= 12) + else if(x.sig_words() <= 6 && x.size() >= 6 && + y.sig_words() <= 6 && y.size() >= 6 && z.size() >= 12) { - bigint_comba_mul6(z, x, y); + bigint_comba_mul6(z.mutable_data(), x.data(), y.data()); } - else if(x_sw <= 8 && x_size >= 8 && - y_sw <= 8 && y_size >= 8 && z_size >= 16) + else if(x.sig_words() <= 8 && x.size() >= 8 && + y.sig_words() <= 8 && y.size() >= 8 && z.size() >= 16) { - bigint_comba_mul8(z, x, y); + bigint_comba_mul8(z.mutable_data(), x.data(), y.data()); } - else if(x_sw <= 9 && x_size >= 9 && - y_sw <= 9 && y_size >= 9 && z_size >= 18) + else if(x.sig_words() <= 9 && x.size() >= 9 && + y.sig_words() <= 9 && y.size() >= 9 && z.size() >= 18) { - bigint_comba_mul9(z, x, y); + bigint_comba_mul9(z.mutable_data(), x.data(), y.data()); } - else if(x_sw <= 16 && x_size >= 16 && - y_sw <= 16 && y_size >= 16 && z_size >= 32) + else if(x.sig_words() <= 16 && x.size() >= 16 && + y.sig_words() <= 16 && y.size() >= 16 && z.size() >= 32) { - bigint_comba_mul16(z, x, y); + bigint_comba_mul16(z.mutable_data(), x.data(), y.data()); } - else if(x_sw < KARATSUBA_MULTIPLY_THRESHOLD || - y_sw < KARATSUBA_MULTIPLY_THRESHOLD || + else if(x.sig_words() < KARATSUBA_MULTIPLY_THRESHOLD || + y.sig_words() < KARATSUBA_MULTIPLY_THRESHOLD || !workspace) { - basecase_mul(z, x, x_sw, y, y_sw); + basecase_mul(z.mutable_data(), x.data(), x.sig_words(), y.data(), y.sig_words()); } else { - const size_t N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw); + const size_t N = karatsuba_size(z.size(), x.size(), x.sig_words(), y.size(), y.sig_words()); if(N) - karatsuba_mul(z, x, y, N, workspace); + karatsuba_mul(z.mutable_data(), x.data(), y.data(), N, workspace); else - basecase_mul(z, x, x_sw, y, y_sw); + basecase_mul(z.mutable_data(), x.data(), x.sig_words(), y.data(), y.sig_words()); } } diff --git a/src/lib/math/mp/mp_monty.cpp b/src/lib/math/mp/mp_monty.cpp index 7e427b540..88b5de715 100644 --- a/src/lib/math/mp/mp_monty.cpp +++ b/src/lib/math/mp/mp_monty.cpp @@ -2,10 +2,12 @@ * Montgomery Reduction * (C) 1999-2011 Jack Lloyd * 2006 Luca Piccarreta +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/bigint.h> #include <botan/internal/mp_core.h> #include <botan/internal/mp_madd.h> #include <botan/internal/mp_asmi.h> @@ -92,30 +94,25 @@ void bigint_monty_redc(word z[], BOTAN_ASSERT(borrow == 0 || borrow == 1, "Expected borrow"); } -void bigint_monty_mul(word z[], size_t z_size, - const word x[], size_t x_size, size_t x_sw, - const word y[], size_t y_size, size_t y_sw, +void bigint_monty_mul(BigInt& z, const BigInt& x, const BigInt& y, const word p[], size_t p_size, word p_dash, word ws[]) { - bigint_mul(&z[0], z_size, &ws[0], - &x[0], x_size, x_sw, - &y[0], y_size, y_sw); + bigint_mul(z, x, y, &ws[0]); - bigint_monty_redc(&z[0], + bigint_monty_redc(z.mutable_data(), &p[0], p_size, p_dash, &ws[0]); + } -void bigint_monty_sqr(word z[], size_t z_size, - const word x[], size_t x_size, size_t x_sw, - const word p[], size_t p_size, word p_dash, - word ws[]) +void bigint_monty_sqr(BigInt& z, const BigInt& x, const word p[], + size_t p_size, word p_dash, word ws[]) { - bigint_sqr(&z[0], z_size, &ws[0], - &x[0], x_size, x_sw); + bigint_sqr(z.mutable_data(), z.size(), &ws[0], + x.data(), x.size(), x.sig_words()); - bigint_monty_redc(&z[0], + bigint_monty_redc(z.mutable_data(), &p[0], p_size, p_dash, &ws[0]); } diff --git a/src/lib/math/numbertheory/mp_numth.cpp b/src/lib/math/numbertheory/mp_numth.cpp index 3373b9ee7..d78d21128 100644 --- a/src/lib/math/numbertheory/mp_numth.cpp +++ b/src/lib/math/numbertheory/mp_numth.cpp @@ -1,6 +1,7 @@ /* * Fused and Important MP Algorithms * (C) 1999-2007 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -40,20 +41,13 @@ BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c) if(a.sign() != b.sign()) sign = BigInt::Negative; - const size_t a_sw = a.sig_words(); - const size_t b_sw = b.sig_words(); - const size_t c_sw = c.sig_words(); - - BigInt r(sign, std::max(a.size() + b.size(), c_sw) + 1); + BigInt r(sign, std::max(a.size() + b.size(), c.sig_words()) + 1); secure_vector<word> workspace(r.size()); - bigint_mul(r.mutable_data(), r.size(), - workspace.data(), - a.data(), a.size(), a_sw, - b.data(), b.size(), b_sw); + bigint_mul(r, a, b, workspace.data()); - const size_t r_size = std::max(r.sig_words(), c_sw); - bigint_add2(r.mutable_data(), r_size, c.data(), c_sw); + const size_t r_size = std::max(r.sig_words(), c.sig_words()); + bigint_add2(r.mutable_data(), r_size, c.data(), c.sig_words()); return r; } diff --git a/src/lib/math/numbertheory/powm_mnt.cpp b/src/lib/math/numbertheory/powm_mnt.cpp index 5c441db3a..572f0de98 100644 --- a/src/lib/math/numbertheory/powm_mnt.cpp +++ b/src/lib/math/numbertheory/powm_mnt.cpp @@ -1,6 +1,7 @@ /* * Montgomery Exponentiation * (C) 1999-2010,2012 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,6 +9,7 @@ #include <botan/internal/def_powm.h> #include <botan/numthry.h> #include <botan/internal/mp_core.h> +#include <iostream> namespace Botan { @@ -34,36 +36,26 @@ void Montgomery_Exponentiator::set_base(const BigInt& base) m_g[0] = 1; - bigint_monty_mul(z.mutable_data(), z.size(), - m_g[0].data(), m_g[0].size(), m_g[0].sig_words(), - m_R2_mod.data(), m_R2_mod.size(), m_R2_mod.sig_words(), + bigint_monty_mul(z, m_g[0], m_R2_mod, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); - m_g[0] = z; m_g[1] = (base >= m_modulus) ? (base % m_modulus) : base; - bigint_monty_mul(z.mutable_data(), z.size(), - m_g[1].data(), m_g[1].size(), m_g[1].sig_words(), - m_R2_mod.data(), m_R2_mod.size(), m_R2_mod.sig_words(), + bigint_monty_mul(z, m_g[1], m_R2_mod, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); m_g[1] = z; const BigInt& x = m_g[1]; - const size_t x_sig = x.sig_words(); for(size_t i = 2; i != m_g.size(); ++i) { const BigInt& y = m_g[i-1]; - const size_t y_sig = y.sig_words(); - bigint_monty_mul(z.mutable_data(), z.size(), - x.data(), x.size(), x_sig, - y.data(), y.size(), y_sig, - m_modulus.data(), m_mod_words, m_mod_prime, + bigint_monty_mul(z, x, y, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); m_g[i] = z; @@ -82,15 +74,13 @@ BigInt Montgomery_Exponentiator::execute() const const size_t z_size = 2*(m_mod_words + 1); BigInt z(BigInt::Positive, z_size); - secure_vector<word> workspace(z_size); + secure_vector<word> workspace(z.size()); for(size_t i = exp_nibbles; i > 0; --i) { for(size_t k = 0; k != m_window_bits; ++k) { - bigint_monty_sqr(z.mutable_data(), z_size, - x.data(), x.size(), x.sig_words(), - m_modulus.data(), m_mod_words, m_mod_prime, + bigint_monty_sqr(z, x, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); x = z; @@ -100,9 +90,7 @@ BigInt Montgomery_Exponentiator::execute() const const BigInt& y = m_g[nibble]; - bigint_monty_mul(z.mutable_data(), z_size, - x.data(), x.size(), x.sig_words(), - y.data(), y.size(), y.sig_words(), + bigint_monty_mul(z, x, y, m_modulus.data(), m_mod_words, m_mod_prime, workspace.data()); diff --git a/src/lib/pk_pad/hash_id/hash_id.cpp b/src/lib/pk_pad/hash_id/hash_id.cpp index 882c30a4c..2af0f6878 100644 --- a/src/lib/pk_pad/hash_id/hash_id.cpp +++ b/src/lib/pk_pad/hash_id/hash_id.cpp @@ -12,18 +12,10 @@ namespace Botan { namespace { -const byte MD2_PKCS_ID[] = { -0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, -0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 }; - const byte MD5_PKCS_ID[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; -const byte RIPEMD_128_PKCS_ID[] = { -0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, -0x02, 0x05, 0x00, 0x04, 0x14 }; - const byte RIPEMD_160_PKCS_ID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; @@ -67,18 +59,10 @@ std::vector<byte> pkcs_hash_id(const std::string& name) if(name == "Parallel(MD5,SHA-160)") return std::vector<byte>(); - if(name == "MD2") - return std::vector<byte>(MD2_PKCS_ID, - MD2_PKCS_ID + sizeof(MD2_PKCS_ID)); - if(name == "MD5") return std::vector<byte>(MD5_PKCS_ID, MD5_PKCS_ID + sizeof(MD5_PKCS_ID)); - if(name == "RIPEMD-128") - return std::vector<byte>(RIPEMD_128_PKCS_ID, - RIPEMD_128_PKCS_ID + sizeof(RIPEMD_128_PKCS_ID)); - if(name == "RIPEMD-160") return std::vector<byte>(RIPEMD_160_PKCS_ID, RIPEMD_160_PKCS_ID + sizeof(RIPEMD_160_PKCS_ID)); @@ -127,7 +111,6 @@ byte ieee1363_hash_id(const std::string& name) if(name == "SHA-512") return 0x35; if(name == "RIPEMD-160") return 0x31; - if(name == "RIPEMD-128") return 0x32; if(name == "Whirlpool") return 0x37; diff --git a/src/lib/prov/openssl/openssl_hash.cpp b/src/lib/prov/openssl/openssl_hash.cpp index 574cfed91..c14c551e4 100644 --- a/src/lib/prov/openssl/openssl_hash.cpp +++ b/src/lib/prov/openssl/openssl_hash.cpp @@ -96,10 +96,6 @@ make_evp_hash_maker(const EVP_MD* md, const char* algo) BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-512", EVP_sha512); #endif -#if !defined(OPENSSL_NO_MD2) - BOTAN_REGISTER_OPENSSL_EVP_HASH("MD2", EVP_md2); -#endif - #if !defined(OPENSSL_NO_MD4) BOTAN_REGISTER_OPENSSL_EVP_HASH("MD4", EVP_md4); #endif diff --git a/src/lib/pubkey/curve25519/donna.cpp b/src/lib/pubkey/curve25519/donna.cpp index 9b28e412c..a0e4d249f 100644 --- a/src/lib/pubkey/curve25519/donna.cpp +++ b/src/lib/pubkey/curve25519/donna.cpp @@ -39,6 +39,26 @@ typedef byte u8; typedef u64bit limb; typedef limb felem[5]; +typedef struct + { + limb* x; + limb* z; + } fmonty_pair_t; + +typedef struct + { + fmonty_pair_t q; + fmonty_pair_t q_dash; + const limb* q_minus_q_dash; + } fmonty_in_t; + +typedef struct + { + fmonty_pair_t two_q; + fmonty_pair_t q_plus_q_dash; + } fmonty_out_t; + + #if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128) typedef donna128 uint128_t; #endif @@ -273,44 +293,41 @@ fcontract(u8 *output, const felem input) { /* Input: Q, Q', Q-Q' * Output: 2Q, Q+Q' * - * x2 z3: long form - * x3 z3: long form - * x z: short form, destroyed - * xprime zprime: short form, destroyed - * qmqp: short form, preserved + * result.two_q (2*Q): long form + * result.q_plus_q_dash (Q + Q): long form + * in.q: short form, destroyed + * in.q_dash: short form, destroyed + * in.q_minus_q_dash: short form, preserved */ static void -fmonty(limb *x2, limb *z2, /* output 2Q */ - limb *x3, limb *z3, /* output Q + Q' */ - limb *x, limb *z, /* input Q */ - limb *xprime, limb *zprime, /* input Q' */ - const limb *qmqp /* input Q - Q' */) { +fmonty(fmonty_out_t& result, fmonty_in_t& in) +{ limb origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5], - zzprime[5], zzzprime[5]; + zzprime[5], zzzprime[5]; - copy_mem(origx, x, 5); - fsum(x, z); - fdifference_backwards(z, origx); // does x - z + copy_mem(origx, in.q.x, 5); + fsum(in.q.x, in.q.z); + fdifference_backwards(in.q.z, origx); // does x - z - copy_mem(origxprime, xprime, 5); - fsum(xprime, zprime); - fdifference_backwards(zprime, origxprime); - fmul(xxprime, xprime, z); - fmul(zzprime, x, zprime); + copy_mem(origxprime, in.q_dash.x, 5); + fsum(in.q_dash.x, in.q_dash.z); + fdifference_backwards(in.q_dash.z, origxprime); + fmul(xxprime, in.q_dash.x, in.q.z); + fmul(zzprime, in.q.x, in.q_dash.z); copy_mem(origxprime, xxprime, 5); fsum(xxprime, zzprime); fdifference_backwards(zzprime, origxprime); - fsquare_times(x3, xxprime, 1); + fsquare_times(result.q_plus_q_dash.x, xxprime, 1); fsquare_times(zzzprime, zzprime, 1); - fmul(z3, zzzprime, qmqp); + fmul(result.q_plus_q_dash.z, zzzprime, in.q_minus_q_dash); - fsquare_times(xx, x, 1); - fsquare_times(zz, z, 1); - fmul(x2, xx, zz); + fsquare_times(xx, in.q.x, 1); + fsquare_times(zz, in.q.z, 1); + fmul(result.two_q.x, xx, zz); fdifference_backwards(zz, xx); // does zz = xx - zz fscalar_product(zzz, zz, 121665); fsum(zzz, xx); - fmul(z2, zz, zzz); + fmul(result.two_q.z, zz, zzz); } // ----------------------------------------------------------------------------- @@ -356,11 +373,10 @@ cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { swap_conditional(nqx, nqpqx, bit); swap_conditional(nqz, nqpqz, bit); - fmonty(nqx2, nqz2, - nqpqx2, nqpqz2, - nqx, nqz, - nqpqx, nqpqz, - q); + + fmonty_out_t result { nqx2, nqz2, nqpqx2, nqpqz2 }; + fmonty_in_t in { nqx, nqz, nqpqx, nqpqz, q }; + fmonty(result, in); swap_conditional(nqx2, nqpqx2, bit); swap_conditional(nqz2, nqpqz2, bit); diff --git a/src/lib/pubkey/if_algo/if_algo.cpp b/src/lib/pubkey/if_algo/if_algo.cpp deleted file mode 100644 index e5f3ae20f..000000000 --- a/src/lib/pubkey/if_algo/if_algo.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -* IF Scheme -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/if_algo.h> -#include <botan/numthry.h> -#include <botan/workfactor.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> - -namespace Botan { - -size_t IF_Scheme_PublicKey::estimated_strength() const - { - return if_work_factor(m_n.bits()); - } - -AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const - { - return AlgorithmIdentifier(get_oid(), - AlgorithmIdentifier::USE_NULL_PARAM); - } - -std::vector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(m_n) - .encode(m_e) - .end_cons() - .get_contents_unlocked(); - } - -IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&, - const secure_vector<byte>& key_bits) - { - BER_Decoder(key_bits) - .start_cons(SEQUENCE) - .decode(m_n) - .decode(m_e) - .verify_end() - .end_cons(); - } - -/* -* Check IF Scheme Public Parameters -*/ -bool IF_Scheme_PublicKey::check_key(RandomNumberGenerator&, bool) const - { - if(m_n < 35 || m_n.is_even() || m_e < 2) - return false; - return true; - } - -secure_vector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(static_cast<size_t>(0)) - .encode(m_n) - .encode(m_e) - .encode(m_d) - .encode(m_p) - .encode(m_q) - .encode(m_d1) - .encode(m_d2) - .encode(m_c) - .end_cons() - .get_contents(); - } - -IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, - const AlgorithmIdentifier&, - const secure_vector<byte>& key_bits) - { - BER_Decoder(key_bits) - .start_cons(SEQUENCE) - .decode_and_check<size_t>(0, "Unknown PKCS #1 key format version") - .decode(m_n) - .decode(m_e) - .decode(m_d) - .decode(m_p) - .decode(m_q) - .decode(m_d1) - .decode(m_d2) - .decode(m_c) - .end_cons(); - - load_check(rng); - } - -IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, - const BigInt& prime1, - const BigInt& prime2, - const BigInt& exp, - const BigInt& d_exp, - const BigInt& mod) : - m_d{ d_exp }, m_p{ prime1 }, m_q{ prime2 }, m_d1{}, m_d2{}, m_c{ inverse_mod( m_q, m_p ) } - { - m_n = mod.is_nonzero() ? mod : m_p * m_q; - m_e = exp; - - if(m_d == 0) - { - BigInt inv_for_d = lcm(m_p - 1, m_q - 1); - if(m_e.is_even()) - inv_for_d >>= 1; - - m_d = inverse_mod(m_e, inv_for_d); - } - - m_d1 = m_d % (m_p - 1); - m_d2 = m_d % (m_q - 1); - - load_check(rng); - } - -/* -* Check IF Scheme Private Parameters -*/ -bool IF_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng, - bool strong) const - { - if(m_n < 35 || m_n.is_even() || m_e < 2 || m_d < 2 || m_p < 3 || m_q < 3 || m_p*m_q != m_n) - return false; - - if(m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverse_mod(m_q, m_p)) - return false; - - const size_t prob = (strong) ? 56 : 12; - - if(!is_prime(m_p, rng, prob) || !is_prime(m_q, rng, prob)) - return false; - return true; - } - -} diff --git a/src/lib/pubkey/if_algo/if_algo.h b/src/lib/pubkey/if_algo/if_algo.h deleted file mode 100644 index 46dbd51a9..000000000 --- a/src/lib/pubkey/if_algo/if_algo.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -* IF Scheme -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_IF_ALGO_H__ -#define BOTAN_IF_ALGO_H__ - -#include <botan/bigint.h> -#include <botan/x509_key.h> - -namespace Botan { - -/** -* This class represents public keys -* of integer factorization based (IF) public key schemes. -*/ -class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key - { - public: - IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits); - - IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) : - m_n(n), m_e(e) {} - - bool check_key(RandomNumberGenerator& rng, bool) const override; - - AlgorithmIdentifier algorithm_identifier() const override; - - std::vector<byte> x509_subject_public_key() const override; - - /** - * @return public modulus - */ - const BigInt& get_n() const { return m_n; } - - /** - * @return public exponent - */ - const BigInt& get_e() const { return m_e; } - - size_t max_input_bits() const override { return (m_n.bits() - 1); } - - size_t estimated_strength() const override; - - protected: - IF_Scheme_PublicKey() {} - - BigInt m_n, m_e; - }; - -/** -* This class represents public keys -* of integer factorization based (IF) public key schemes. -*/ -class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, - public virtual Private_Key - { - public: - - IF_Scheme_PrivateKey(RandomNumberGenerator& rng, - const BigInt& prime1, const BigInt& prime2, - const BigInt& exp, const BigInt& d_exp, - const BigInt& mod); - - IF_Scheme_PrivateKey(RandomNumberGenerator& rng, - const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits); - - bool check_key(RandomNumberGenerator& rng, bool) const override; - - /** - * Get the first prime p. - * @return prime p - */ - const BigInt& get_p() const { return m_p; } - - /** - * Get the second prime q. - * @return prime q - */ - const BigInt& get_q() const { return m_q; } - - /** - * Get d with exp * d = 1 mod (p - 1, q - 1). - * @return d - */ - const BigInt& get_d() const { return m_d; } - - const BigInt& get_c() const { return m_c; } - const BigInt& get_d1() const { return m_d1; } - const BigInt& get_d2() const { return m_d2; } - - secure_vector<byte> pkcs8_private_key() const override; - - protected: - IF_Scheme_PrivateKey() {} - - BigInt m_d, m_p, m_q, m_d1, m_d2, m_c; - }; - -} - -#endif diff --git a/src/lib/pubkey/if_algo/info.txt b/src/lib/pubkey/if_algo/info.txt deleted file mode 100644 index 5ceec0a89..000000000 --- a/src/lib/pubkey/if_algo/info.txt +++ /dev/null @@ -1,9 +0,0 @@ -define IF_PUBLIC_KEY_FAMILY 20131128 - -load_on dep - -<requires> -asn1 -bigint -numbertheory -</requires> diff --git a/src/lib/pubkey/nr/info.txt b/src/lib/pubkey/nr/info.txt deleted file mode 100644 index 78ca6ef29..000000000 --- a/src/lib/pubkey/nr/info.txt +++ /dev/null @@ -1,8 +0,0 @@ -define NYBERG_RUEPPEL 20131128 - -<requires> -dl_algo -dl_group -keypair -numbertheory -</requires> diff --git a/src/lib/pubkey/nr/nr.cpp b/src/lib/pubkey/nr/nr.cpp deleted file mode 100644 index 5e2cb1be5..000000000 --- a/src/lib/pubkey/nr/nr.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* -* Nyberg-Rueppel -* (C) 1999-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/internal/pk_utils.h> -#include <botan/nr.h> -#include <botan/keypair.h> -#include <botan/reducer.h> -#include <future> - -namespace Botan { - -NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits) : - DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) - { - } - -/* -* NR_PublicKey Constructor -*/ -NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1) - { - m_group = grp; - m_y = y1; - } - -/* -* Create a NR private key -*/ -NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& grp, - const BigInt& x_arg) - { - m_group = grp; - m_x = x_arg; - - if(m_x == 0) - m_x = BigInt::random_integer(rng, 2, group_q() - 1); - - m_y = power_mod(group_g(), m_x, group_p()); - - if(x_arg == 0) - gen_check(rng); - else - load_check(rng); - } - -NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits, - RandomNumberGenerator& rng) : - DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) - { - m_y = power_mod(group_g(), m_x, group_p()); - - load_check(rng); - } - -/* -* Check Private Nyberg-Rueppel Parameters -*/ -bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const - { - if(!DL_Scheme_PrivateKey::check_key(rng, strong) || m_x >= group_q()) - return false; - - if(!strong) - return true; - - return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)"); - } - -namespace { - -/** -* Nyberg-Rueppel signature operation -*/ -class NR_Signature_Operation : public PK_Ops::Signature_with_EMSA - { - public: - typedef NR_PrivateKey Key_Type; - NR_Signature_Operation(const NR_PrivateKey& nr, const std::string& emsa) : - PK_Ops::Signature_with_EMSA(emsa), - m_q(nr.group_q()), - m_x(nr.get_x()), - m_powermod_g_p(nr.group_g(), nr.group_p()), - m_mod_q(nr.group_q()) - { - } - - size_t message_parts() const override { return 2; } - size_t message_part_size() const override { return m_q.bytes(); } - size_t max_input_bits() const override { return (m_q.bits() - 1); } - - secure_vector<byte> raw_sign(const byte msg[], size_t msg_len, - RandomNumberGenerator& rng) override; - private: - const BigInt& m_q; - const BigInt& m_x; - Fixed_Base_Power_Mod m_powermod_g_p; - Modular_Reducer m_mod_q; - }; - -secure_vector<byte> -NR_Signature_Operation::raw_sign(const byte msg[], size_t msg_len, - RandomNumberGenerator& rng) - { - rng.add_entropy(msg, msg_len); - - BigInt f(msg, msg_len); - - if(f >= m_q) - throw Invalid_Argument("NR_Signature_Operation: Input is out of range"); - - BigInt c, d; - - while(c == 0) - { - BigInt k; - do - k.randomize(rng, m_q.bits()); - while(k >= m_q); - - c = m_mod_q.reduce(m_powermod_g_p(k) + f); - d = m_mod_q.reduce(k - m_x * c); - } - - secure_vector<byte> output(2*m_q.bytes()); - c.binary_encode(&output[output.size() / 2 - c.bytes()]); - d.binary_encode(&output[output.size() - d.bytes()]); - return output; - } - - -/** -* Nyberg-Rueppel verification operation -*/ -class NR_Verification_Operation : public PK_Ops::Verification_with_EMSA - { - public: - typedef NR_PublicKey Key_Type; - NR_Verification_Operation(const NR_PublicKey& nr, const std::string& emsa) : - PK_Ops::Verification_with_EMSA(emsa), - m_q(nr.group_q()), m_y(nr.get_y()), m_powermod_g_p{Fixed_Base_Power_Mod(nr.group_g(), nr.group_p())}, - m_powermod_y_p{Fixed_Base_Power_Mod(m_y, nr.group_p())}, m_mod_p{Modular_Reducer(nr.group_p())}, - m_mod_q{Modular_Reducer(nr.group_q())} - {} - - size_t message_parts() const override { return 2; } - size_t message_part_size() const override { return m_q.bytes(); } - size_t max_input_bits() const override { return (m_q.bits() - 1); } - - bool with_recovery() const override { return true; } - - secure_vector<byte> verify_mr(const byte msg[], size_t msg_len) override; - private: - const BigInt& m_q; - const BigInt& m_y; - - Fixed_Base_Power_Mod m_powermod_g_p, m_powermod_y_p; - Modular_Reducer m_mod_p, m_mod_q; - }; - -secure_vector<byte> -NR_Verification_Operation::verify_mr(const byte msg[], size_t msg_len) - { - const BigInt& q = m_mod_q.get_modulus(); - - if(msg_len != 2*q.bytes()) - throw Invalid_Argument("NR verification: Invalid signature"); - - BigInt c(msg, q.bytes()); - BigInt d(msg + q.bytes(), q.bytes()); - - if(c.is_zero() || c >= q || d >= q) - throw Invalid_Argument("NR verification: Invalid signature"); - - auto future_y_c = std::async(std::launch::async, m_powermod_y_p, c); - BigInt g_d = m_powermod_g_p(d); - - BigInt i = m_mod_p.multiply(g_d, future_y_c.get()); - return BigInt::encode_locked(m_mod_q.reduce(c - i)); - } -} - -BOTAN_REGISTER_PK_SIGNATURE_OP("NR", NR_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("NR", NR_Verification_Operation); - -} diff --git a/src/lib/pubkey/nr/nr.h b/src/lib/pubkey/nr/nr.h deleted file mode 100644 index 425ad2642..000000000 --- a/src/lib/pubkey/nr/nr.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Nyberg-Rueppel -* (C) 1999-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_NYBERG_RUEPPEL_H__ -#define BOTAN_NYBERG_RUEPPEL_H__ - -#include <botan/dl_algo.h> - -namespace Botan { - -/** -* Nyberg-Rueppel Public Key -*/ -class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey - { - public: - std::string algo_name() const override { return "NR"; } - - DL_Group::Format group_format() const override { return DL_Group::ANSI_X9_57; } - - size_t message_parts() const override { return 2; } - size_t message_part_size() const override { return group_q().bytes(); } - size_t max_input_bits() const override { return (group_q().bits() - 1); } - - NR_PublicKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits); - - NR_PublicKey(const DL_Group& group, const BigInt& pub_key); - protected: - NR_PublicKey() {} - }; - -/** -* Nyberg-Rueppel Private Key -*/ -class BOTAN_DLL NR_PrivateKey : public NR_PublicKey, - public virtual DL_Scheme_PrivateKey - { - public: - bool check_key(RandomNumberGenerator& rng, bool strong) const override; - - NR_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits, - RandomNumberGenerator& rng); - - NR_PrivateKey(RandomNumberGenerator& rng, - const DL_Group& group, - const BigInt& x = 0); - }; - -} - -#endif diff --git a/src/lib/pubkey/pk_algs.cpp b/src/lib/pubkey/pk_algs.cpp index 9dbde28af..ac6f4a11f 100644 --- a/src/lib/pubkey/pk_algs.cpp +++ b/src/lib/pubkey/pk_algs.cpp @@ -36,14 +36,6 @@ #include <botan/gost_3410.h> #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr.h> -#endif - -#if defined(BOTAN_HAS_RW) - #include <botan/rw.h> -#endif - #if defined(BOTAN_HAS_ELGAMAL) #include <botan/elgamal.h> #endif @@ -74,11 +66,6 @@ Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, return new RSA_PublicKey(alg_id, key_bits); #endif -#if defined(BOTAN_HAS_RW) - if(alg_name == "RW") - return new RW_PublicKey(alg_id, key_bits); -#endif - #if defined(BOTAN_HAS_DSA) if(alg_name == "DSA") return new DSA_PublicKey(alg_id, key_bits); @@ -89,11 +76,6 @@ Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, return new DH_PublicKey(alg_id, key_bits); #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - if(alg_name == "NR") - return new NR_PublicKey(alg_id, key_bits); -#endif - #if defined(BOTAN_HAS_ELGAMAL) if(alg_name == "ElGamal") return new ElGamal_PublicKey(alg_id, key_bits); @@ -150,11 +132,6 @@ Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, return new RSA_PrivateKey(alg_id, key_bits, rng); #endif -#if defined(BOTAN_HAS_RW) - if(alg_name == "RW") - return new RW_PrivateKey(alg_id, key_bits, rng); -#endif - #if defined(BOTAN_HAS_DSA) if(alg_name == "DSA") return new DSA_PrivateKey(alg_id, key_bits, rng); @@ -165,11 +142,6 @@ Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, return new DH_PrivateKey(alg_id, key_bits, rng); #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - if(alg_name == "NR") - return new NR_PrivateKey(alg_id, key_bits, rng); -#endif - #if defined(BOTAN_HAS_ELGAMAL) if(alg_name == "ElGamal") return new ElGamal_PrivateKey(alg_id, key_bits, rng); diff --git a/src/lib/pubkey/rsa/info.txt b/src/lib/pubkey/rsa/info.txt index 91eec565a..6df380696 100644 --- a/src/lib/pubkey/rsa/info.txt +++ b/src/lib/pubkey/rsa/info.txt @@ -1,7 +1,6 @@ -define RSA 20131128 +define RSA 20160730 <requires> -if_algo keypair numbertheory emsa_pssr diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp index 6a645ec88..7f72ba210 100644 --- a/src/lib/pubkey/rsa/rsa.cpp +++ b/src/lib/pubkey/rsa/rsa.cpp @@ -1,6 +1,6 @@ /* * RSA -* (C) 1999-2010,2015 Jack Lloyd +* (C) 1999-2010,2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -11,10 +11,118 @@ #include <botan/keypair.h> #include <botan/blinding.h> #include <botan/reducer.h> +#include <botan/workfactor.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <future> namespace Botan { +size_t RSA_PublicKey::estimated_strength() const + { + return if_work_factor(m_n.bits()); + } + +AlgorithmIdentifier RSA_PublicKey::algorithm_identifier() const + { + return AlgorithmIdentifier(get_oid(), + AlgorithmIdentifier::USE_NULL_PARAM); + } + +std::vector<byte> RSA_PublicKey::x509_subject_public_key() const + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(m_n) + .encode(m_e) + .end_cons() + .get_contents_unlocked(); + } + +RSA_PublicKey::RSA_PublicKey(const AlgorithmIdentifier&, + const secure_vector<byte>& key_bits) + { + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(m_n) + .decode(m_e) + .verify_end() + .end_cons(); + } + +/* +* Check RSA Public Parameters +*/ +bool RSA_PublicKey::check_key(RandomNumberGenerator&, bool) const + { + if(m_n < 35 || m_n.is_even() || m_e < 2) + return false; + return true; + } + +secure_vector<byte> RSA_PrivateKey::pkcs8_private_key() const + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(static_cast<size_t>(0)) + .encode(m_n) + .encode(m_e) + .encode(m_d) + .encode(m_p) + .encode(m_q) + .encode(m_d1) + .encode(m_d2) + .encode(m_c) + .end_cons() + .get_contents(); + } + +RSA_PrivateKey::RSA_PrivateKey(const AlgorithmIdentifier&, + const secure_vector<byte>& key_bits, + RandomNumberGenerator& rng) + { + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode_and_check<size_t>(0, "Unknown PKCS #1 key format version") + .decode(m_n) + .decode(m_e) + .decode(m_d) + .decode(m_p) + .decode(m_q) + .decode(m_d1) + .decode(m_d2) + .decode(m_c) + .end_cons(); + + load_check(rng); + } + +RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, + const BigInt& prime1, + const BigInt& prime2, + const BigInt& exp, + const BigInt& d_exp, + const BigInt& mod) : + m_d{ d_exp }, m_p{ prime1 }, m_q{ prime2 }, m_d1{}, m_d2{}, m_c{ inverse_mod( m_q, m_p ) } + { + m_n = mod.is_nonzero() ? mod : m_p * m_q; + m_e = exp; + + if(m_d == 0) + { + BigInt inv_for_d = lcm(m_p - 1, m_q - 1); + if(m_e.is_even()) + inv_for_d >>= 1; + + m_d = inverse_mod(m_e, inv_for_d); + } + + m_d1 = m_d % (m_p - 1); + m_d2 = m_d % (m_q - 1); + + load_check(rng); + } + /* * Create a RSA private key */ @@ -49,16 +157,26 @@ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, */ bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const { - if(!IF_Scheme_PrivateKey::check_key(rng, strong)) + if(m_n < 35 || m_n.is_even() || m_e < 2 || m_d < 2 || m_p < 3 || m_q < 3 || m_p*m_q != m_n) return false; - if(!strong) - return true; + if(m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverse_mod(m_q, m_p)) + return false; + + const size_t prob = (strong) ? 56 : 12; - if((m_e * m_d) % lcm(m_p - 1, m_q - 1) != 1) + if(!is_prime(m_p, rng, prob) || !is_prime(m_q, rng, prob)) return false; - return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-256)"); + if(strong) + { + if((m_e * m_d) % lcm(m_p - 1, m_q - 1) != 1) + return false; + + return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-256)"); + } + + return true; } namespace { diff --git a/src/lib/pubkey/rsa/rsa.h b/src/lib/pubkey/rsa/rsa.h index 4a57b9f63..85bd7ce58 100644 --- a/src/lib/pubkey/rsa/rsa.h +++ b/src/lib/pubkey/rsa/rsa.h @@ -1,6 +1,6 @@ /* * RSA -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2008,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,23 +8,19 @@ #ifndef BOTAN_RSA_H__ #define BOTAN_RSA_H__ -#include <botan/if_algo.h> - +#include <botan/bigint.h> +#include <botan/x509_key.h> namespace Botan { /** * RSA Public Key */ -class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey +class BOTAN_DLL RSA_PublicKey : public virtual Public_Key { public: - std::string algo_name() const override { return "RSA"; } - RSA_PublicKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits) : - IF_Scheme_PublicKey(alg_id, key_bits) - {} + const secure_vector<byte>& key_bits); /** * Create a RSA_PublicKey @@ -32,26 +28,45 @@ class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey * @arg e the exponent */ RSA_PublicKey(const BigInt& n, const BigInt& e) : - IF_Scheme_PublicKey(n, e) - {} + m_n(n), m_e(e) {} + + std::string algo_name() const override { return "RSA"; } + + bool check_key(RandomNumberGenerator& rng, bool) const override; + + AlgorithmIdentifier algorithm_identifier() const override; + + std::vector<byte> x509_subject_public_key() const override; + + /** + * @return public modulus + */ + const BigInt& get_n() const { return m_n; } + + /** + * @return public exponent + */ + const BigInt& get_e() const { return m_e; } + + size_t max_input_bits() const override { return (m_n.bits() - 1); } + + size_t estimated_strength() const override; protected: RSA_PublicKey() {} + + BigInt m_n, m_e; }; /** * RSA Private Key */ -class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, - public IF_Scheme_PrivateKey +class BOTAN_DLL RSA_PrivateKey : public Private_Key, public RSA_PublicKey { public: - bool check_key(RandomNumberGenerator& rng, bool) const override; - RSA_PrivateKey(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits, - RandomNumberGenerator& rng) : - IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} + RandomNumberGenerator& rng); /** * Construct a private key from the specified parameters. @@ -68,8 +83,7 @@ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, RSA_PrivateKey(RandomNumberGenerator& rng, const BigInt& p, const BigInt& q, const BigInt& e, const BigInt& d = 0, - const BigInt& n = 0) : - IF_Scheme_PrivateKey(rng, p, q, e, d, n) {} + const BigInt& n = 0); /** * Create a new private key with the specified bit length @@ -79,6 +93,34 @@ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, */ RSA_PrivateKey(RandomNumberGenerator& rng, size_t bits, size_t exp = 65537); + + bool check_key(RandomNumberGenerator& rng, bool) const override; + + /** + * Get the first prime p. + * @return prime p + */ + const BigInt& get_p() const { return m_p; } + + /** + * Get the second prime q. + * @return prime q + */ + const BigInt& get_q() const { return m_q; } + + /** + * Get d with exp * d = 1 mod (p - 1, q - 1). + * @return d + */ + const BigInt& get_d() const { return m_d; } + + const BigInt& get_c() const { return m_c; } + const BigInt& get_d1() const { return m_d1; } + const BigInt& get_d2() const { return m_d2; } + + secure_vector<byte> pkcs8_private_key() const override; + private: + BigInt m_d, m_p, m_q, m_d1, m_d2, m_c; }; } diff --git a/src/lib/pubkey/rw/info.txt b/src/lib/pubkey/rw/info.txt deleted file mode 100644 index 7cf1d1780..000000000 --- a/src/lib/pubkey/rw/info.txt +++ /dev/null @@ -1,7 +0,0 @@ -define RW 20131128 - -<requires> -if_algo -keypair -numbertheory -</requires> diff --git a/src/lib/pubkey/rw/rw.cpp b/src/lib/pubkey/rw/rw.cpp deleted file mode 100644 index bf6b647a1..000000000 --- a/src/lib/pubkey/rw/rw.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* -* Rabin-Williams -* (C) 1999-2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/internal/pk_utils.h> -#include <botan/rw.h> -#include <botan/keypair.h> -#include <botan/parsing.h> -#include <botan/reducer.h> -#include <botan/blinding.h> -#include <algorithm> -#include <future> - -namespace Botan { - -/* -* Create a Rabin-Williams private key -*/ -RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, - size_t bits, size_t exp) - { - if(bits < 1024) - throw Invalid_Argument(algo_name() + ": Can't make a key that is only " + - std::to_string(bits) + " bits long"); - if(exp < 2 || exp % 2 == 1) - throw Invalid_Argument(algo_name() + ": Invalid encryption exponent"); - - m_e = exp; - - do - { - m_p = random_prime(rng, (bits + 1) / 2, m_e / 2, 3, 4); - m_q = random_prime(rng, bits - m_p.bits(), m_e / 2, ((m_p % 8 == 3) ? 7 : 3), 8); - m_n = m_p * m_q; - } while(m_n.bits() != bits); - - m_d = inverse_mod(m_e, lcm(m_p - 1, m_q - 1) >> 1); - m_d1 = m_d % (m_p - 1); - m_d2 = m_d % (m_q - 1); - m_c = inverse_mod(m_q, m_p); - - gen_check(rng); - } - -/* -* Check Private Rabin-Williams Parameters -*/ -bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const - { - if(!IF_Scheme_PrivateKey::check_key(rng, strong)) - return false; - - if(!strong) - return true; - - if((m_e * m_d) % (lcm(m_p - 1, m_q - 1) / 2) != 1) - return false; - - return KeyPair::signature_consistency_check(rng, *this, "EMSA2(SHA-1)"); - } - -namespace { - -/** -* Rabin-Williams Signature Operation -*/ -class RW_Signature_Operation : public PK_Ops::Signature_with_EMSA - { - public: - typedef RW_PrivateKey Key_Type; - - RW_Signature_Operation(const RW_PrivateKey& rw, - const std::string& emsa) : - PK_Ops::Signature_with_EMSA(emsa), - m_n(rw.get_n()), - m_e(rw.get_e()), - m_q(rw.get_q()), - m_c(rw.get_c()), - m_powermod_d1_p(rw.get_d1(), rw.get_p()), - m_powermod_d2_q(rw.get_d2(), rw.get_q()), - m_mod_p(rw.get_p()), - m_blinder(m_n, - [this](const BigInt& k) { return power_mod(k, m_e, m_n); }, - [this](const BigInt& k) { return inverse_mod(k, m_n); }) - { - } - - size_t max_input_bits() const override { return (m_n.bits() - 1); } - - secure_vector<byte> raw_sign(const byte msg[], size_t msg_len, - RandomNumberGenerator& rng) override; - private: - const BigInt& m_n; - const BigInt& m_e; - const BigInt& m_q; - const BigInt& m_c; - - Fixed_Exponent_Power_Mod m_powermod_d1_p, m_powermod_d2_q; - Modular_Reducer m_mod_p; - Blinder m_blinder; - }; - -secure_vector<byte> -RW_Signature_Operation::raw_sign(const byte msg[], size_t msg_len, - RandomNumberGenerator&) - { - BigInt i(msg, msg_len); - - if(i >= m_n || i % 16 != 12) - throw Invalid_Argument("Rabin-Williams: invalid input"); - - if(jacobi(i, m_n) != 1) - i >>= 1; - - i = m_blinder.blind(i); - - auto future_j1 = std::async(std::launch::async, m_powermod_d1_p, i); - const BigInt j2 = m_powermod_d2_q(i); - BigInt j1 = future_j1.get(); - - j1 = m_mod_p.reduce(sub_mul(j1, j2, m_c)); - - const BigInt r = m_blinder.unblind(mul_add(j1, m_q, j2)); - - return BigInt::encode_1363(std::min(r, m_n - r), m_n.bytes()); - } - -/** -* Rabin-Williams Verification Operation -*/ -class RW_Verification_Operation : public PK_Ops::Verification_with_EMSA - { - public: - typedef RW_PublicKey Key_Type; - - RW_Verification_Operation(const RW_PublicKey& rw, const std::string& emsa) : - PK_Ops::Verification_with_EMSA(emsa), - m_n(rw.get_n()), m_powermod_e_n(rw.get_e(), rw.get_n()) - {} - - size_t max_input_bits() const override { return (m_n.bits() - 1); } - bool with_recovery() const override { return true; } - - secure_vector<byte> verify_mr(const byte msg[], size_t msg_len) override; - - private: - const BigInt& m_n; - Fixed_Exponent_Power_Mod m_powermod_e_n; - }; - -secure_vector<byte> -RW_Verification_Operation::verify_mr(const byte msg[], size_t msg_len) - { - BigInt m(msg, msg_len); - - if((m > (m_n >> 1)) || m.is_negative()) - throw Invalid_Argument("RW signature verification: m > n / 2 || m < 0"); - - BigInt r = m_powermod_e_n(m); - if(r % 16 == 12) - return BigInt::encode_locked(r); - if(r % 8 == 6) - return BigInt::encode_locked(2*r); - - r = m_n - r; - if(r % 16 == 12) - return BigInt::encode_locked(r); - if(r % 8 == 6) - return BigInt::encode_locked(2*r); - - throw Invalid_Argument("RW signature verification: Invalid signature"); - } - -BOTAN_REGISTER_PK_SIGNATURE_OP("RW", RW_Signature_Operation); -BOTAN_REGISTER_PK_VERIFY_OP("RW", RW_Verification_Operation); - -} - -} diff --git a/src/lib/pubkey/rw/rw.h b/src/lib/pubkey/rw/rw.h deleted file mode 100644 index 2a010441e..000000000 --- a/src/lib/pubkey/rw/rw.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -* Rabin-Williams -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_RW_H__ -#define BOTAN_RW_H__ - -#include <botan/if_algo.h> - -namespace Botan { - -/** -* Rabin-Williams Public Key -*/ -class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey - { - public: - std::string algo_name() const override { return "RW"; } - - RW_PublicKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits) : - IF_Scheme_PublicKey(alg_id, key_bits) - {} - - RW_PublicKey(const BigInt& mod, const BigInt& exponent) : - IF_Scheme_PublicKey(mod, exponent) - {} - - protected: - RW_PublicKey() {} - }; - -/** -* Rabin-Williams Private Key -*/ -class BOTAN_DLL RW_PrivateKey : public RW_PublicKey, - public IF_Scheme_PrivateKey - { - public: - RW_PrivateKey(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits, - RandomNumberGenerator& rng) : - IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} - - RW_PrivateKey(RandomNumberGenerator& rng, - const BigInt& p, const BigInt& q, - const BigInt& e, const BigInt& d = 0, - const BigInt& n = 0) : - IF_Scheme_PrivateKey(rng, p, q, e, d, n) {} - - RW_PrivateKey(RandomNumberGenerator& rng, size_t bits, size_t = 2); - - bool check_key(RandomNumberGenerator& rng, bool) const override; - }; - -} - -#endif diff --git a/src/lib/rng/hmac_rng/hmac_rng.cpp b/src/lib/rng/hmac_rng/hmac_rng.cpp index d66c538ab..081d8b38a 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.cpp +++ b/src/lib/rng/hmac_rng/hmac_rng.cpp @@ -16,7 +16,7 @@ HMAC_RNG::HMAC_RNG(std::unique_ptr<MessageAuthenticationCode> prf, RandomNumberGenerator& underlying_rng, Entropy_Sources& entropy_sources, size_t reseed_interval) : - Stateful_RNG(underlying_rng, reseed_interval), + Stateful_RNG(underlying_rng, entropy_sources, reseed_interval), m_prf(std::move(prf)) { BOTAN_ASSERT_NONNULL(m_prf); diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index 40da93029..c35363112 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -7,6 +7,7 @@ #include <botan/chacha.h> #include <botan/loadstor.h> +#include <botan/cpuid.h> namespace Botan { @@ -16,58 +17,87 @@ ChaCha::ChaCha(size_t rounds) : m_rounds(rounds) throw Invalid_Argument("ChaCha only supports 8, 12 or 20 rounds"); } -namespace { - -void chacha(byte output[64], const u32bit input[16], size_t rounds) +//static +void ChaCha::chacha_x4(byte output[64*4], u32bit input[16], size_t rounds) { BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds"); - u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], - x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], - x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], - x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; - -#define CHACHA_QUARTER_ROUND(a, b, c, d) \ - do { \ - a += b; d ^= a; d = rotate_left(d, 16); \ - c += d; b ^= c; b = rotate_left(b, 12); \ - a += b; d ^= a; d = rotate_left(d, 8); \ - c += d; b ^= c; b = rotate_left(b, 7); \ - } while(0) - - for(size_t i = 0; i != rounds / 2; ++i) +#if defined(BOTAN_HAS_CHACHA_SSE2) + if(CPUID::has_sse2()) { - CHACHA_QUARTER_ROUND(x00, x04, x08, x12); - CHACHA_QUARTER_ROUND(x01, x05, x09, x13); - CHACHA_QUARTER_ROUND(x02, x06, x10, x14); - CHACHA_QUARTER_ROUND(x03, x07, x11, x15); - - CHACHA_QUARTER_ROUND(x00, x05, x10, x15); - CHACHA_QUARTER_ROUND(x01, x06, x11, x12); - CHACHA_QUARTER_ROUND(x02, x07, x08, x13); - CHACHA_QUARTER_ROUND(x03, x04, x09, x14); + return ChaCha::chacha_sse2_x4(output, input, rounds); } +#endif + + // TODO interleave rounds + for(size_t i = 0; i != 4; ++i) + { + u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], + x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], + x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], + x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; + +#define CHACHA_QUARTER_ROUND(a, b, c, d) \ + do { \ + a += b; d ^= a; d = rotate_left(d, 16); \ + c += d; b ^= c; b = rotate_left(b, 12); \ + a += b; d ^= a; d = rotate_left(d, 8); \ + c += d; b ^= c; b = rotate_left(b, 7); \ + } while(0) + + for(size_t i = 0; i != rounds / 2; ++i) + { + CHACHA_QUARTER_ROUND(x00, x04, x08, x12); + CHACHA_QUARTER_ROUND(x01, x05, x09, x13); + CHACHA_QUARTER_ROUND(x02, x06, x10, x14); + CHACHA_QUARTER_ROUND(x03, x07, x11, x15); + + CHACHA_QUARTER_ROUND(x00, x05, x10, x15); + CHACHA_QUARTER_ROUND(x01, x06, x11, x12); + CHACHA_QUARTER_ROUND(x02, x07, x08, x13); + CHACHA_QUARTER_ROUND(x03, x04, x09, x14); + } #undef CHACHA_QUARTER_ROUND - store_le(x00 + input[ 0], output + 4 * 0); - store_le(x01 + input[ 1], output + 4 * 1); - store_le(x02 + input[ 2], output + 4 * 2); - store_le(x03 + input[ 3], output + 4 * 3); - store_le(x04 + input[ 4], output + 4 * 4); - store_le(x05 + input[ 5], output + 4 * 5); - store_le(x06 + input[ 6], output + 4 * 6); - store_le(x07 + input[ 7], output + 4 * 7); - store_le(x08 + input[ 8], output + 4 * 8); - store_le(x09 + input[ 9], output + 4 * 9); - store_le(x10 + input[10], output + 4 * 10); - store_le(x11 + input[11], output + 4 * 11); - store_le(x12 + input[12], output + 4 * 12); - store_le(x13 + input[13], output + 4 * 13); - store_le(x14 + input[14], output + 4 * 14); - store_le(x15 + input[15], output + 4 * 15); + x00 += input[0]; + x01 += input[1]; + x02 += input[2]; + x03 += input[3]; + x04 += input[4]; + x05 += input[5]; + x06 += input[6]; + x07 += input[7]; + x08 += input[8]; + x09 += input[9]; + x10 += input[10]; + x11 += input[11]; + x12 += input[12]; + x13 += input[13]; + x14 += input[14]; + x15 += input[15]; + + store_le(x00, output + 64 * i + 4 * 0); + store_le(x01, output + 64 * i + 4 * 1); + store_le(x02, output + 64 * i + 4 * 2); + store_le(x03, output + 64 * i + 4 * 3); + store_le(x04, output + 64 * i + 4 * 4); + store_le(x05, output + 64 * i + 4 * 5); + store_le(x06, output + 64 * i + 4 * 6); + store_le(x07, output + 64 * i + 4 * 7); + store_le(x08, output + 64 * i + 4 * 8); + store_le(x09, output + 64 * i + 4 * 9); + store_le(x10, output + 64 * i + 4 * 10); + store_le(x11, output + 64 * i + 4 * 11); + store_le(x12, output + 64 * i + 4 * 12); + store_le(x13, output + 64 * i + 4 * 13); + store_le(x14, output + 64 * i + 4 * 14); + store_le(x15, output + 64 * i + 4 * 15); + + input[12]++; + input[13] += input[12] < i; // carry? + } } -} /* * Combine cipher stream with message @@ -80,11 +110,7 @@ void ChaCha::cipher(const byte in[], byte out[], size_t length) length -= (m_buffer.size() - m_position); in += (m_buffer.size() - m_position); out += (m_buffer.size() - m_position); - chacha(m_buffer.data(), m_state.data(), m_rounds); - - ++m_state[12]; - m_state[13] += (m_state[12] == 0); - + chacha_x4(m_buffer.data(), m_state.data(), m_rounds); m_position = 0; } @@ -106,8 +132,12 @@ void ChaCha::key_schedule(const byte key[], size_t length) const u32bit* CONSTANTS = (length == 16) ? TAU : SIGMA; + // Repeat the key if 128 bits + const byte* key2 = (length == 32) ? key + 16 : key; + + m_position = 0; m_state.resize(16); - m_buffer.resize(64); + m_buffer.resize(4*64); m_state[0] = CONSTANTS[0]; m_state[1] = CONSTANTS[1]; @@ -119,16 +149,12 @@ void ChaCha::key_schedule(const byte key[], size_t length) m_state[6] = load_le<u32bit>(key, 2); m_state[7] = load_le<u32bit>(key, 3); - if(length == 32) - key += 16; - - m_state[8] = load_le<u32bit>(key, 0); - m_state[9] = load_le<u32bit>(key, 1); - m_state[10] = load_le<u32bit>(key, 2); - m_state[11] = load_le<u32bit>(key, 3); - - m_position = 0; + m_state[8] = load_le<u32bit>(key2, 0); + m_state[9] = load_le<u32bit>(key2, 1); + m_state[10] = load_le<u32bit>(key2, 2); + m_state[11] = load_le<u32bit>(key2, 3); + // Default all-zero IV const byte ZERO[8] = { 0 }; set_iv(ZERO, sizeof(ZERO)); } @@ -153,10 +179,7 @@ void ChaCha::set_iv(const byte iv[], size_t length) m_state[15] = load_le<u32bit>(iv, 2); } - chacha(m_buffer.data(), m_state.data(), m_rounds); - ++m_state[12]; - m_state[13] += (m_state[12] == 0); - + chacha_x4(m_buffer.data(), m_state.data(), m_rounds); m_position = 0; } @@ -176,12 +199,11 @@ void ChaCha::seek(u64bit offset) { if (m_state.size() == 0 && m_buffer.size() == 0) { - throw Invalid_State("You have to setup the stream cipher (key and iv)"); + throw Invalid_State("You have to setup the stream cipher (key and iv)"); } - m_position = offset % m_buffer.size(); - - u64bit counter = offset / m_buffer.size(); + // Find the block offset + u64bit counter = offset / 64; byte out[8]; @@ -190,9 +212,7 @@ void ChaCha::seek(u64bit offset) m_state[12] = load_le<u32bit>(out, 0); m_state[13] += load_le<u32bit>(out, 1); - chacha(m_buffer.data(), m_state.data(), m_rounds); - - ++m_state[12]; - m_state[13] += (m_state[12] == 0); + chacha_x4(m_buffer.data(), m_state.data(), m_rounds); + m_position = offset % 64; } } diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h index 7ba37012f..9b4c5d76f 100644 --- a/src/lib/stream/chacha/chacha.h +++ b/src/lib/stream/chacha/chacha.h @@ -47,6 +47,14 @@ class BOTAN_DLL ChaCha final : public StreamCipher private: void key_schedule(const byte key[], size_t key_len) override; + void incr_state_counter(size_t howmany); + + void chacha_x4(byte output[64*4], u32bit state[16], size_t rounds); + +#if defined(BOTAN_HAS_CHACHA_SSE2) + void chacha_sse2_x4(byte output[64*4], u32bit state[16], size_t rounds); +#endif + size_t m_rounds; secure_vector<u32bit> m_state; secure_vector<byte> m_buffer; diff --git a/src/lib/stream/chacha/chacha_sse2/chacha_sse2.cpp b/src/lib/stream/chacha/chacha_sse2/chacha_sse2.cpp new file mode 100644 index 000000000..e39b285b3 --- /dev/null +++ b/src/lib/stream/chacha/chacha_sse2/chacha_sse2.cpp @@ -0,0 +1,259 @@ +/* +* SSE2 ChaCha +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/chacha.h> +#include <emmintrin.h> + +namespace Botan { + +//static +void ChaCha::chacha_sse2_x4(byte output[64], u32bit input[16], size_t rounds) + { + BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds"); + + const __m128i* input_mm = reinterpret_cast<const __m128i*>(input); + __m128i* output_mm = reinterpret_cast<__m128i*>(output); + + __m128i input0 = _mm_loadu_si128(input_mm); + __m128i input1 = _mm_loadu_si128(input_mm + 1); + __m128i input2 = _mm_loadu_si128(input_mm + 2); + __m128i input3 = _mm_loadu_si128(input_mm + 3); + + // TODO: try transposing, which would avoid the permutations each round + +#define mm_rotl(r, n) \ + _mm_or_si128(_mm_slli_epi32(r, n), _mm_srli_epi32(r, 32-n)) + + __m128i r0_0 = input0; + __m128i r0_1 = input1; + __m128i r0_2 = input2; + __m128i r0_3 = input3; + + __m128i r1_0 = input0; + __m128i r1_1 = input1; + __m128i r1_2 = input2; + __m128i r1_3 = input3; + r1_3 = _mm_add_epi64(r0_3, _mm_set_epi32(0, 0, 0, 1)); + + __m128i r2_0 = input0; + __m128i r2_1 = input1; + __m128i r2_2 = input2; + __m128i r2_3 = input3; + r2_3 = _mm_add_epi64(r0_3, _mm_set_epi32(0, 0, 0, 2)); + + __m128i r3_0 = input0; + __m128i r3_1 = input1; + __m128i r3_2 = input2; + __m128i r3_3 = input3; + r3_3 = _mm_add_epi64(r0_3, _mm_set_epi32(0, 0, 0, 3)); + + for(size_t r = 0; r != rounds / 2; ++r) + { + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = mm_rotl(r0_3, 16); + r1_3 = mm_rotl(r1_3, 16); + r2_3 = mm_rotl(r2_3, 16); + r3_3 = mm_rotl(r3_3, 16); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = mm_rotl(r0_1, 12); + r1_1 = mm_rotl(r1_1, 12); + r2_1 = mm_rotl(r2_1, 12); + r3_1 = mm_rotl(r3_1, 12); + + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = mm_rotl(r0_3, 8); + r1_3 = mm_rotl(r1_3, 8); + r2_3 = mm_rotl(r2_3, 8); + r3_3 = mm_rotl(r3_3, 8); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = mm_rotl(r0_1, 7); + r1_1 = mm_rotl(r1_1, 7); + r2_1 = mm_rotl(r2_1, 7); + r3_1 = mm_rotl(r3_1, 7); + + r0_1 = _mm_shuffle_epi32(r0_1, _MM_SHUFFLE(0, 3, 2, 1)); + r0_2 = _mm_shuffle_epi32(r0_2, _MM_SHUFFLE(1, 0, 3, 2)); + r0_3 = _mm_shuffle_epi32(r0_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r1_1 = _mm_shuffle_epi32(r1_1, _MM_SHUFFLE(0, 3, 2, 1)); + r1_2 = _mm_shuffle_epi32(r1_2, _MM_SHUFFLE(1, 0, 3, 2)); + r1_3 = _mm_shuffle_epi32(r1_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r2_1 = _mm_shuffle_epi32(r2_1, _MM_SHUFFLE(0, 3, 2, 1)); + r2_2 = _mm_shuffle_epi32(r2_2, _MM_SHUFFLE(1, 0, 3, 2)); + r2_3 = _mm_shuffle_epi32(r2_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r3_1 = _mm_shuffle_epi32(r3_1, _MM_SHUFFLE(0, 3, 2, 1)); + r3_2 = _mm_shuffle_epi32(r3_2, _MM_SHUFFLE(1, 0, 3, 2)); + r3_3 = _mm_shuffle_epi32(r3_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = mm_rotl(r0_3, 16); + r1_3 = mm_rotl(r1_3, 16); + r2_3 = mm_rotl(r2_3, 16); + r3_3 = mm_rotl(r3_3, 16); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = mm_rotl(r0_1, 12); + r1_1 = mm_rotl(r1_1, 12); + r2_1 = mm_rotl(r2_1, 12); + r3_1 = mm_rotl(r3_1, 12); + + r0_0 = _mm_add_epi32(r0_0, r0_1); + r1_0 = _mm_add_epi32(r1_0, r1_1); + r2_0 = _mm_add_epi32(r2_0, r2_1); + r3_0 = _mm_add_epi32(r3_0, r3_1); + + r0_3 = _mm_xor_si128(r0_3, r0_0); + r1_3 = _mm_xor_si128(r1_3, r1_0); + r2_3 = _mm_xor_si128(r2_3, r2_0); + r3_3 = _mm_xor_si128(r3_3, r3_0); + + r0_3 = mm_rotl(r0_3, 8); + r1_3 = mm_rotl(r1_3, 8); + r2_3 = mm_rotl(r2_3, 8); + r3_3 = mm_rotl(r3_3, 8); + + r0_2 = _mm_add_epi32(r0_2, r0_3); + r1_2 = _mm_add_epi32(r1_2, r1_3); + r2_2 = _mm_add_epi32(r2_2, r2_3); + r3_2 = _mm_add_epi32(r3_2, r3_3); + + r0_1 = _mm_xor_si128(r0_1, r0_2); + r1_1 = _mm_xor_si128(r1_1, r1_2); + r2_1 = _mm_xor_si128(r2_1, r2_2); + r3_1 = _mm_xor_si128(r3_1, r3_2); + + r0_1 = mm_rotl(r0_1, 7); + r1_1 = mm_rotl(r1_1, 7); + r2_1 = mm_rotl(r2_1, 7); + r3_1 = mm_rotl(r3_1, 7); + + r0_1 = _mm_shuffle_epi32(r0_1, _MM_SHUFFLE(2, 1, 0, 3)); + r0_2 = _mm_shuffle_epi32(r0_2, _MM_SHUFFLE(1, 0, 3, 2)); + r0_3 = _mm_shuffle_epi32(r0_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r1_1 = _mm_shuffle_epi32(r1_1, _MM_SHUFFLE(2, 1, 0, 3)); + r1_2 = _mm_shuffle_epi32(r1_2, _MM_SHUFFLE(1, 0, 3, 2)); + r1_3 = _mm_shuffle_epi32(r1_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r2_1 = _mm_shuffle_epi32(r2_1, _MM_SHUFFLE(2, 1, 0, 3)); + r2_2 = _mm_shuffle_epi32(r2_2, _MM_SHUFFLE(1, 0, 3, 2)); + r2_3 = _mm_shuffle_epi32(r2_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r3_1 = _mm_shuffle_epi32(r3_1, _MM_SHUFFLE(2, 1, 0, 3)); + r3_2 = _mm_shuffle_epi32(r3_2, _MM_SHUFFLE(1, 0, 3, 2)); + r3_3 = _mm_shuffle_epi32(r3_3, _MM_SHUFFLE(0, 3, 2, 1)); + } + + r0_0 = _mm_add_epi32(r0_0, input0); + r0_1 = _mm_add_epi32(r0_1, input1); + r0_2 = _mm_add_epi32(r0_2, input2); + r0_3 = _mm_add_epi32(r0_3, input3); + + r1_0 = _mm_add_epi32(r1_0, input0); + r1_1 = _mm_add_epi32(r1_1, input1); + r1_2 = _mm_add_epi32(r1_2, input2); + r1_3 = _mm_add_epi32(r1_3, input3); + r1_3 = _mm_add_epi64(r1_3, _mm_set_epi32(0, 0, 0, 1)); + + r2_0 = _mm_add_epi32(r2_0, input0); + r2_1 = _mm_add_epi32(r2_1, input1); + r2_2 = _mm_add_epi32(r2_2, input2); + r2_3 = _mm_add_epi32(r2_3, input3); + r2_3 = _mm_add_epi64(r2_3, _mm_set_epi32(0, 0, 0, 2)); + + r3_0 = _mm_add_epi32(r3_0, input0); + r3_1 = _mm_add_epi32(r3_1, input1); + r3_2 = _mm_add_epi32(r3_2, input2); + r3_3 = _mm_add_epi32(r3_3, input3); + r3_3 = _mm_add_epi64(r3_3, _mm_set_epi32(0, 0, 0, 3)); + + _mm_storeu_si128(output_mm + 0, r0_0); + _mm_storeu_si128(output_mm + 1, r0_1); + _mm_storeu_si128(output_mm + 2, r0_2); + _mm_storeu_si128(output_mm + 3, r0_3); + + _mm_storeu_si128(output_mm + 4, r1_0); + _mm_storeu_si128(output_mm + 5, r1_1); + _mm_storeu_si128(output_mm + 6, r1_2); + _mm_storeu_si128(output_mm + 7, r1_3); + + _mm_storeu_si128(output_mm + 8, r2_0); + _mm_storeu_si128(output_mm + 9, r2_1); + _mm_storeu_si128(output_mm + 10, r2_2); + _mm_storeu_si128(output_mm + 11, r2_3); + + _mm_storeu_si128(output_mm + 12, r3_0); + _mm_storeu_si128(output_mm + 13, r3_1); + _mm_storeu_si128(output_mm + 14, r3_2); + _mm_storeu_si128(output_mm + 15, r3_3); + +#undef mm_rotl + + input[12] += 4; + if(input[12] < 4) + input[13]++; + } + +} diff --git a/src/lib/stream/chacha/chacha_sse2/info.txt b/src/lib/stream/chacha/chacha_sse2/info.txt new file mode 100644 index 000000000..965479746 --- /dev/null +++ b/src/lib/stream/chacha/chacha_sse2/info.txt @@ -0,0 +1,3 @@ +define CHACHA_SSE2 20160831 + +need_isa sse2 diff --git a/src/lib/tls/info.txt b/src/lib/tls/info.txt index b26179226..667726318 100644 --- a/src/lib/tls/info.txt +++ b/src/lib/tls/info.txt @@ -6,6 +6,7 @@ load_on auto credentials_manager.h tls_alert.h tls_blocking.h +tls_callbacks.h tls_channel.h tls_ciphersuite.h tls_client.h diff --git a/src/lib/tls/msg_cert_verify.cpp b/src/lib/tls/msg_cert_verify.cpp index 2598255eb..6b59e703f 100644 --- a/src/lib/tls/msg_cert_verify.cpp +++ b/src/lib/tls/msg_cert_verify.cpp @@ -82,6 +82,8 @@ bool Certificate_Verify::verify(const X509_Certificate& cert, { std::unique_ptr<Public_Key> key(cert.subject_public_key()); + policy.check_peer_key_acceptable(*key); + std::pair<std::string, Signature_Format> format = state.parse_sig_format(*key.get(), m_hash_algo, m_sig_algo, true, policy); diff --git a/src/lib/tls/msg_certificate.cpp b/src/lib/tls/msg_certificate.cpp index 32e3e17f0..10ee7c95f 100644 --- a/src/lib/tls/msg_certificate.cpp +++ b/src/lib/tls/msg_certificate.cpp @@ -31,7 +31,7 @@ Certificate::Certificate(Handshake_IO& io, /** * Deserialize a Certificate message */ -Certificate::Certificate(const std::vector<byte>& buf) +Certificate::Certificate(const std::vector<byte>& buf, const Policy& /*policy_currently_unused*/) { if(buf.size() < 3) throw Decoding_Error("Certificate: Message malformed"); diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp index 23807215f..69f9a5e11 100644 --- a/src/lib/tls/msg_client_hello.cpp +++ b/src/lib/tls/msg_client_hello.cpp @@ -1,6 +1,7 @@ /* * TLS Hello Request and Client Hello Messages * (C) 2004-2011,2015,2016 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -68,22 +69,20 @@ std::vector<byte> Hello_Request::serialize() const */ Client_Hello::Client_Hello(Handshake_IO& io, Handshake_Hash& hash, - Protocol_Version version, const Policy& policy, RandomNumberGenerator& rng, const std::vector<byte>& reneg_info, - const std::vector<std::string>& next_protocols, - const std::string& hostname, - const std::string& srp_identifier) : - m_version(version), + const Client_Hello::Settings& client_settings, + const std::vector<std::string>& next_protocols) : + m_version(client_settings.protocol_version()), m_random(make_hello_random(rng, policy)), - m_suites(policy.ciphersuite_list(m_version, (srp_identifier != ""))), + m_suites(policy.ciphersuite_list(m_version, + client_settings.srp_identifier() != "")), m_comp_methods(policy.compression()) { m_extensions.add(new Extended_Master_Secret); m_extensions.add(new Renegotiation_Extension(reneg_info)); - - m_extensions.add(new Server_Name_Indicator(hostname)); + m_extensions.add(new Server_Name_Indicator(client_settings.hostname())); m_extensions.add(new Session_Ticket()); m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves())); @@ -96,20 +95,23 @@ Client_Hello::Client_Hello(Handshake_IO& io, if(reneg_info.empty() && !next_protocols.empty()) m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols)); + + if(policy.negotiate_encrypt_then_mac()) + m_extensions.add(new Encrypt_then_MAC); #if defined(BOTAN_HAS_SRP6) - m_extensions.add(new SRP_Identifier(srp_identifier)); + m_extensions.add(new SRP_Identifier(client_settings.srp_identifier())); #else - if(!srp_identifier.empty()) + if(!client_settings.srp_identifier().empty()) { throw Invalid_State("Attempting to initiate SRP session but TLS-SRP support disabled"); } #endif - BOTAN_ASSERT(policy.acceptable_protocol_version(version), + BOTAN_ASSERT(policy.acceptable_protocol_version(client_settings.protocol_version()), "Our policy accepts the version we are offering"); - if(policy.send_fallback_scsv(version)) + if(policy.send_fallback_scsv(client_settings.protocol_version())) m_suites.push_back(TLS_FALLBACK_SCSV); hash.update(io.send(*this)); @@ -155,6 +157,9 @@ Client_Hello::Client_Hello(Handshake_IO& io, if(reneg_info.empty() && !next_protocols.empty()) m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols)); + + if(policy.negotiate_encrypt_then_mac()) + m_extensions.add(new Encrypt_then_MAC); #if defined(BOTAN_HAS_SRP6) m_extensions.add(new SRP_Identifier(session.srp_identifier())); diff --git a/src/lib/tls/msg_client_kex.cpp b/src/lib/tls/msg_client_kex.cpp index 77e9795f4..bc4d33d52 100644 --- a/src/lib/tls/msg_client_kex.cpp +++ b/src/lib/tls/msg_client_kex.cpp @@ -92,13 +92,6 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, if(reader.remaining_bytes()) throw Decoding_Error("Bad params size for DH key exchange"); - if(p.bits() < policy.minimum_dh_group_size()) - throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, - "Server sent DH group of " + - std::to_string(p.bits()) + - " bits, policy requires at least " + - std::to_string(policy.minimum_dh_group_size())); - /* * A basic check for key validity. As we do not know q here we * cannot check that Y is in the right subgroup. However since @@ -117,6 +110,8 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, DH_PublicKey counterparty_key(group, Y); + policy.check_peer_key_acceptable(counterparty_key); + DH_PrivateKey priv_key(rng, group); PK_Key_Agreement ka(priv_key, "Raw"); @@ -160,6 +155,8 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve())); + policy.check_peer_key_acceptable(counterparty_key); + ECDH_PrivateKey priv_key(rng, group); PK_Key_Agreement ka(priv_key, "Raw"); diff --git a/src/lib/tls/msg_server_hello.cpp b/src/lib/tls/msg_server_hello.cpp index f8d0c63c7..ebe8fb085 100644 --- a/src/lib/tls/msg_server_hello.cpp +++ b/src/lib/tls/msg_server_hello.cpp @@ -1,6 +1,7 @@ /* * TLS Server Hello and Server Hello Done * (C) 2004-2011,2015,2016 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -23,25 +24,28 @@ Server_Hello::Server_Hello(Handshake_IO& io, RandomNumberGenerator& rng, const std::vector<byte>& reneg_info, const Client_Hello& client_hello, - const std::vector<byte>& new_session_id, - Protocol_Version new_session_version, - u16bit ciphersuite, - byte compression, - bool offer_session_ticket, - const std::string& next_protocol) : - m_version(new_session_version), - m_session_id(new_session_id), + const Server_Hello::Settings& server_settings, + const std::string next_protocol) : + m_version(server_settings.protocol_version()), + m_session_id(server_settings.session_id()), m_random(make_hello_random(rng, policy)), - m_ciphersuite(ciphersuite), - m_comp_method(compression) + m_ciphersuite(server_settings.ciphersuite()), + m_comp_method(server_settings.compression()) { if(client_hello.supports_extended_master_secret()) m_extensions.add(new Extended_Master_Secret); + if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) + { + Ciphersuite c = Ciphersuite::by_id(m_ciphersuite); + if(c.cbc_ciphersuite()) + m_extensions.add(new Encrypt_then_MAC); + } + if(client_hello.secure_renegotiation()) m_extensions.add(new Renegotiation_Extension(reneg_info)); - if(client_hello.supports_session_ticket() && offer_session_ticket) + if(client_hello.supports_session_ticket() && server_settings.offer_session_ticket()) m_extensions.add(new Session_Ticket()); if(!next_protocol.empty() && client_hello.supports_alpn()) @@ -90,6 +94,13 @@ Server_Hello::Server_Hello(Handshake_IO& io, if(client_hello.supports_extended_master_secret()) m_extensions.add(new Extended_Master_Secret); + if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) + { + Ciphersuite c = resumed_session.ciphersuite(); + if(c.cbc_ciphersuite()) + m_extensions.add(new Encrypt_then_MAC); + } + if(client_hello.secure_renegotiation()) m_extensions.add(new Renegotiation_Extension(reneg_info)); diff --git a/src/lib/tls/msg_server_kex.cpp b/src/lib/tls/msg_server_kex.cpp index 98e3ad1f0..10581fe45 100644 --- a/src/lib/tls/msg_server_kex.cpp +++ b/src/lib/tls/msg_server_kex.cpp @@ -236,6 +236,8 @@ bool Server_Key_Exchange::verify(const Public_Key& server_key, const Handshake_State& state, const Policy& policy) const { + policy.check_peer_key_acceptable(server_key); + std::pair<std::string, Signature_Format> format = state.parse_sig_format(server_key, m_hash_algo, m_sig_algo, false, policy); diff --git a/src/lib/tls/tls_blocking.cpp b/src/lib/tls/tls_blocking.cpp index a1867b6b5..9408972fd 100644 --- a/src/lib/tls/tls_blocking.cpp +++ b/src/lib/tls/tls_blocking.cpp @@ -1,6 +1,7 @@ /* * TLS Blocking API * (C) 2013 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -23,10 +24,13 @@ Blocking_Client::Blocking_Client(read_fn reader, const Protocol_Version& offer_version, const std::vector<std::string>& next) : m_read(reader), - m_channel(writer, - std::bind(&Blocking_Client::data_cb, this, _1, _2), - std::bind(&Blocking_Client::alert_cb, this, _1, _2, _3), - std::bind(&Blocking_Client::handshake_cb, this, _1), + m_callbacks(new TLS::Compat_Callbacks( + writer, + std::bind(&Blocking_Client::data_cb, this, _1, _2), + std::function<void (Alert)>(std::bind(&Blocking_Client::alert_cb, this, _1)), + std::bind(&Blocking_Client::handshake_cb, this, _1) + )), + m_channel(*m_callbacks.get(), session_manager, creds, policy, @@ -42,7 +46,7 @@ bool Blocking_Client::handshake_cb(const Session& session) return this->handshake_complete(session); } -void Blocking_Client::alert_cb(const Alert& alert, const byte[], size_t) +void Blocking_Client::alert_cb(const Alert& alert) { this->alert_notification(alert); } diff --git a/src/lib/tls/tls_blocking.h b/src/lib/tls/tls_blocking.h index 00e65cbaf..0f2986710 100644 --- a/src/lib/tls/tls_blocking.h +++ b/src/lib/tls/tls_blocking.h @@ -1,6 +1,7 @@ /* * TLS Blocking API * (C) 2013 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -32,6 +33,7 @@ class BOTAN_DLL Blocking_Client typedef std::function<size_t (byte[], size_t)> read_fn; typedef std::function<void (const byte[], size_t)> write_fn; + BOTAN_DEPRECATED("Use the regular TLS::Client interface") Blocking_Client(read_fn reader, write_fn writer, Session_Manager& session_manager, @@ -89,9 +91,10 @@ class BOTAN_DLL Blocking_Client void data_cb(const byte data[], size_t data_len); - void alert_cb(const Alert& alert, const byte data[], size_t data_len); + void alert_cb(const Alert& alert); read_fn m_read; + std::unique_ptr<Compat_Callbacks> m_callbacks; TLS::Client m_channel; secure_vector<byte> m_plaintext; }; diff --git a/src/lib/tls/tls_callbacks.h b/src/lib/tls/tls_callbacks.h new file mode 100644 index 000000000..75887c23f --- /dev/null +++ b/src/lib/tls/tls_callbacks.h @@ -0,0 +1,203 @@ +/* +* TLS Callbacks +* (C) 2016 Matthias Gierlings +* 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_TLS_CALLBACKS_H__ +#define BOTAN_TLS_CALLBACKS_H__ + +#include <botan/tls_session.h> +#include <botan/tls_alert.h> +namespace Botan { + +namespace TLS { + +class Handshake_Message; + +/** +* Encapsulates the callbacks that a TLS channel will make which are due to +* channel specific operations. +*/ +class BOTAN_DLL Callbacks + { + public: + virtual ~Callbacks(); + + /** + * Mandatory callback: output function + * The channel will call this with data which needs to be sent to the peer + * (eg, over a socket or some other form of IPC). The array will be overwritten + * when the function returns so a copy must be made if the data cannot be + * sent immediately. + * + * @param data the vector of data to send + * + * @param size the number of bytes to send + */ + virtual void tls_emit_data(const uint8_t data[], size_t size) = 0; + + /** + * Mandatory callback: process application data + * Called when application data record is received from the peer. + * Again the array is overwritten immediately after the function returns. + * + * @param seq_no the underlying TLS/DTLS record sequence number + * + * @param data the vector containing the received record + * + * @param size the length of the received record, in bytes + */ + virtual void tls_record_received(u64bit seq_no, const uint8_t data[], size_t size) = 0; + + /** + * Mandary callback: alert received + * Called when an alert is received from the peer + * If fatal, the connection is closing. If not fatal, the connection may + * still be closing (depending on the error and the peer). + * + * @param alert the source of the alert + */ + virtual void tls_alert(Alert alert) = 0; + + /** + * Mandatory callback: session established + * Called when a session is established. Throw an exception to abort + * the connection. + * + * @param session the session descriptor + * + * @return return false to prevent the session from being cached, + * return true to cache the session in the configured session manager + */ + virtual bool tls_session_established(const Session& session) = 0; + + /** + * Optional callback: inspect handshake message + * Throw an exception to abort the handshake. + * Default simply ignores the message. + * + * @param message the handshake message + */ + virtual void tls_inspect_handshake_msg(const Handshake_Message& message); + + /** + * Optional callback for server: choose ALPN protocol + * ALPN (RFC 7301) works by the client sending a list of application + * protocols it is willing to negotiate. The server then selects which + * protocol to use, which is not necessarily even on the list that + * the client sent. + * + * @param client_protos the vector of protocols the client is willing to negotiate + * + * @return the protocol selected by the server, which need not be on the + * list that the client sent; if this is the empty string, the server ignores the + * client ALPN extension. Default return value is empty string. + */ + virtual std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos); + + /** + * Optional callback: debug logging. (not currently used) + */ + virtual bool tls_log_debug(const char*) { return false; } + }; + +/** +* TLS::Callbacks using std::function for compatability with the old API signatures. +* This type is only provided for backward compatibility. +* New implementations should derive from TLS::Callbacks instead. +*/ +class BOTAN_DLL Compat_Callbacks final : public Callbacks + { + public: + typedef std::function<void (const byte[], size_t)> output_fn; + typedef std::function<void (const byte[], size_t)> data_cb; + typedef std::function<void (Alert, const byte[], size_t)> alert_cb; + typedef std::function<bool (const Session&)> handshake_cb; + typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; + typedef std::function<std::string (std::vector<std::string>)> next_protocol_fn; + + /** + * @param output_fn is called with data for the outbound socket + * + * @param app_data_cb is called when new application data is received + * + * @param alert_cb is called when a TLS alert is received + * + * @param handshake_cb is called when a handshake is completed + */ + BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") + Compat_Callbacks(output_fn out, data_cb app_data_cb, alert_cb alert_cb, + handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr, + next_protocol_fn next_proto = nullptr) + : m_output_function(out), m_app_data_cb(app_data_cb), + m_alert_cb(std::bind(alert_cb, std::placeholders::_1, nullptr, 0)), + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {} + + BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") + Compat_Callbacks(output_fn out, data_cb app_data_cb, + std::function<void (Alert)> alert_cb, + handshake_cb hs_cb, + handshake_msg_cb hs_msg_cb = nullptr, + next_protocol_fn next_proto = nullptr) + : m_output_function(out), m_app_data_cb(app_data_cb), + m_alert_cb(alert_cb), + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {} + + void tls_emit_data(const byte data[], size_t size) override + { + BOTAN_ASSERT(m_output_function != nullptr, + "Invalid TLS output function callback."); + m_output_function(data, size); + } + + void tls_record_received(u64bit /*seq_no*/, const byte data[], size_t size) override + { + BOTAN_ASSERT(m_app_data_cb != nullptr, + "Invalid TLS app data callback."); + m_app_data_cb(data, size); + } + + void tls_alert(Alert alert) override + { + BOTAN_ASSERT(m_alert_cb != nullptr, + "Invalid TLS alert callback."); + m_alert_cb(alert); + } + + bool tls_session_established(const Session& session) override + { + BOTAN_ASSERT(m_hs_cb != nullptr, + "Invalid TLS handshake callback."); + return m_hs_cb(session); + } + + std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override + { + if(m_next_proto != nullptr) { return m_next_proto(client_protos); } + return ""; + } + + void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override + { + // The handshake message callback is optional so we can + // not assume it has been set. + if(m_hs_msg_cb != nullptr) { m_hs_msg_cb(hmsg); } + } + + private: + const output_fn m_output_function; + const data_cb m_app_data_cb; + const std::function<void (Alert)> m_alert_cb; + const handshake_cb m_hs_cb; + const handshake_msg_cb m_hs_msg_cb; + const next_protocol_fn m_next_proto; + }; + +} + +} + +#endif diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp index f445eef99..5e9207da7 100644 --- a/src/lib/tls/tls_channel.cpp +++ b/src/lib/tls/tls_channel.cpp @@ -1,6 +1,7 @@ /* * TLS Channels -* (C) 2011,2012,2014,2015 Jack Lloyd +* (C) 2011,2012,2014,2015,2016 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -18,32 +19,63 @@ namespace Botan { namespace TLS { -Channel::Channel(output_fn output_fn, - data_cb data_cb, - alert_cb alert_cb, - handshake_cb handshake_cb, - handshake_msg_cb handshake_msg_cb, +Callbacks::~Callbacks() {} + +void Callbacks::tls_inspect_handshake_msg(const Handshake_Message&) + { + // default is no op + } + +std::string Callbacks::tls_server_choose_app_protocol(const std::vector<std::string>&) + { + return ""; + } + +size_t TLS::Channel::IO_BUF_DEFAULT_SIZE = 10*1024; + +Channel::Channel(Callbacks& callbacks, Session_Manager& session_manager, RandomNumberGenerator& rng, const Policy& policy, bool is_datagram, size_t reserved_io_buffer_size) : m_is_datagram(is_datagram), - m_data_cb(data_cb), - m_alert_cb(alert_cb), - m_output_fn(output_fn), - m_handshake_cb(handshake_cb), - m_handshake_msg_cb(handshake_msg_cb), + m_callbacks(callbacks), m_session_manager(session_manager), m_policy(policy), m_rng(rng) { + init(reserved_io_buffer_size); + } + +Channel::Channel(output_fn out, + data_cb app_data_cb, + alert_cb alert_cb, + handshake_cb hs_cb, + handshake_msg_cb hs_msg_cb, + Session_Manager& session_manager, + RandomNumberGenerator& rng, + const Policy& policy, + bool is_datagram, + size_t io_buf_sz) : + m_is_datagram(is_datagram), + m_compat_callbacks(new Compat_Callbacks(out, app_data_cb, alert_cb, hs_cb, hs_msg_cb)), + m_callbacks(*m_compat_callbacks.get()), + m_session_manager(session_manager), + m_policy(policy), + m_rng(rng) + { + init(io_buf_sz); + } + +void Channel::init(size_t io_buf_sz) + { /* epoch 0 is plaintext, thus null cipher state */ m_write_cipher_states[0] = nullptr; m_read_cipher_states[0] = nullptr; - m_writebuf.reserve(reserved_io_buffer_size); - m_readbuf.reserve(reserved_io_buffer_size); + m_writebuf.reserve(io_buf_sz); + m_readbuf.reserve(io_buf_sz); } void Channel::reset_state() @@ -183,7 +215,8 @@ void Channel::change_cipher_spec_reader(Connection_Side side) (side == CLIENT) ? SERVER : CLIENT, false, pending->ciphersuite(), - pending->session_keys())); + pending->session_keys(), + pending->server_hello()->supports_encrypt_then_mac())); m_read_cipher_states[epoch] = read_state; } @@ -210,7 +243,8 @@ void Channel::change_cipher_spec_writer(Connection_Side side) side, true, pending->ciphersuite(), - pending->session_keys())); + pending->session_keys(), + pending->server_hello()->supports_encrypt_then_mac())); m_write_cipher_states[epoch] = write_state; } @@ -263,23 +297,19 @@ size_t Channel::received_data(const byte input[], size_t input_size) { while(!is_closed() && input_size) { - secure_vector<byte> record; + secure_vector<byte> record_data; u64bit record_sequence = 0; Record_Type record_type = NO_RECORD; Protocol_Version record_version; size_t consumed = 0; + Record_Raw_Input raw_input(input, input_size, consumed, m_is_datagram); + Record record(record_data, &record_sequence, &record_version, &record_type); const size_t needed = read_record(m_readbuf, - input, - input_size, - m_is_datagram, - consumed, + raw_input, record, - &record_sequence, - &record_version, - &record_type, m_sequence_numbers.get(), std::bind(&TLS::Channel::read_cipher_state_epoch, this, std::placeholders::_1)); @@ -298,105 +328,21 @@ size_t Channel::received_data(const byte input[], size_t input_size) if(input_size == 0 && needed != 0) return needed; // need more data to complete record - if(record.size() > MAX_PLAINTEXT_SIZE) + if(record_data.size() > MAX_PLAINTEXT_SIZE) throw TLS_Exception(Alert::RECORD_OVERFLOW, "TLS plaintext record is larger than allowed maximum"); if(record_type == HANDSHAKE || record_type == CHANGE_CIPHER_SPEC) { - if(!m_pending_state) - { - // No pending handshake, possibly new: - if(record_version.is_datagram_protocol()) - { - if(m_sequence_numbers) - { - /* - * Might be a peer retransmit under epoch - 1 in which - * case we must retransmit last flight - */ - sequence_numbers().read_accept(record_sequence); - - const u16bit epoch = record_sequence >> 48; - - if(epoch == sequence_numbers().current_read_epoch()) - { - create_handshake_state(record_version); - } - else if(epoch == sequence_numbers().current_read_epoch() - 1) - { - BOTAN_ASSERT(m_active_state, "Have active state here"); - m_active_state->handshake_io().add_record(unlock(record), - record_type, - record_sequence); - } - } - else if(record_sequence == 0) - { - create_handshake_state(record_version); - } - } - else - { - create_handshake_state(record_version); - } - } - - // May have been created in above conditional - if(m_pending_state) - { - m_pending_state->handshake_io().add_record(unlock(record), - record_type, - record_sequence); - - while(auto pending = m_pending_state.get()) - { - auto msg = pending->get_next_handshake_msg(); - - if(msg.first == HANDSHAKE_NONE) // no full handshake yet - break; - - process_handshake_msg(active_state(), *pending, - msg.first, msg.second); - } - } + process_handshake_ccs(record_data, record_sequence, record_type, record_version); } else if(record_type == APPLICATION_DATA) { - if(!active_state()) - throw Unexpected_Message("Application data before handshake done"); - - /* - * OpenSSL among others sends empty records in versions - * before TLS v1.1 in order to randomize the IV of the - * following record. Avoid spurious callbacks. - */ - if(record.size() > 0) - m_data_cb(record.data(), record.size()); + process_application_data(record_sequence, record_data); } else if(record_type == ALERT) { - Alert alert_msg(record); - - if(alert_msg.type() == Alert::NO_RENEGOTIATION) - m_pending_state.reset(); - - m_alert_cb(alert_msg, nullptr, 0); - - if(alert_msg.is_fatal()) - { - if(auto active = active_state()) - m_session_manager.remove_entry(active->server_hello()->session_id()); - } - - if(alert_msg.type() == Alert::CLOSE_NOTIFY) - send_warning_alert(Alert::CLOSE_NOTIFY); // reply in kind - - if(alert_msg.type() == Alert::CLOSE_NOTIFY || alert_msg.is_fatal()) - { - reset_state(); - return 0; - } + process_alert(record_data); } else if(record_type != NO_RECORD) throw Unexpected_Message("Unexpected record type " + @@ -428,6 +374,108 @@ size_t Channel::received_data(const byte input[], size_t input_size) } } +void Channel::process_handshake_ccs(const secure_vector<byte>& record, + u64bit record_sequence, + Record_Type record_type, + Protocol_Version record_version) + { + if(!m_pending_state) + { + // No pending handshake, possibly new: + if(record_version.is_datagram_protocol()) + { + if(m_sequence_numbers) + { + /* + * Might be a peer retransmit under epoch - 1 in which + * case we must retransmit last flight + */ + sequence_numbers().read_accept(record_sequence); + + const u16bit epoch = record_sequence >> 48; + + if(epoch == sequence_numbers().current_read_epoch()) + { + create_handshake_state(record_version); + } + else if(epoch == sequence_numbers().current_read_epoch() - 1) + { + BOTAN_ASSERT(m_active_state, "Have active state here"); + m_active_state->handshake_io().add_record(unlock(record), + record_type, + record_sequence); + } + } + else if(record_sequence == 0) + { + create_handshake_state(record_version); + } + } + else + { + create_handshake_state(record_version); + } + } + + // May have been created in above conditional + if(m_pending_state) + { + m_pending_state->handshake_io().add_record(unlock(record), + record_type, + record_sequence); + + while(auto pending = m_pending_state.get()) + { + auto msg = pending->get_next_handshake_msg(); + + if(msg.first == HANDSHAKE_NONE) // no full handshake yet + break; + + process_handshake_msg(active_state(), *pending, + msg.first, msg.second); + } + } + } + +void Channel::process_application_data(u64bit seq_no, const secure_vector<byte>& record) + { + if(!active_state()) + throw Unexpected_Message("Application data before handshake done"); + + /* + * OpenSSL among others sends empty records in versions + * before TLS v1.1 in order to randomize the IV of the + * following record. Avoid spurious callbacks. + */ + if(record.size() > 0) + callbacks().tls_record_received(seq_no, record.data(), record.size()); + } + +void Channel::process_alert(const secure_vector<byte>& record) + { + Alert alert_msg(record); + + if(alert_msg.type() == Alert::NO_RENEGOTIATION) + m_pending_state.reset(); + + callbacks().tls_alert(alert_msg); + + if(alert_msg.is_fatal()) + { + if(auto active = active_state()) + m_session_manager.remove_entry(active->server_hello()->session_id()); + } + + if(alert_msg.type() == Alert::CLOSE_NOTIFY) + send_warning_alert(Alert::CLOSE_NOTIFY); // reply in kind + + if(alert_msg.type() == Alert::CLOSE_NOTIFY || alert_msg.is_fatal()) + { + reset_state(); + } + } + + void Channel::write_record(Connection_Cipher_State* cipher_state, u16bit epoch, byte record_type, const byte input[], size_t length) { @@ -436,16 +484,16 @@ void Channel::write_record(Connection_Cipher_State* cipher_state, u16bit epoch, Protocol_Version record_version = (m_pending_state) ? (m_pending_state->version()) : (m_active_state->version()); + Record_Message record_message(record_type, 0, input, length); + TLS::write_record(m_writebuf, - record_type, - input, - length, + record_message, record_version, sequence_numbers().next_write_sequence(epoch), cipher_state, m_rng); - m_output_fn(m_writebuf.data(), m_writebuf.size()); + callbacks().tls_emit_data(m_writebuf.data(), m_writebuf.size()); } void Channel::send_record_array(u16bit epoch, byte type, const byte input[], size_t length) diff --git a/src/lib/tls/tls_channel.h b/src/lib/tls/tls_channel.h index e0219c242..073af760f 100644 --- a/src/lib/tls/tls_channel.h +++ b/src/lib/tls/tls_channel.h @@ -1,6 +1,7 @@ /* * TLS Channel * (C) 2011,2012,2014,2015 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -12,6 +13,7 @@ #include <botan/tls_session.h> #include <botan/tls_alert.h> #include <botan/tls_session_manager.h> +#include <botan/tls_callbacks.h> #include <botan/x509cert.h> #include <vector> #include <string> @@ -37,7 +39,20 @@ class BOTAN_DLL Channel typedef std::function<void (Alert, const byte[], size_t)> alert_cb; typedef std::function<bool (const Session&)> handshake_cb; typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; + static size_t IO_BUF_DEFAULT_SIZE; + Channel(Callbacks& callbacks, + Session_Manager& session_manager, + RandomNumberGenerator& rng, + const Policy& policy, + bool is_datagram, + size_t io_buf_sz = IO_BUF_DEFAULT_SIZE); + + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new implementations. + */ + BOTAN_DEPRECATED("Use TLS::Channel(TLS::Callbacks ...)") Channel(output_fn out, data_cb app_data_cb, alert_cb alert_cb, @@ -47,7 +62,7 @@ class BOTAN_DLL Channel RandomNumberGenerator& rng, const Policy& policy, bool is_datagram, - size_t io_buf_sz = 16*1024); + size_t io_buf_sz = IO_BUF_DEFAULT_SIZE); Channel(const Channel&) = delete; @@ -200,10 +215,12 @@ class BOTAN_DLL Channel const Policy& policy() const { return m_policy; } - bool save_session(const Session& session) const { return m_handshake_cb(session); } + bool save_session(const Session& session) const { return callbacks().tls_session_established(session); } - handshake_msg_cb get_handshake_msg_cb() const { return m_handshake_msg_cb; } + Callbacks& callbacks() const { return m_callbacks; } private: + void init(size_t io_buf_sze); + void send_record(byte record_type, const std::vector<byte>& record); void send_record_under_epoch(u16bit epoch, byte record_type, @@ -227,14 +244,21 @@ class BOTAN_DLL Channel const Handshake_State* pending_state() const { return m_pending_state.get(); } + /* methods to handle incoming traffic through Channel::receive_data. */ + void process_handshake_ccs(const secure_vector<byte>& record, + u64bit record_sequence, + Record_Type record_type, + Protocol_Version record_version); + + void process_application_data(u64bit req_no, const secure_vector<byte>& record); + + void process_alert(const secure_vector<byte>& record); + bool m_is_datagram; /* callbacks */ - data_cb m_data_cb; - alert_cb m_alert_cb; - output_fn m_output_fn; - handshake_cb m_handshake_cb; - handshake_msg_cb m_handshake_msg_cb; + std::unique_ptr<Compat_Callbacks> m_compat_callbacks; + Callbacks& m_callbacks; /* external state */ Session_Manager& m_session_manager; diff --git a/src/lib/tls/tls_ciphersuite.cpp b/src/lib/tls/tls_ciphersuite.cpp index dc0c71278..9a52e0e0e 100644 --- a/src/lib/tls/tls_ciphersuite.cpp +++ b/src/lib/tls/tls_ciphersuite.cpp @@ -35,6 +35,13 @@ bool Ciphersuite::ecc_ciphersuite() const return (sig_algo() == "ECDSA" || kex_algo() == "ECDH" || kex_algo() == "ECDHE_PSK"); } +bool Ciphersuite::cbc_ciphersuite() const + { + return (cipher_algo() == "3DES" || cipher_algo() == "SEED" || + cipher_algo() == "AES-128" || cipher_algo() == "AES-256" || + cipher_algo() == "Camellia-128" || cipher_algo() == "Camellia-256"); + } + Ciphersuite Ciphersuite::by_id(u16bit suite) { const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites(); diff --git a/src/lib/tls/tls_ciphersuite.h b/src/lib/tls/tls_ciphersuite.h index 199e126b1..6708e3ca6 100644 --- a/src/lib/tls/tls_ciphersuite.h +++ b/src/lib/tls/tls_ciphersuite.h @@ -63,6 +63,11 @@ class BOTAN_DLL Ciphersuite bool ecc_ciphersuite() const; /** + * @return true if this suite uses a CBC cipher + */ + bool cbc_ciphersuite() const; + + /** * @return key exchange algorithm used by this ciphersuite */ std::string kex_algo() const { return m_kex_algo; } diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index 301c77c6b..0e72b9a28 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -1,6 +1,7 @@ /* * TLS Client * (C) 2004-2011,2012,2015,2016 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -23,7 +24,7 @@ class Client_Handshake_State : public Handshake_State public: // using Handshake_State::Handshake_State; - Client_Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State(io, cb) {} + Client_Handshake_State(Handshake_IO* io, Callbacks& cb) : Handshake_State(io, cb) {} const Public_Key& get_server_public_Key() const { @@ -42,6 +43,23 @@ class Client_Handshake_State : public Handshake_State /* * TLS Client Constructor */ +Client::Client(Callbacks& callbacks, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const Server_Information& info, + const Protocol_Version& offer_version, + const std::vector<std::string>& next_protos, + size_t io_buf_sz) : + Channel(callbacks, session_manager, rng, policy, offer_version.is_datagram_protocol(), + io_buf_sz), + m_creds(creds), + m_info(info) + { + init(offer_version, next_protos); + } + Client::Client(output_fn output_fn, data_cb proc_cb, alert_cb alert_cb, @@ -59,10 +77,7 @@ Client::Client(output_fn output_fn, m_creds(creds), m_info(info) { - const std::string srp_identifier = m_creds.srp_identifier("tls-client", m_info.hostname()); - - Handshake_State& state = create_handshake_state(offer_version); - send_client_hello(state, false, offer_version, srp_identifier, next_protos); + init(offer_version, next_protos); } Client::Client(output_fn output_fn, @@ -82,15 +97,22 @@ Client::Client(output_fn output_fn, m_creds(creds), m_info(info) { + init(offer_version, next_protos); + } + +void Client::init(const Protocol_Version& protocol_version, + const std::vector<std::string>& next_protocols) + { const std::string srp_identifier = m_creds.srp_identifier("tls-client", m_info.hostname()); - Handshake_State& state = create_handshake_state(offer_version); - send_client_hello(state, false, offer_version, srp_identifier, next_protos); + Handshake_State& state = create_handshake_state(protocol_version); + send_client_hello(state, false, protocol_version, + srp_identifier, next_protocols); } Handshake_State* Client::new_handshake_state(Handshake_IO* io) { - return new Client_Handshake_State(io, get_handshake_msg_cb()); + return new Client_Handshake_State(io, callbacks()); } std::vector<X509_Certificate> @@ -145,16 +167,15 @@ void Client::send_client_hello(Handshake_State& state_base, if(!state.client_hello()) // not resuming { + Client_Hello::Settings client_settings(version, m_info.hostname(), srp_identifier); state.client_hello(new Client_Hello( state.handshake_io(), state.hash(), - version, policy(), rng(), secure_renegotiation_data_for_client_hello(), - next_protocols, - m_info.hostname(), - srp_identifier)); + client_settings, + next_protocols)); } secure_renegotiation_check(state.client_hello()); @@ -352,7 +373,7 @@ void Client::process_handshake_msg(const Handshake_State* active_state, state.set_expected_next(SERVER_HELLO_DONE); } - state.server_certs(new Certificate(contents)); + state.server_certs(new Certificate(contents, policy())); const std::vector<X509_Certificate>& server_certs = state.server_certs()->cert_chain(); @@ -419,11 +440,9 @@ void Client::process_handshake_msg(const Handshake_State* active_state, "tls-client", m_info.hostname()); - state.client_certs( - new Certificate(state.handshake_io(), - state.hash(), - client_certs) - ); + state.client_certs(new Certificate(state.handshake_io(), + state.hash(), + client_certs)); } state.client_kex( @@ -510,6 +529,7 @@ void Client::process_handshake_msg(const Handshake_State* active_state, state.server_hello()->compression_method(), CLIENT, state.server_hello()->supports_extended_master_secret(), + state.server_hello()->supports_encrypt_then_mac(), get_peer_cert_chain(state), session_ticket, m_info, diff --git a/src/lib/tls/tls_client.h b/src/lib/tls/tls_client.h index 45a741878..09af053af 100644 --- a/src/lib/tls/tls_client.h +++ b/src/lib/tls/tls_client.h @@ -1,6 +1,7 @@ /* * TLS Client * (C) 2004-2011 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -22,9 +23,49 @@ namespace TLS { class BOTAN_DLL Client final : public Channel { public: + /** * Set up a new TLS client session * + * @param callbacks contains a set of callback function references + * required by the TLS client. + * + * @param session_manager manages session state + * + * @param creds manages application/user credentials + * + * @param policy specifies other connection policy information + * + * @param rng a random number generator + * + * @param server_info is identifying information about the TLS server + * + * @param offer_version specifies which version we will offer + * to the TLS server. + * + * @param next_protocols specifies protocols to advertise with ALPN + * + * @param reserved_io_buffer_size This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. + */ + Client(Callbacks& callbacks, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const Server_Information& server_info = Server_Information(), + const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(), + const std::vector<std::string>& next_protocols = {}, + size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE + ); + + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new code. + * + * Set up a new TLS client session + * * @param output_fn is called with data for the outbound socket * * @param app_data_cb is called when new application data is received @@ -52,7 +93,7 @@ class BOTAN_DLL Client final : public Channel * be preallocated for the read and write buffers. Smaller * values just mean reallocations and copies are more likely. */ - + BOTAN_DEPRECATED("Use TLS::Client(TLS::Callbacks ...)") Client(output_fn out, data_cb app_data_cb, alert_cb alert_cb, @@ -64,9 +105,14 @@ class BOTAN_DLL Client final : public Channel const Server_Information& server_info = Server_Information(), const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(), const std::vector<std::string>& next_protocols = {}, - size_t reserved_io_buffer_size = 16*1024 + size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE ); + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new implementations. + */ + BOTAN_DEPRECATED("Use TLS::Client(TLS::Callbacks ...)") Client(output_fn out, data_cb app_data_cb, alert_cb alert_cb, @@ -83,6 +129,9 @@ class BOTAN_DLL Client final : public Channel const std::string& application_protocol() const { return m_application_protocol; } private: + void init(const Protocol_Version& protocol_version, + const std::vector<std::string>& next_protocols); + std::vector<X509_Certificate> get_peer_cert_chain(const Handshake_State& state) const override; diff --git a/src/lib/tls/tls_extensions.cpp b/src/lib/tls/tls_extensions.cpp index 3ea97203c..3dceb505a 100644 --- a/src/lib/tls/tls_extensions.cpp +++ b/src/lib/tls/tls_extensions.cpp @@ -1,6 +1,7 @@ /* * TLS Extensions * (C) 2011,2012,2015,2016 Jack Lloyd +* 2016 Juraj Somorovsky * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -47,6 +48,9 @@ Extension* make_extension(TLS_Data_Reader& reader, case TLSEXT_EXTENDED_MASTER_SECRET: return new Extended_Master_Secret(reader, size); + case TLSEXT_ENCRYPT_THEN_MAC: + return new Encrypt_then_MAC(reader, size); + case TLSEXT_SESSION_TICKET: return new Session_Ticket(reader, size); @@ -519,6 +523,18 @@ std::vector<byte> Extended_Master_Secret::serialize() const return std::vector<byte>(); } +Encrypt_then_MAC::Encrypt_then_MAC(TLS_Data_Reader&, + u16bit extension_size) + { + if(extension_size != 0) + throw Decoding_Error("Invalid encrypt_then_mac extension"); + } + +std::vector<byte> Encrypt_then_MAC::serialize() const + { + return std::vector<byte>(); + } + } } diff --git a/src/lib/tls/tls_extensions.h b/src/lib/tls/tls_extensions.h index a5aac0020..dc69eec36 100644 --- a/src/lib/tls/tls_extensions.h +++ b/src/lib/tls/tls_extensions.h @@ -1,6 +1,8 @@ /* * TLS Extensions * (C) 2011,2012,2016 Jack Lloyd +* 2016 Juraj Somorovsky +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -34,9 +36,9 @@ enum Handshake_Extension_Type { TLSEXT_SRP_IDENTIFIER = 12, TLSEXT_SIGNATURE_ALGORITHMS = 13, TLSEXT_USE_SRTP = 14, - TLSEXT_HEARTBEAT_SUPPORT = 15, TLSEXT_ALPN = 16, + TLSEXT_ENCRYPT_THEN_MAC = 22, TLSEXT_EXTENDED_MASTER_SECRET = 23, TLSEXT_SESSION_TICKET = 35, @@ -341,6 +343,26 @@ class Extended_Master_Secret final : public Extension }; /** +* Encrypt-then-MAC Extension (RFC 7366) +*/ +class Encrypt_then_MAC final : public Extension + { + public: + static Handshake_Extension_Type static_type() + { return TLSEXT_ENCRYPT_THEN_MAC; } + + Handshake_Extension_Type type() const override { return static_type(); } + + std::vector<byte> serialize() const override; + + bool empty() const override { return false; } + + Encrypt_then_MAC() {} + + Encrypt_then_MAC(TLS_Data_Reader& reader, u16bit extension_size); + }; + +/** * Represents a block of extensions in a hello message */ class Extensions diff --git a/src/lib/tls/tls_handshake_msg.h b/src/lib/tls/tls_handshake_msg.h index 7e527abf4..618ae8d76 100644 --- a/src/lib/tls/tls_handshake_msg.h +++ b/src/lib/tls/tls_handshake_msg.h @@ -1,6 +1,7 @@ /* * TLS Handshake Message * (C) 2012 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -16,6 +17,9 @@ namespace Botan { namespace TLS { +class Handshake_IO; +class Handshake_Hash; + /** * TLS Handshake Message Base Class */ diff --git a/src/lib/tls/tls_handshake_state.cpp b/src/lib/tls/tls_handshake_state.cpp index afc32ba87..71cacdabd 100644 --- a/src/lib/tls/tls_handshake_state.cpp +++ b/src/lib/tls/tls_handshake_state.cpp @@ -8,6 +8,7 @@ #include <botan/internal/tls_handshake_state.h> #include <botan/internal/tls_messages.h> #include <botan/internal/tls_record.h> +#include <botan/tls_callbacks.h> namespace Botan { @@ -174,8 +175,8 @@ std::string handshake_mask_to_string(u32bit mask) /* * Initialize the SSL/TLS Handshake State */ -Handshake_State::Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : - m_msg_callback(cb), +Handshake_State::Handshake_State(Handshake_IO* io, Callbacks& cb) : + m_callbacks(cb), m_handshake_io(io), m_version(m_handshake_io->initial_record_version()) { @@ -183,6 +184,11 @@ Handshake_State::Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State::~Handshake_State() {} +void Handshake_State::note_message(const Handshake_Message& msg) + { + m_callbacks.tls_inspect_handshake_msg(msg); + } + void Handshake_State::hello_verify_request(const Hello_Verify_Request& hello_verify) { note_message(hello_verify); diff --git a/src/lib/tls/tls_handshake_state.h b/src/lib/tls/tls_handshake_state.h index 2943a8637..bdec10d14 100644 --- a/src/lib/tls/tls_handshake_state.h +++ b/src/lib/tls/tls_handshake_state.h @@ -24,6 +24,7 @@ class KDF; namespace TLS { +class Callbacks; class Policy; class Hello_Verify_Request; @@ -45,9 +46,7 @@ class Finished; class Handshake_State { public: - typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; - - Handshake_State(Handshake_IO* io, handshake_msg_cb cb); + Handshake_State(Handshake_IO* io, Callbacks& callbacks); virtual ~Handshake_State(); @@ -164,15 +163,10 @@ class Handshake_State const Handshake_Hash& hash() const { return m_handshake_hash; } - void note_message(const Handshake_Message& msg) - { - if(m_msg_callback) - m_msg_callback(msg); - } - + void note_message(const Handshake_Message& msg); private: - handshake_msg_cb m_msg_callback; + Callbacks& m_callbacks; std::unique_ptr<Handshake_IO> m_handshake_io; diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h index 3bee89e13..8ccb2fbff 100644 --- a/src/lib/tls/tls_messages.h +++ b/src/lib/tls/tls_messages.h @@ -1,6 +1,7 @@ /* * TLS Messages * (C) 2004-2011,2015 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -61,6 +62,26 @@ class Hello_Verify_Request final : public Handshake_Message class Client_Hello final : public Handshake_Message { public: + class Settings + { + public: + Settings(const Protocol_Version version, + const std::string& hostname = "", + const std::string& srp_identifier = "") + : m_new_session_version(version), + m_hostname(hostname), + m_srp_identifier(srp_identifier) {}; + + const Protocol_Version protocol_version() const { return m_new_session_version; }; + const std::string& hostname() const { return m_hostname; }; + const std::string& srp_identifier() const { return m_srp_identifier; } + + private: + const Protocol_Version m_new_session_version; + const std::string m_hostname; + const std::string m_srp_identifier; + }; + Handshake_Type type() const override { return CLIENT_HELLO; } Protocol_Version version() const { return m_version; } @@ -141,6 +162,11 @@ class Client_Hello final : public Handshake_Message return m_extensions.has<Extended_Master_Secret>(); } + bool supports_encrypt_then_mac() const + { + return m_extensions.has<Encrypt_then_MAC>(); + } + std::vector<std::string> next_protocols() const { if(auto alpn = m_extensions.get<Application_Layer_Protocol_Notification>()) @@ -162,13 +188,11 @@ class Client_Hello final : public Handshake_Message Client_Hello(Handshake_IO& io, Handshake_Hash& hash, - Protocol_Version version, const Policy& policy, RandomNumberGenerator& rng, const std::vector<byte>& reneg_info, - const std::vector<std::string>& next_protocols, - const std::string& hostname = "", - const std::string& srp_identifier = ""); + const Client_Hello::Settings& client_settings, + const std::vector<std::string>& next_protocols); Client_Hello(Handshake_IO& io, Handshake_Hash& hash, @@ -199,6 +223,35 @@ class Client_Hello final : public Handshake_Message class Server_Hello final : public Handshake_Message { public: + class Settings + { + public: + Settings(const std::vector<byte> new_session_id, + Protocol_Version new_session_version, + u16bit ciphersuite, + byte compression, + bool offer_session_ticket) + : m_new_session_id(new_session_id), + m_new_session_version(new_session_version), + m_ciphersuite(ciphersuite), + m_compression(compression), + m_offer_session_ticket(offer_session_ticket) {}; + + const std::vector<byte>& session_id() const { return m_new_session_id; }; + Protocol_Version protocol_version() const { return m_new_session_version; }; + u16bit ciphersuite() const { return m_ciphersuite; }; + byte compression() const { return m_compression; } + bool offer_session_ticket() const { return m_offer_session_ticket; } + + private: + const std::vector<byte> m_new_session_id; + Protocol_Version m_new_session_version; + u16bit m_ciphersuite; + byte m_compression; + bool m_offer_session_ticket; + }; + + Handshake_Type type() const override { return SERVER_HELLO; } Protocol_Version version() const { return m_version; } @@ -228,6 +281,11 @@ class Server_Hello final : public Handshake_Message return m_extensions.has<Extended_Master_Secret>(); } + bool supports_encrypt_then_mac() const + { + return m_extensions.has<Encrypt_then_MAC>(); + } + bool supports_session_ticket() const { return m_extensions.has<Session_Ticket>(); @@ -262,12 +320,8 @@ class Server_Hello final : public Handshake_Message RandomNumberGenerator& rng, const std::vector<byte>& secure_reneg_info, const Client_Hello& client_hello, - const std::vector<byte>& new_session_id, - Protocol_Version new_session_version, - u16bit ciphersuite, - byte compression, - bool offer_session_ticket, - const std::string& next_protocol); + const Server_Hello::Settings& settings, + const std::string next_protocol); Server_Hello(Handshake_IO& io, Handshake_Hash& hash, @@ -341,7 +395,7 @@ class Certificate final : public Handshake_Message Handshake_Hash& hash, const std::vector<X509_Certificate>& certs); - explicit Certificate(const std::vector<byte>& buf); + explicit Certificate(const std::vector<byte>& buf, const Policy &policy); private: std::vector<byte> serialize() const override; diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index 10b193215..592d4f572 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -1,6 +1,7 @@ /* * Policies for TLS * (C) 2004-2010,2012,2015,2016 Jack Lloyd +* 2016 Christian Mainka * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -119,14 +120,75 @@ std::string Policy::choose_curve(const std::vector<std::string>& curve_names) co std::string Policy::dh_group() const { + // We offer 2048 bit DH because we can return "modp/ietf/2048"; } size_t Policy::minimum_dh_group_size() const { + // Many servers still send 1024 bit return 1024; } +size_t Policy::minimum_ecdsa_group_size() const + { + // Here we are at the mercy of whatever the CA signed, but most certs should be 256 bit by now + return 256; + } + +size_t Policy::minimum_ecdh_group_size() const + { + // P-256 is smallest curve currently supplrted for TLS key exchange (after 1.11.29) + return 256; + } + +size_t Policy::minimum_rsa_bits() const + { + /* Default assumption is all end-entity certificates should + be at least 2048 bits these days. + + If you are connecting to arbitrary servers on the Internet + (ie as a web browser or SMTP client) you'll probably have to reduce this + to 1024 bits, or perhaps even lower. + */ + return 2048; + } + +void Policy::check_peer_key_acceptable(const Public_Key& public_key) const + { + const std::string algo_name = public_key.algo_name(); + + // FIXME this is not really the right way to do this + size_t keylength = public_key.max_input_bits(); + size_t expected_keylength = 0; + + if(algo_name == "RSA") + { + expected_keylength = minimum_rsa_bits(); + keylength += 1; // fixup for use of max_input_bits above + } + else if(algo_name == "DH") + { + expected_keylength = minimum_dh_group_size(); + } + else if(algo_name == "ECDH") + { + expected_keylength = minimum_ecdh_group_size(); + } + else if(algo_name == "ECDSA") + { + expected_keylength = minimum_ecdsa_group_size(); + } + // else some other algo, so leave expected_keylength as zero and the check is a no-op + + if(keylength < expected_keylength) + throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, + "Peer sent " + + std::to_string(keylength) + " bit " + algo_name + " key" + ", policy requires at least " + + std::to_string(expected_keylength)); + } + /* * Return allowed compression algorithms */ @@ -147,10 +209,17 @@ bool Policy::send_fallback_scsv(Protocol_Version version) const bool Policy::acceptable_protocol_version(Protocol_Version version) const { - if(version.is_datagram_protocol()) - return (version >= Protocol_Version::DTLS_V12); - else - return (version >= Protocol_Version::TLS_V10); + // Uses boolean optimization: + // First check the current version (left part), then if it is allowed + // (right part) + // checks are ordered according to their probability + return ( + ( ( version == Protocol_Version::TLS_V12) && allow_tls12() ) || + ( ( version == Protocol_Version::TLS_V10) && allow_tls10() ) || + ( ( version == Protocol_Version::TLS_V11) && allow_tls11() ) || + ( ( version == Protocol_Version::DTLS_V12) && allow_dtls12() ) || + ( ( version == Protocol_Version::DTLS_V10) && allow_dtls10() ) + ); } Protocol_Version Policy::latest_supported_version(bool datagram) const @@ -168,9 +237,15 @@ bool Policy::acceptable_ciphersuite(const Ciphersuite&) const bool Policy::allow_server_initiated_renegotiation() const { return false; } bool Policy::allow_insecure_renegotiation() const { return false; } +bool Policy::allow_tls10() const { return true; } +bool Policy::allow_tls11() const { return true; } +bool Policy::allow_tls12() const { return true; } +bool Policy::allow_dtls10() const { return false; } +bool Policy::allow_dtls12() const { return true; } bool Policy::include_time_in_hello_random() const { return true; } bool Policy::hide_unknown_users() const { return false; } bool Policy::server_uses_own_ciphersuite_preferences() const { return true; } +bool Policy::negotiate_encrypt_then_mac() const { return true; } // 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1 size_t Policy::dtls_initial_timeout() const { return 1*1000; } @@ -339,6 +414,11 @@ void print_bool(std::ostream& o, void Policy::print(std::ostream& o) const { + print_bool(o, "allow_tls10", allow_tls10()); + print_bool(o, "allow_tls11", allow_tls11()); + print_bool(o, "allow_tls12", allow_tls12()); + print_bool(o, "allow_dtls10", allow_dtls10()); + print_bool(o, "allow_dtls12", allow_dtls12()); print_vec(o, "ciphers", allowed_ciphers()); print_vec(o, "macs", allowed_macs()); print_vec(o, "signature_hashes", allowed_signature_hashes()); @@ -351,9 +431,12 @@ void Policy::print(std::ostream& o) const print_bool(o, "allow_server_initiated_renegotiation", allow_server_initiated_renegotiation()); print_bool(o, "hide_unknown_users", hide_unknown_users()); print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences()); + print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac()); o << "session_ticket_lifetime = " << session_ticket_lifetime() << '\n'; o << "dh_group = " << dh_group() << '\n'; o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n'; + o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n'; + o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n'; } std::vector<std::string> Strict_Policy::allowed_ciphers() const @@ -376,13 +459,11 @@ std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const return { "ECDH" }; } -bool Strict_Policy::acceptable_protocol_version(Protocol_Version version) const - { - if(version.is_datagram_protocol()) - return (version >= Protocol_Version::DTLS_V12); - else - return (version >= Protocol_Version::TLS_V12); - } +bool Strict_Policy::allow_tls10() const { return false; } +bool Strict_Policy::allow_tls11() const { return false; } +bool Strict_Policy::allow_tls12() const { return true; } +bool Strict_Policy::allow_dtls10() const { return false; } +bool Strict_Policy::allow_dtls12() const { return true; } } diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index 999ba2887..76e80ddde 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -101,15 +101,79 @@ class BOTAN_DLL Policy * Allow servers to initiate a new handshake */ virtual bool allow_server_initiated_renegotiation() const; + + /** + * Allow TLS v1.0 + */ + virtual bool allow_tls10() const; + + /** + * Allow TLS v1.1 + */ + virtual bool allow_tls11() const; + + /** + * Allow TLS v1.2 + */ + virtual bool allow_tls12() const; + + /** + * Allow DTLS v1.0 + */ + virtual bool allow_dtls10() const; + + /** + * Allow DTLS v1.2 + */ + virtual bool allow_dtls12() const; virtual std::string dh_group() const; /** * Return the minimum DH group size we're willing to use + * Default is currently 1024 (insecure), should be 2048 */ virtual size_t minimum_dh_group_size() const; + + /** + * For ECDSA authenticated ciphersuites, the smallest key size the + * client will accept. + * This policy is currently only enforced on the server by the client. + */ + virtual size_t minimum_ecdsa_group_size() const; + + /** + * Return the minimum ECDH group size we're willing to use + * for key exchange + * + * Default 256, allowing P-256 and larger + * P-256 is the smallest curve we will negotiate + */ + virtual size_t minimum_ecdh_group_size() const; + + /** + * Return the minimum bit size we're willing to accept for RSA + * key exchange or server signatures. + * + * It does not place any requirements on the size of any RSA signature(s) + * which were used to check the server certificate. This is only + * concerned with the server's public key. + * + * Default is 2048 which is smallest RSA key size still secure + * for medium term security. + */ + virtual size_t minimum_rsa_bits() const; /** + * Throw an exception if you don't like the peer's key. + * Default impl checks the key size against minimum_rsa_bits, minimum_ecdsa_group_size, + * or minimum_ecdh_group_size depending on the key's type. + * Override if you'd like to perform some other kind of test on + * (or logging of) the peer's keys. + */ + virtual void check_peer_key_acceptable(const Public_Key& public_key) const; + + /** * If this function returns false, unknown SRP/PSK identifiers * will be rejected with an unknown_psk_identifier alert as soon * as the non-existence is identified. Otherwise, a false @@ -168,6 +232,12 @@ class BOTAN_DLL Policy virtual bool server_uses_own_ciphersuite_preferences() const; /** + * Indicates whether the encrypt-then-MAC extension should be negotiated + * (RFC 7366) + */ + virtual bool negotiate_encrypt_then_mac() const; + + /** * Return allowed ciphersuites, in order of preference */ virtual std::vector<u16bit> ciphersuite_list(Protocol_Version version, @@ -207,9 +277,12 @@ class BOTAN_DLL NSA_Suite_B_128 : public Policy std::vector<std::string> allowed_ecc_curves() const override { return std::vector<std::string>({"secp256r1"}); } - - bool acceptable_protocol_version(Protocol_Version version) const override - { return version == Protocol_Version::TLS_V12; } + + bool allow_tls10() const override { return false; } + bool allow_tls11() const override { return false; } + bool allow_tls12() const override { return true; } + bool allow_dtls10() const override { return false; } + bool allow_dtls12() const override { return false; } }; /** @@ -220,9 +293,12 @@ class BOTAN_DLL Datagram_Policy : public Policy public: std::vector<std::string> allowed_macs() const override { return std::vector<std::string>({"AEAD"}); } - - bool acceptable_protocol_version(Protocol_Version version) const override - { return version == Protocol_Version::DTLS_V12; } + + bool allow_tls10() const override { return false; } + bool allow_tls11() const override { return false; } + bool allow_tls12() const override { return false; } + bool allow_dtls10() const override { return false; } + bool allow_dtls12() const override { return true; } }; /* @@ -243,7 +319,11 @@ class BOTAN_DLL Strict_Policy : public Policy std::vector<std::string> allowed_key_exchange_methods() const override; - bool acceptable_protocol_version(Protocol_Version version) const override; + bool allow_tls10() const override; + bool allow_tls11() const override; + bool allow_tls12() const override; + bool allow_dtls10() const override; + bool allow_dtls12() const override; }; class BOTAN_DLL Text_Policy : public Policy @@ -267,6 +347,21 @@ class BOTAN_DLL Text_Policy : public Policy std::vector<std::string> allowed_ecc_curves() const override { return get_list("ecc_curves", Policy::allowed_ecc_curves()); } + + bool allow_tls10() const override + { return get_bool("allow_tls10", Policy::allow_tls10()); } + + bool allow_tls11() const override + { return get_bool("allow_tls11", Policy::allow_tls11()); } + + bool allow_tls12() const override + { return get_bool("allow_tls12", Policy::allow_tls12()); } + + bool allow_dtls10() const override + { return get_bool("allow_dtls10", Policy::allow_dtls10()); } + + bool allow_dtls12() const override + { return get_bool("allow_dtls12", Policy::allow_dtls12()); } bool allow_insecure_renegotiation() const override { return get_bool("allow_insecure_renegotiation", Policy::allow_insecure_renegotiation()); } @@ -280,12 +375,24 @@ class BOTAN_DLL Text_Policy : public Policy bool server_uses_own_ciphersuite_preferences() const override { return get_bool("server_uses_own_ciphersuite_preferences", Policy::server_uses_own_ciphersuite_preferences()); } + bool negotiate_encrypt_then_mac() const override + { return get_bool("negotiate_encrypt_then_mac", Policy::negotiate_encrypt_then_mac()); } + std::string dh_group() const override { return get_str("dh_group", Policy::dh_group()); } + size_t minimum_ecdh_group_size() const override + { return get_len("minimum_ecdh_group_size", Policy::minimum_ecdh_group_size()); } + + size_t minimum_ecdsa_group_size() const override + { return get_len("minimum_ecdsa_group_size", Policy::minimum_ecdsa_group_size()); } + size_t minimum_dh_group_size() const override { return get_len("minimum_dh_group_size", Policy::minimum_dh_group_size()); } + size_t minimum_rsa_bits() const override + { return get_len("minimum_rsa_bits", Policy::minimum_rsa_bits()); } + bool hide_unknown_users() const override { return get_bool("hide_unknown_users", Policy::hide_unknown_users()); } diff --git a/src/lib/tls/tls_record.cpp b/src/lib/tls/tls_record.cpp index eacf313a8..877b81b41 100644 --- a/src/lib/tls/tls_record.cpp +++ b/src/lib/tls/tls_record.cpp @@ -1,6 +1,8 @@ /* * TLS Record Handling -* (C) 2012,2013,2014,2015 Jack Lloyd +* (C) 2012,2013,2014,2015,2016 Jack Lloyd +* 2016 Juraj Somorovsky +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -23,10 +25,12 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version, Connection_Side side, bool our_side, const Ciphersuite& suite, - const Session_Keys& keys) : + const Session_Keys& keys, + bool uses_encrypt_then_mac) : m_start_time(std::chrono::system_clock::now()), m_nonce_bytes_from_handshake(suite.nonce_bytes_from_handshake()), - m_nonce_bytes_from_record(suite.nonce_bytes_from_record()) + m_nonce_bytes_from_record(suite.nonce_bytes_from_record()), + m_uses_encrypt_then_mac(uses_encrypt_then_mac) { SymmetricKey mac_key, cipher_key; InitializationVector iv; @@ -152,7 +156,7 @@ Connection_Cipher_State::format_ad(u64bit msg_sequence, } void write_record(secure_vector<byte>& output, - byte msg_type, const byte msg[], size_t msg_length, + Record_Message msg, Protocol_Version version, u64bit seq, Connection_Cipher_State* cs, @@ -160,7 +164,7 @@ void write_record(secure_vector<byte>& output, { output.clear(); - output.push_back(msg_type); + output.push_back(msg.get_type()); output.push_back(version.major_version()); output.push_back(version.minor_version()); @@ -172,17 +176,17 @@ void write_record(secure_vector<byte>& output, if(!cs) // initial unencrypted handshake records { - output.push_back(get_byte(0, static_cast<u16bit>(msg_length))); - output.push_back(get_byte(1, static_cast<u16bit>(msg_length))); + output.push_back(get_byte<u16bit>(0, static_cast<u16bit>(msg.get_size()))); + output.push_back(get_byte<u16bit>(1, static_cast<u16bit>(msg.get_size()))); - output.insert(output.end(), msg, msg + msg_length); + output.insert(output.end(), msg.get_data(), msg.get_data() + msg.get_size()); return; } if(AEAD_Mode* aead = cs->aead()) { - const size_t ctext_size = aead->output_length(msg_length); + const size_t ctext_size = aead->output_length(msg.get_size()); const std::vector<byte> nonce = cs->aead_nonce(seq); @@ -193,17 +197,16 @@ void write_record(secure_vector<byte>& output, output.push_back(get_byte(0, static_cast<u16bit>(rec_size))); output.push_back(get_byte(1, static_cast<u16bit>(rec_size))); - aead->set_ad(cs->format_ad(seq, msg_type, version, static_cast<u16bit>(msg_length))); + aead->set_ad(cs->format_ad(seq, msg.get_type(), version, static_cast<u16bit>(msg.get_size()))); if(cs->nonce_bytes_from_record() > 0) { output += std::make_pair(&nonce[cs->nonce_bytes_from_handshake()], cs->nonce_bytes_from_record()); } - BOTAN_ASSERT(aead->start(nonce).empty(), "AEAD doesn't return anything from start"); const size_t offset = output.size(); - output += std::make_pair(msg, msg_length); + output += std::make_pair(msg.get_data(), msg.get_size()); aead->finish(output, offset); BOTAN_ASSERT(output.size() == offset + ctext_size, "Expected size"); @@ -213,77 +216,151 @@ void write_record(secure_vector<byte>& output, return; } - cs->mac()->update(cs->format_ad(seq, msg_type, version, static_cast<u16bit>(msg_length))); - - cs->mac()->update(msg, msg_length); - const size_t block_size = cs->block_size(); const size_t iv_size = cs->iv_size(); const size_t mac_size = cs->mac_size(); - const size_t buf_size = round_up( - iv_size + msg_length + mac_size + (block_size ? 1 : 0), - block_size); + if(!cs->uses_encrypt_then_mac()) + { + cs->mac()->update(cs->format_ad(seq, msg.get_type(), version, static_cast<u16bit>(msg.get_size()))); + cs->mac()->update(msg.get_data(), msg.get_size()); - if(buf_size > MAX_CIPHERTEXT_SIZE) - throw Internal_Error("Output record is larger than allowed by protocol"); + const size_t buf_size = round_up( + iv_size + msg.get_size() + mac_size + (block_size ? 1 : 0), + block_size); - output.push_back(get_byte(0, static_cast<u16bit>(buf_size))); - output.push_back(get_byte(1, static_cast<u16bit>(buf_size))); + if(buf_size > MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Output record is larger than allowed by protocol"); - const size_t header_size = output.size(); + output.push_back(get_byte(0, static_cast<u16bit>(buf_size))); + output.push_back(get_byte(1, static_cast<u16bit>(buf_size))); - if(iv_size) - { - output.resize(output.size() + iv_size); - rng.randomize(&output[output.size() - iv_size], iv_size); - } + const size_t header_size = output.size(); - output.insert(output.end(), msg, msg + msg_length); + if(iv_size) + { + output.resize(output.size() + iv_size); + rng.randomize(&output[output.size() - iv_size], iv_size); + } - output.resize(output.size() + mac_size); - cs->mac()->final(&output[output.size() - mac_size]); + output.insert(output.end(), msg.get_data(), msg.get_data() + msg.get_size()); - if(block_size) - { - const size_t pad_val = - buf_size - (iv_size + msg_length + mac_size + 1); + output.resize(output.size() + mac_size); + cs->mac()->final(&output[output.size() - mac_size]); - for(size_t i = 0; i != pad_val + 1; ++i) - output.push_back(static_cast<byte>(pad_val)); - } + if(block_size) + { + const size_t pad_val = + buf_size - (iv_size + msg.get_size() + mac_size + 1); - if(buf_size > MAX_CIPHERTEXT_SIZE) - throw Internal_Error("Produced ciphertext larger than protocol allows"); + for(size_t i = 0; i != pad_val + 1; ++i) + output.push_back(static_cast<byte>(pad_val)); + } + + if(buf_size > MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Produced ciphertext larger than protocol allows"); - BOTAN_ASSERT_EQUAL(buf_size + header_size, output.size(), + BOTAN_ASSERT_EQUAL(buf_size + header_size, output.size(), "Output buffer is sized properly"); - if(BlockCipher* bc = cs->block_cipher()) - { - secure_vector<byte>& cbc_state = cs->cbc_state(); + if(BlockCipher* bc = cs->block_cipher()) + { + secure_vector<byte>& cbc_state = cs->cbc_state(); - BOTAN_ASSERT(buf_size % block_size == 0, + BOTAN_ASSERT(buf_size % block_size == 0, "Buffer is an even multiple of block size"); - byte* buf = &output[header_size]; + byte* buf = &output[header_size]; + + const size_t blocks = buf_size / block_size; - const size_t blocks = buf_size / block_size; + xor_buf(buf, cbc_state.data(), block_size); + bc->encrypt(buf); - xor_buf(buf, cbc_state.data(), block_size); - bc->encrypt(buf); + for(size_t i = 1; i < blocks; ++i) + { + xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size); + bc->encrypt(&buf[block_size*i]); + } - for(size_t i = 1; i < blocks; ++i) + cbc_state.assign(&buf[block_size*(blocks-1)], + &buf[block_size*blocks]); + } + else { - xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size); - bc->encrypt(&buf[block_size*i]); + throw Internal_Error("NULL cipher not supported"); } + } + else + { + const size_t enc_size = round_up( + iv_size + msg.get_size() + (block_size ? 1 : 0), + block_size); + + const size_t buf_size = enc_size + mac_size; + + if(buf_size > MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Output record is larger than allowed by protocol"); + + output.push_back(get_byte<u16bit>(0, buf_size)); + output.push_back(get_byte<u16bit>(1, buf_size)); + + const size_t header_size = output.size(); - cbc_state.assign(&buf[block_size*(blocks-1)], + if(iv_size) + { + output.resize(output.size() + iv_size); + rng.randomize(&output[output.size() - iv_size], iv_size); + } + + output.insert(output.end(), msg.get_data(), msg.get_data() + msg.get_size()); + + if(block_size) + { + const size_t pad_val = + enc_size - (iv_size + msg.get_size() + 1); + + for(size_t i = 0; i != pad_val + 1; ++i) + output.push_back(pad_val); + } + + if(BlockCipher* bc = cs->block_cipher()) + { + secure_vector<byte>& cbc_state = cs->cbc_state(); + + BOTAN_ASSERT( enc_size % block_size == 0, + "Buffer is an even multiple of block size"); + + byte* buf = &output[header_size]; + + const size_t blocks = enc_size / block_size; + + xor_buf(buf, cbc_state.data(), block_size); + bc->encrypt(buf); + + for(size_t i = 1; i < blocks; ++i) + { + xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size); + bc->encrypt(&buf[block_size*i]); + } + + cbc_state.assign(&buf[block_size*(blocks-1)], &buf[block_size*blocks]); + + cs->mac()->update(cs->format_ad(seq, msg.get_type(), version, enc_size)); + cs->mac()->update(buf, enc_size); + + output.resize(output.size() + mac_size); + cs->mac()->final(&output[output.size() - mac_size]); + + BOTAN_ASSERT_EQUAL(buf_size + header_size, output.size(), + "Output buffer is sized properly"); + } + else + { + throw Internal_Error("NULL cipher not supported"); + } } - else - throw Internal_Error("NULL cipher not supported"); } namespace { @@ -409,117 +486,147 @@ void decrypt_record(secure_vector<byte>& output, const size_t mac_size = cs.mac_size(); const size_t iv_size = cs.iv_size(); - // This early exit does not leak info because all the values are public - if((record_len < mac_size + iv_size) || (record_len % cs.block_size() != 0)) - throw Decoding_Error("Record sent with invalid length"); + if(!cs.uses_encrypt_then_mac()) + { + // This early exit does not leak info because all the values are public + if((record_len < mac_size + iv_size) || (record_len % cs.block_size() != 0)) + throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); - CT::poison(record_contents, record_len); + CT::poison(record_contents, record_len); - cbc_decrypt_record(record_contents, record_len, cs, *bc); + cbc_decrypt_record(record_contents, record_len, cs, *bc); - // 0 if padding was invalid, otherwise 1 + padding_bytes - u16bit pad_size = tls_padding_check(record_contents, record_len); + // 0 if padding was invalid, otherwise 1 + padding_bytes + u16bit pad_size = tls_padding_check(record_contents, record_len); - // This mask is zero if there is not enough room in the packet - const u16bit size_ok_mask = CT::is_lte<u16bit>(static_cast<u16bit>(mac_size + pad_size + iv_size), static_cast<u16bit>(record_len)); - pad_size &= size_ok_mask; + // This mask is zero if there is not enough room in the packet to get + // a valid MAC. We have to accept empty packets, since otherwise we + // are not compatible with the BEAST countermeasure (thus record_len+1). + const u16bit size_ok_mask = CT::is_lte<u16bit>(static_cast<u16bit>(mac_size + pad_size + iv_size), static_cast<u16bit>(record_len + 1)); + pad_size &= size_ok_mask; - CT::unpoison(record_contents, record_len); + CT::unpoison(record_contents, record_len); - /* - This is unpoisoned sooner than it should. The pad_size leaks to plaintext_length and - then to the timing channel in the MAC computation described in the Lucky 13 paper. - */ - CT::unpoison(pad_size); + /* + This is unpoisoned sooner than it should. The pad_size leaks to plaintext_length and + then to the timing channel in the MAC computation described in the Lucky 13 paper. + */ + CT::unpoison(pad_size); - const byte* plaintext_block = &record_contents[iv_size]; - const u16bit plaintext_length = static_cast<u16bit>(record_len - mac_size - iv_size - pad_size); + const byte* plaintext_block = &record_contents[iv_size]; + const u16bit plaintext_length = static_cast<u16bit>(record_len - mac_size - iv_size - pad_size); - cs.mac()->update(cs.format_ad(record_sequence, record_type, record_version, plaintext_length)); - cs.mac()->update(plaintext_block, plaintext_length); + cs.mac()->update(cs.format_ad(record_sequence, record_type, record_version, plaintext_length)); + cs.mac()->update(plaintext_block, plaintext_length); - std::vector<byte> mac_buf(mac_size); - cs.mac()->final(mac_buf.data()); + std::vector<byte> mac_buf(mac_size); + cs.mac()->final(mac_buf.data()); - const size_t mac_offset = record_len - (mac_size + pad_size); + const size_t mac_offset = record_len - (mac_size + pad_size); - const bool mac_ok = same_mem(&record_contents[mac_offset], mac_buf.data(), mac_size); + const bool mac_ok = same_mem(&record_contents[mac_offset], mac_buf.data(), mac_size); - const u16bit ok_mask = size_ok_mask & CT::expand_mask<u16bit>(mac_ok) & CT::expand_mask<u16bit>(pad_size); + const u16bit ok_mask = size_ok_mask & CT::expand_mask<u16bit>(mac_ok) & CT::expand_mask<u16bit>(pad_size); - CT::unpoison(ok_mask); + CT::unpoison(ok_mask); - if(ok_mask) - { - output.assign(plaintext_block, plaintext_block + plaintext_length); + if(ok_mask) + { + output.assign(plaintext_block, plaintext_block + plaintext_length); + } + else + { + throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); + } } else { - throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); + const size_t enc_size = record_len - mac_size; + // This early exit does not leak info because all the values are public + if((record_len < mac_size + iv_size) || ( enc_size % cs.block_size() != 0)) + throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); + + cs.mac()->update(cs.format_ad(record_sequence, record_type, record_version, enc_size)); + cs.mac()->update(record_contents, enc_size); + + std::vector<byte> mac_buf(mac_size); + cs.mac()->final(mac_buf.data()); + + const size_t mac_offset = enc_size; + + const bool mac_ok = same_mem(&record_contents[mac_offset], mac_buf.data(), mac_size); + + if(!mac_ok) + { + throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); + } + + cbc_decrypt_record(record_contents, enc_size, cs, *bc); + + // 0 if padding was invalid, otherwise 1 + padding_bytes + u16bit pad_size = tls_padding_check(record_contents, enc_size); + + const byte* plaintext_block = &record_contents[iv_size]; + const u16bit plaintext_length = enc_size - iv_size - pad_size; + + output.assign(plaintext_block, plaintext_block + plaintext_length); } } } size_t read_tls_record(secure_vector<byte>& readbuf, - const byte input[], - size_t input_sz, - size_t& consumed, - secure_vector<byte>& record, - u64bit* record_sequence, - Protocol_Version* record_version, - Record_Type* record_type, + Record_Raw_Input& raw_input, + Record& rec, Connection_Sequence_Numbers* sequence_numbers, get_cipherstate_fn get_cipherstate) { - consumed = 0; - if(readbuf.size() < TLS_HEADER_SIZE) // header incomplete? { if(size_t needed = fill_buffer_to(readbuf, - input, input_sz, consumed, + raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(), TLS_HEADER_SIZE)) return needed; BOTAN_ASSERT_EQUAL(readbuf.size(), TLS_HEADER_SIZE, "Have an entire header"); } - *record_version = Protocol_Version(readbuf[1], readbuf[2]); + *rec.get_protocol_version() = Protocol_Version(readbuf[1], readbuf[2]); - BOTAN_ASSERT(!record_version->is_datagram_protocol(), "Expected TLS"); + BOTAN_ASSERT(!rec.get_protocol_version()->is_datagram_protocol(), "Expected TLS"); - const size_t record_len = make_u16bit(readbuf[TLS_HEADER_SIZE-2], + const size_t record_size = make_u16bit(readbuf[TLS_HEADER_SIZE-2], readbuf[TLS_HEADER_SIZE-1]); - if(record_len > MAX_CIPHERTEXT_SIZE) + if(record_size > MAX_CIPHERTEXT_SIZE) throw TLS_Exception(Alert::RECORD_OVERFLOW, "Received a record that exceeds maximum size"); - if(record_len == 0) + if(record_size == 0) throw TLS_Exception(Alert::DECODE_ERROR, "Received a completely empty record"); if(size_t needed = fill_buffer_to(readbuf, - input, input_sz, consumed, - TLS_HEADER_SIZE + record_len)) + raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(), + TLS_HEADER_SIZE + record_size)) return needed; - BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_len, + BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_size, readbuf.size(), "Have the full record"); - *record_type = static_cast<Record_Type>(readbuf[0]); + *rec.get_type() = static_cast<Record_Type>(readbuf[0]); u16bit epoch = 0; if(sequence_numbers) { - *record_sequence = sequence_numbers->next_read_sequence(); + *rec.get_sequence() = sequence_numbers->next_read_sequence(); epoch = sequence_numbers->current_read_epoch(); } else { // server initial handshake case - *record_sequence = 0; + *rec.get_sequence() = 0; epoch = 0; } @@ -527,7 +634,7 @@ size_t read_tls_record(secure_vector<byte>& readbuf, if(epoch == 0) // Unencrypted initial handshake { - record.assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_len); + rec.get_data().assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_size); readbuf.clear(); return 0; // got a full record } @@ -537,37 +644,30 @@ size_t read_tls_record(secure_vector<byte>& readbuf, BOTAN_ASSERT(cs, "Have cipherstate for this epoch"); - decrypt_record(record, + decrypt_record(rec.get_data(), record_contents, - record_len, - *record_sequence, - *record_version, - *record_type, + record_size, + *rec.get_sequence(), + *rec.get_protocol_version(), + *rec.get_type(), *cs); if(sequence_numbers) - sequence_numbers->read_accept(*record_sequence); + sequence_numbers->read_accept(*rec.get_sequence()); readbuf.clear(); return 0; } size_t read_dtls_record(secure_vector<byte>& readbuf, - const byte input[], - size_t input_sz, - size_t& consumed, - secure_vector<byte>& record, - u64bit* record_sequence, - Protocol_Version* record_version, - Record_Type* record_type, + Record_Raw_Input& raw_input, + Record& rec, Connection_Sequence_Numbers* sequence_numbers, get_cipherstate_fn get_cipherstate) { - consumed = 0; - if(readbuf.size() < DTLS_HEADER_SIZE) // header incomplete? { - if(fill_buffer_to(readbuf, input, input_sz, consumed, DTLS_HEADER_SIZE)) + if(fill_buffer_to(readbuf, raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(), DTLS_HEADER_SIZE)) { readbuf.clear(); return 0; @@ -576,38 +676,35 @@ size_t read_dtls_record(secure_vector<byte>& readbuf, BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE, "Have an entire header"); } - *record_version = Protocol_Version(readbuf[1], readbuf[2]); + *rec.get_protocol_version() = Protocol_Version(readbuf[1], readbuf[2]); - BOTAN_ASSERT(record_version->is_datagram_protocol(), "Expected DTLS"); + BOTAN_ASSERT(rec.get_protocol_version()->is_datagram_protocol(), "Expected DTLS"); - const size_t record_len = make_u16bit(readbuf[DTLS_HEADER_SIZE-2], - readbuf[DTLS_HEADER_SIZE-1]); + const size_t record_size = make_u16bit(readbuf[DTLS_HEADER_SIZE-2], + readbuf[DTLS_HEADER_SIZE-1]); - // Invalid packet: - if(record_len == 0 || record_len > MAX_CIPHERTEXT_SIZE) - { - readbuf.clear(); - return 0; - } + if(record_size > MAX_CIPHERTEXT_SIZE) + throw TLS_Exception(Alert::RECORD_OVERFLOW, + "Got message that exceeds maximum size"); - if(fill_buffer_to(readbuf, input, input_sz, consumed, DTLS_HEADER_SIZE + record_len)) + if(fill_buffer_to(readbuf, raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(), DTLS_HEADER_SIZE + record_size)) { // Truncated packet? readbuf.clear(); return 0; } - BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_len, readbuf.size(), + BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_size, readbuf.size(), "Have the full record"); - *record_type = static_cast<Record_Type>(readbuf[0]); + *rec.get_type() = static_cast<Record_Type>(readbuf[0]); u16bit epoch = 0; - *record_sequence = load_be<u64bit>(&readbuf[3], 0); - epoch = (*record_sequence >> 48); + *rec.get_sequence() = load_be<u64bit>(&readbuf[3], 0); + epoch = (*rec.get_sequence() >> 48); - if(sequence_numbers && sequence_numbers->already_seen(*record_sequence)) + if(sequence_numbers && sequence_numbers->already_seen(*rec.get_sequence())) { readbuf.clear(); return 0; @@ -617,7 +714,7 @@ size_t read_dtls_record(secure_vector<byte>& readbuf, if(epoch == 0) // Unencrypted initial handshake { - record.assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_len); + rec.get_data().assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_size); readbuf.clear(); return 0; // got a full record } @@ -629,23 +726,23 @@ size_t read_dtls_record(secure_vector<byte>& readbuf, BOTAN_ASSERT(cs, "Have cipherstate for this epoch"); - decrypt_record(record, + decrypt_record(rec.get_data(), record_contents, - record_len, - *record_sequence, - *record_version, - *record_type, + record_size, + *rec.get_sequence(), + *rec.get_protocol_version(), + *rec.get_type(), *cs); } catch(std::exception) { readbuf.clear(); - *record_type = NO_RECORD; + *rec.get_type() = NO_RECORD; return 0; } if(sequence_numbers) - sequence_numbers->read_accept(*record_sequence); + sequence_numbers->read_accept(*rec.get_sequence()); readbuf.clear(); return 0; @@ -654,24 +751,16 @@ size_t read_dtls_record(secure_vector<byte>& readbuf, } size_t read_record(secure_vector<byte>& readbuf, - const byte input[], - size_t input_sz, - bool is_datagram, - size_t& consumed, - secure_vector<byte>& record, - u64bit* record_sequence, - Protocol_Version* record_version, - Record_Type* record_type, + Record_Raw_Input& raw_input, + Record& rec, Connection_Sequence_Numbers* sequence_numbers, get_cipherstate_fn get_cipherstate) { - if(is_datagram) - return read_dtls_record(readbuf, input, input_sz, consumed, - record, record_sequence, record_version, record_type, + if(raw_input.is_datagram()) + return read_dtls_record(readbuf, raw_input, rec, sequence_numbers, get_cipherstate); else - return read_tls_record(readbuf, input, input_sz, consumed, - record, record_sequence, record_version, record_type, + return read_tls_record(readbuf, raw_input, rec, sequence_numbers, get_cipherstate); } diff --git a/src/lib/tls/tls_record.h b/src/lib/tls/tls_record.h index e3b0b9b58..4420a9c66 100644 --- a/src/lib/tls/tls_record.h +++ b/src/lib/tls/tls_record.h @@ -1,6 +1,7 @@ /* * TLS Record Handling * (C) 2004-2012 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -38,7 +39,8 @@ class Connection_Cipher_State Connection_Side which_side, bool is_our_side, const Ciphersuite& suite, - const Session_Keys& keys); + const Session_Keys& keys, + bool uses_encrypt_then_mac); AEAD_Mode* aead() { return m_aead.get(); } @@ -66,6 +68,8 @@ class Connection_Cipher_State size_t nonce_bytes_from_handshake() const { return m_nonce_bytes_from_handshake; } + bool uses_encrypt_then_mac() const { return m_uses_encrypt_then_mac; } + bool cbc_without_explicit_iv() const { return (m_block_size > 0) && (m_iv_size == 0); } @@ -88,8 +92,84 @@ class Connection_Cipher_State size_t m_nonce_bytes_from_handshake; size_t m_nonce_bytes_from_record; size_t m_iv_size = 0; + + bool m_uses_encrypt_then_mac; }; +class Record + { + public: + Record(secure_vector<byte>& data, + u64bit* sequence, + Protocol_Version* protocol_version, + Record_Type* type) + : m_data(data), m_sequence(sequence), m_protocol_version(protocol_version), + m_type(type), m_size(data.size()) {}; + + secure_vector<byte>& get_data() { return m_data; } + + Protocol_Version* get_protocol_version() { return m_protocol_version; } + + u64bit* get_sequence() { return m_sequence; } + + Record_Type* get_type() { return m_type; } + + size_t& get_size() { return m_size; } + + private: + secure_vector<byte>& m_data; + u64bit* m_sequence; + Protocol_Version* m_protocol_version; + Record_Type* m_type; + size_t m_size; + }; + +class Record_Message + { + public: + Record_Message(const byte* data, size_t size) + : m_type(0), m_sequence(0), m_data(data), m_size(size) {}; + Record_Message(byte type, u64bit sequence, const byte* data, size_t size) + : m_type(type), m_sequence(sequence), m_data(data), + m_size(size) {}; + + byte& get_type() { return m_type; }; + u64bit& get_sequence() { return m_sequence; }; + const byte* get_data() { return m_data; }; + size_t& get_size() { return m_size; }; + + private: + byte m_type; + u64bit m_sequence; + const byte* m_data; + size_t m_size; +}; + +class Record_Raw_Input + { + public: + Record_Raw_Input(const byte* data, size_t size, size_t& consumed, + bool is_datagram) + : m_data(data), m_size(size), m_consumed(consumed), + m_is_datagram(is_datagram) {}; + + const byte*& get_data() { return m_data; }; + + size_t& get_size() { return m_size; }; + + size_t& get_consumed() { return m_consumed; }; + void set_consumed(size_t consumed) { m_consumed = consumed; } + + bool is_datagram() { return m_is_datagram; }; + + private: + const byte* m_data; + size_t m_size; + size_t& m_consumed; + bool m_is_datagram; + }; + + /** * Create a TLS record * @param write_buffer the output record is placed here @@ -103,7 +183,7 @@ class Connection_Cipher_State * @return number of bytes written to write_buffer */ void write_record(secure_vector<byte>& write_buffer, - byte msg_type, const byte msg[], size_t msg_length, + Record_Message rec_msg, Protocol_Version version, u64bit msg_sequence, Connection_Cipher_State* cipherstate, @@ -117,14 +197,8 @@ typedef std::function<std::shared_ptr<Connection_Cipher_State> (u16bit)> get_cip * @return zero if full message, else number of bytes still needed */ size_t read_record(secure_vector<byte>& read_buffer, - const byte input[], - size_t input_length, - bool is_datagram, - size_t& input_consumed, - secure_vector<byte>& record, - u64bit* record_sequence, - Protocol_Version* record_version, - Record_Type* record_type, + Record_Raw_Input& raw_input, + Record& rec, Connection_Sequence_Numbers* sequence_numbers, get_cipherstate_fn get_cipherstate); diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 41b14ae08..40aa18d27 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -1,6 +1,7 @@ /* * TLS Server * (C) 2004-2011,2012,2016 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -9,30 +10,41 @@ #include <botan/internal/tls_handshake_state.h> #include <botan/internal/tls_messages.h> #include <botan/internal/stl_util.h> +#include <botan/tls_magic.h> namespace Botan { namespace TLS { -namespace { - class Server_Handshake_State : public Handshake_State { public: - // using Handshake_State::Handshake_State; + Server_Handshake_State(Handshake_IO* io, Callbacks& cb) + : Handshake_State(io, cb) {} + + Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key; } + void set_server_rsa_kex_key(Private_Key* key) + { m_server_rsa_kex_key = key; } + + bool allow_session_resumption() const + { return m_allow_session_resumption; } + void set_allow_session_resumption(bool allow_session_resumption) + { m_allow_session_resumption = allow_session_resumption; } - Server_Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State(io, cb) {} + private: // Used by the server only, in case of RSA key exchange. Not owned - Private_Key* server_rsa_kex_key = nullptr; + Private_Key* m_server_rsa_kex_key = nullptr; /* * Used by the server to know if resumption should be allowed on * a server-initiated renegotiation */ - bool allow_session_resumption = true; + bool m_allow_session_resumption = true; }; +namespace { + bool check_for_resume(Session& session_info, Session_Manager& session_manager, Credentials_Manager& credentials, @@ -118,6 +130,19 @@ bool check_for_resume(Session& session_info, } } + // Checking encrypt_then_mac on resume (RFC 7366 section 3.1) + if( !client_hello->supports_encrypt_then_mac() && session_info.supports_encrypt_then_mac()) + { + + /* + Client previously negotiated session with Encrypt-then-MAC, + but has now attempted to resume without the extension: abort + */ + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, + "Client resumed Encrypt-then-MAC session without sending extension"); + + } + return true; } @@ -225,6 +250,19 @@ get_server_certs(const std::string& hostname, /* * TLS Server Constructor */ +Server::Server(Callbacks& callbacks, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + bool is_datagram, + size_t io_buf_sz) : + Channel(callbacks, session_manager, rng, policy, + is_datagram, io_buf_sz), + m_creds(creds) + { + } + Server::Server(output_fn output, data_cb data_cb, alert_cb alert_cb, @@ -236,13 +274,15 @@ Server::Server(output_fn output, next_protocol_fn next_proto, bool is_datagram, size_t io_buf_sz) : - Channel(output, data_cb, alert_cb, handshake_cb, Channel::handshake_msg_cb(), - session_manager, rng, policy, is_datagram, io_buf_sz), + Channel(output, data_cb, alert_cb, handshake_cb, + Channel::handshake_msg_cb(), session_manager, + rng, policy, is_datagram, io_buf_sz), m_creds(creds), m_choose_next_protocol(next_proto) { } + Server::Server(output_fn output, data_cb data_cb, alert_cb alert_cb, @@ -263,8 +303,7 @@ Server::Server(output_fn output, Handshake_State* Server::new_handshake_state(Handshake_IO* io) { - std::unique_ptr<Handshake_State> state( - new Server_Handshake_State(io, get_handshake_msg_cb())); + std::unique_ptr<Handshake_State> state(new Server_Handshake_State(io, callbacks())); state->set_expected_next(CLIENT_HELLO); return state.release(); @@ -284,441 +323,516 @@ Server::get_peer_cert_chain(const Handshake_State& state) const void Server::initiate_handshake(Handshake_State& state, bool force_full_renegotiation) { - dynamic_cast<Server_Handshake_State&>(state).allow_session_resumption = - !force_full_renegotiation; + dynamic_cast<Server_Handshake_State&>(state). + set_allow_session_resumption(!force_full_renegotiation); Hello_Request hello_req(state.handshake_io()); } /* -* Process a handshake message +* Process a CLIENT HELLO Message */ -void Server::process_handshake_msg(const Handshake_State* active_state, - Handshake_State& state_base, - Handshake_Type type, - const std::vector<byte>& contents) - { - Server_Handshake_State& state = dynamic_cast<Server_Handshake_State&>(state_base); - - state.confirm_transition_to(type); - - /* - * The change cipher spec message isn't technically a handshake - * message so it's not included in the hash. The finished and - * certificate verify messages are verified based on the current - * state of the hash *before* this message so we delay adding them - * to the hash computation until we've processed them below. - */ - if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY) +void Server::process_client_hello_msg(const Handshake_State* active_state, + Server_Handshake_State& pending_state, + const std::vector<byte>& contents) +{ + const bool initial_handshake = !active_state; + + if(!policy().allow_insecure_renegotiation() && + !(initial_handshake || secure_renegotiation_supported())) { - state.hash().update(state.handshake_io().format(contents, type)); + send_warning_alert(Alert::NO_RENEGOTIATION); + return; } - if(type == CLIENT_HELLO) + pending_state.client_hello(new Client_Hello(contents)); + const Protocol_Version client_version = pending_state.client_hello()->version(); + + Protocol_Version negotiated_version; + + const Protocol_Version latest_supported = + policy().latest_supported_version(client_version.is_datagram_protocol()); + + if((initial_handshake && client_version.known_version()) || + (!initial_handshake && client_version == active_state->version())) { - const bool initial_handshake = !active_state; + /* + Common cases: new client hello with some known version, or a + renegotiation using the same version as previously + negotiated. + */ - if(!policy().allow_insecure_renegotiation() && - !(initial_handshake || secure_renegotiation_supported())) + negotiated_version = client_version; + } + else if(!initial_handshake && (client_version != active_state->version())) + { + /* + * If this is a renegotiation, and the client has offered a + * later version than what it initially negotiated, negotiate + * the old version. This matches OpenSSL's behavior. If the + * client is offering a version earlier than what it initially + * negotiated, reject as a probable attack. + */ + if(active_state->version() > client_version) { - send_warning_alert(Alert::NO_RENEGOTIATION); - return; + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Client negotiated " + + active_state->version().to_string() + + " then renegotiated with " + + client_version.to_string()); } + else + negotiated_version = active_state->version(); + } + else + { + /* + New negotiation using a version we don't know. Offer them the + best we currently know and support + */ + negotiated_version = latest_supported; + } - state.client_hello(new Client_Hello(contents)); + if(!policy().acceptable_protocol_version(negotiated_version)) + { + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Client version " + negotiated_version.to_string() + + " is unacceptable by policy"); + } - const Protocol_Version client_version = state.client_hello()->version(); + if(pending_state.client_hello()->sent_fallback_scsv()) + { + if(latest_supported > client_version) + throw TLS_Exception(Alert::INAPPROPRIATE_FALLBACK, + "Client signalled fallback SCSV, possible attack"); + } - Protocol_Version negotiated_version; + secure_renegotiation_check(pending_state.client_hello()); - const Protocol_Version latest_supported = - policy().latest_supported_version(client_version.is_datagram_protocol()); + pending_state.set_version(negotiated_version); - if((initial_handshake && client_version.known_version()) || - (!initial_handshake && client_version == active_state->version())) - { - /* - Common cases: new client hello with some known version, or a - renegotiation using the same version as previously - negotiated. - */ + Session session_info; + const bool resuming = + pending_state.allow_session_resumption() && + check_for_resume(session_info, + session_manager(), + m_creds, + pending_state.client_hello(), + std::chrono::seconds(policy().session_ticket_lifetime())); - negotiated_version = client_version; - } - else if(!initial_handshake && (client_version != active_state->version())) - { - /* - * If this is a renegotiation, and the client has offered a - * later version than what it initially negotiated, negotiate - * the old version. This matches OpenSSL's behavior. If the - * client is offering a version earlier than what it initially - * negotiated, reject as a probable attack. - */ - if(active_state->version() > client_version) - { - throw TLS_Exception(Alert::PROTOCOL_VERSION, - "Client negotiated " + - active_state->version().to_string() + - " then renegotiated with " + - client_version.to_string()); - } - else - negotiated_version = active_state->version(); - } - else - { - /* - New negotiation using a version we don't know. Offer them the - best we currently know and support - */ - negotiated_version = latest_supported; - } + bool have_session_ticket_key = false; - if(!policy().acceptable_protocol_version(negotiated_version)) - { - throw TLS_Exception(Alert::PROTOCOL_VERSION, - "Client version " + negotiated_version.to_string() + - " is unacceptable by policy"); - } + try + { + have_session_ticket_key = + m_creds.psk("tls-server", "session-ticket", "").length() > 0; + } + catch(...) {} + + m_next_protocol = ""; + if(pending_state.client_hello()->supports_alpn()) + { + m_next_protocol = callbacks().tls_server_choose_app_protocol(pending_state.client_hello()->next_protocols()); - if(state.client_hello()->sent_fallback_scsv()) + // if the callback return was empty, fall back to the (deprecated) std::function + if(m_next_protocol.empty() && m_choose_next_protocol) { - if(latest_supported > client_version) - throw TLS_Exception(Alert::INAPPROPRIATE_FALLBACK, - "Client signalled fallback SCSV, possible attack"); + m_next_protocol = m_choose_next_protocol(pending_state.client_hello()->next_protocols()); } + } - secure_renegotiation_check(state.client_hello()); + if(resuming) + { + this->session_resume(pending_state, have_session_ticket_key, session_info); + } + else // new session + { + this->session_create(pending_state, have_session_ticket_key); + } +} - state.set_version(negotiated_version); +void Server::process_certificate_msg(Server_Handshake_State& pending_state, + const std::vector<byte>& contents) +{ + pending_state.client_certs(new Certificate(contents, policy())); + pending_state.set_expected_next(CLIENT_KEX); +} - Session session_info; - const bool resuming = - state.allow_session_resumption && - check_for_resume(session_info, - session_manager(), - m_creds, - state.client_hello(), - std::chrono::seconds(policy().session_ticket_lifetime())); +void Server::process_client_key_exchange_msg(Server_Handshake_State& pending_state, + const std::vector<byte>& contents) +{ + if(pending_state.received_handshake_msg(CERTIFICATE) && !pending_state.client_certs()->empty()) + pending_state.set_expected_next(CERTIFICATE_VERIFY); + else + pending_state.set_expected_next(HANDSHAKE_CCS); - bool have_session_ticket_key = false; + pending_state.client_kex( + new Client_Key_Exchange(contents, pending_state, + pending_state.server_rsa_kex_key(), + m_creds, policy(), rng()) + ); - try - { - have_session_ticket_key = - m_creds.psk("tls-server", "session-ticket", "").length() > 0; - } - catch(...) {} + pending_state.compute_session_keys(); +} - m_next_protocol = ""; - if(m_choose_next_protocol && state.client_hello()->supports_alpn()) - m_next_protocol = m_choose_next_protocol(state.client_hello()->next_protocols()); +void Server::process_change_cipher_spec_msg(Server_Handshake_State& pending_state) +{ + pending_state.set_expected_next(FINISHED); + change_cipher_spec_reader(SERVER); +} - if(resuming) - { - // Only offer a resuming client a new ticket if they didn't send one this time, - // ie, resumed via server-side resumption. TODO: also send one if expiring soon? - - const bool offer_new_session_ticket = - (state.client_hello()->supports_session_ticket() && - state.client_hello()->session_ticket().empty() && - have_session_ticket_key); - - state.server_hello(new Server_Hello( - state.handshake_io(), - state.hash(), - policy(), - rng(), - secure_renegotiation_data_for_server_hello(), - *state.client_hello(), - session_info, - offer_new_session_ticket, - m_next_protocol - )); - - secure_renegotiation_check(state.server_hello()); - - state.compute_session_keys(session_info.master_secret()); - - if(!save_session(session_info)) - { - session_manager().remove_entry(session_info.session_id()); - - if(state.server_hello()->supports_session_ticket()) // send an empty ticket - { - state.new_session_ticket( - new New_Session_Ticket(state.handshake_io(), - state.hash()) - ); - } - } +void Server::process_certificate_verify_msg(Server_Handshake_State& pending_state, + Handshake_Type type, + const std::vector<byte>& contents) +{ + pending_state.client_verify ( new Certificate_Verify ( contents, pending_state.version() ) ); + + const std::vector<X509_Certificate>& client_certs = + pending_state.client_certs()->cert_chain(); + + const bool sig_valid = + pending_state.client_verify()->verify ( client_certs[0], pending_state, policy() ); + + pending_state.hash().update ( pending_state.handshake_io().format ( contents, type ) ); + + /* + * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for + * "A handshake cryptographic operation failed, including being + * unable to correctly verify a signature, ..." + */ + if ( !sig_valid ) + throw TLS_Exception ( Alert::DECRYPT_ERROR, "Client cert verify failed" ); + + try + { + m_creds.verify_certificate_chain ( "tls-server", "", client_certs ); + } + catch ( std::exception& e ) + { + throw TLS_Exception ( Alert::BAD_CERTIFICATE, e.what() ); + } + + pending_state.set_expected_next ( HANDSHAKE_CCS ); +} - if(state.server_hello()->supports_session_ticket() && !state.new_session_ticket()) - { - try - { - const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); - - state.new_session_ticket( - new New_Session_Ticket(state.handshake_io(), - state.hash(), - session_info.encrypt(ticket_key, rng()), - policy().session_ticket_lifetime()) - ); - } - catch(...) {} - - if(!state.new_session_ticket()) - { - state.new_session_ticket( - new New_Session_Ticket(state.handshake_io(), state.hash()) - ); - } - } +void Server::process_finished_msg(Server_Handshake_State& pending_state, + Handshake_Type type, + const std::vector<byte>& contents) +{ + pending_state.set_expected_next ( HANDSHAKE_NONE ); - state.handshake_io().send(Change_Cipher_Spec()); + pending_state.client_finished ( new Finished ( contents ) ); - change_cipher_spec_writer(SERVER); + if ( !pending_state.client_finished()->verify ( pending_state, CLIENT ) ) + throw TLS_Exception ( Alert::DECRYPT_ERROR, + "Finished message didn't verify" ); - state.server_finished(new Finished(state.handshake_io(), state, SERVER)); - state.set_expected_next(HANDSHAKE_CCS); - } - else // new session - { - std::map<std::string, std::vector<X509_Certificate> > cert_chains; + if ( !pending_state.server_finished() ) + { + // already sent finished if resuming, so this is a new session - const std::string sni_hostname = state.client_hello()->sni_hostname(); + pending_state.hash().update ( pending_state.handshake_io().format ( contents, type ) ); - cert_chains = get_server_certs(sni_hostname, m_creds); + Session session_info( + pending_state.server_hello()->session_id(), + pending_state.session_keys().master_secret(), + pending_state.server_hello()->version(), + pending_state.server_hello()->ciphersuite(), + pending_state.server_hello()->compression_method(), + SERVER, + pending_state.server_hello()->supports_extended_master_secret(), + pending_state.server_hello()->supports_encrypt_then_mac(), + get_peer_cert_chain ( pending_state ), + std::vector<byte>(), + Server_Information(pending_state.client_hello()->sni_hostname()), + pending_state.srp_identifier(), + pending_state.server_hello()->srtp_profile() + ); - if(sni_hostname != "" && cert_chains.empty()) + if ( save_session ( session_info ) ) { - cert_chains = get_server_certs("", m_creds); - - /* - * Only send the unrecognized_name alert if we couldn't - * find any certs for the requested name but did find at - * least one cert to use in general. That avoids sending an - * unrecognized_name when a server is configured for purely - * anonymous operation. - */ - if(!cert_chains.empty()) - send_alert(Alert(Alert::UNRECOGNIZED_NAME)); + if ( pending_state.server_hello()->supports_session_ticket() ) + { + try + { + const SymmetricKey ticket_key = m_creds.psk ( "tls-server", "session-ticket", "" ); + + pending_state.new_session_ticket ( + new New_Session_Ticket ( pending_state.handshake_io(), + pending_state.hash(), + session_info.encrypt ( ticket_key, rng() ), + policy().session_ticket_lifetime() ) + ); + } + catch ( ... ) {} + } + else + session_manager().save ( session_info ); } - state.server_hello(new Server_Hello( - state.handshake_io(), - state.hash(), - policy(), - rng(), - secure_renegotiation_data_for_server_hello(), - *state.client_hello(), - make_hello_random(rng(), policy()), // new session ID - state.version(), - choose_ciphersuite(policy(), state.version(), m_creds, cert_chains, state.client_hello()), - choose_compression(policy(), state.client_hello()->compression_methods()), - have_session_ticket_key, - m_next_protocol) + if ( !pending_state.new_session_ticket() && + pending_state.server_hello()->supports_session_ticket() ) + { + pending_state.new_session_ticket ( + new New_Session_Ticket ( pending_state.handshake_io(), pending_state.hash() ) ); + } - secure_renegotiation_check(state.server_hello()); + pending_state.handshake_io().send ( Change_Cipher_Spec() ); - const std::string sig_algo = state.ciphersuite().sig_algo(); - const std::string kex_algo = state.ciphersuite().kex_algo(); + change_cipher_spec_writer ( SERVER ); - if(sig_algo != "") - { - BOTAN_ASSERT(!cert_chains[sig_algo].empty(), - "Attempting to send empty certificate chain"); + pending_state.server_finished ( new Finished ( pending_state.handshake_io(), pending_state, SERVER ) ); + } - state.server_certs(new Certificate(state.handshake_io(), - state.hash(), - cert_chains[sig_algo])); - } + activate_session(); - Private_Key* private_key = nullptr; +} - if(kex_algo == "RSA" || sig_algo != "") - { - private_key = m_creds.private_key_for( - state.server_certs()->cert_chain()[0], - "tls-server", - sni_hostname); +/* +* Process a handshake message +*/ +void Server::process_handshake_msg(const Handshake_State* active_state, + Handshake_State& state_base, + Handshake_Type type, + const std::vector<byte>& contents) + { + Server_Handshake_State& state = dynamic_cast<Server_Handshake_State&>(state_base); + state.confirm_transition_to(type); - if(!private_key) - throw Internal_Error("No private key located for associated server cert"); - } + /* + * The change cipher spec message isn't technically a handshake + * message so it's not included in the hash. The finished and + * certificate verify messages are verified based on the current + * state of the hash *before* this message so we delay adding them + * to the hash computation until we've processed them below. + */ + if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY) + { + state.hash().update(state.handshake_io().format(contents, type)); + } - if(kex_algo == "RSA") - { - state.server_rsa_kex_key = private_key; - } - else - { - state.server_kex(new Server_Key_Exchange(state.handshake_io(), - state, policy(), - m_creds, rng(), private_key)); - } + switch(type) + { + case CLIENT_HELLO: + this->process_client_hello_msg(active_state, state, contents); + break; + + case CERTIFICATE: + this->process_certificate_msg(state, contents); + break; + + case CLIENT_KEX: + this->process_client_key_exchange_msg(state, contents); + break; + + case CERTIFICATE_VERIFY: + this->process_certificate_verify_msg(state, type, contents); + break; + + case HANDSHAKE_CCS: + this->process_change_cipher_spec_msg(state); + break; - auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname); + case FINISHED: + this->process_finished_msg(state, type, contents); + break; - std::vector<X509_DN> client_auth_CAs; + default: + throw Unexpected_Message("Unknown handshake message received"); + break; + } + } - for(auto store : trusted_CAs) +void Server::session_resume(Server_Handshake_State& pending_state, + bool have_session_ticket_key, + Session& session_info) + { + // Only offer a resuming client a new ticket if they didn't send one this time, + // ie, resumed via server-side resumption. TODO: also send one if expiring soon? + + const bool offer_new_session_ticket = + (pending_state.client_hello()->supports_session_ticket() && + pending_state.client_hello()->session_ticket().empty() && + have_session_ticket_key); + + pending_state.server_hello(new Server_Hello( + pending_state.handshake_io(), + pending_state.hash(), + policy(), + rng(), + secure_renegotiation_data_for_server_hello(), + *pending_state.client_hello(), + session_info, + offer_new_session_ticket, + m_next_protocol + )); + + secure_renegotiation_check(pending_state.server_hello()); + + pending_state.compute_session_keys(session_info.master_secret()); + + if(!save_session(session_info)) + { + session_manager().remove_entry(session_info.session_id()); + + if(pending_state.server_hello()->supports_session_ticket()) // send an empty ticket { - auto subjects = store->all_subjects(); - client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); + pending_state.new_session_ticket( + new New_Session_Ticket(pending_state.handshake_io(), + pending_state.hash()) + ); } + } - if(!client_auth_CAs.empty() && state.ciphersuite().sig_algo() != "") + if(pending_state.server_hello()->supports_session_ticket() && !pending_state.new_session_ticket()) + { + try { - state.cert_req( - new Certificate_Req(state.handshake_io(), state.hash(), - policy(), client_auth_CAs, state.version())); + const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); - state.set_expected_next(CERTIFICATE); + pending_state.new_session_ticket( + new New_Session_Ticket(pending_state.handshake_io(), + pending_state.hash(), + session_info.encrypt(ticket_key, rng()), + policy().session_ticket_lifetime()) + ); } + catch(...) {} - /* - * If the client doesn't have a cert they want to use they are - * allowed to send either an empty cert message or proceed - * directly to the client key exchange, so allow either case. - */ - state.set_expected_next(CLIENT_KEX); - - state.server_hello_done(new Server_Hello_Done(state.handshake_io(), state.hash())); + if(!pending_state.new_session_ticket()) + { + pending_state.new_session_ticket( + new New_Session_Ticket(pending_state.handshake_io(), pending_state.hash()) + ); + } } - } - else if(type == CERTIFICATE) - { - state.client_certs(new Certificate(contents)); - state.set_expected_next(CLIENT_KEX); - } - else if(type == CLIENT_KEX) - { - if(state.received_handshake_msg(CERTIFICATE) && !state.client_certs()->empty()) - state.set_expected_next(CERTIFICATE_VERIFY); - else - state.set_expected_next(HANDSHAKE_CCS); + pending_state.handshake_io().send(Change_Cipher_Spec()); - state.client_kex( - new Client_Key_Exchange(contents, state, - state.server_rsa_kex_key, - m_creds, policy(), rng()) - ); + change_cipher_spec_writer(SERVER); - state.compute_session_keys(); - } - else if(type == CERTIFICATE_VERIFY) - { - state.client_verify(new Certificate_Verify(contents, state.version())); + pending_state.server_finished(new Finished(pending_state.handshake_io(), pending_state, SERVER)); + pending_state.set_expected_next(HANDSHAKE_CCS); + } - const std::vector<X509_Certificate>& client_certs = - state.client_certs()->cert_chain(); +void Server::session_create(Server_Handshake_State& pending_state, + bool have_session_ticket_key) + { + std::map<std::string, std::vector<X509_Certificate> > cert_chains; - const bool sig_valid = - state.client_verify()->verify(client_certs[0], state, policy()); + const std::string sni_hostname = pending_state.client_hello()->sni_hostname(); - state.hash().update(state.handshake_io().format(contents, type)); + cert_chains = get_server_certs(sni_hostname, m_creds); + + if(sni_hostname != "" && cert_chains.empty()) + { + cert_chains = get_server_certs("", m_creds); /* - * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for - * "A handshake cryptographic operation failed, including being - * unable to correctly verify a signature, ..." + * Only send the unrecognized_name alert if we couldn't + * find any certs for the requested name but did find at + * least one cert to use in general. That avoids sending an + * unrecognized_name when a server is configured for purely + * anonymous operation. */ - if(!sig_valid) - throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed"); - - try - { - m_creds.verify_certificate_chain("tls-server", "", client_certs); - } - catch(std::exception& e) - { - throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); - } - - state.set_expected_next(HANDSHAKE_CCS); - } - else if(type == HANDSHAKE_CCS) - { - state.set_expected_next(FINISHED); - change_cipher_spec_reader(SERVER); + if(!cert_chains.empty()) + send_alert(Alert(Alert::UNRECOGNIZED_NAME)); } - else if(type == FINISHED) + + Server_Hello::Settings srv_settings( + make_hello_random(rng(), policy()), // new session ID + pending_state.version(), + choose_ciphersuite(policy(), + pending_state.version(), + m_creds, + cert_chains, + pending_state.client_hello()), + choose_compression(policy(), + pending_state.client_hello()->compression_methods()), + have_session_ticket_key); + + pending_state.server_hello(new Server_Hello( + pending_state.handshake_io(), + pending_state.hash(), + policy(), + rng(), + secure_renegotiation_data_for_server_hello(), + *pending_state.client_hello(), + srv_settings, + m_next_protocol) + ); + + secure_renegotiation_check(pending_state.server_hello()); + + const std::string sig_algo = pending_state.ciphersuite().sig_algo(); + const std::string kex_algo = pending_state.ciphersuite().kex_algo(); + + if(sig_algo != "") { - state.set_expected_next(HANDSHAKE_NONE); + BOTAN_ASSERT(!cert_chains[sig_algo].empty(), + "Attempting to send empty certificate chain"); - state.client_finished(new Finished(contents)); + pending_state.server_certs(new Certificate(pending_state.handshake_io(), + pending_state.hash(), + cert_chains[sig_algo])); + } - if(!state.client_finished()->verify(state, CLIENT)) - throw TLS_Exception(Alert::DECRYPT_ERROR, - "Finished message didn't verify"); + Private_Key* private_key = nullptr; - if(!state.server_finished()) - { - // already sent finished if resuming, so this is a new session + if(kex_algo == "RSA" || sig_algo != "") + { + private_key = m_creds.private_key_for( + pending_state.server_certs()->cert_chain()[0], + "tls-server", + sni_hostname); - state.hash().update(state.handshake_io().format(contents, type)); + if(!private_key) + throw Internal_Error("No private key located for associated server cert"); + } - Session session_info( - state.server_hello()->session_id(), - state.session_keys().master_secret(), - state.server_hello()->version(), - state.server_hello()->ciphersuite(), - state.server_hello()->compression_method(), - SERVER, - state.server_hello()->supports_extended_master_secret(), - get_peer_cert_chain(state), - std::vector<byte>(), - Server_Information(state.client_hello()->sni_hostname()), - state.srp_identifier(), - state.server_hello()->srtp_profile() - ); + if(kex_algo == "RSA") + { + pending_state.set_server_rsa_kex_key(private_key); + } + else + { + pending_state.server_kex(new Server_Key_Exchange(pending_state.handshake_io(), + pending_state, policy(), + m_creds, rng(), private_key)); + } - if(save_session(session_info)) - { - if(state.server_hello()->supports_session_ticket()) - { - try - { - const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); - - state.new_session_ticket( - new New_Session_Ticket(state.handshake_io(), - state.hash(), - session_info.encrypt(ticket_key, rng()), - policy().session_ticket_lifetime()) - ); - } - catch(...) {} - } - else - session_manager().save(session_info); - } + auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname); - if(!state.new_session_ticket() && - state.server_hello()->supports_session_ticket()) - { - state.new_session_ticket( - new New_Session_Ticket(state.handshake_io(), state.hash()) - ); - } + std::vector<X509_DN> client_auth_CAs; - state.handshake_io().send(Change_Cipher_Spec()); + for(auto store : trusted_CAs) + { + auto subjects = store->all_subjects(); + client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); + } - change_cipher_spec_writer(SERVER); + if(!client_auth_CAs.empty() && pending_state.ciphersuite().sig_algo() != "") + { + pending_state.cert_req( + new Certificate_Req(pending_state.handshake_io(), + pending_state.hash(), + policy(), + client_auth_CAs, + pending_state.version())); + + pending_state.set_expected_next(CERTIFICATE); + } - state.server_finished(new Finished(state.handshake_io(), state, SERVER)); - } + /* + * If the client doesn't have a cert they want to use they are + * allowed to send either an empty cert message or proceed + * directly to the client key exchange, so allow either case. + */ + pending_state.set_expected_next(CLIENT_KEX); - activate_session(); - } - else - throw Unexpected_Message("Unknown handshake message received"); + pending_state.server_hello_done(new Server_Hello_Done(pending_state.handshake_io(), pending_state.hash())); } - } } diff --git a/src/lib/tls/tls_server.h b/src/lib/tls/tls_server.h index 5ea2a1318..051eda445 100644 --- a/src/lib/tls/tls_server.h +++ b/src/lib/tls/tls_server.h @@ -1,6 +1,7 @@ /* * TLS Server * (C) 2004-2011 Jack Lloyd +* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -12,10 +13,13 @@ #include <botan/credentials_manager.h> #include <vector> + namespace Botan { namespace TLS { +class Server_Handshake_State; + /** * TLS Server */ @@ -26,7 +30,39 @@ class BOTAN_DLL Server final : public Channel /** * Server initialization + * + * @param callbacks contains a set of callback function references + * required by the TLS client. + * + * @param session_manager manages session state + * + * @param creds manages application/user credentials + * + * @param policy specifies other connection policy information + * + * @param rng a random number generator + * + * @param is_datagram set to true if this server should expect DTLS + * connections. Otherwise TLS connections are expected. + * + * @param reserved_io_buffer_size This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. */ + Server(Callbacks& callbacks, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + bool is_datagram = false, + size_t reserved_io_buffer_size = TLS::Server::IO_BUF_DEFAULT_SIZE + ); + + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new implementations. + */ + BOTAN_DEPRECATED("Use TLS::Server(TLS::Callbacks ...)") Server(output_fn output, data_cb data_cb, alert_cb alert_cb, @@ -37,9 +73,14 @@ class BOTAN_DLL Server final : public Channel RandomNumberGenerator& rng, next_protocol_fn next_proto = next_protocol_fn(), bool is_datagram = false, - size_t reserved_io_buffer_size = 16*1024 + size_t reserved_io_buffer_size = TLS::Server::IO_BUF_DEFAULT_SIZE ); + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new implementations. + */ + BOTAN_DEPRECATED("Use TLS::Server(TLS::Callbacks ...)") Server(output_fn output, data_cb data_cb, alert_cb alert_cb, @@ -73,12 +114,40 @@ class BOTAN_DLL Server final : public Channel Handshake_Type type, const std::vector<byte>& contents) override; + void process_client_hello_msg(const Handshake_State* active_state, + Server_Handshake_State& pending_state, + const std::vector<byte>& contents); + + void process_certificate_msg(Server_Handshake_State& pending_state, + const std::vector<byte>& contents); + + void process_client_key_exchange_msg(Server_Handshake_State& pending_state, + const std::vector<byte>& contents); + + void process_change_cipher_spec_msg(Server_Handshake_State& pending_state); + + void process_certificate_verify_msg(Server_Handshake_State& pending_state, + Handshake_Type type, + const std::vector<byte>& contents); + + void process_finished_msg(Server_Handshake_State& pending_state, + Handshake_Type type, + const std::vector<byte>& contents); + + void session_resume(Server_Handshake_State& pending_state, + bool have_session_ticket_key, + Session& session_info); + + void session_create(Server_Handshake_State& pending_state, + bool have_session_ticket_key); + Handshake_State* new_handshake_state(Handshake_IO* io) override; Credentials_Manager& m_creds; + std::string m_next_protocol; + // Set by deprecated constructor, Server calls both this fn and Callbacks version next_protocol_fn m_choose_next_protocol; - std::string m_next_protocol; }; } diff --git a/src/lib/tls/tls_session.cpp b/src/lib/tls/tls_session.cpp index 18c9b357c..d6b52846f 100644 --- a/src/lib/tls/tls_session.cpp +++ b/src/lib/tls/tls_session.cpp @@ -24,6 +24,7 @@ Session::Session(const std::vector<byte>& session_identifier, byte compression_method, Connection_Side side, bool extended_master_secret, + bool encrypt_then_mac, const std::vector<X509_Certificate>& certs, const std::vector<byte>& ticket, const Server_Information& server_info, @@ -39,6 +40,7 @@ Session::Session(const std::vector<byte>& session_identifier, m_connection_side(side), m_srtp_profile(srtp_profile), m_extended_master_secret(extended_master_secret), + m_encrypt_then_mac(encrypt_then_mac), m_peer_certs(certs), m_server_info(server_info), m_srp_identifier(srp_identifier) @@ -83,6 +85,7 @@ Session::Session(const byte ber[], size_t ber_len) .decode_integer_type(side_code) .decode_integer_type(fragment_size) .decode(m_extended_master_secret) + .decode(m_encrypt_then_mac) .decode(m_master_secret, OCTET_STRING) .decode(peer_cert_bits, OCTET_STRING) .decode(server_hostname) @@ -142,6 +145,7 @@ secure_vector<byte> Session::DER_encode() const .encode(static_cast<size_t>(m_connection_side)) .encode(static_cast<size_t>(/*old fragment size*/0)) .encode(m_extended_master_secret) + .encode(m_encrypt_then_mac) .encode(m_master_secret, OCTET_STRING) .encode(peer_cert_bits, OCTET_STRING) .encode(ASN1_String(m_server_info.hostname(), UTF8_STRING)) diff --git a/src/lib/tls/tls_session.h b/src/lib/tls/tls_session.h index 8ca646cf2..643b79ac6 100644 --- a/src/lib/tls/tls_session.h +++ b/src/lib/tls/tls_session.h @@ -38,7 +38,8 @@ class BOTAN_DLL Session m_compression_method(0), m_connection_side(static_cast<Connection_Side>(0)), m_srtp_profile(0), - m_extended_master_secret(false) + m_extended_master_secret(false), + m_encrypt_then_mac(false) {} /** @@ -51,6 +52,7 @@ class BOTAN_DLL Session byte compression_method, Connection_Side side, bool supports_extended_master_secret, + bool supports_encrypt_then_mac, const std::vector<X509_Certificate>& peer_certs, const std::vector<byte>& session_ticket, const Server_Information& server_info, @@ -157,6 +159,8 @@ class BOTAN_DLL Session bool supports_extended_master_secret() const { return m_extended_master_secret; } + bool supports_encrypt_then_mac() const { return m_encrypt_then_mac; } + /** * Return the certificate chain of the peer (possibly empty) */ @@ -180,7 +184,7 @@ class BOTAN_DLL Session const Server_Information& server_info() const { return m_server_info; } private: - enum { TLS_SESSION_PARAM_STRUCT_VERSION = 20160103 }; + enum { TLS_SESSION_PARAM_STRUCT_VERSION = 20160812}; std::chrono::system_clock::time_point m_start_time; @@ -194,6 +198,7 @@ class BOTAN_DLL Session Connection_Side m_connection_side; u16bit m_srtp_profile; bool m_extended_master_secret; + bool m_encrypt_then_mac; std::vector<X509_Certificate> m_peer_certs; Server_Information m_server_info; // optional diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp index eab509984..2f17da952 100644 --- a/src/lib/utils/os_utils.cpp +++ b/src/lib/utils/os_utils.cpp @@ -40,49 +40,92 @@ uint32_t get_process_id() uint64_t get_processor_timestamp() { - uint64_t rtc = 0; - #if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) LARGE_INTEGER tv; ::QueryPerformanceCounter(&tv); - rtc = tv.QuadPart; -#endif - -#if defined(BOTAN_USE_GCC_INLINE_ASM) + return tv.QuadPart; -#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) if(CPUID::has_rdtsc()) // not available on all x86 CPUs { uint32_t rtc_low = 0, rtc_high = 0; asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low)); - rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; + return (static_cast<u64bit>(rtc_high) << 32) | rtc_low; } -#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) uint32_t rtc_low = 0, rtc_high = 0; asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low)); - rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; + return (static_cast<u64bit>(rtc_high) << 32) | rtc_low; -#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA) +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_ALPHA) + uint64_t rtc = 0; asm volatile("rpcc %0" : "=r" (rtc)); + return rtc; -#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD) // OpenBSD does not trap access to the %tick register +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD) + uint64_t rtc = 0; asm volatile("rd %%tick, %0" : "=r" (rtc)); + return rtc; -#elif defined(BOTAN_TARGET_ARCH_IS_IA64) +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_IA64) + uint64_t rtc = 0; asm volatile("mov %0=ar.itc" : "=r" (rtc)); + return rtc; -#elif defined(BOTAN_TARGET_ARCH_IS_S390X) +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_S390X) + uint64_t rtc = 0; asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc"); + return rtc; -#elif defined(BOTAN_TARGET_ARCH_IS_HPPA) +#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_HPPA) + uint64_t rtc = 0; asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only? + return rtc; #endif + /* + If we got here either we either don't have an asm instruction + above, or (for x86) RDTSC is not available at runtime. Try some + clock_gettimes and return the first one that works, or otherwise + fall back to std::chrono. + */ + +#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) + + // The ordering here is somewhat arbitrary... + const clockid_t clock_types[] = { +#if defined(CLOCK_MONOTONIC_HR) + CLOCK_MONOTONIC_HR, +#endif +#if defined(CLOCK_MONOTONIC_RAW) + CLOCK_MONOTONIC_RAW, #endif +#if defined(CLOCK_MONOTONIC) + CLOCK_MONOTONIC, +#endif +#if defined(CLOCK_PROCESS_CPUTIME_ID) + CLOCK_PROCESS_CPUTIME_ID, +#endif +#if defined(CLOCK_THREAD_CPUTIME_ID) + CLOCK_THREAD_CPUTIME_ID, +#endif + }; - return rtc; + for(clockid_t clock : clock_types) + { + struct timespec ts; + if(::clock_gettime(clock, &ts) == 0) + { + return (static_cast<uint64_t>(ts.tv_sec) * 1000000000) + static_cast<uint64_t>(ts.tv_nsec); + } + } +#endif + + // Plain C++11 fallback + auto now = std::chrono::high_resolution_clock::now().time_since_epoch(); + return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count(); } uint64_t get_system_timestamp_ns() diff --git a/src/lib/utils/simd/simd_32.h b/src/lib/utils/simd/simd_32.h index 0b4ca8f03..c29c55c7a 100644 --- a/src/lib/utils/simd/simd_32.h +++ b/src/lib/utils/simd/simd_32.h @@ -100,7 +100,9 @@ class SIMD_4x32 __vector unsigned char perm = vec_lvsl(0, in_32); - perm = vec_xor(perm, vec_splat_u8(3)); +#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + perm = vec_xor(perm, vec_splat_u8(3)); // bswap vector +#endif R0 = vec_perm(R0, R1, perm); @@ -124,6 +126,10 @@ class SIMD_4x32 __vector unsigned char perm = vec_lvsl(0, in_32); +#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) + perm = vec_xor(perm, vec_splat_u8(3)); // bswap vector +#endif + R0 = vec_perm(R0, R1, perm); return SIMD_4x32(R0); @@ -142,7 +148,9 @@ class SIMD_4x32 #elif defined(BOTAN_SIMD_USE_ALTIVEC) __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr)); +#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) perm = vec_xor(perm, vec_splat_u8(3)); // bswap vector +#endif union { __vector unsigned int V; |