aboutsummaryrefslogtreecommitdiff
path: root/src/key.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/key.cpp')
-rw-r--r--src/key.cpp41
1 files changed, 31 insertions, 10 deletions
diff --git a/src/key.cpp b/src/key.cpp
index 76c45d0635..23f315203e 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -186,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)
@@ -245,12 +259,16 @@ CPrivKey CKey::GetPrivKey() const
bool CKey::SetPubKey(const CPubKey& vchPubKey)
{
const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
- if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
- return false;
- fSet = true;
- if (vchPubKey.vchPubKey.size() == 33)
- SetCompressedPubKey();
- return true;
+ if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
+ {
+ fSet = true;
+ if (vchPubKey.vchPubKey.size() == 33)
+ SetCompressedPubKey();
+ return true;
+ }
+ pkey = NULL;
+ Reset();
+ return false;
}
CPubKey CKey::GetPubKey() const
@@ -377,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;