add Crypto PKCS12/EC; update VS projects

This commit is contained in:
Alex Fabijanic
2017-09-16 00:44:39 -05:00
parent 3f1e82ad86
commit e89e3745ee
85 changed files with 5061 additions and 1866 deletions

View File

@@ -0,0 +1,107 @@
//
// CryptoException.cpp
//
//
// Library: Crypto
// Package: Crypto
// Module: CryptoException
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/CryptoException.h"
#include "Poco/NumberFormatter.h"
#include <typeinfo>
namespace Poco {
namespace Crypto {
POCO_IMPLEMENT_EXCEPTION(CryptoException, Exception, "Crypto Exception")
OpenSSLException::OpenSSLException(int otherCode): CryptoException(otherCode)
{
setExtMessage();
}
OpenSSLException::OpenSSLException(const std::string& msg, int otherCode): CryptoException(msg, otherCode)
{
setExtMessage();
}
OpenSSLException::OpenSSLException(const std::string& msg, const std::string& arg, int otherCode): CryptoException(msg, arg, otherCode)
{
setExtMessage();
}
OpenSSLException::OpenSSLException(const std::string& msg, const Poco::Exception& exc, int otherCode): CryptoException(msg, exc, otherCode)
{
setExtMessage();
}
OpenSSLException::OpenSSLException(const OpenSSLException& exc): CryptoException(exc)
{
setExtMessage();
}
OpenSSLException::~OpenSSLException() throw()
{
}
OpenSSLException& OpenSSLException::operator = (const OpenSSLException& exc)
{
CryptoException::operator = (exc);
return *this;
}
const char* OpenSSLException::name() const throw()
{
return "OpenSSLException";
}
const char* OpenSSLException::className() const throw()
{
return typeid(*this).name();
}
Poco::Exception* OpenSSLException::clone() const
{
return new OpenSSLException(*this);
}
void OpenSSLException::setExtMessage()
{
unsigned long e = ERR_get_error();
char buf[128] = { 0 };
char* pErr = ERR_error_string(e, buf);
std::string err;
if (pErr) err = pErr;
else err = NumberFormatter::format(e);
extendedMessage(err);
}
void OpenSSLException::rethrow() const
{
throw *this;
}
} } // namespace Poco::Crypto

View File

@@ -0,0 +1,100 @@
//
// ECDSADigestEngine.cpp
//
//
// Library: Crypto
// Package: ECDSA
// Module: ECDSADigestEngine
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/ECDSADigestEngine.h"
#include <openssl/ecdsa.h>
namespace Poco {
namespace Crypto {
ECDSADigestEngine::ECDSADigestEngine(const ECKey& key, const std::string &name):
_key(key),
_engine(name)
{
}
ECDSADigestEngine::~ECDSADigestEngine()
{
}
std::size_t ECDSADigestEngine::digestLength() const
{
return _engine.digestLength();
}
void ECDSADigestEngine::reset()
{
_engine.reset();
_digest.clear();
_signature.clear();
}
const DigestEngine::Digest& ECDSADigestEngine::digest()
{
if (_digest.empty())
{
_digest = _engine.digest();
}
return _digest;
}
const DigestEngine::Digest& ECDSADigestEngine::signature()
{
if (_signature.empty())
{
digest();
_signature.resize(_key.size());
unsigned sigLen = static_cast<unsigned>(_signature.size());
if (!ECDSA_sign(0, &_digest[0], static_cast<unsigned>(_digest.size()),
&_signature[0], &sigLen, _key.impl()->getECKey()))
{
throw OpenSSLException();
}
if (sigLen < _signature.size()) _signature.resize(sigLen);
}
return _signature;
}
bool ECDSADigestEngine::verify(const DigestEngine::Digest& sig)
{
digest();
EC_KEY* pKey = _key.impl()->getECKey();
if (pKey)
{
int ret = ECDSA_verify(0, &_digest[0], static_cast<unsigned>(_digest.size()),
&sig[0], static_cast<unsigned>(sig.size()),
pKey);
if (1 == ret) return true;
else if (0 == ret) return false;
}
throw OpenSSLException();
}
void ECDSADigestEngine::updateImpl(const void* data, std::size_t length)
{
_engine.update(data, length);
}
} } // namespace Poco::Crypto

75
Crypto/src/ECKey.cpp Normal file
View File

