diff options
Diffstat (limited to 'src/tests')
-rw-r--r-- | src/tests/data/pubkey/ecgdsa.vec | 98 | ||||
-rw-r--r-- | src/tests/test_ecgdsa.cpp | 78 | ||||
-rw-r--r-- | src/tests/test_pubkey.cpp | 2 | ||||
-rw-r--r-- | src/tests/test_pubkey.h | 8 | ||||
-rw-r--r-- | src/tests/test_rng.h | 92 |
5 files changed, 275 insertions, 3 deletions
diff --git a/src/tests/data/pubkey/ecgdsa.vec b/src/tests/data/pubkey/ecgdsa.vec new file mode 100644 index 000000000..5f3a7b55c --- /dev/null +++ b/src/tests/data/pubkey/ecgdsa.vec @@ -0,0 +1,98 @@ + +# The Digital Signature Scheme ECGDSA, Erwin Hess, Marcus Schafheutle, and Pascale Serf, Siemens AG, October 24, 2006 +# https://www.teletrust.de/fileadmin/files/oid/ecgdsa_final.pdf + +# 2.4.1 ECGDSA over GF(p) with RIPEMD-160 + +Group = brainpool192r1 +X = 0x80F2425E89B4F585F27F3536ED834D68E3E492DE08FE84B9 + +Msg = 4578616d706c65206f662045434744534120776974682074686520686173682066756e6374696f6e20524950454d442d313630 +Hash = RIPEMD-160 +Nonce = 22C17C2A367DD85AB8A365ED06F19C43F9ED18349A9BC044 +Signature = 2D017BE7F117FF994ED6FC63CA5B4C7A0430E9FA095DAFC4C02B5CC5C51D5411060BF0245049F824839F671D78A1BBF1 + +Group = brainpool256r1 +X = 0x47B3A27862DEF03749ACF0D600E69F9B851D01EDAEFA531F4D168E787307F4D8 +Nonce = 908E3099776261A4558FF7A9FA6DFFE0CA6BB3F9CB35C2E4E1DC73FD5E8C08A3 +Signature = 62CCD1D291E62F6A4FFBD966C66C85AABA990BB6AB0C087DBD54A456CCC84E4C9119719B08EEA0D6BC56E4D1D37369BCF3768445EF65CAE4A37BF6D43BD01646 + +Group = brainpool320r1 +X = 0x486835945A3A284FFC52629AD48D8F37F4B2E9939C52BC72362A996140192AEF7D2AAFF0C73A51C5 +Nonce = C70BC00A77AD78725D36CEEC27D6F956FB546EEF6DC90E3531452BD87ECE8A4A7AD730ADC299D81B +Signature = 3C925969FAB22F7AE7B8CC5D50CB0867DFDB2CF4FADA3D490DF75D72F7563186419494C98F9C82A606AB5250B31A8E935619489461733200E4FD5C1275C0AB37E7E411495BAAE14541DF6DE666B8CA56 + + +# 2.4.2 ECGDSA over GF(p) with SHA-1 + +Group = brainpool192r1 +X = 0x80F2425E89B4F585F27F3536ED834D68E3E492DE08FE84B9 + +Msg = 4578616d706c65206f662045434744534120776974682074686520686173682066756e6374696f6e205348412d31 +Hash = SHA-1 +Nonce = 22C17C2A367DD85AB8A365ED06F19C43F9ED18349A9BC044 +Signature = 2D017BE7F117FF994ED6FC63CA5B4C7A0430E9FA095DAFC418FD604E5F00F55B3585C0528C319A2B05B8F2DDEE9CF1A6 + + +# 2.4.3 ECGDSA over GF(p) with SHA-224 + +Group = brainpool256r1 +X = 0x47B3A27862DEF03749ACF0D600E69F9B851D01EDAEFA531F4D168E787307F4D8 + +Msg = 4578616d706c65206f662045434744534120776974682074686520686173682066756e6374696f6e205348412d323234 +Hash = SHA-224 +Nonce = 908E3099776261A4558FF7A9FA6DFFE0CA6BB3F9CB35C2E4E1DC73FD5E8C08A3 +Signature = 62CCD1D291E62F6A4FFBD966C66C85AABA990BB6AB0C087DBD54A456CCC84E4C6F029D921CBD25526EDCCF1C45E3CBF7B7A5D8D4E005F0C41C49B052DECB04EA + +Group = brainpool320r1 +X = 0x486835945A3A284FFC52629AD48D8F37F4B2E9939C52BC72362A996140192AEF7D2AAFF0C73A51C5 +Nonce = C70BC00A77AD78725D36CEEC27D6F956FB546EEF6DC90E3531452BD87ECE8A4A7AD730ADC299D81B +Signature = 3C925969FAB22F7AE7B8CC5D50CB0867DFDB2CF4FADA3D490DF75D72F7563186419494C98F9C82A66EA191CA0D468AC3E95687689338357C7D0BACB3F1D87E0DEC05F635B7ADB84275AA008660F812CF + + +# 2.4.4 ECGDSA over GF(p) with SHA-256 + +Group = brainpool256r1 +X = 0x47B3A27862DEF03749ACF0D600E69F9B851D01EDAEFA531F4D168E787307F4D8 + +Msg = 4578616d706c65206f662045434744534120776974682074686520686173682066756e6374696f6e205348412d323536 +Hash = SHA-256 +Nonce = 908E3099776261A4558FF7A9FA6DFFE0CA6BB3F9CB35C2E4E1DC73FD5E8C08A3 +Signature = 62CCD1D291E62F6A4FFBD966C66C85AABA990BB6AB0C087DBD54A456CCC84E4C1DD53F822F8BE769F601FC5826B10AB603898374B8501B53D6976BA1AAE17A45 + +Group = brainpool320r1 +X = 0x486835945A3A284FFC52629AD48D8F37F4B2E9939C52BC72362A996140192AEF7D2AAFF0C73A51C5 +Nonce = C70BC00A77AD78725D36CEEC27D6F956FB546EEF6DC90E3531452BD87ECE8A4A7AD730ADC299D81B +Signature = 3C925969FAB22F7AE7B8CC5D50CB0867DFDB2CF4FADA3D490DF75D72F7563186419494C98F9C82A624370797A9D11717BBBB2B762E08ECD07DD7E033F544E47CBF3C6D16FD90B51DCC2E4DD8E6ECD8CD + +Group = brainpool384r1 +X = 0x60BABEC49D0A4E36328879591B1A598F339F7971E8A1AD35788486EB081C838B5612F6DEBD6B38A0BA720BD857AB2354 +Nonce = 43E01A2A95EE7695955334410F32C73BD1394BBF2CD7B8A18656B447A951342C82F52E833FFB3B74612679437C13ACB5 +Signature = 2A2676EFF87A75EE9ECBA1FDD7A5437697294166063C8CD90F8AEBA399BF450FFA244C0EE69B3E1FFCA395CD27AFFC6156F6A18906455867EB51EBE46049A11D79AEED1500D1D1A43D876E422C9234ED6F59AB7D336BCE12CED3D7ECBC09CAE3 + + +# 2.4.5 ECGDSA over GF(p) with SHA-384 + +Group = brainpool384r1 +X = 0x60BABEC49D0A4E36328879591B1A598F339F7971E8A1AD35788486EB081C838B5612F6DEBD6B38A0BA720BD857AB2354 + +Msg = 4578616d706c65206f662045434744534120776974682074686520686173682066756e6374696f6e205348412d333834 +Hash = SHA-384 +Nonce = 43E01A2A95EE7695955334410F32C73BD1394BBF2CD7B8A18656B447A951342C82F52E833FFB3B74612679437C13ACB5 +Signature = 2A2676EFF87A75EE9ECBA1FDD7A5437697294166063C8CD90F8AEBA399BF450FFA244C0EE69B3E1FFCA395CD27AFFC61733F4E370AF3F9A2DF9499F9953E091D7BD28CA8E80FB3B4AAEB1FF324CCDF6E4D7F6B4576071321D8B34C20CAF0CD01 + +Group = brainpool512r1 +X = 0x92006A988AF96D9157AADCF8627169627CE2ECC4C58ECE5C1A0A864211AB764C04236FA0160857A78E71CCAE4D79D52E5A69A4578AF506581F598FA9B4F7DA68 +Nonce = 6942B01D5901BEC1506BB8749618E22EC0FCD7F35159D51ED53BA77A78752128A58232AD8E0E021AFDE1477FF4C74FDFFE88AE2D15D89B56F6D73C0377631D2B +Signature = 0104918B2B32B1A549BD43C30092953B4164CA01A1A97B5B0756EA063AC16B41B88A1BAB4538CD7D8466180B3E3F5C8646AC4A45F564E9B68FEE72ED00C7AC483D233E9FD9EB152E889F4F7CF325B4640894E5EA44C5144354305CD4BF70D2348257C2DBE06C554492CE9FDD6861A56577B53E5EE80E606231A4CF068FA1EC21 + + +# 2.4.5 ECGDSA over GF(p) with SHA-512 + +Group = brainpool512r1 +X = 0x92006A988AF96D9157AADCF8627169627CE2ECC4C58ECE5C1A0A864211AB764C04236FA0160857A78E71CCAE4D79D52E5A69A4578AF506581F598FA9B4F7DA68 + +Msg = 4578616d706c65206f662045434744534120776974682074686520686173682066756e6374696f6e205348412d353132 +Hash = SHA-512 +Nonce = 6942B01D5901BEC1506BB8749618E22EC0FCD7F35159D51ED53BA77A78752128A58232AD8E0E021AFDE1477FF4C74FDFFE88AE2D15D89B56F6D73C0377631D2B +Signature = 0104918B2B32B1A549BD43C30092953B4164CA01A1A97B5B0756EA063AC16B41B88A1BAB4538CD7D8466180B3E3F5C8646AC4A45F564E9B68FEE72ED00C7AC4817A011F8DD7B56652B27AA6D6E7BDF3C7C23B5FA32910FBAA107E6270E1CA8A7A263F6618E6098A0D6CD6BA1C03544C5425875ECB3418AF5A3EE3F32143E48D2 diff --git a/src/tests/test_ecgdsa.cpp b/src/tests/test_ecgdsa.cpp new file mode 100644 index 000000000..7fbdaccc5 --- /dev/null +++ b/src/tests/test_ecgdsa.cpp @@ -0,0 +1,78 @@ +/* +* (C) 2016 René Korthaus, Sirrix AG +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "tests.h" + +#include "test_rng.h" + +#if defined(BOTAN_HAS_ECGDSA) + #include "test_pubkey.h" + #include <botan/ecgdsa.h> + #include <botan/oids.h> +#endif + +namespace Botan_Tests { + +namespace { + +#if defined(BOTAN_HAS_ECGDSA) + +class ECGDSA_Signature_KAT_Tests : public PK_Signature_Generation_Test + { + public: + ECGDSA_Signature_KAT_Tests() : PK_Signature_Generation_Test( + "ECGDSA", + "pubkey/ecgdsa.vec", + {"Group", "X", "Hash", "Msg", "Nonce", "Signature"}) + {} + + bool clear_between_callbacks() const override { return false; } + + std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override + { + const std::string group_id = get_req_str(vars, "Group"); + const BigInt x = get_req_bn(vars, "X"); + Botan::EC_Group group(Botan::OIDS::lookup(group_id)); + + std::unique_ptr<Botan::Private_Key> key(new Botan::ECGDSA_PrivateKey(Test::rng(), group, x)); + return key; + } + + std::string default_padding(const VarMap& vars) const override + { + return "EMSA1(" + get_req_str(vars, "Hash") + ")"; + } + + Botan::RandomNumberGenerator* test_rng(const std::vector<uint8_t>& nonce) const override + { + // ecgdsa signature generation extracts more random than just the nonce, + // but the nonce is extracted first + return new Fixed_Output_Position_RNG(nonce, 1); + } + }; + +class ECGDSA_Keygen_Tests : public PK_Key_Generation_Test + { + public: + std::vector<std::string> keygen_params() const override { return { "secp256r1", "secp384r1", "secp521r1" }; } + + std::unique_ptr<Botan::Private_Key> make_key(Botan::RandomNumberGenerator& rng, + const std::string& param) const override + { + Botan::EC_Group group(param); + std::unique_ptr<Botan::Private_Key> key(new Botan::ECGDSA_PrivateKey(rng, group)); + return key; + } + }; + +BOTAN_REGISTER_TEST("ecgdsa", ECGDSA_Signature_KAT_Tests); +BOTAN_REGISTER_TEST("ecgdsa_keygen", ECGDSA_Keygen_Tests); + +#endif + +} + +} diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index 4d795ae1d..2f6de639d 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -113,7 +113,7 @@ PK_Signature_Generation_Test::run_one_test(const std::string&, const VarMap& var std::unique_ptr<Botan::RandomNumberGenerator> rng; if(vars.count("Nonce")) { - rng.reset(new Fixed_Output_RNG(get_req_bin(vars, "Nonce"))); + rng.reset(test_rng(get_req_bin(vars, "Nonce"))); } const std::vector<uint8_t> generated_signature = diff --git a/src/tests/test_pubkey.h b/src/tests/test_pubkey.h index 086c0bea1..b5a79bf55 100644 --- a/src/tests/test_pubkey.h +++ b/src/tests/test_pubkey.h @@ -9,6 +9,8 @@ #include "tests.h" +#include "test_rng.h" + #if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO) #include <botan/pubkey.h> @@ -30,6 +32,12 @@ class PK_Signature_Generation_Test : public Text_Based_Test } virtual std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) = 0; + + virtual Botan::RandomNumberGenerator* test_rng(const std::vector<uint8_t>& nonce) const + { + return new Fixed_Output_RNG(nonce); + } + private: Test::Result run_one_test(const std::string&, const VarMap& vars) override; }; diff --git a/src/tests/test_rng.h b/src/tests/test_rng.h index f7b0bf6fe..c14ed7fb7 100644 --- a/src/tests/test_rng.h +++ b/src/tests/test_rng.h @@ -1,5 +1,6 @@ /* * (C) 2009 Jack Lloyd +* (C) 2016 René Korthaus, Sirrix AG * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -12,15 +13,27 @@ #include <string> #include <botan/rng.h> #include <botan/hex.h> +#include <botan/exceptn.h> + +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include <botan/system_rng.h> +#else + #include <botan/auto_rng.h> +#endif + namespace Botan_Tests { +/** + * RNG that outputs only a given set of fixed bytes, throws otherwise. + * Useful for test vectors with fixed nonces, where the algorithm consumes only the fixed nonce. + */ class Fixed_Output_RNG : public Botan::RandomNumberGenerator { public: bool is_seeded() const override { return !m_buf.empty(); } - uint8_t random() + virtual uint8_t random() { if(!is_seeded()) throw Test_Error("Fixed output RNG ran out of bytes, test bug?"); @@ -63,10 +76,85 @@ class Fixed_Output_RNG : public Botan::RandomNumberGenerator Fixed_Output_RNG() {} protected: size_t remaining() const { return m_buf.size(); } - private: + std::deque<uint8_t> m_buf; }; +/** + * RNG that outputs a given set of fixed bytes for a specific request count, outputs random otherwise. + * Useful for test vectors with fixed nonces, where the algorithm consumes more random than just the fixed nonce. + */ +class Fixed_Output_Position_RNG : public Fixed_Output_RNG + { + public: + bool is_seeded() const override { return !m_buf.empty() || m_rng->is_seeded(); } + + uint8_t random() override + { + if(m_buf.empty()) + { + throw Test_Error("Fixed output RNG ran out of bytes, test bug?"); + } + + uint8_t out = m_buf.front(); + m_buf.pop_front(); + return out; + } + + void randomize(uint8_t out[], size_t len) override + { + ++m_requests; + + if(m_requests == m_pos) + { // return fixed output + for(size_t j = 0; j != len; j++) + { + out[j] = random(); + } + } + else + { // return random + m_rng->randomize(out,len); + } + } + + void add_entropy(const uint8_t*, size_t) override + { + throw Botan::Exception("add_entropy() not supported by this RNG, test bug?"); + } + + std::string name() const override { return "Fixed_Output_Position_RNG"; } + + explicit Fixed_Output_Position_RNG(const std::vector<uint8_t>& in, uint32_t pos) : + Fixed_Output_RNG(in), + m_pos(pos), + m_rng{} + { +#if defined(BOTAN_HAS_SYSTEM_RNG) + m_rng.reset(new Botan::System_RNG); +#else + m_rng.reset(new Botan::AutoSeeded_RNG); +#endif + } + + explicit Fixed_Output_Position_RNG(const std::string& in_str, uint32_t pos) : + Fixed_Output_RNG(in_str), + m_pos(pos), + m_rng{} + { +#if defined(BOTAN_HAS_SYSTEM_RNG) + m_rng.reset(new Botan::System_RNG); +#else + m_rng.reset(new Botan::AutoSeeded_RNG); +#endif + } + + private: + uint32_t m_pos = 0; + uint32_t m_requests = 0; + std::unique_ptr<RandomNumberGenerator> m_rng; + }; + } #endif |