EVPPKey == operator; PKCS12 copy/move

This commit is contained in:
Alex Fabijanic 2017-09-26 15:28:23 -05:00
parent dc2c4dcd27
commit 4ac56bff0c
7 changed files with 149 additions and 27 deletions

View File

@ -85,16 +85,33 @@ public:
/// Assignment operator.
#ifdef POCO_ENABLE_CPP11
EVPPKey(EVPPKey&& other);
/// Move constructor.
EVPPKey& operator=(EVPPKey&& other);
/// Assignment move operator.
#endif // POCO_ENABLE_CPP11
~EVPPKey();
/// Destroys the EVPPKey.
bool operator == (const EVPPKey& other) const;
/// Comparison operator.
/// Returns true if public key components and parameters
/// of the other key are equal to this key.
///
/// Works as expected when one key contains only public key,
/// while the other one contains private (thus also public) key.
bool operator != (const EVPPKey& other) const;
/// Comparison operator.
/// Returns true if public key components and parameters
/// of the other key are different from this key.
///
/// Works as expected when one key contains only public key,
/// while the other one contains private (thus also public) key.
void save(const std::string& publicKeyFile, const std::string& privateKeyFile = "", const std::string& privateKeyPassphrase = "") const;
/// Exports the public and/or private keys to the given files.
///
@ -119,10 +136,14 @@ public:
operator EVP_PKEY*();
/// Returns pointer to the OpenSSL EVP_PKEY structure.
static EVP_PKEY* duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey);
/// Duplicates pFromKey into *pToKey and returns
// the pointer to duplicated EVP_PKEY.
private:
EVPPKey();
static int type(EVP_PKEY* pEVPPKey);
static int type(const EVP_PKEY* pEVPPKey);
void newECKey(const char* group);
void duplicate(EVP_PKEY* pEVPPKey);
@ -248,7 +269,20 @@ private:
// inlines
//
inline int EVPPKey::type(EVP_PKEY* pEVPPKey)
inline bool EVPPKey::operator == (const EVPPKey& other) const
{
poco_assert_dbg(other._pEVPPKey && _pEVPPKey);
return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey));
}
inline bool EVPPKey::operator != (const EVPPKey& other) const
{
return !(other == *this);
}
inline int EVPPKey::type(const EVP_PKEY* pEVPPKey)
{
if (!pEVPPKey) return NID_undef;

View File

@ -46,12 +46,22 @@ public:
explicit PKCS12Container(const std::string& str, const std::string& password = "");
/// Creates the PKCS12Container object from a string.
PKCS12Container(const PKCS12Container& cert);
PKCS12Container(const PKCS12Container& cont);
/// Copy constructor.
PKCS12Container& operator = (const PKCS12Container& cert);
PKCS12Container& operator = (const PKCS12Container& cont);
/// Assignment operator.
#ifdef POCO_ENABLE_CPP11
PKCS12Container(PKCS12Container&& cont);
/// Move constructor.
PKCS12Container& operator = (PKCS12Container&& cont);
/// Move assignment operator.
#endif // POCO_ENABLE_CPP11
~PKCS12Container();
/// Destroys the PKCS12Container.

View File

@ -37,7 +37,7 @@ EVPPKey::EVPPKey(const char* ecCurveName): _pEVPPKey(0)
EVPPKey::EVPPKey(EVP_PKEY* pEVPPKey): _pEVPPKey(0)
{
duplicate(pEVPPKey);
duplicate(pEVPPKey, &_pEVPPKey);
}
@ -73,13 +73,13 @@ EVPPKey::EVPPKey(std::istream* pPublicKeyStream,
EVPPKey::EVPPKey(const EVPPKey& other)
{
duplicate(other._pEVPPKey);
duplicate(other._pEVPPKey, &_pEVPPKey);
}
EVPPKey& EVPPKey::operator=(const EVPPKey& other)
{
duplicate(other._pEVPPKey);
duplicate(other._pEVPPKey, &_pEVPPKey);
return *this;
}
@ -207,24 +207,24 @@ void EVPPKey::save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStre
}
void EVPPKey::duplicate(EVP_PKEY* pEVPPKey)
EVP_PKEY* EVPPKey::duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey)
{
if (!pEVPPKey) throw NullPointerException("EVPPKey::duplicate(): "
if (!pFromKey) throw NullPointerException("EVPPKey::duplicate(): "
"provided key pointer is null.");
_pEVPPKey = EVP_PKEY_new();
if (!_pEVPPKey) throw NullPointerException("EVPPKey::duplicate(): "
*pToKey = EVP_PKEY_new();
if (!*pToKey) throw NullPointerException("EVPPKey::duplicate(): "
"EVP_PKEY_new() returned null.");
int keyType = type(pEVPPKey);
int keyType = type(pFromKey);
switch (keyType)
{
case EVP_PKEY_RSA:
{
RSA* pRSA = EVP_PKEY_get1_RSA(pEVPPKey);
RSA* pRSA = EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pFromKey));
if (pRSA)
{
EVP_PKEY_set1_RSA(_pEVPPKey, pRSA);
EVP_PKEY_set1_RSA(*pToKey, pRSA);
RSA_free(pRSA);
}
else throw OpenSSLException();
@ -232,10 +232,10 @@ void EVPPKey::duplicate(EVP_PKEY* pEVPPKey)
}
case EVP_PKEY_EC:
{
EC_KEY* pEC = EVP_PKEY_get1_EC_KEY(pEVPPKey);
EC_KEY* pEC = EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pFromKey));
if (pEC)
{
EVP_PKEY_set1_EC_KEY(_pEVPPKey, pEC);
EVP_PKEY_set1_EC_KEY(*pToKey, pEC);
EC_KEY_free(pEC);
}
else throw OpenSSLException();
@ -245,6 +245,7 @@ void EVPPKey::duplicate(EVP_PKEY* pEVPPKey)
throw NotImplementedException("EVPPKey:duplicate(); Key type: " +
NumberFormatter::format(keyType));
}
return *pToKey;
}