@@ -0,0 +1,75 @@
//
// ECKey.cpp
//
//
// Library: Crypto
// Package: EC
// Module: ECKey
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/ECKey.h"
#include <openssl/rsa.h>
namespace Poco {
namespace Crypto {
ECKey::ECKey(const EVPPKey& key):
KeyPair(new ECKeyImpl(key)),
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
{
}
ECKey::ECKey(const X509Certificate& cert):
KeyPair(new ECKeyImpl(cert)),
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
{
}
ECKey::ECKey(const PKCS12Container& cont):
KeyPair(new ECKeyImpl(cont)),
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
{
}
ECKey::ECKey(const std::string& eccGroup):
KeyPair(new ECKeyImpl(OBJ_txt2nid(eccGroup.c_str()))),
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
{
}
ECKey::ECKey(const std::string& publicKeyFile,
const std::string& privateKeyFile,
const std::string& privateKeyPassphrase):
KeyPair(new ECKeyImpl(publicKeyFile, privateKeyFile, privateKeyPassphrase)),
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
{
}
ECKey::ECKey(std::istream* pPublicKeyStream,
std::istream* pPrivateKeyStream,
const std::string& privateKeyPassphrase):
KeyPair(new ECKeyImpl(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase)),
_pImpl(KeyPair::impl().cast<ECKeyImpl>())
{
}
ECKey::~ECKey()
{
}
} } // namespace Poco::Crypto

357
Crypto/src/ECKeyImpl.cpp Normal file
View File

