diff --git a/src/crypto/PKCS12Signer.cpp b/src/crypto/PKCS12Signer.cpp index 16bb69a95..17acd4349 100644 --- a/src/crypto/PKCS12Signer.cpp +++ b/src/crypto/PKCS12Signer.cpp @@ -71,53 +71,48 @@ vector PKCS12Signer::sign(const string &method, const vector signature; + size_t size = 0; + SCOPE(EVP_PKEY_CTX, ctx, EVP_PKEY_CTX_new(d->key, nullptr)); + if(!ctx || EVP_PKEY_sign_init(ctx.get()) <= 0) + THROW_OPENSSLEXCEPTION("Failed to sign the digest"); switch(EVP_PKEY_base_id(d->key)) { case EVP_PKEY_RSA: { - SCOPE(RSA, rsa, EVP_PKEY_get1_RSA(d->key)); - signature.resize(size_t(RSA_size(rsa.get()))); - int nid = Digest::toMethod(method); if(Digest::isRsaPssUri(method)) { - vector em(signature.size()); - if(!RSA_padding_add_PKCS1_PSS_mgf1(rsa.get(), em.data(), digest.data(), EVP_get_digestbynid(nid), nullptr, RSA_PSS_SALTLEN_DIGEST)) + if(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx.get(), RSA_PSS_SALTLEN_DIGEST) <= 0) break; - if(RSA_private_encrypt(RSA_size(rsa.get()), em.data(), signature.data(), rsa.get(), RSA_NO_PADDING) == RSA_size(rsa.get())) - result = 1; - } else { - unsigned int size = (unsigned int)signature.size(); - result = RSA_sign(nid, digest.data(), (unsigned int)digest.size(), signature.data(), &size, rsa.get()); - } + } else if(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) <= 0) + break; + if(EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_get_digestbynid(Digest::toMethod(method))) <= 0 || + EVP_PKEY_sign(ctx.get(), nullptr, &size, digest.data(), digest.size()) <= 0) + break; + signature.resize(size); + result = EVP_PKEY_sign(ctx.get(), signature.data(), &size, digest.data(), digest.size()); break; } #ifndef OPENSSL_NO_ECDSA case EVP_PKEY_EC: { - SCOPE(EC_KEY, ec, EVP_PKEY_get1_EC_KEY(d->key)); - SCOPE(ECDSA_SIG, sig, ECDSA_do_sign(digest.data(), int(digest.size()), ec.get())); - if(!sig) - break; - - size_t keyLen = 0; - if(const EC_GROUP *group = EC_KEY_get0_group(ec.get())) - { - BIGNUM *order = BN_new(); - if (EC_GROUP_get_order(group, order, nullptr)) - keyLen = size_t(BN_num_bytes(order)); - BN_clear_free(order); - } - if(keyLen == 0) - THROW("Error caclulating signature size"); - signature.resize(keyLen * 2); - + if(EVP_PKEY_sign(ctx.get(), nullptr, &size, digest.data(), digest.size()) <= 0) + break; + vector asn1(size); + result = EVP_PKEY_sign(ctx.get(), asn1.data(), &size, digest.data(), digest.size()); + if(result <= 0) + break; + const unsigned char *p = asn1.data(); + SCOPE(ECDSA_SIG, sig, d2i_ECDSA_SIG(nullptr, &p, long(asn1.size()))); const BIGNUM *r = nullptr, *s = nullptr; ECDSA_SIG_get0(sig.get(), &r, &s); - if(BN_bn2bin(r, &signature[keyLen - size_t(BN_num_bytes(r))]) <= 0) + size_t r_len = size_t(BN_num_bytes(r)); + size_t s_len = size_t(BN_num_bytes(s)); + size_t keyLen = max(r_len, s_len); + signature.resize(keyLen * 2); + if(BN_bn2bin(r, &signature[keyLen - r_len]) <= 0) THROW("Error copying signature 'r' value to buffer"); - if(BN_bn2bin(s, &signature[keyLen*2 - size_t(BN_num_bytes(s))]) <= 0) + if(BN_bn2bin(s, &signature[keyLen*2 - s_len]) <= 0) THROW("Error copying signature 's' value to buffer"); - - result = 1; break; } #endif diff --git a/src/crypto/X509Crypto.cpp b/src/crypto/X509Crypto.cpp index bcf3a2b48..f51613c9e 100644 --- a/src/crypto/X509Crypto.cpp +++ b/src/crypto/X509Crypto.cpp @@ -211,28 +211,33 @@ bool X509Crypto::verify(const string &method, const vector &diges if(!key) THROW("Certificate does not have a public key, can not verify signature."); + SCOPE(EVP_PKEY_CTX, ctx, EVP_PKEY_CTX_new(key, nullptr)); int result = 0; switch(EVP_PKEY_base_id(key)) { case EVP_PKEY_RSA: { - SCOPE(RSA, rsa, EVP_PKEY_get1_RSA(key)); - auto decrypt = [&rsa, &signature](int padding) { - vector decrypted(size_t(RSA_size(rsa.get()))); - int size = RSA_public_decrypt(int(signature.size()), signature.data(), decrypted.data(), rsa.get(), padding); - if(size <= 0) - decrypted.clear(); - return decrypted; - }; int nid = Digest::toMethod(method); - if(Digest::isRsaPssUri(method)) { - vector decrypted = decrypt(RSA_NO_PADDING); - result = RSA_verify_PKCS1_PSS_mgf1(rsa.get(), digest.data(), EVP_get_digestbynid(nid), nullptr, decrypted.data(), RSA_PSS_SALTLEN_DIGEST); + if(ctx && + EVP_PKEY_verify_init(ctx.get()) == 1 && + EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING) == 1 && + EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx.get(), RSA_PSS_SALTLEN_DIGEST) == 1 && + EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_get_digestbynid(nid)) == 1) + result = EVP_PKEY_verify(ctx.get(), signature.data(), signature.size(), digest.data(), digest.size()); } else { - vector out = decrypt(RSA_PKCS1_PADDING); - const unsigned char *p = out.data(); - SCOPE(X509_SIG, sig, d2i_X509_SIG(nullptr, &p, long(out.size()))); + size_t size = 0; + if(!ctx || + EVP_PKEY_verify_recover_init(ctx.get()) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING) <= 0 || + EVP_PKEY_verify_recover(ctx.get(), nullptr, &size, signature.data(), signature.size()) <= 0) + break; + vector decrypted(size); + if(EVP_PKEY_verify_recover(ctx.get(), decrypted.data(), &size, signature.data(), signature.size()) <= 0) + break; + decrypted.resize(size); + const unsigned char *p = decrypted.data(); + SCOPE(X509_SIG, sig, d2i_X509_SIG(nullptr, &p, long(decrypted.size()))); if(!sig) break; const X509_ALGOR *algor = nullptr; @@ -251,12 +256,13 @@ bool X509Crypto::verify(const string &method, const vector &diges #ifndef OPENSSL_NO_ECDSA case EVP_PKEY_EC: { - SCOPE(EC_KEY, ec, EVP_PKEY_get1_EC_KEY(key)); SCOPE(ECDSA_SIG, sig, ECDSA_SIG_new()); ECDSA_SIG_set0(sig.get(), BN_bin2bn(signature.data(), int(signature.size()/2), nullptr), BN_bin2bn(&signature[signature.size()/2], int(signature.size()/2), nullptr)); - result = ECDSA_do_verify(digest.data(), int(digest.size()), sig.get(), ec.get()); + vector asn1 = i2d(sig.get(), i2d_ECDSA_SIG); + if(ctx && EVP_PKEY_verify_init(ctx.get()) == 1) + result = EVP_PKEY_verify(ctx.get(), asn1.data(), asn1.size(), digest.data(), digest.size()); break; } #endif