View File

@ -24,7 +24,7 @@ namespace Poco {
namespace Crypto {
PKCS12Container::PKCS12Container(std::istream& istr, const std::string& password): _pKey(0)
PKCS12Container::PKCS12Container(std::istream& istr, const std::string& password): _pKey(0)
{
std::ostringstream ostr;
Poco::StreamCopier::copyStream(istr, ostr);
@ -36,12 +36,12 @@ namespace Crypto {
PKCS12* pPKCS12 = 0;
d2i_PKCS12_bio(pBIO, &pPKCS12);
BIO_free(pBIO);
if (!pPKCS12) throw OpenSSLException();
if (!pPKCS12) throw OpenSSLException("PKCS12Container(istream&, const string&)");
load(pPKCS12, password);
}
else
{
throw OpenSSLException();
throw Poco::NullPointerException("PKCS12Container(istream&, const string&)");
}
}
@ -53,7 +53,7 @@ PKCS12Container::PKCS12Container(const std::string& path, const std::string& pas
{
PKCS12* pPKCS12 = d2i_PKCS12_fp(pFile, NULL);
fclose (pFile);
if (!pPKCS12) throw OpenSSLException();
if (!pPKCS12) throw OpenSSLException("PKCS12Container(const string&, const string&)");
load(pPKCS12, password);
}
else
@ -63,17 +63,59 @@ PKCS12Container::PKCS12Container(const std::string& path, const std::string& pas
}
PKCS12Container::PKCS12Container(const PKCS12Container& cont)
PKCS12Container::PKCS12Container(const PKCS12Container& other):
_pKey(EVPPKey::duplicate(other._pKey, &_pKey)),
_pX509Cert(new X509Certificate(*other._pX509Cert)),
_caCertList(other._caCertList),
_pkcsFriendlyname(other._pkcsFriendlyname)
{
}
PKCS12Container& PKCS12Container::operator = (const PKCS12Container& cert)
PKCS12Container& PKCS12Container::operator = (const PKCS12Container& other)
{
if (&other != this)
{
if (_pKey) EVP_PKEY_free(_pKey);
_pKey = EVPPKey::duplicate(other._pKey, &_pKey);
_pX509Cert.reset(new X509Certificate(*other._pX509Cert));
_caCertList = other._caCertList;
_pkcsFriendlyname = other._pkcsFriendlyname;
}
return *this;
}
#ifdef POCO_ENABLE_CPP11
PKCS12Container::PKCS12Container(PKCS12Container&& other):
_pKey(other._pKey),
_pX509Cert(std::move(other._pX509Cert)),
_caCertList(std::move(other._caCertList)),
_pkcsFriendlyname(std::move(other._pkcsFriendlyname))
{
other._pKey = 0;
}
PKCS12Container& PKCS12Container::operator = (PKCS12Container&& other)
{
if (&other != this)
{
if (_pKey) EVP_PKEY_free(_pKey);
_pKey = other._pKey; other._pKey = 0;
_pX509Cert = std::move(other._pX509Cert);
_caCertList = std::move(other._caCertList);
_pkcsFriendlyname = std::move(other._pkcsFriendlyname);
}
return *this;
}
#endif // POCO_ENABLE_CPP11
PKCS12Container::~PKCS12Container()
{
if (_pKey) EVP_PKEY_free(_pKey);

View File

@ -157,6 +157,16 @@ void EVPTest::testRSAEVPSaveLoadStream()
std::istringstream iPub(pubKey);
std::istringstream iPriv(privKey);
EVPPKey key2(&iPub, &iPriv, "testpwd");
assert (key == key2);
assert (!(key != key2));
RSAKey rsaKeyNE(RSAKey::KL_1024, RSAKey::EXP_LARGE);
EVPPKey keyNE(&rsaKeyNE);
assert (key != keyNE);
assert (!(key == keyNE));
assert (key2 != keyNE);;
assert (!(key2 == keyNE));
std::ostringstream strPub2;
std::ostringstream strPriv2;
key2.save(&strPub2, &strPriv2, "testpwd");
@ -301,6 +311,16 @@ void EVPTest::testECEVPSaveLoadStream()
std::istringstream iPub(pubKey);
std::istringstream iPriv(privKey);
EVPPKey key2(&iPub, &iPriv, "testpwd");
assert (key == key2);
assert (!(key != key2));
ECKey ecKeyNE("secp112r2");
EVPPKey keyNE(&ecKeyNE);
assert (key != keyNE);
assert (!(key == keyNE));
assert (key2 != keyNE);
assert (!(key2 == keyNE));
std::ostringstream strPub2;
std::ostringstream strPriv2;
key2.save(&strPub2, &strPriv2, "testpwd");

View File

@ -45,7 +45,26 @@ void PKCS12ContainerTest::testFullPKCS12()
full(PKCS12Container(file.c_str(), "crypto"));
std::ifstream ifs(file.c_str(), std::ios::binary);
full(PKCS12Container(ifs, "crypto"));
PKCS12Container pkcs(ifs, "crypto");
full(pkcs);
PKCS12Container pkcs2(pkcs);
full(pkcs2);
PKCS12Container pkcs3(pkcs);
pkcs3 = pkcs2;
full(pkcs3);
#ifdef POCO_ENABLE_CPP11
pkcs3 = std::move(pkcs);
full(pkcs3);
PKCS12Container pkcs4(std::move(pkcs2));
full(pkcs4);
#endif // POCO_ENABLE_CPP11
}
catch (Poco::Exception& ex)
{

View File

@ -40,10 +40,6 @@
// #define POCO_NO_AUTOMATIC_LIB_INIT
// Comment to enable using of internally built OpenSSL
// #define POCO_EXTERNAL_OPENSSL
// Define to disable FPEnvironment support
// #define POCO_NO_FPENVIRONMENT