diff options
Diffstat (limited to 'src/key.cpp')
-rw-r--r-- | src/key.cpp | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/src/key.cpp b/src/key.cpp index 4bb141f701..23f315203e 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -8,7 +8,6 @@ #include <openssl/obj_mac.h> #include "key.h" -#include "util.h" // Generate a private key from just the secret parameter int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) @@ -187,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) @@ -243,18 +256,22 @@ CPrivKey CKey::GetPrivKey() const return vchPrivKey; } -bool CKey::SetPubKey(const std::vector<unsigned char>& 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<unsigned char> CKey::GetPubKey() const +CPubKey CKey::GetPubKey() const { int nSize = i2o_ECPublicKey(pkey, NULL); if (!nSize) @@ -263,7 +280,7 @@ std::vector<unsigned char> 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<unsigned char>& vchSig) @@ -378,6 +395,9 @@ bool CKey::IsValid() if (!fSet) return false; + if (!EC_KEY_check_key(pkey)) + return false; + bool fCompr; CSecret secret = GetSecret(fCompr); CKey key2; |