Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable compilation on Ubuntu 20.1 #104

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 109 additions & 95 deletions src/bignum.h

Large diffs are not rendered by default.

25 changes: 13 additions & 12 deletions src/crypter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned
int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0;
vchCiphertext = std::vector<unsigned char> (nCLen);

EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();

bool fOk = true;

EVP_CIPHER_CTX_init(&ctx);
if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
EVP_CIPHER_CTX_cleanup(&ctx);
EVP_CIPHER_CTX_init(ctx);
if (fOk) fOk = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
if (fOk) fOk = EVP_EncryptUpdate(ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
if (fOk) fOk = EVP_EncryptFinal_ex(ctx, (&vchCiphertext[0])+nCLen, &nFLen);
EVP_CIPHER_CTX_free(ctx);

if (!fOk) return false;

Expand All @@ -84,15 +84,16 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM

vchPlaintext = CKeyingMaterial(nPLen);

EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();

bool fOk = true;

EVP_CIPHER_CTX_init(&ctx);
if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
EVP_CIPHER_CTX_cleanup(&ctx);
EVP_CIPHER_CTX_init(ctx);
if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0])+nPLen, &nFLen);

EVP_CIPHER_CTX_free(ctx);

if (!fOk) return false;

Expand Down
134 changes: 68 additions & 66 deletions src/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
#include <openssl/rand.h>
#include <openssl/opensslv.h>

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
typedef struct ECDSA_SIG_st {
BIGNUM *r;
BIGNUM *s;
} ECDSA_SIG;
#endif

#if OPENSSL_VERSION_NUMBER < 0x10100000L
// Compatibility Layer for older versions of Open SSL
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
#endif