@@ -0,0 +1,357 @@
//
// ECKeyImpl.cpp
//
//
// Library: Crypto
// Package: EC
// Module: ECKeyImpl
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/ECKeyImpl.h"
#include "Poco/Crypto/X509Certificate.h"
#include "Poco/Crypto/PKCS12Container.h"
#include "Poco/FileStream.h"
#include "Poco/StreamCopier.h"
#include <sstream>
#include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
#include <openssl/bn.h>
#endif
namespace Poco {
namespace Crypto {
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&)");
}
ECKeyImpl::ECKeyImpl(const X509Certificate& cert):
KeyPairImpl("ec", KT_EC_IMPL),
_pEC(0)
{
const X509* pCert = cert.certificate();
if (pCert)
{
EVP_PKEY* pKey = X509_get_pubkey(const_cast<X509*>(pCert));
if (pKey)
{
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
EVP_PKEY_free(pKey);
return;
}
}
throw OpenSSLException("ECKeyImpl(const X509Certificate&)");
}
ECKeyImpl::ECKeyImpl(const PKCS12Container& cont):
KeyPairImpl("ec", KT_EC_IMPL),
_pEC(EVP_PKEY_get1_EC_KEY(cont.getKey()))
{
if (!_pEC) throw OpenSSLException();
}
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)");
}
ECKeyImpl::ECKeyImpl(const std::string& publicKeyFile,
const std::string& privateKeyFile,
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
{
if (loadKey(PEM_read_PrivateKey, privateKeyFile, privateKeyPassphrase))
return; // private key is enough
// no private key, this must be public key only, otherwise throw
if (!loadKey(PEM_read_PUBKEY, publicKeyFile))
{
throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&");
}
}
ECKeyImpl::ECKeyImpl(std::istream* pPublicKeyStream,
std::istream* pPrivateKeyStream,
const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
{
if (loadKey(PEM_read_bio_PrivateKey, pPrivateKeyStream, privateKeyPassphrase))
return; // private key is enough
// no private key, this must be public key only, otherwise throw
if (!loadKey(PEM_read_bio_PUBKEY, pPublicKeyStream))
{
throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&");
}
}
ECKeyImpl::~ECKeyImpl()
{
freeEC();
}
void ECKeyImpl::freeEC()
{
if (_pEC)
{
EC_KEY_free(_pEC);
_pEC = 0;
}
}
int ECKeyImpl::passCB(char* buf, int size, int, void* pass)
{
int len = (int) strlen((char*)pass);
if (len > size) len = size;
memcpy(buf, pass, len);
return len;
}
bool ECKeyImpl::loadKey(PEM_read_Key_fn func, const std::string& keyFile, const std::string& pass)
{
if (!keyFile.empty())
{
EVP_PKEY* pKey = EVP_PKEY_new();
if (pKey)
{
FILE* pFile = fopen(keyFile.c_str(), "r");
if (pFile)
{
func(pFile, &pKey, passCB, pass.empty() ? (void*)0 : (void*)pass.c_str());
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
EVP_PKEY_free(pKey);
if (!_pEC) goto error;
return true;
}
else
{
EVP_PKEY_free(pKey);
throw IOException("ECKeyImpl, cannot open file", keyFile);
}
}
else goto error;
}
return false;
error:
throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&)");
}
bool ECKeyImpl::loadKey(PEM_read_bio_Key_fn func, std::istream* pIstr, const std::string& pass)
{
if (pIstr)
{
std::ostringstream ostr;
Poco::StreamCopier::copyStream(*pIstr, ostr);
std::string key = ostr.str();
BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(key.data()), static_cast<int>(key.size()));
if (pBIO)
{
EVP_PKEY* pKey = EVP_PKEY_new();
if (pKey)
{
if (func(pBIO, &pKey, passCB, pass.empty() ? (void*)0 : (void*)pass.c_str()))
{
_pEC = EVP_PKEY_get1_EC_KEY(pKey);
EVP_PKEY_free(pKey);
BIO_free(pBIO);
if (!_pEC) goto error;
return true;
}
goto error;
}
else
{
BIO_free(pBIO);
goto error;
}
}
else goto error;
}
return false;
error:
throw OpenSSLException("ECKeyImpl::ECKeyImpl(const string&, const string&, const string&)");
}
int ECKeyImpl::size() const
{
int sz = -1;
EVP_PKEY* pKey = EVP_PKEY_new();
if (pKey && EVP_PKEY_set1_EC_KEY(pKey, _pEC))
{
sz = EVP_PKEY_bits(pKey);
EVP_PKEY_free(pKey);
return sz;
}
throw OpenSSLException("ECKeyImpl::size()");
}
std::string ECKeyImpl::groupName() const
{
if (_pEC)
{
const EC_GROUP* ecGroup = EC_KEY_get0_group(_pEC);
if (ecGroup)
{
return OBJ_nid2sn(EC_GROUP_get_curve_name(ecGroup));
}
else
{
throw OpenSSLException("ECKeyImpl::groupName()");
}
}
throw NullPointerException("ECKeyImpl::groupName() => _pEC");
}
void ECKeyImpl::save(const std::string& publicKeyFile,
const std::string& privateKeyFile,
const std::string& privateKeyPassphrase)
{
if (!publicKeyFile.empty())
{
BIO* bio = BIO_new(BIO_s_file());
if (!bio) throw Poco::IOException("Cannot create BIO for writing public key file", publicKeyFile);
try
{
if (BIO_write_filename(bio, const_cast<char*>(publicKeyFile.c_str())))
{
EVPPKey pKey(_pEC);
if (!PEM_write_bio_PUBKEY(bio, pKey))
{
throw Poco::WriteFileException("Failed to write public key to file", publicKeyFile);
}
}
else throw Poco::CreateFileException("Cannot create public key file");
}
catch (...)
{
BIO_free(bio);
throw;
}
BIO_free(bio);
}
if (!privateKeyFile.empty())
{
BIO* bio = BIO_new(BIO_s_file());
if (!bio) throw Poco::IOException("Cannot create BIO for writing private key file", privateKeyFile);
try
{
if (BIO_write_filename(bio, const_cast<char*>(privateKeyFile.c_str())))
{
EVPPKey pKey(_pEC);
int rc = 0;
if (privateKeyPassphrase.empty())
{
rc = PEM_write_bio_PrivateKey(bio, pKey, 0, 0, 0, 0, 0);
}
else
{
rc = PEM_write_bio_PrivateKey(bio, pKey, EVP_des_ede3_cbc(),
reinterpret_cast<unsigned char*>(const_cast<char*>(privateKeyPassphrase.c_str())),
static_cast<int>(privateKeyPassphrase.length()), 0, 0);
}
if (!rc)
throw Poco::FileException("Failed to write private key to file", privateKeyFile);
}
else throw Poco::CreateFileException("Cannot create private key file", privateKeyFile);
}
catch (...)
{
BIO_free(bio);
throw;
}
BIO_free(bio);
}
}
void ECKeyImpl::save(std::ostream* pPublicKeyStream,
std::ostream* pPrivateKeyStream,
const std::string& privateKeyPassphrase)
{
if (pPublicKeyStream)
{
BIO* bio = BIO_new(BIO_s_mem());
if (!bio) throw Poco::IOException("Cannot create BIO for writing public key");
EVPPKey pKey(_pEC);
if (!PEM_write_bio_PUBKEY(bio, pKey))
{
BIO_free(bio);
throw Poco::WriteFileException("Failed to write public key to stream");
}
char* pData;
long size = BIO_get_mem_data(bio, &pData);
pPublicKeyStream->write(pData, static_cast<std::streamsize>(size));
BIO_free(bio);
}
if (pPrivateKeyStream)
{
BIO* bio = BIO_new(BIO_s_mem());
if (!bio) throw Poco::IOException("Cannot create BIO for writing public key");
EVPPKey pKey(_pEC);
int rc = 0;
if (privateKeyPassphrase.empty())
rc = PEM_write_bio_PrivateKey(bio, pKey, 0, 0, 0, 0, 0);
else
rc = PEM_write_bio_PrivateKey(bio, pKey, EVP_des_ede3_cbc(),
reinterpret_cast<unsigned char*>(const_cast<char*>(privateKeyPassphrase.c_str())),
static_cast<int>(privateKeyPassphrase.length()), 0, 0);
if (!rc)
{
BIO_free(bio);
throw Poco::FileException("Failed to write private key to stream");
}
char* pData;
long size = BIO_get_mem_data(bio, &pData);
pPrivateKeyStream->write(pData, static_cast<std::streamsize>(size));
BIO_free(bio);
}
}
ECKeyImpl::ByteVec ECKeyImpl::convertToByteVec(const BIGNUM* bn)
{
int numBytes = BN_num_bytes(bn);
ByteVec byteVector(numBytes);
ByteVec::value_type* buffer = new ByteVec::value_type[numBytes];
BN_bn2bin(bn, buffer);
for (int i = 0; i < numBytes; ++i)
byteVector[i] = buffer[i];
delete [] buffer;
return byteVector;
}
} } // namespace Poco::Crypto

