consensus: cache the openssl EC_GROUP to avoid a race condition for each CECKey instantiation

This commit is contained in:
Cory Fields 2015-08-18 00:54:19 -04:00
parent 87f37e259d
commit 1d1073c2d3

View file

@ -13,6 +13,29 @@
namespace { namespace {
class ecgroup_order
{
public:
static const EC_GROUP* get()
{
static const ecgroup_order wrapper;
return wrapper.pgroup;
}
private:
ecgroup_order()
: pgroup(EC_GROUP_new_by_curve_name(NID_secp256k1))
{
}
~ecgroup_order()
{
EC_GROUP_free(pgroup);
}
EC_GROUP* pgroup;
};
/** /**
* Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields * Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
* recid selects which key is recovered * recid selects which key is recovered
@ -92,8 +115,10 @@ err:
} // anon namespace } // anon namespace
CECKey::CECKey() { CECKey::CECKey() {
pkey = EC_KEY_new_by_curve_name(NID_secp256k1); pkey = EC_KEY_new();
assert(pkey != NULL); assert(pkey != NULL);
int result = EC_KEY_set_group(pkey, ecgroup_order::get());
assert(result);
} }
CECKey::~CECKey() { CECKey::~CECKey() {
@ -185,11 +210,9 @@ bool CECKey::TweakPublic(const unsigned char vchTweak[32]) {
bool CECKey::SanityCheck() bool CECKey::SanityCheck()
{ {
EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); const EC_GROUP *pgroup = ecgroup_order::get();
if(pkey == NULL) if(pgroup == NULL)
return false; return false;
EC_KEY_free(pkey);
// TODO Is there more EC functionality that could be missing? // TODO Is there more EC functionality that could be missing?
return true; return true;
} }