// anonymous namespace with local implementation code (OpenSSL interaction)
namespace {
Expand Down Expand Up @@ -74,6 +93,11 @@ int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned ch
int n = 0;
int i = recid / 2;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const BIGNUM *sig_r, *sig_s;
ECDSA_SIG_get0(ecsig, &sig_r, &sig_s);
#endif

const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
BN_CTX_start(ctx);
Expand All @@ -82,7 +106,11 @@ int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned ch
x = BN_CTX_get(ctx);
if (!BN_copy(x, order)) { ret=-1; goto err; }
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (!BN_add(x, x, sig_r)) { ret=-1; goto err; }
#else
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
#endif
field = BN_CTX_get(ctx);
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
Expand All @@ -103,9 +131,17 @@ int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned ch
if (!BN_zero(zero)) { ret=-1; goto err; }
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
rr = BN_CTX_get(ctx);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (!BN_mod_inverse(rr, sig_r, order, ctx)) { ret=-1; goto err; }
#else
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
#endif
sor = BN_CTX_get(ctx);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (!BN_mod_mul(sor, sig_s, rr, order, ctx)) { ret=-1; goto err; }
#else
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
#endif
eor = BN_CTX_get(ctx);
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
Expand Down Expand Up @@ -150,13 +186,13 @@ class CECKey {

void SetSecretBytes(const unsigned char vch[32]) {
bool ret;
BIGNUM bn;
BN_init(&bn);
ret = BN_bin2bn(vch, 32, &bn);
BIGNUM *bn;
bn = BN_new();
ret = BN_bin2bn(vch, 32, bn);
assert(ret);
ret = EC_KEY_regenerate_key(pkey, &bn);
ret = EC_KEY_regenerate_key(pkey, bn);
assert(ret);
BN_clear_free(&bn);
BN_clear_free(bn);
}

void GetPrivKey(CPrivKey &privkey, bool fCompressed) {
Expand All @@ -174,7 +210,7 @@ class CECKey {
if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
if(fSkipCheck)
return true;

// d2i_ECPrivateKey returns true if parsing succeeds.
// This doesn't necessarily mean the key is valid.
if (EC_KEY_check_key(pkey))
Expand Down Expand Up @@ -228,52 +264,10 @@ class CECKey {
}

bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
//if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
//return false;
//return true;
if (vchSig.empty()) {
//printf("empty sig\n");
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);
//printf("d2i failed\n");
return false;
}
int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der);
ECDSA_SIG_free(norm_sig);
if (derlen <= 0) {
//printf("derlen<=0\n");
return false;
}
// -1 = error, 0 = bad sig, 1 = good
/*if (vchSig.size()>2 && vchSig[0] == 0x30 && vchSig[1] == 0x45 && vchSig[2] == 0x02) {
LogPrintf("ECDSA_verify\n");
LogPrintf("(%d) ",sizeof(hash));
for (int i=0; i<sizeof(hash); i++) {
LogPrintf("%02x",((unsigned char *)&hash)[i]);
}
LogPrintf("\n(%d)",derlen);
for (int i=0; i<derlen; i++) {
LogPrintf("%02x",norm_der[i]);
}
LogPrintf("\n");
}*/
bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
OPENSSL_free(norm_der);
return ret;
// -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 SignCompact(const uint256 &hash, unsigned char *p64, int &rec) {
Expand Down Expand Up @@ -316,8 +310,20 @@ class CECKey {
if (rec<0 || rec>=3)
return false;
ECDSA_SIG *sig = ECDSA_SIG_new();
BN_bin2bn(&p64[0], 32, sig->r);
BN_bin2bn(&p64[32], 32, sig->s);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
BIGNUM *sig_r = NULL;
BIGNUM *sig_s = NULL;
if (!(sig_r = BN_bin2bn(&p64[0], 32, nullptr)) ||
!(sig_s = BN_bin2bn(&p64[32], 32, nullptr)) ||
!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
BN_free(sig_r);
BN_free(sig_s);
return false;
}
#else
BN_bin2bn(&p64[0], 32, sig->r);
BN_bin2bn(&p64[32], 32, sig->s);
#endif
bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1;
ECDSA_SIG_free(sig);
return ret;
Expand Down Expand Up @@ -463,32 +469,28 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
CECKey key;
if (!key.SetPrivKey(privkey, fSkipCheck))
return false;

key.GetSecretBytes(vch);
fCompressed = vchPubKey.IsCompressed();
fValid = true;

if (fSkipCheck)
return true;

if (GetPubKey() != vchPubKey)
return false;

return true;
}

bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
return false;
CECKey key;
if (!key.SetPubKey(*this)) {
//printf("cpubkey::verify: !key.SetPubKey\n");
return false;
}
if (!key.Verify(hash, vchSig)) {
//printf("cpubkey::verify: !key.Verify\n");
return false;
}
if (!key.SetPubKey(*this))
return false;
if (!key.Verify(hash, vchSig))
return false;
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions src/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ class CPubKey {
// secure_allocator is defined in allocators.h
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
// CSecret is a serialization of just the secret parameter (32 bytes)
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;

/** An encapsulated private key. */
class CKey {
Expand Down
34 changes: 27 additions & 7 deletions src/qt/paymentrequestplus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include "paymentrequestplus.h"

#include "util.h"

#include <stdexcept>

#include <openssl/x509.h>
Expand Down Expand Up @@ -149,7 +151,13 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
int result = X509_verify_cert(store_ctx);
if (result != 1) {
int error = X509_STORE_CTX_get_error(store_ctx);
throw SSLVerifyError(X509_verify_cert_error_string(error));
// For testing payment requests, we allow self signed root certs!
// This option is just shown in the UI options, if -help-debug is enabled.
if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) {
throw SSLVerifyError(X509_verify_cert_error_string(error));
} else {
qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true.";
}
}
X509_NAME *certname = X509_get_subject_name(signing_cert);

Expand All @@ -159,16 +167,28 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c
std::string data_to_verify; // Everything but the signature
rcopy.SerializeToString(&data_to_verify);

EVP_MD_CTX ctx;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
if (!ctx) throw SSLVerifyError("Error allocating OpenSSL context.");
#else
EVP_MD_CTX _ctx;
EVP_MD_CTX *ctx;
ctx = &_ctx;
#endif

EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
EVP_MD_CTX_init(&ctx);
if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) ||
!EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) ||
!EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) {

throw SSLVerifyError("Bad signature, invalid PaymentRequest.");
EVP_MD_CTX_init(ctx);
if (!EVP_VerifyInit_ex(ctx, digestAlgorithm, NULL) ||
!EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) ||
!EVP_VerifyFinal(ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) {
throw SSLVerifyError("Bad signature, invalid payment request.");
}

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_MD_CTX_free(ctx);
#endif

// OpenSSL API for getting human printable strings from certs is baroque.
int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0);
website = new char[textlen + 1];
Expand Down
3 changes: 3 additions & 0 deletions src/qt/paymentrequestplus.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
#include "paymentrequest.pb.h"

#include "base58.h"
#include <openssl/x509.h>

#include <QByteArray>
#include <QList>
#include <QString>

static const bool DEFAULT_SELFSIGNED_ROOTCERTS = false;

//
// Wraps dumb protocol buffer paymentRequest
// with extra methods
Expand Down
Loading