From df7c2f7e4f426310e29c5b74fcf143ddb9fb7224 Mon Sep 17 00:00:00 2001 From: nzsquirrell Date: Fri, 28 Aug 2015 19:56:52 +1200 Subject: [PATCH] fix failed tests and issues with versions of openssl changes sourced from: https://github.com/bitcoin/bitcoin/commit/b8e81b7ccd4490155e3345fc73346ff8c3a77524 https://github.com/bitcoin/bitcoin/commit/60c51f1c381bbd93c70cfdf41c6688609a7956fc https://github.com/bitcoin/bitcoin/commit/037bfefe6bccbdf656e628a1f4526db8f80c3922 --- src/key.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 71a8bd27..6a502e62 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -227,11 +227,35 @@ public: } bool Verify(const uint256 &hash, const std::vector& vchSig) { + if (vchSig.empty()) + return false; + + // 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 - if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) - return false; - return true; - } + bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; + OPENSSL_free(norm_der); + return ret; + } bool SignCompact(const uint256 &hash, unsigned char *p64, int &rec) { bool fOk = false;