134
Crypto/src/EVPPKey.cpp Normal file
View File

@@ -0,0 +1,134 @@
//
// EVPPKey.cpp
//
//
// Library: Crypto
// Package: CryptoCore
// Module: EVPPKey
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/EVPPKey.h"
#include "Poco/NumberFormatter.h"
namespace Poco {
namespace Crypto {
EVPPKey::EVPPKey(const std::string& ecCurveName): _pEVPPKey(0)
{
newECKey(ecCurveName.c_str());
}
EVPPKey::EVPPKey(const char* ecCurveName): _pEVPPKey(0)
{
newECKey(ecCurveName);
}
EVPPKey::EVPPKey(EVP_PKEY* pEVPPKey): _pEVPPKey(0)
{
duplicate(pEVPPKey);
}
EVPPKey::EVPPKey(const EVPPKey& other)
{
duplicate(other._pEVPPKey);
}
EVPPKey& EVPPKey::operator=(const EVPPKey& other)
{
duplicate(other._pEVPPKey);
return *this;
}
#ifdef POCO_ENABLE_CPP11
EVPPKey::EVPPKey(EVPPKey&& other): _pEVPPKey(other._pEVPPKey)
{
other._pEVPPKey = nullptr;
}
EVPPKey& EVPPKey::operator=(EVPPKey&& other)
{
_pEVPPKey = other._pEVPPKey;
other._pEVPPKey = nullptr;
return *this;
}
#endif // POCO_ENABLE_CPP11
EVPPKey::~EVPPKey()
{
if (_pEVPPKey) EVP_PKEY_free(_pEVPPKey);
}
void EVPPKey::duplicate(EVP_PKEY* pEVPPKey)
{
if (!pEVPPKey) throw NullPointerException("EVPPKey::duplicate(): "
"provided key pointer is null.");
_pEVPPKey = EVP_PKEY_new();
if (!_pEVPPKey) throw NullPointerException("EVPPKey::duplicate(): "
"EVP_PKEY_new() returned null.");
switch (pEVPPKey->type)
{
case EVP_PKEY_RSA:
{
RSA* pRSA = EVP_PKEY_get1_RSA(pEVPPKey);
if (pRSA)
{
EVP_PKEY_set1_RSA(_pEVPPKey, pRSA);
RSA_free(pRSA);
}
else throw OpenSSLException();
break;
}
case EVP_PKEY_EC:
{
EC_KEY* pEC = EVP_PKEY_get1_EC_KEY(pEVPPKey);
if (pEC)
{
EVP_PKEY_set1_EC_KEY(_pEVPPKey, pEC);
EC_KEY_free(pEC);
}
else throw OpenSSLException();
break;
}
default:
throw NotImplementedException("EVPPKey:duplicate(); Key type: " +
NumberFormatter::format(pEVPPKey->type));
}
}
void EVPPKey::newECKey(const char* ecCurveName)
{
int curveID = OBJ_txt2nid(ecCurveName);
EC_KEY* pEC = EC_KEY_new_by_curve_name(curveID);
if (!pEC) goto err;
if (!EC_KEY_generate_key(pEC)) goto err;
_pEVPPKey = EVP_PKEY_new();
if (!_pEVPPKey) goto err;
if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pEC)) goto err;
EC_KEY_free(pEC);
return;
err:
throw OpenSSLException();
}
} } // namespace Poco::Crypto

