Skip to content

Commit 488ed32

Browse files
committed
consensus: guard against openssl's new strict DER checks
New versions of OpenSSL will reject non-canonical DER signatures. However, it'll happily decode them. Decode then re-encode before verification in order to ensure that it is properly consumed.
1 parent d0c97bb commit 488ed32

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

src/ecwrapper.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,20 @@ bool CECKey::SetPubKey(const unsigned char* pubkey, size_t size) {
117117
}
118118

119119
bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
120-
// -1 = error, 0 = bad sig, 1 = good
121-
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
120+
// New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
121+
unsigned char *norm_der = NULL;
122+
ECDSA_SIG *norm_sig = ECDSA_SIG_new();
123+
const unsigned char* sigptr = &vchSig[0];
124+
d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size());
125+
int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
126+
ECDSA_SIG_free(norm_sig);
127+
if (derlen <= 0)
122128
return false;
123-
return true;
129+
130+
// -1 = error, 0 = bad sig, 1 = good
131+
bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
132+
OPENSSL_free(norm_der);
133+
return ret;
124134
}
125135

126136
bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec)

0 commit comments

Comments
 (0)