X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fkey.cpp;h=1ed4e25087db9e8786db0a40170f5aef19efe1ae;hb=128b5cec3c7f20b34a40541be2236c11fe204df6;hp=6657ffd70b328e6f47edd79722a99bedbf5ad7b6;hpb=3e59ebf3286bcd620e6ff79fa84eb9aa50a6c59e;p=novacoin.git diff --git a/src/key.cpp b/src/key.cpp index 6657ffd..1ed4e25 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -463,20 +463,17 @@ bool CPubKey::SetCompactSignature(uint256 hash, const std::vector ECDSA_SIG *sig = ECDSA_SIG_new(); BN_bin2bn(&vchSig[1],32,sig->r); BN_bin2bn(&vchSig[33],32,sig->s); - + bool fSuccessful = false; EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { nV -= 4; EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); } - do { if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) != 1) break; - ECDSA_SIG_free(sig); - int nSize = i2o_ECPublicKey(pkey, NULL); if (!nSize) break; @@ -485,13 +482,14 @@ bool CPubKey::SetCompactSignature(uint256 hash, const std::vector if (i2o_ECPublicKey(pkey, &pbegin) != nSize) break; Set(vchPubKey.begin(), vchPubKey.end()); - return IsValid(); + fSuccessful = IsValid(); } while (false); - ECDSA_SIG_free(sig); - Invalidate(); - return false; + EC_KEY_free(pkey); + if (!fSuccessful) + Invalidate(); + return fSuccessful; } bool CPubKey::Verify(const uint256 &hash, const std::vector& vchSig) const @@ -499,35 +497,37 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector& vchS if (vchSig.empty() || !IsValid()) return false; - const unsigned char* pbegin = &vbytes[0]; EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); - if (!o2i_ECPublicKey(&pkey, &pbegin, size())) - return false; // Unable to parse public key - - // 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) + assert(pkey); + + bool ret = false; + do { - /* 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); + int derlen; + uint8_t *norm_der = NULL; + const uint8_t* pbegin = &vbytes[0]; + const uint8_t* sigptr = &vchSig[0]; + + // Trying to parse public key + if (!o2i_ECPublicKey(&pkey, &pbegin, size())) + break; + // New versions of OpenSSL are rejecting a non-canonical DER signatures, de/re-serialize first. + if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) + break; + if ((derlen = i2d_ECDSA_SIG(norm_sig, &norm_der)) <= 0) + break; + + // -1 = error, 0 = bad sig, 1 = good + ret = ECDSA_verify(0, (const unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; + OPENSSL_free(norm_der); + } while(false); + ECDSA_SIG_free(norm_sig); - if (derlen <= 0) - return false; + EC_KEY_free(pkey); - // -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; }