34
Crypto/src/KeyPair.cpp Normal file
View File

@@ -0,0 +1,34 @@
//
// KeyPair.cpp
//
//
// Library: Crypto
// Package: CryptoCore
// Module: KeyPair
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/KeyPair.h"
#include <openssl/rsa.h>
namespace Poco {
namespace Crypto {
KeyPair::KeyPair(KeyPairImpl::Ptr pKeyPairImpl): _pImpl(pKeyPairImpl)
{
}
KeyPair::~KeyPair()
{
}
} } // namespace Poco::Crypto

View File

@@ -0,0 +1,35 @@
//
// KeyPairImpl.cpp
//
//
// Library: Crypto
// Package: CryptoCore
// Module: KeyPairImpl
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/KeyPairImpl.h"
namespace Poco {
namespace Crypto {
KeyPairImpl::KeyPairImpl(const std::string& name, Type type):
_name(name),
_type(type)
{
}
KeyPairImpl::~KeyPairImpl()
{
}
} } // namespace Poco::Crypto

View File

@@ -0,0 +1,135 @@
//
// PKCS12Container.cpp
//
//
// Library: Crypto
// Package: Certificate
// Module: PKCS12Container
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Crypto/PKCS12Container.h"
#include "Poco/NumberFormatter.h"
#include "Poco/StreamCopier.h"
#include <sstream>
#include <openssl/err.h>
namespace Poco {
namespace Crypto {
PKCS12Container::PKCS12Container(std::istream& istr, const std::string& password): _pKey(0)
{
std::ostringstream ostr;
Poco::StreamCopier::copyStream(istr, ostr);
const std::string& cont = ostr.str();
BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(cont.data()), static_cast<int>(cont.size()));
if (pBIO)
{
PKCS12* pPKCS12 = 0;
d2i_PKCS12_bio(pBIO, &pPKCS12);
BIO_free(pBIO);
if (!pPKCS12) throw OpenSSLException();
load(pPKCS12, password);
}
else
{
throw OpenSSLException();
}
}
PKCS12Container::PKCS12Container(const std::string& path, const std::string& password): _pKey(0)
{
FILE* pFile = fopen(path.c_str(), "rb");
if (pFile)
{
PKCS12* pPKCS12 = d2i_PKCS12_fp(pFile, NULL);
fclose (pFile);
if (!pPKCS12) throw OpenSSLException();
load(pPKCS12, password);
}
else
{
throw Poco::OpenFileException("PKCS12Container: " + path);
}
}
PKCS12Container::PKCS12Container(const PKCS12Container& cont)
{
}
PKCS12Container& PKCS12Container::operator = (const PKCS12Container& cert)
{
return *this;
}
PKCS12Container::~PKCS12Container()
{
if (_pKey) EVP_PKEY_free(_pKey);
}
void PKCS12Container::load(PKCS12* pPKCS12, const std::string& password)
{
if (pPKCS12)
{
X509* pCert = 0;
STACK_OF(X509)* pCA = 0;
if (PKCS12_parse(pPKCS12, password.c_str(), &_pKey, &pCert, &pCA))
{
if (pCert)
{
STACK_OF(PKCS12_SAFEBAG)* pBags = 0;
_pX509Cert.reset(new X509Certificate(pCert, true));
PKCS12_SAFEBAG* pBag = PKCS12_add_cert(&pBags, pCert);
if (pBag)
{
char*pBuffer = PKCS12_get_friendlyname(pBag);
if(pBuffer)
{
_pkcsFriendlyname = pBuffer;
CRYPTO_free(pBuffer);
}else _pkcsFriendlyname.clear();
if(pBags) sk_PKCS12_SAFEBAG_pop_free(pBags, PKCS12_SAFEBAG_free);
}
else throw OpenSSLException();
}
else _pX509Cert.reset();
_caCertList.clear();
if (pCA)
{
int certCount = sk_X509_num(pCA);
for (int i = 0; i < certCount; ++i)
{
_caCertList.push_back(X509Certificate(sk_X509_value(pCA, i), true));
}
}
}
else
{
throw OpenSSLException();
}
PKCS12_free(pPKCS12);
sk_X509_pop_free(pCA, X509_free);
X509_free(pCert);
}
else
{
throw NullPointerException("PKCS12Container: struct PKCS12");
}
}
} } // namespace Poco::Crypto

