Skip to content

Commit

Permalink
Merge pull request #145 from glv2/openssl-DER-signature
Browse files Browse the repository at this point in the history
Guard against openssl's new strict DER checks.
  • Loading branch information
brossi committed Jan 16, 2015
2 parents 51122f4 + 322ce19 commit 0cf0117
Showing 1 changed file with 26 additions and 3 deletions.
29 changes: 26 additions & 3 deletions src/key.cpp
Expand Up @@ -356,11 +356,34 @@ bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& v

bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
{
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
if (vchSig.empty())
return false;

return true;
// New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
unsigned char *norm_der = NULL;
ECDSA_SIG *norm_sig = ECDSA_SIG_new();
const unsigned char* sigptr = &vchSig[0];
assert(norm_sig);
if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL)
{
/* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on
* error. But OpenSSL's own use of this function redundantly frees the
* result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a
* clear contract for the function behaving the same way is more
* conservative.
*/
ECDSA_SIG_free(norm_sig);
return false;
}
int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
ECDSA_SIG_free(norm_sig);
if (derlen <= 0)
return false;

// -1 = error, 0 = bad sig, 1 = good
bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
OPENSSL_free(norm_der);
return ret;
}

bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
Expand Down

0 comments on commit 0cf0117

Please sign in to comment.