X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fkey.cpp;h=d9c28328d9dcbaea9394780884decb14bc3af45a;hb=9624915443073c8ad61d1e0223571dc6f827ee22;hp=ece835d1472412b02841dcedc03043b02f4bb24f;hpb=4aa8021a9651257605e8c16df2973eee8aebe575;p=novacoin.git diff --git a/src/key.cpp b/src/key.cpp index ece835d..d9c2832 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -1,6 +1,8 @@ // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include #include #include @@ -46,7 +48,7 @@ err: // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields // recid selects which key is recovered -// if check is nonzero, additional checks are performed +// if check is non-zero, additional checks are performed int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) { if (!eckey) return 0; @@ -127,6 +129,8 @@ void CKey::SetCompressedPubKey() void CKey::Reset() { fCompressedPubKey = false; + if (pkey != NULL) + EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (pkey == NULL) throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed"); @@ -135,6 +139,7 @@ void CKey::Reset() CKey::CKey() { + pkey = NULL; Reset(); } @@ -181,10 +186,24 @@ void CKey::MakeNewKey(bool fCompressed) bool CKey::SetPrivKey(const CPrivKey& vchPrivKey) { const unsigned char* pbegin = &vchPrivKey[0]; - if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size())) - return false; - fSet = true; - return true; + if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size())) + { + // In testing, d2i_ECPrivateKey can return true + // but fill in pkey with a key that fails + // EC_KEY_check_key, so: + if (EC_KEY_check_key(pkey)) + { + fSet = true; + return true; + } + } + // If vchPrivKey data is bad d2i_ECPrivateKey() can + // leave pkey in a state where calling EC_KEY_free() + // crashes. To avoid that, set pkey to NULL and + // leak the memory (a leak is better than a crash) + pkey = NULL; + Reset(); + return false; } bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed) @@ -237,18 +256,22 @@ CPrivKey CKey::GetPrivKey() const return vchPrivKey; } -bool CKey::SetPubKey(const std::vector& vchPubKey) +bool CKey::SetPubKey(const CPubKey& vchPubKey) { - const unsigned char* pbegin = &vchPubKey[0]; - if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size())) - return false; - fSet = true; - if (vchPubKey.size() == 33) - SetCompressedPubKey(); - return true; + const unsigned char* pbegin = &vchPubKey.vchPubKey[0]; + if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size())) + { + fSet = true; + if (vchPubKey.vchPubKey.size() == 33) + SetCompressedPubKey(); + return true; + } + pkey = NULL; + Reset(); + return false; } -std::vector CKey::GetPubKey() const +CPubKey CKey::GetPubKey() const { int nSize = i2o_ECPublicKey(pkey, NULL); if (!nSize) @@ -257,7 +280,7 @@ std::vector CKey::GetPubKey() const unsigned char* pbegin = &vchPubKey[0]; if (i2o_ECPublicKey(pkey, &pbegin) != nSize) throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size"); - return vchPubKey; + return CPubKey(vchPubKey); } bool CKey::Sign(uint256 hash, std::vector& vchSig) @@ -305,7 +328,10 @@ bool CKey::SignCompact(uint256 hash, std::vector& vchSig) } if (nRecId == -1) + { + ECDSA_SIG_free(sig); throw key_error("CKey::SignCompact() : unable to construct recoverable key"); + } vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0); BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]); @@ -344,6 +370,7 @@ bool CKey::SetCompactSignature(uint256 hash, const std::vector& v ECDSA_SIG_free(sig); return true; } + ECDSA_SIG_free(sig); return false; } @@ -352,6 +379,7 @@ bool CKey::Verify(uint256 hash, const std::vector& vchSig) // -1 = error, 0 = bad sig, 1 = good if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) return false; + return true; } @@ -362,6 +390,7 @@ bool CKey::VerifyCompact(uint256 hash, const std::vector& vchSig) return false; if (GetPubKey() != key.GetPubKey()) return false; + return true; } @@ -370,6 +399,9 @@ bool CKey::IsValid() if (!fSet) return false; + if (!EC_KEY_check_key(pkey)) + return false; + bool fCompr; CSecret secret = GetSecret(fCompr); CKey key2;