View File

@@ -18,6 +18,10 @@
#include "Poco/DateTimeParser.h"
#include <sstream>
#include <openssl/pem.h>
#ifdef _WIN32
// fix for WIN32 header conflict
#undef X509_NAME
#endif
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -29,7 +33,7 @@ namespace Crypto {
X509Certificate::X509Certificate(std::istream& istr):
_pCert(0)
{
{
load(istr);
}
@@ -103,17 +107,17 @@ X509Certificate::~X509Certificate()
void X509Certificate::load(std::istream& istr)
{
poco_assert (!_pCert);
std::stringstream certStream;
Poco::StreamCopier::copyStream(istr, certStream);
std::string cert = certStream.str();
BIO *pBIO = BIO_new_mem_buf(const_cast<char*>(cert.data()), static_cast<int>(cert.size()));
if (!pBIO) throw Poco::IOException("Cannot create BIO for reading certificate");
_pCert = PEM_read_bio_X509(pBIO, 0, 0, 0);
BIO_free(pBIO);
if (!_pCert) throw Poco::IOException("Faild to load certificate from stream");
if (!_pCert) throw Poco::IOException("Failed to load certificate from stream");
init();
}
@@ -130,10 +134,10 @@ void X509Certificate::load(const std::string& path)
BIO_free(pBIO);
throw Poco::OpenFileException("Cannot open certificate file for reading", path);
}
_pCert = PEM_read_bio_X509(pBIO, 0, 0, 0);
BIO_free(pBIO);
if (!_pCert) throw Poco::ReadFileException("Faild to load certificate from", path);
init();
@@ -205,24 +209,24 @@ std::string X509Certificate::commonName() const
std::string X509Certificate::issuerName(NID nid) const
{
if (X509_NAME* issuer = X509_get_issuer_name(_pCert))
{
{
char buffer[NAME_BUFFER_SIZE];
if (X509_NAME_get_text_by_NID(issuer, nid, buffer, sizeof(buffer)) >= 0)
return std::string(buffer);
}
return std::string();
}
return std::string();
}
std::string X509Certificate::subjectName(NID nid) const
{
if (X509_NAME* subj = X509_get_subject_name(_pCert))
{
{
char buffer[NAME_BUFFER_SIZE];
if (X509_NAME_get_text_by_NID(subj, nid, buffer, sizeof(buffer)) >= 0)
return std::string(buffer);
}
return std::string();
}
return std::string();
}
@@ -230,16 +234,16 @@ void X509Certificate::extractNames(std::string& cmnName, std::set<std::string>&
{
domainNames.clear();
if (STACK_OF(GENERAL_NAME)* names = static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(_pCert, NID_subject_alt_name, 0, 0)))
{
{
for (int i = 0; i < sk_GENERAL_NAME_num(names); ++i)
{
{
const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
if (name->type == GEN_DNS)
{
const char* data = reinterpret_cast<char*>(ASN1_STRING_data(name->d.ia5));
std::size_t len = ASN1_STRING_length(name->d.ia5);
domainNames.insert(std::string(data, len));
}
}
}
GENERAL_NAMES_free(names);
}
@@ -290,4 +294,19 @@ bool X509Certificate::equals(const X509Certificate& otherCertificate) const
}
void X509Certificate::print(std::ostream& out) const
{
out << "subjectName: " << subjectName() << std::endl;
out << "issuerName: " << issuerName() << std::endl;
out << "commonName: " << commonName() << std::endl;
out << "country: " << subjectName(X509Certificate::NID_COUNTRY) << std::endl;
out << "localityName: " << subjectName(X509Certificate::NID_LOCALITY_NAME) << std::endl;
out << "stateOrProvince: " << subjectName(X509Certificate::NID_STATE_OR_PROVINCE) << std::endl;
out << "organizationName: " << subjectName(X509Certificate::NID_ORGANIZATION_NAME) << std::endl;
out << "organizationUnitName: " << subjectName(X509Certificate::NID_ORGANIZATION_UNIT_NAME) << std::endl;
out << "emailAddress: " << subjectName(X509Certificate::NID_PKCS9_EMAIL_ADDRESS) << std::endl;
out << "serialNumber: " << subjectName(X509Certificate::NID_SERIAL_NUMBER) << std::endl;
}
} } // namespace Poco::Crypto