mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-30 13:47:10 +01:00
fix incomplete EC key creation from curve name; make sure tests use curves that exist; add validation checks on EC key creation
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "Poco/Crypto/X509Certificate.h"
|
||||
#include "Poco/Crypto/PKCS12Container.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/Format.h"
|
||||
#include <sstream>
|
||||
#include <openssl/evp.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
|
||||
@@ -32,7 +33,7 @@ ECKeyImpl::ECKeyImpl(const EVPPKey& key):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>((const EVP_PKEY*)key)))
|
||||
{
|
||||
if (!_pEC) throw OpenSSLException("ECKeyImpl(const EVPPKey&)");
|
||||
checkEC("ECKeyImpl(const EVPPKey&)", "EVP_PKEY_get1_EC_KEY()");
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +49,7 @@ ECKeyImpl::ECKeyImpl(const X509Certificate& cert):
|
||||
{
|
||||
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
|
||||
EVP_PKEY_free(pKey);
|
||||
checkEC("ECKeyImpl(const const X509Certificate&)", "EVP_PKEY_get1_EC_KEY()");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -59,7 +61,7 @@ ECKeyImpl::ECKeyImpl(const PKCS12Container& cont):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(EVP_PKEY_get1_EC_KEY(cont.getKey()))
|
||||
{
|
||||
if (!_pEC) throw OpenSSLException();
|
||||
checkEC("ECKeyImpl(const PKCS12Container&)", "EVP_PKEY_get1_EC_KEY()");
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +69,11 @@ ECKeyImpl::ECKeyImpl(int curve):
|
||||
KeyPairImpl("ec", KT_EC_IMPL),
|
||||
_pEC(EC_KEY_new_by_curve_name(curve))
|
||||
{
|
||||
if (!EC_KEY_generate_key(_pEC))
|
||||
throw OpenSSLException("ECKeyImpl(int)");
|
||||
poco_check_ptr(_pEC);
|
||||
EC_KEY_set_asn1_flag(_pEC, OPENSSL_EC_NAMED_CURVE);
|
||||
if (!(EC_KEY_generate_key(_pEC)))
|
||||
throw OpenSSLException("ECKeyImpl(int curve): EC_KEY_generate_key()");
|
||||
checkEC("ECKeyImpl(int curve)", "EC_KEY_generate_key()");
|
||||
}
|
||||
|
||||
|
||||
@@ -77,13 +82,21 @@ ECKeyImpl::ECKeyImpl(const std::string& publicKeyFile,
|
||||
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
|
||||
{
|
||||
if (EVPPKey::loadKey(&_pEC, PEM_read_PrivateKey, EVP_PKEY_get1_EC_KEY, privateKeyFile, privateKeyPassphrase))
|
||||
{
|
||||
checkEC(Poco::format("ECKeyImpl(%s, %s, %s)",
|
||||
publicKeyFile, privateKeyFile, privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
|
||||
"PEM_read_PrivateKey() or EVP_PKEY_get1_EC_KEY()");
|
||||
return; // private key is enough
|
||||
}
|
||||
|
||||
// no private key, this must be public key only, otherwise throw
|
||||
if (!EVPPKey::loadKey(&_pEC, PEM_read_PUBKEY, EVP_PKEY_get1_EC_KEY, publicKeyFile))
|
||||
{
|
||||
throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&");
|
||||
}
|
||||
checkEC(Poco::format("ECKeyImpl(%s, %s, %s)",
|
||||
publicKeyFile, privateKeyFile, privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
|
||||
"PEM_read_PUBKEY() or EVP_PKEY_get1_EC_KEY()");
|
||||
}
|
||||
|
||||
|
||||
@@ -92,13 +105,21 @@ ECKeyImpl::ECKeyImpl(std::istream* pPublicKeyStream,
|
||||
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
|
||||
{
|
||||
if (EVPPKey::loadKey(&_pEC, PEM_read_bio_PrivateKey, EVP_PKEY_get1_EC_KEY, pPrivateKeyStream, privateKeyPassphrase))
|
||||
{
|
||||
checkEC(Poco::format("ECKeyImpl(stream, stream, %s)",
|
||||
privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
|
||||
"PEM_read_bio_PrivateKey() or EVP_PKEY_get1_EC_KEY()");
|
||||
return; // private key is enough
|
||||
}
|
||||
|
||||
// no private key, this must be public key only, otherwise throw
|
||||
if (!EVPPKey::loadKey(&_pEC, PEM_read_bio_PUBKEY, EVP_PKEY_get1_EC_KEY, pPublicKeyStream))
|
||||
{
|
||||
throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&");
|
||||
}
|
||||
checkEC(Poco::format("ECKeyImpl(stream, stream, %s)",
|
||||
privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
|
||||
"PEM_read_bio_PUBKEY() or EVP_PKEY_get1_EC_KEY()");
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +129,14 @@ ECKeyImpl::~ECKeyImpl()
|
||||
}
|
||||
|
||||
|
||||
void ECKeyImpl::checkEC(const std::string& method, const std::string& func) const
|
||||
{
|
||||
if (!_pEC) throw OpenSSLException(Poco::format("%s: %s", method, func));
|
||||
if (!EC_KEY_check_key(_pEC))
|
||||
throw OpenSSLException(Poco::format("%s: EC_KEY_check_key()", method));
|
||||
}
|
||||
|
||||
|
||||
void ECKeyImpl::freeEC()
|
||||
{
|
||||
if (_pEC)
|
||||
@@ -150,4 +179,28 @@ int ECKeyImpl::groupId() const
|
||||
}
|
||||
|
||||
|
||||
std::string ECKeyImpl::getCurveName(int nid)
|
||||
{
|
||||
std::string curveName;
|
||||
size_t len = EC_get_builtin_curves(NULL, 0);
|
||||
EC_builtin_curve* pCurves =
|
||||
(EC_builtin_curve*) OPENSSL_malloc(sizeof(EC_builtin_curve) * len);
|
||||
if (!pCurves) return curveName;
|
||||
|
||||
if (!EC_get_builtin_curves(pCurves, len))
|
||||
{
|
||||
OPENSSL_free(pCurves);
|
||||
return curveName;
|
||||
}
|
||||
|
||||
if (-1 == nid) nid = pCurves[0].nid;
|
||||
int bufLen = 128;
|
||||
char buf[bufLen] = {0};
|
||||
OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
|
||||
curveName = buf;
|
||||
OPENSSL_free(pCurves);
|
||||
return curveName;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Crypto
|
||||
|
||||
Reference in New Issue
Block a user