diff options
author | lloyd <[email protected]> | 2010-03-16 17:36:31 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-03-16 17:36:31 +0000 |
commit | 651aa262cab86a8e98ee9815ec365ea68ffff5b1 (patch) | |
tree | dd8f53acea45c204d169edaaec36aa4dfeeb9268 | |
parent | 3b285e35294dfe67650063cc774d6f4e4e77b934 (diff) |
Add a couple of verification tests for GOST 34.10
Generating the test vectors found yet another inane (and, of course,
undocumented) behavior in the GOST implementation included in OpenSSL;
it treats the hash inputs as little endian. Just out of curiousity, I
checked RFC 5832, which supposedly specifies this algorithm; not a
peep about endian conversions.
The more I deal with standards coming out of the CryptoPro people, the
less confidence I have in them.
-rw-r--r-- | checks/pk.cpp | 31 | ||||
-rw-r--r-- | checks/pk_valid.dat | 18 | ||||
-rw-r--r-- | src/pubkey/gost_3410/gost_3410.cpp | 19 |
3 files changed, 65 insertions, 3 deletions
diff --git a/checks/pk.cpp b/checks/pk.cpp index bc1308f1c..23ceda7fe 100644 --- a/checks/pk.cpp +++ b/checks/pk.cpp @@ -512,6 +512,34 @@ u32bit validate_ecdsa_sig(const std::string& algo, return 2; } +u32bit validate_gost_ver(const std::string& algo, + const std::vector<std::string>& str) + { + if(str.size() != 5) + throw std::runtime_error("Invalid input from pk_valid.dat"); + +#if defined(BOTAN_HAS_GOST_34_10_2001) + + EC_Domain_Params group(OIDS::lookup(str[0])); + + PointGFp public_point = OS2ECP(decode_hex(str[1]), group.get_curve()); + + GOST_3410_PublicKey gost(group, public_point); + + std::string emsa = algo.substr(13, std::string::npos); + + PK_Verifier v(gost, emsa); + + SecureVector<byte> msg = decode_hex(str[2]); + SecureVector<byte> sig = decode_hex(str[3]); + + bool passed = v.verify_message(msg, msg.size(), sig, sig.size()); + return (passed ? 0 : 1); +#endif + + return 2; + } + u32bit validate_dsa_ver(const std::string& algo, const std::vector<std::string>& str) { @@ -820,6 +848,9 @@ u32bit do_pk_validation_tests(const std::string& filename, else if(algorithm.find("ECDSA/") == 0) new_errors = validate_ecdsa_sig(algorithm, substr); + else if(algorithm.find("GOST_3410_VA/") == 0) + new_errors = validate_gost_ver(algorithm, substr); + else if(algorithm.find("RSAES_PKCS8/") == 0) new_errors = validate_rsa_enc_pkcs8(algorithm, substr, rng); else if(algorithm.find("RSAVA_X509/") == 0) diff --git a/checks/pk_valid.dat b/checks/pk_valid.dat index 40bd830c2..1190886e9 100644 --- a/checks/pk_valid.dat +++ b/checks/pk_valid.dat @@ -4200,6 +4200,24 @@ x962_p239v1:\ 2CB7F36803EBB9C427C58D8265F11FC5084747133078FC279DE874FBECB0\ 2EEAE988104E9C2234A3C2BEB1F53BFA5DC11FF36A875D1E3CCB1F7E45CF +# ECC verification format is group name:public key:message:signature +[GOST_3410_VA/EMSA1(GOST-34.11)] +gost_256A:\ +0400B6F1D75EF48902B0C2302F52CCC71233EC55B903061673AAA586A2B5\ +864048EA2675E8FD8DB1FEDFC7DD40E3CF3A319EE3130E0BE9FDF994B625\ +BC1885F271:\ +:\ +AA3CB0563295A3E281BA368DF8471DE0A4150B3CFCEA575D8A9CC9779035EC36\ +FE406F383A54127453AED406FA9A3B610B28F89FC918C07A5A75289E97B3A991 + +gost_256A:\ +04BFE0BA366BE575E45C5BBA339C51ACD75D517008A9D3169E3CCEA6EF08\ +046DA74312382D835BEEA1C561A75AFCAFDA0F75A4E5D9787F9DB2870A03\ +2AC1D90465:\ +:\ +B7AB61F33E0B70166C355963BB80B8F6DF54F7F6A43872295CD42B6ACF7DF678\ +F3AFCBE1398DDC01F0A9E4B45397F3ACD8F343399BD2805FB6293E9CB871123A + # NR Format: p:q:g:y:x:message:k:output [NR/EMSA1(SHA-1)] # Trickiness: in some of these, we put a leading 0 digit on the nonce (k). This diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp index 505d92a61..e6f68526e 100644 --- a/src/pubkey/gost_3410/gost_3410.cpp +++ b/src/pubkey/gost_3410/gost_3410.cpp @@ -84,6 +84,20 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, } } +namespace { + +BigInt decode_le(const byte msg[], u32bit msg_len) + { + SecureVector<byte> msg_le(msg, msg_len); + + for(size_t i = 0; i != msg_le.size() / 2; ++i) + std::swap(msg_le[i], msg_le[msg_le.size()-1-i]); + + return BigInt(msg_le, msg_le.size()); + } + +} + GOST_3410_Signature_Operation::GOST_3410_Signature_Operation( const GOST_3410_PrivateKey& gost_3410) : @@ -102,7 +116,7 @@ GOST_3410_Signature_Operation::sign(const byte msg[], u32bit msg_len, k.randomize(rng, order.bits()-1); while(k >= order); - BigInt e(msg, msg_len); + BigInt e = decode_le(msg, msg_len); e %= order; if(e == 0) @@ -124,7 +138,6 @@ GOST_3410_Signature_Operation::sign(const byte msg[], u32bit msg_len, return output; } - GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) : base_point(gost.domain().get_base_point()), public_point(gost.public_point()), @@ -138,7 +151,7 @@ bool GOST_3410_Verification_Operation::verify(const byte msg[], u32bit msg_len, if(sig_len != order.bytes()*2) return false; - BigInt e(msg, msg_len); + BigInt e = decode_le(msg, msg_len); BigInt r(sig, sig_len / 2); BigInt s(sig + sig_len / 2, sig_len / 2); |