#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)
// 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;
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");
CKey::CKey()
{
+ pkey = NULL;
Reset();
}
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)
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)
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)
}
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]);
ECDSA_SIG_free(sig);
return true;
}
+ ECDSA_SIG_free(sig);
return false;
}
if (!fSet)
return false;
+ if (!EC_KEY_check_key(pkey))
+ return false;
+
bool fCompr;
CSecret secret = GetSecret(fCompr);
CKey key2;