aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/Crypto/src
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/poco/Crypto/src
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/poco/Crypto/src')
-rw-r--r--contrib/libs/poco/Crypto/src/Cipher.cpp140
-rw-r--r--contrib/libs/poco/Crypto/src/CipherFactory.cpp65
-rw-r--r--contrib/libs/poco/Crypto/src/CipherImpl.cpp272
-rw-r--r--contrib/libs/poco/Crypto/src/CipherKey.cpp49
-rw-r--r--contrib/libs/poco/Crypto/src/CipherKeyImpl.cpp224
-rw-r--r--contrib/libs/poco/Crypto/src/CryptoException.cpp108
-rw-r--r--contrib/libs/poco/Crypto/src/CryptoStream.cpp355
-rw-r--r--contrib/libs/poco/Crypto/src/CryptoTransform.cpp38
-rw-r--r--contrib/libs/poco/Crypto/src/DigestEngine.cpp80
-rw-r--r--contrib/libs/poco/Crypto/src/ECDSADigestEngine.cpp100
-rw-r--r--contrib/libs/poco/Crypto/src/ECKey.cpp75
-rw-r--r--contrib/libs/poco/Crypto/src/ECKeyImpl.cpp258
-rw-r--r--contrib/libs/poco/Crypto/src/EVPPKey.cpp321
-rw-r--r--contrib/libs/poco/Crypto/src/KeyPair.cpp34
-rw-r--r--contrib/libs/poco/Crypto/src/KeyPairImpl.cpp35
-rw-r--r--contrib/libs/poco/Crypto/src/OpenSSLInitializer.cpp190
-rw-r--r--contrib/libs/poco/Crypto/src/PKCS12Container.cpp202
-rw-r--r--contrib/libs/poco/Crypto/src/RSACipherImpl.cpp344
-rw-r--r--contrib/libs/poco/Crypto/src/RSADigestEngine.cpp96
-rw-r--r--contrib/libs/poco/Crypto/src/RSAKey.cpp87
-rw-r--r--contrib/libs/poco/Crypto/src/RSAKeyImpl.cpp386
-rw-r--r--contrib/libs/poco/Crypto/src/X509Certificate.cpp386
22 files changed, 3845 insertions, 0 deletions
diff --git a/contrib/libs/poco/Crypto/src/Cipher.cpp b/contrib/libs/poco/Crypto/src/Cipher.cpp
new file mode 100644
index 0000000000..8b4d57964f
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/Cipher.cpp
@@ -0,0 +1,140 @@
+//
+// Cipher.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: Cipher
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/Cipher.h"
+#include "Poco/Crypto/CryptoStream.h"
+#include "Poco/Crypto/CryptoTransform.h"
+#include "Poco/Base64Encoder.h"
+#include "Poco/Base64Decoder.h"
+#include "Poco/HexBinaryEncoder.h"
+#include "Poco/HexBinaryDecoder.h"
+#include "Poco/StreamCopier.h"
+#include "Poco/Exception.h"
+#include <sstream>
+#include <memory>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+Cipher::Cipher()
+{
+}
+
+
+Cipher::~Cipher()
+{
+}
+
+
+std::string Cipher::encryptString(const std::string& str, Encoding encoding)
+{
+ std::istringstream source(str);
+ std::ostringstream sink;
+
+ encrypt(source, sink, encoding);
+
+ return sink.str();
+}
+
+
+std::string Cipher::decryptString(const std::string& str, Encoding encoding)
+{
+ std::istringstream source(str);
+ std::ostringstream sink;
+
+ decrypt(source, sink, encoding);
+ return sink.str();
+}
+
+
+void Cipher::encrypt(std::istream& source, std::ostream& sink, Encoding encoding)
+{
+ CryptoInputStream encryptor(source, createEncryptor());
+
+ switch (encoding)
+ {
+ case ENC_NONE:
+ StreamCopier::copyStream(encryptor, sink);
+ break;
+
+ case ENC_BASE64:
+ case ENC_BASE64_NO_LF:
+ {
+ Poco::Base64Encoder encoder(sink);
+ if (encoding == ENC_BASE64_NO_LF)
+ {
+ encoder.rdbuf()->setLineLength(0);
+ }
+ StreamCopier::copyStream(encryptor, encoder);
+ encoder.close();
+ }
+ break;
+
+ case ENC_BINHEX:
+ case ENC_BINHEX_NO_LF:
+ {
+ Poco::HexBinaryEncoder encoder(sink);
+ if (encoding == ENC_BINHEX_NO_LF)
+ {
+ encoder.rdbuf()->setLineLength(0);
+ }
+ StreamCopier::copyStream(encryptor, encoder);
+ encoder.close();
+ }
+ break;
+
+ default:
+ throw Poco::InvalidArgumentException("Invalid argument", "encoding");
+ }
+}
+
+
+void Cipher::decrypt(std::istream& source, std::ostream& sink, Encoding encoding)
+{
+ CryptoOutputStream decryptor(sink, createDecryptor());
+
+ switch (encoding)
+ {
+ case ENC_NONE:
+ StreamCopier::copyStream(source, decryptor);
+ decryptor.close();
+ break;
+
+ case ENC_BASE64:
+ case ENC_BASE64_NO_LF:
+ {
+ Poco::Base64Decoder decoder(source);
+ StreamCopier::copyStream(decoder, decryptor);
+ decryptor.close();
+ }
+ break;
+
+ case ENC_BINHEX:
+ case ENC_BINHEX_NO_LF:
+ {
+ Poco::HexBinaryDecoder decoder(source);
+ StreamCopier::copyStream(decoder, decryptor);
+ decryptor.close();
+ }
+ break;
+
+ default:
+ throw Poco::InvalidArgumentException("Invalid argument", "encoding");
+ }
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/CipherFactory.cpp b/contrib/libs/poco/Crypto/src/CipherFactory.cpp
new file mode 100644
index 0000000000..28ba374864
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CipherFactory.cpp
@@ -0,0 +1,65 @@
+//
+// CipherFactory.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: CipherFactory
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/CipherFactory.h"
+#include "Poco/Crypto/Cipher.h"
+#include "Poco/Crypto/CipherKey.h"
+#include "Poco/Crypto/RSAKey.h"
+#include "Poco/Crypto/CipherImpl.h"
+#include "Poco/Crypto/RSACipherImpl.h"
+#include "Poco/Exception.h"
+#include "Poco/SingletonHolder.h"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+CipherFactory::CipherFactory()
+{
+}
+
+
+CipherFactory::~CipherFactory()
+{
+}
+
+
+namespace
+{
+ static Poco::SingletonHolder<CipherFactory> holder;
+}
+
+
+CipherFactory& CipherFactory::defaultFactory()
+{
+ return *holder.get();
+}
+
+
+Cipher* CipherFactory::createCipher(const CipherKey& key)
+{
+ return new CipherImpl(key);
+}
+
+
+Cipher* CipherFactory::createCipher(const RSAKey& key, RSAPaddingMode paddingMode)
+{
+ return new RSACipherImpl(key, paddingMode);
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/CipherImpl.cpp b/contrib/libs/poco/Crypto/src/CipherImpl.cpp
new file mode 100644
index 0000000000..ae57477595
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CipherImpl.cpp
@@ -0,0 +1,272 @@
+//
+// CipherImpl.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: CipherImpl
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/CipherImpl.h"
+#include "Poco/Crypto/CryptoTransform.h"
+#include "Poco/Exception.h"
+#include "Poco/Buffer.h"
+#include <openssl/err.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+namespace
+{
+ void throwError()
+ {
+ unsigned long err;
+ std::string msg;
+
+ while ((err = ERR_get_error()))
+ {
+ if (!msg.empty())
+ msg.append("; ");
+ msg.append(ERR_error_string(err, 0));
+ }
+
+ throw Poco::IOException(msg);
+ }
+
+
+ class CryptoTransformImpl: public CryptoTransform
+ {
+ public:
+ typedef Cipher::ByteVec ByteVec;
+
+ enum Direction
+ {
+ DIR_ENCRYPT,
+ DIR_DECRYPT
+ };
+
+ CryptoTransformImpl(
+ const EVP_CIPHER* pCipher,
+ const ByteVec& key,
+ const ByteVec& iv,
+ Direction dir);
+
+ ~CryptoTransformImpl();
+
+ std::size_t blockSize() const;
+ int setPadding(int padding);
+ std::string getTag(std::size_t tagSize);
+ void setTag(const std::string& tag);
+
+ std::streamsize transform(
+ const unsigned char* input,
+ std::streamsize inputLength,
+ unsigned char* output,
+ std::streamsize outputLength);
+
+ std::streamsize finalize(
+ unsigned char* output,
+ std::streamsize length);
+
+ private:
+ const EVP_CIPHER* _pCipher;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ EVP_CIPHER_CTX* _pContext;
+#else
+ EVP_CIPHER_CTX _context;
+#endif
+ ByteVec _key;
+ ByteVec _iv;
+ };
+
+
+ CryptoTransformImpl::CryptoTransformImpl(
+ const EVP_CIPHER* pCipher,
+ const ByteVec& key,
+ const ByteVec& iv,
+ Direction dir):
+ _pCipher(pCipher),
+ _key(key),
+ _iv(iv)
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ _pContext = EVP_CIPHER_CTX_new();
+ EVP_CipherInit(
+ _pContext,
+ _pCipher,
+ &_key[0],
+ _iv.empty() ? 0 : &_iv[0],
+ (dir == DIR_ENCRYPT) ? 1 : 0);
+#else
+ EVP_CipherInit(
+ &_context,
+ _pCipher,
+ &_key[0],
+ _iv.empty() ? 0 : &_iv[0],
+ (dir == DIR_ENCRYPT) ? 1 : 0);
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ if (_iv.size() != EVP_CIPHER_iv_length(_pCipher) && EVP_CIPHER_mode(_pCipher) == EVP_CIPH_GCM_MODE)
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ int rc = EVP_CIPHER_CTX_ctrl(_pContext, EVP_CTRL_GCM_SET_IVLEN, _iv.size(), NULL);
+#else
+ int rc = EVP_CIPHER_CTX_ctrl(&_context, EVP_CTRL_GCM_SET_IVLEN, _iv.size(), NULL);
+#endif
+ if (rc == 0) throwError();
+ }
+#endif
+ }
+
+
+ CryptoTransformImpl::~CryptoTransformImpl()
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ EVP_CIPHER_CTX_cleanup(_pContext);
+ EVP_CIPHER_CTX_free(_pContext);
+#else
+ EVP_CIPHER_CTX_cleanup(&_context);
+#endif
+ }
+
+
+ std::size_t CryptoTransformImpl::blockSize() const
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ return EVP_CIPHER_CTX_block_size(_pContext);
+#else
+ return EVP_CIPHER_CTX_block_size(&_context);
+#endif
+ }
+
+
+ int CryptoTransformImpl::setPadding(int padding)
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ return EVP_CIPHER_CTX_block_size(_pContext);
+#else
+ return EVP_CIPHER_CTX_set_padding(&_context, padding);
+#endif
+ }
+
+
+ std::string CryptoTransformImpl::getTag(std::size_t tagSize)
+ {
+ std::string tag;
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ Poco::Buffer<char> buffer(tagSize);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ int rc = EVP_CIPHER_CTX_ctrl(_pContext, EVP_CTRL_GCM_GET_TAG, tagSize, buffer.begin());
+#else
+ int rc = EVP_CIPHER_CTX_ctrl(&_context, EVP_CTRL_GCM_GET_TAG, tagSize, buffer.begin());
+#endif
+ if (rc == 0) throwError();
+ tag.assign(buffer.begin(), tagSize);
+#endif
+ return tag;
+ }
+
+
+ void CryptoTransformImpl::setTag(const std::string& tag)
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ int rc = EVP_CIPHER_CTX_ctrl(_pContext, EVP_CTRL_GCM_SET_TAG, tag.size(), const_cast<char*>(tag.data()));
+#elif OPENSSL_VERSION_NUMBER >= 0x10001000L
+ int rc = EVP_CIPHER_CTX_ctrl(&_context, EVP_CTRL_GCM_SET_TAG, tag.size(), const_cast<char*>(tag.data()));
+#else
+ int rc = 0;
+#endif
+ if (rc == 0) throwError();
+ }
+
+
+ std::streamsize CryptoTransformImpl::transform(
+ const unsigned char* input,
+ std::streamsize inputLength,
+ unsigned char* output,
+ std::streamsize outputLength)
+ {
+ poco_assert (outputLength >= (inputLength + blockSize() - 1));
+
+ int outLen = static_cast<int>(outputLength);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ int rc = EVP_CipherUpdate(
+ _pContext,
+ output,
+ &outLen,
+ input,
+ static_cast<int>(inputLength));
+#else
+ int rc = EVP_CipherUpdate(
+ &_context,
+ output,
+ &outLen,
+ input,
+ static_cast<int>(inputLength));
+#endif
+ if (rc == 0)
+ throwError();
+
+ return static_cast<std::streamsize>(outLen);
+ }
+
+
+ std::streamsize CryptoTransformImpl::finalize(
+ unsigned char* output,
+ std::streamsize length)
+ {
+ poco_assert (length >= blockSize());
+
+ int len = static_cast<int>(length);
+
+ // Use the '_ex' version that does not perform implicit cleanup since we
+ // will call EVP_CIPHER_CTX_cleanup() from the dtor as there is no
+ // guarantee that finalize() will be called if an error occurred.
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ int rc = EVP_CipherFinal_ex(_pContext, output, &len);
+#else
+ int rc = EVP_CipherFinal_ex(&_context, output, &len);
+#endif
+
+ if (rc == 0)
+ throwError();
+
+ return static_cast<std::streamsize>(len);
+ }
+}
+
+
+CipherImpl::CipherImpl(const CipherKey& key):
+ _key(key)
+{
+}
+
+
+CipherImpl::~CipherImpl()
+{
+}
+
+
+CryptoTransform* CipherImpl::createEncryptor()
+{
+ CipherKeyImpl::Ptr p = _key.impl();
+ return new CryptoTransformImpl(p->cipher(), p->getKey(), p->getIV(), CryptoTransformImpl::DIR_ENCRYPT);
+}
+
+
+CryptoTransform* CipherImpl::createDecryptor()
+{
+ CipherKeyImpl::Ptr p = _key.impl();
+ return new CryptoTransformImpl(p->cipher(), p->getKey(), p->getIV(), CryptoTransformImpl::DIR_DECRYPT);
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/CipherKey.cpp b/contrib/libs/poco/Crypto/src/CipherKey.cpp
new file mode 100644
index 0000000000..275edd1c88
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CipherKey.cpp
@@ -0,0 +1,49 @@
+//
+// CipherKey.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: CipherKey
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/CipherKey.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+CipherKey::CipherKey(const std::string& name,
+ const std::string& passphrase,
+ const std::string& salt,
+ int iterationCount,
+ const std::string &digest):
+ _pImpl(new CipherKeyImpl(name, passphrase, salt, iterationCount, digest))
+{
+}
+
+
+CipherKey::CipherKey(const std::string& name, const ByteVec& key, const ByteVec& iv):
+ _pImpl(new CipherKeyImpl(name, key, iv))
+{
+}
+
+
+CipherKey::CipherKey(const std::string& name):
+ _pImpl(new CipherKeyImpl(name))
+{
+}
+
+
+CipherKey::~CipherKey()
+{
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/CipherKeyImpl.cpp b/contrib/libs/poco/Crypto/src/CipherKeyImpl.cpp
new file mode 100644
index 0000000000..2af173bce8
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CipherKeyImpl.cpp
@@ -0,0 +1,224 @@
+//
+// CipherKeyImpl.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: CipherKeyImpl
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/CipherKeyImpl.h"
+#include "Poco/Crypto/CryptoTransform.h"
+#include "Poco/Crypto/CipherFactory.h"
+#include "Poco/Exception.h"
+#include "Poco/RandomStream.h"
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+CipherKeyImpl::CipherKeyImpl(const std::string& name,
+ const std::string& passphrase,
+ const std::string& salt,
+ int iterationCount,
+ const std::string& digest):
+ _pCipher(0),
+ _pDigest(0),
+ _name(name),
+ _key(),
+ _iv()
+{
+ // dummy access to Cipherfactory so that the EVP lib is initilaized
+ CipherFactory::defaultFactory();
+ _pCipher = EVP_get_cipherbyname(name.c_str());
+
+ if (!_pCipher)
+ throw Poco::NotFoundException("Cipher " + name + " was not found");
+
+ _pDigest = EVP_get_digestbyname(digest.c_str());
+
+ if (!_pDigest)
+ throw Poco::NotFoundException("Digest " + name + " was not found");
+
+ _key = ByteVec(keySize());
+ _iv = ByteVec(ivSize());
+ generateKey(passphrase, salt, iterationCount);
+}
+
+
+CipherKeyImpl::CipherKeyImpl(const std::string& name,
+ const ByteVec& key,
+ const ByteVec& iv):
+ _pCipher(0),
+ _pDigest(0),
+ _name(name),
+ _key(key),
+ _iv(iv)
+{
+ // dummy access to Cipherfactory so that the EVP lib is initialized
+ CipherFactory::defaultFactory();
+ _pCipher = EVP_get_cipherbyname(name.c_str());
+
+ if (!_pCipher)
+ throw Poco::NotFoundException("Cipher " + name + " was not found");
+}
+
+
+CipherKeyImpl::CipherKeyImpl(const std::string& name):
+ _pCipher(0),
+ _pDigest(0),
+ _name(name),
+ _key(),
+ _iv()
+{
+ // dummy access to Cipherfactory so that the EVP lib is initilaized
+ CipherFactory::defaultFactory();
+ _pCipher = EVP_get_cipherbyname(name.c_str());
+
+ if (!_pCipher)
+ throw Poco::NotFoundException("Cipher " + name + " was not found");
+ _key = ByteVec(keySize());
+ _iv = ByteVec(ivSize());
+ generateKey();
+}
+
+
+CipherKeyImpl::~CipherKeyImpl()
+{
+}
+
+
+CipherKeyImpl::Mode CipherKeyImpl::mode() const
+{
+ switch (EVP_CIPHER_mode(_pCipher))
+ {
+ case EVP_CIPH_STREAM_CIPHER:
+ return MODE_STREAM_CIPHER;
+
+ case EVP_CIPH_ECB_MODE:
+ return MODE_ECB;
+
+ case EVP_CIPH_CBC_MODE:
+ return MODE_CBC;
+
+ case EVP_CIPH_CFB_MODE:
+ return MODE_CFB;
+
+ case EVP_CIPH_OFB_MODE:
+ return MODE_OFB;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ case EVP_CIPH_CTR_MODE:
+ return MODE_CTR;
+
+ case EVP_CIPH_GCM_MODE:
+ return MODE_GCM;
+
+ case EVP_CIPH_CCM_MODE:
+ return MODE_CCM;
+#endif
+ }
+ throw Poco::IllegalStateException("Unexpected value of EVP_CIPHER_mode()");
+}
+
+
+void CipherKeyImpl::generateKey()
+{
+ ByteVec vec;
+
+ getRandomBytes(vec, keySize());
+ setKey(vec);
+
+ getRandomBytes(vec, ivSize());
+ setIV(vec);
+}
+
+
+void CipherKeyImpl::getRandomBytes(ByteVec& vec, std::size_t count)
+{
+ Poco::RandomInputStream random;
+
+ vec.clear();
+ vec.reserve(count);
+
+ for (int i = 0; i < count; ++i)
+ vec.push_back(static_cast<unsigned char>(random.get()));
+}
+
+
+void CipherKeyImpl::generateKey(
+ const std::string& password,
+ const std::string& salt,
+ int iterationCount)
+{
+ unsigned char keyBytes[EVP_MAX_KEY_LENGTH];
+ unsigned char ivBytes[EVP_MAX_IV_LENGTH];
+
+ // OpenSSL documentation specifies that the salt must be an 8-byte array.
+ unsigned char saltBytes[8];
+
+ if (!salt.empty())
+ {
+ int len = static_cast<int>(salt.size());
+ // Create the salt array from the salt string
+ for (int i = 0; i < 8; ++i)
+ saltBytes[i] = salt.at(i % len);
+ for (int i = 8; i < len; ++i)
+ saltBytes[i % 8] ^= salt.at(i);
+ }
+
+ // Now create the key and IV, using the MD5 digest algorithm.
+ int keySize = EVP_BytesToKey(
+ _pCipher,
+ _pDigest ? _pDigest : EVP_md5(),
+ (salt.empty() ? 0 : saltBytes),
+ reinterpret_cast<const unsigned char*>(password.data()),
+ static_cast<int>(password.size()),
+ iterationCount,
+ keyBytes,
+ ivBytes);
+
+ // Copy the buffers to our member byte vectors.
+ _key.assign(keyBytes, keyBytes + keySize);
+
+ if (ivSize() == 0)
+ _iv.clear();
+ else
+ _iv.assign(ivBytes, ivBytes + ivSize());
+}
+
+
+int CipherKeyImpl::keySize() const
+{
+ return EVP_CIPHER_key_length(_pCipher);
+}
+
+
+int CipherKeyImpl::blockSize() const
+{
+ return EVP_CIPHER_block_size(_pCipher);
+}
+
+
+int CipherKeyImpl::ivSize() const
+{
+ return EVP_CIPHER_iv_length(_pCipher);
+}
+
+
+void CipherKeyImpl::setIV(const ByteVec& iv)
+{
+ poco_assert(mode() == MODE_GCM || iv.size() == static_cast<ByteVec::size_type>(ivSize()));
+ _iv = iv;
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/CryptoException.cpp b/contrib/libs/poco/Crypto/src/CryptoException.cpp
new file mode 100644
index 0000000000..e30940d229
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CryptoException.cpp
@@ -0,0 +1,108 @@
+//
+// 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>
+#include <openssl/err.h>
+
+
+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() noexcept
+{
+}
+
+
+OpenSSLException& OpenSSLException::operator = (const OpenSSLException& exc)
+{
+ CryptoException::operator = (exc);
+ return *this;
+}
+
+
+const char* OpenSSLException::name() const noexcept
+{
+ return "OpenSSLException";
+}
+
+
+const char* OpenSSLException::className() const noexcept
+{
+ return typeid(*this).name();
+}
+
+
+Poco::Exception* OpenSSLException::clone() const
+{
+ return new OpenSSLException(*this);
+}
+
+
+void OpenSSLException::setExtMessage()
+{
+ Poco::UInt64 e = static_cast<Poco::UInt64>(ERR_get_error());
+ char buf[128] = { 0 };
+ char* pErr = ERR_error_string(static_cast<unsigned long>(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
diff --git a/contrib/libs/poco/Crypto/src/CryptoStream.cpp b/contrib/libs/poco/Crypto/src/CryptoStream.cpp
new file mode 100644
index 0000000000..6b29b7f077
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CryptoStream.cpp
@@ -0,0 +1,355 @@
+//
+// CryptoStream.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: CryptoStream
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/CryptoStream.h"
+#include "Poco/Crypto/CryptoTransform.h"
+#include "Poco/Crypto/Cipher.h"
+#include "Poco/Exception.h"
+#include <algorithm>
+
+
+#undef min
+#undef max
+
+
+namespace Poco {
+namespace Crypto {
+
+
+//
+// CryptoStreamBuf
+//
+
+
+CryptoStreamBuf::CryptoStreamBuf(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize):
+ Poco::BufferedStreamBuf(bufferSize, std::ios::in),
+ _pTransform(pTransform),
+ _pIstr(&istr),
+ _pOstr(0),
+ _eof(false),
+ _buffer(static_cast<std::size_t>(bufferSize))
+{
+ poco_check_ptr (pTransform);
+ poco_assert (bufferSize > 2 * pTransform->blockSize());
+}
+
+
+CryptoStreamBuf::CryptoStreamBuf(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize):
+ Poco::BufferedStreamBuf(bufferSize, std::ios::out),
+ _pTransform(pTransform),
+ _pIstr(0),
+ _pOstr(&ostr),
+ _eof(false),
+ _buffer(static_cast<std::size_t>(bufferSize))
+{
+ poco_check_ptr (pTransform);
+ poco_assert (bufferSize > 2 * pTransform->blockSize());
+}
+
+
+CryptoStreamBuf::~CryptoStreamBuf()
+{
+ try
+ {
+ close();
+ }
+ catch (...)
+ {
+ }
+ delete _pTransform;
+}
+
+
+void CryptoStreamBuf::close()
+{
+ sync();
+
+ if (_pIstr)
+ {
+ _pIstr = 0;
+ }
+ else if (_pOstr)
+ {
+ // Close can be called multiple times. By zeroing the pointer we make
+ // sure that we call finalize() only once, even if an exception is
+ // thrown.
+ std::ostream* pOstr = _pOstr;
+ _pOstr = 0;
+
+ // Finalize transformation.
+ std::streamsize n = _pTransform->finalize(_buffer.begin(), static_cast<std::streamsize>(_buffer.size()));
+
+ if (n > 0)
+ {
+ pOstr->write(reinterpret_cast<char*>(_buffer.begin()), n);
+ if (!pOstr->good())
+ throw Poco::IOException("Output stream failure");
+ }
+ }
+}
+
+
+int CryptoStreamBuf::readFromDevice(char* buffer, std::streamsize length)
+{
+ if (!_pIstr)
+ return 0;
+
+ int count = 0;
+
+ while (!_eof)
+ {
+ int m = (static_cast<int>(length) - count)/2 - static_cast<int>(_pTransform->blockSize());
+
+ // Make sure we can read at least one more block. Explicitely check
+ // for m < 0 since blockSize() returns an unsigned int and the
+ // comparison might give false results for m < 0.
+ if (m <= 0)
+ break;
+
+ int n = 0;
+
+ if (_pIstr->good())
+ {
+ _pIstr->read(reinterpret_cast<char*>(_buffer.begin()), m);
+ n = static_cast<int>(_pIstr->gcount());
+ }
+
+ if (n == 0)
+ {
+ _eof = true;
+
+ // No more data, finalize transformation
+ count += static_cast<int>(_pTransform->finalize(
+ reinterpret_cast<unsigned char*>(buffer + count),
+ static_cast<int>(length) - count));
+ }
+ else
+ {
+ // Transform next chunk of data
+ count += static_cast<int>(_pTransform->transform(
+ _buffer.begin(),
+ n,
+ reinterpret_cast<unsigned char*>(buffer + count),
+ static_cast<int>(length) - count));
+ }
+ }
+
+ return count;
+}
+
+
+int CryptoStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
+{
+ if (!_pOstr)
+ return 0;
+
+ std::size_t maxChunkSize = _buffer.size()/2;
+ std::size_t count = 0;
+
+ while (count < length)
+ {
+ // Truncate chunk size so that the maximum output fits into _buffer.
+ std::size_t n = static_cast<std::size_t>(length) - count;
+ if (n > maxChunkSize)
+ n = maxChunkSize;
+
+ // Transform next chunk of data
+ std::streamsize k = _pTransform->transform(
+ reinterpret_cast<const unsigned char*>(buffer + count),
+ static_cast<std::streamsize>(n),
+ _buffer.begin(),
+ static_cast<std::streamsize>(_buffer.size()));
+
+ // Attention: (n != k) might be true. In count, we have to track how
+ // many bytes from buffer have been consumed, not how many bytes have
+ // been written to _pOstr!
+ count += n;
+
+ if (k > 0)
+ {
+ _pOstr->write(reinterpret_cast<const char*>(_buffer.begin()), k);
+ if (!_pOstr->good())
+ throw Poco::IOException("Output stream failure");
+ }
+ }
+
+ return static_cast<int>(count);
+}
+
+
+//
+// CryptoIOS
+//
+
+
+CryptoIOS::CryptoIOS(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize):
+ _buf(istr, pTransform, bufferSize)
+{
+ poco_ios_init(&_buf);
+}
+
+
+CryptoIOS::CryptoIOS(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize):
+ _buf(ostr, pTransform, bufferSize)
+{
+ poco_ios_init(&_buf);
+}
+
+
+CryptoIOS::~CryptoIOS()
+{
+}
+
+
+CryptoStreamBuf* CryptoIOS::rdbuf()
+{
+ return &_buf;
+}
+
+
+//
+// CryptoInputStream
+//
+
+
+CryptoInputStream::CryptoInputStream(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize):
+ CryptoIOS(istr, pTransform, bufferSize),
+ std::istream(&_buf)
+{
+}
+
+
+CryptoInputStream::CryptoInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize):
+ CryptoIOS(istr, cipher.createEncryptor(), bufferSize),
+ std::istream(&_buf)
+{
+}
+
+
+CryptoInputStream::~CryptoInputStream()
+{
+}
+
+
+//
+// CryptoOutputStream
+//
+
+
+CryptoOutputStream::CryptoOutputStream(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize):
+ CryptoIOS(ostr, pTransform, bufferSize),
+ std::ostream(&_buf)
+{
+}
+
+
+CryptoOutputStream::CryptoOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize):
+ CryptoIOS(ostr, cipher.createDecryptor(), bufferSize),
+ std::ostream(&_buf)
+{
+}
+
+
+CryptoOutputStream::~CryptoOutputStream()
+{
+}
+
+
+void CryptoOutputStream::close()
+{
+ _buf.close();
+}
+
+
+//
+// EncryptingInputStream
+//
+
+
+EncryptingInputStream::EncryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize):
+ CryptoIOS(istr, cipher.createEncryptor(), bufferSize),
+ std::istream(&_buf)
+{
+}
+
+
+EncryptingInputStream::~EncryptingInputStream()
+{
+}
+
+
+//
+// EncryptingOuputStream
+//
+
+
+EncryptingOutputStream::EncryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize):
+ CryptoIOS(ostr, cipher.createEncryptor(), bufferSize),
+ std::ostream(&_buf)
+{
+}
+
+
+EncryptingOutputStream::~EncryptingOutputStream()
+{
+}
+
+
+void EncryptingOutputStream::close()
+{
+ _buf.close();
+}
+
+
+//
+// DecryptingInputStream
+//
+
+
+DecryptingInputStream::DecryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize):
+ CryptoIOS(istr, cipher.createDecryptor(), bufferSize),
+ std::istream(&_buf)
+{
+}
+
+
+DecryptingInputStream::~DecryptingInputStream()
+{
+}
+
+
+//
+// DecryptingOuputStream
+//
+
+
+DecryptingOutputStream::DecryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize):
+ CryptoIOS(ostr, cipher.createDecryptor(), bufferSize),
+ std::ostream(&_buf)
+{
+}
+
+
+DecryptingOutputStream::~DecryptingOutputStream()
+{
+}
+
+
+void DecryptingOutputStream::close()
+{
+ _buf.close();
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/CryptoTransform.cpp b/contrib/libs/poco/Crypto/src/CryptoTransform.cpp
new file mode 100644
index 0000000000..e4e58fd6e6
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/CryptoTransform.cpp
@@ -0,0 +1,38 @@
+//
+// CryptoTransform.cpp
+//
+// Library: Crypto
+// Package: Cipher
+// Module: CryptoTransform
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/CryptoTransform.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+CryptoTransform::CryptoTransform()
+{
+}
+
+
+CryptoTransform::~CryptoTransform()
+{
+}
+
+
+int CryptoTransform::setPadding(int padding)
+{
+ return 1;
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/DigestEngine.cpp b/contrib/libs/poco/Crypto/src/DigestEngine.cpp
new file mode 100644
index 0000000000..bac2d44e07
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/DigestEngine.cpp
@@ -0,0 +1,80 @@
+//
+// DigestEngine.cpp
+//
+// Library: Crypto
+// Package: Digest
+// Module: DigestEngine
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/DigestEngine.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+DigestEngine::DigestEngine(const std::string& name):
+ _name(name),
+ _pContext(EVP_MD_CTX_create())
+{
+ const EVP_MD* md = EVP_get_digestbyname(_name.c_str());
+ if (!md) throw Poco::NotFoundException(_name);
+ EVP_DigestInit_ex(_pContext, md, NULL);
+}
+
+
+DigestEngine::~DigestEngine()
+{
+ EVP_MD_CTX_destroy(_pContext);
+}
+
+int DigestEngine::nid() const
+{
+ return EVP_MD_nid(EVP_MD_CTX_md(_pContext));
+}
+
+std::size_t DigestEngine::digestLength() const
+{
+ return EVP_MD_CTX_size(_pContext);
+}
+
+
+void DigestEngine::reset()
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ EVP_MD_CTX_free(_pContext);
+ _pContext = EVP_MD_CTX_create();
+#else
+ EVP_MD_CTX_cleanup(_pContext);
+#endif
+ const EVP_MD* md = EVP_get_digestbyname(_name.c_str());
+ if (!md) throw Poco::NotFoundException(_name);
+ EVP_DigestInit_ex(_pContext, md, NULL);
+}
+
+
+const Poco::DigestEngine::Digest& DigestEngine::digest()
+{
+ _digest.clear();
+ unsigned len = EVP_MD_CTX_size(_pContext);
+ _digest.resize(len);
+ EVP_DigestFinal_ex(_pContext, &_digest[0], &len);
+ reset();
+ return _digest;
+}
+
+
+void DigestEngine::updateImpl(const void* data, std::size_t length)
+{
+ EVP_DigestUpdate(_pContext, data, length);
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/ECDSADigestEngine.cpp b/contrib/libs/poco/Crypto/src/ECDSADigestEngine.cpp
new file mode 100644
index 0000000000..59512770cd
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/ECDSADigestEngine.cpp
@@ -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
diff --git a/contrib/libs/poco/Crypto/src/ECKey.cpp b/contrib/libs/poco/Crypto/src/ECKey.cpp
new file mode 100644
index 0000000000..56b8663776
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/ECKey.cpp
@@ -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
diff --git a/contrib/libs/poco/Crypto/src/ECKeyImpl.cpp b/contrib/libs/poco/Crypto/src/ECKeyImpl.cpp
new file mode 100644
index 0000000000..99ffae7606
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/ECKeyImpl.cpp
@@ -0,0 +1,258 @@
+//
+// 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/Format.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)))
+{
+ checkEC("ECKeyImpl(const EVPPKey&)", "EVP_PKEY_get1_EC_KEY()");
+}
+
+
+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);
+ checkEC("ECKeyImpl(const const X509Certificate&)", "EVP_PKEY_get1_EC_KEY()");
+ return;
+ }
+ }
+ throw OpenSSLException("ECKeyImpl(const X509Certificate&)");
+}
+
+
+ECKeyImpl::ECKeyImpl(const PKCS12Container& cont):
+ KeyPairImpl("ec", KT_EC_IMPL),
+ _pEC(EVP_PKEY_get1_EC_KEY(cont.getKey()))
+{
+ checkEC("ECKeyImpl(const PKCS12Container&)", "EVP_PKEY_get1_EC_KEY()");
+}
+
+
+ECKeyImpl::ECKeyImpl(int curve):
+ KeyPairImpl("ec", KT_EC_IMPL),
+ _pEC(EC_KEY_new_by_curve_name(curve))
+{
+ 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()");
+}
+
+
+ECKeyImpl::ECKeyImpl(const std::string& publicKeyFile,
+ const std::string& privateKeyFile,
+ 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()");
+}
+
+
+ECKeyImpl::ECKeyImpl(std::istream* pPublicKeyStream,
+ std::istream* pPrivateKeyStream,
+ 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()");
+}
+
+
+ECKeyImpl::~ECKeyImpl()
+{
+ freeEC();
+}
+
+
+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)
+ {
+ EC_KEY_free(_pEC);
+ _pEC = 0;
+ }
+}
+
+
+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()");
+}
+
+
+int ECKeyImpl::groupId() const
+{
+ if (_pEC)
+ {
+ const EC_GROUP* ecGroup = EC_KEY_get0_group(_pEC);
+ if (ecGroup)
+ {
+ return EC_GROUP_get_curve_name(ecGroup);
+ }
+ else
+ {
+ throw OpenSSLException("ECKeyImpl::groupName()");
+ }
+ }
+ throw NullPointerException("ECKeyImpl::groupName() => _pEC");
+}
+
+
+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;
+ const int bufLen = 128;
+ char buf[bufLen];
+ std::memset(buf, 0, bufLen);
+ OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
+ curveName = buf;
+ OPENSSL_free(pCurves);
+ return curveName;
+}
+
+
+int ECKeyImpl::getCurveNID(std::string& name)
+{
+ std::string curveName;
+ size_t len = EC_get_builtin_curves(NULL, 0);
+ EC_builtin_curve* pCurves =
+ (EC_builtin_curve*)OPENSSL_malloc(static_cast<int>(sizeof(EC_builtin_curve) * len));
+ if (!pCurves) return -1;
+
+ if (!EC_get_builtin_curves(pCurves, len))
+ {
+ OPENSSL_free(pCurves);
+ return -1;
+ }
+
+ int nid = -1;
+ const int bufLen = 128;
+ char buf[bufLen];
+ if (name.empty())
+ {
+ std::memset(buf, 0, bufLen);
+ OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
+ name = buf;
+ nid = pCurves[0].nid;
+ }
+ else
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ std::memset(buf, 0, bufLen);
+ OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(pCurves[i].nid), 0);
+ if (strncmp(name.c_str(), buf, name.size() > bufLen ? bufLen : name.size()) == 0)
+ {
+ nid = pCurves[i].nid;
+ break;
+ }
+ }
+ }
+
+ OPENSSL_free(pCurves);
+ return nid;
+}
+
+
+bool ECKeyImpl::hasCurve(const std::string& name)
+{
+ std::string tmp(name);
+ return (-1 != getCurveNID(tmp));
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/EVPPKey.cpp b/contrib/libs/poco/Crypto/src/EVPPKey.cpp
new file mode 100644
index 0000000000..ffa0a78c07
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/EVPPKey.cpp
@@ -0,0 +1,321 @@
+//
+// 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/Crypto/ECKey.h"
+#include "Poco/Crypto/RSAKey.h"
+#include "Poco/NumberFormatter.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+EVPPKey::EVPPKey(const std::string& ecCurveName): _pEVPPKey(0)
+{
+ newECKey(ecCurveName.c_str());
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey::EVPPKey(const char* ecCurveName): _pEVPPKey(0)
+{
+ newECKey(ecCurveName);
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey::EVPPKey(EVP_PKEY* pEVPPKey): _pEVPPKey(0)
+{
+ duplicate(pEVPPKey, &_pEVPPKey);
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey::EVPPKey(const std::string& publicKeyFile,
+ const std::string& privateKeyFile,
+ const std::string& privateKeyPassphrase): _pEVPPKey(0)
+{
+ if (loadKey(&_pEVPPKey, PEM_read_PrivateKey, (EVP_PKEY_get_Key_fn)0, privateKeyFile, privateKeyPassphrase))
+ {
+ poco_check_ptr(_pEVPPKey);
+ return; // private key is enough
+ }
+
+ // no private key, this must be public key only, otherwise throw
+ if (!loadKey(&_pEVPPKey, PEM_read_PUBKEY, (EVP_PKEY_get_Key_fn)0, publicKeyFile))
+ {
+ throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&");
+ }
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey::EVPPKey(std::istream* pPublicKeyStream,
+ std::istream* pPrivateKeyStream,
+ const std::string& privateKeyPassphrase): _pEVPPKey(0)
+{
+ if (loadKey(&_pEVPPKey, PEM_read_bio_PrivateKey, (EVP_PKEY_get_Key_fn)0, pPrivateKeyStream, privateKeyPassphrase))
+ {
+ poco_check_ptr(_pEVPPKey);
+ return; // private key is enough
+ }
+
+ // no private key, this must be public key only, otherwise throw
+ if (!loadKey(&_pEVPPKey, PEM_read_bio_PUBKEY, (EVP_PKEY_get_Key_fn)0, pPublicKeyStream))
+ {
+ throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&");
+ }
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey::EVPPKey(const EVPPKey& other)
+{
+ duplicate(other._pEVPPKey, &_pEVPPKey);
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey& EVPPKey::operator=(const EVPPKey& other)
+{
+ duplicate(other._pEVPPKey, &_pEVPPKey);
+ poco_check_ptr(_pEVPPKey);
+ return *this;
+}
+
+
+#ifdef POCO_ENABLE_CPP11
+
+EVPPKey::EVPPKey(EVPPKey&& other): _pEVPPKey(other._pEVPPKey)
+{
+ other._pEVPPKey = nullptr;
+ poco_check_ptr(_pEVPPKey);
+}
+
+
+EVPPKey& EVPPKey::operator=(EVPPKey&& other)
+{
+ _pEVPPKey = other._pEVPPKey;
+ other._pEVPPKey = nullptr;
+ poco_check_ptr(_pEVPPKey);
+ return *this;
+}
+
+#endif // POCO_ENABLE_CPP11
+
+EVPPKey::~EVPPKey()
+{
+ if (_pEVPPKey) EVP_PKEY_free(_pEVPPKey);
+}
+
+
+void EVPPKey::save(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase) const
+{
+ if (!publicKeyFile.empty() && (publicKeyFile != privateKeyFile))
+ {
+ 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())))
+ {
+ if (!PEM_write_bio_PUBKEY(bio, _pEVPPKey))
+ {
+ 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())))
+ {
+ int rc = 0;
+ if (privateKeyPassphrase.empty())
+ {
+ rc = PEM_write_bio_PrivateKey(bio, _pEVPPKey, 0, 0, 0, 0, 0);
+ }
+ else
+ {
+ rc = PEM_write_bio_PrivateKey(bio, _pEVPPKey, 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 EVPPKey::save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStream, const std::string& privateKeyPassphrase) const
+{
+ if (pPublicKeyStream && (pPublicKeyStream != pPrivateKeyStream))
+ {
+ BIO* bio = BIO_new(BIO_s_mem());
+ if (!bio) throw Poco::IOException("Cannot create BIO for writing public key");
+ if (!PEM_write_bio_PUBKEY(bio, _pEVPPKey))
+ {
+ 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");
+ int rc = 0;
+ if (privateKeyPassphrase.empty())
+ rc = PEM_write_bio_PrivateKey(bio, _pEVPPKey, 0, 0, 0, 0, 0);
+ else
+ rc = PEM_write_bio_PrivateKey(bio, _pEVPPKey, 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);
+ }
+}
+
+
+EVP_PKEY* EVPPKey::duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey)
+{
+ if (!pFromKey) throw NullPointerException("EVPPKey::duplicate(): "
+ "provided key pointer is null.");
+
+ *pToKey = EVP_PKEY_new();
+ if (!*pToKey) throw NullPointerException("EVPPKey::duplicate(): "
+ "EVP_PKEY_new() returned null.");
+
+ int keyType = type(pFromKey);
+ switch (keyType)
+ {
+ case EVP_PKEY_RSA:
+ {
+ RSA* pRSA = EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pFromKey));
+ if (pRSA)
+ {
+ EVP_PKEY_set1_RSA(*pToKey, pRSA);
+ RSA_free(pRSA);
+ }
+ else throw OpenSSLException("EVPPKey::duplicate(): EVP_PKEY_get1_RSA()");
+ break;
+ }
+ case EVP_PKEY_EC:
+ {
+ EC_KEY* pEC = EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>(pFromKey));
+ if (pEC)
+ {
+ EVP_PKEY_set1_EC_KEY(*pToKey, pEC);
+ EC_KEY_free(pEC);
+ int cmp = EVP_PKEY_cmp_parameters(*pToKey, pFromKey);
+ if (cmp < 0)
+ throw OpenSSLException("EVPPKey::duplicate(): EVP_PKEY_cmp_parameters()");
+ if (0 == cmp)
+ {
+ if(!EVP_PKEY_copy_parameters(*pToKey, pFromKey))
+ throw OpenSSLException("EVPPKey::duplicate(): EVP_PKEY_copy_parameters()");
+ }
+ }
+ else throw OpenSSLException();
+ break;
+ }
+ default:
+ throw NotImplementedException("EVPPKey:duplicate(); Key type: " +
+ NumberFormatter::format(keyType));
+ }
+
+ return *pToKey;
+}
+
+
+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("EVPPKey:newECKey()");
+}
+
+
+void EVPPKey::setKey(ECKey* pKey)
+{
+ poco_check_ptr(pKey);
+ poco_check_ptr(pKey->impl());
+ setKey(pKey->impl()->getECKey());
+}
+
+
+void EVPPKey::setKey(RSAKey* pKey)
+{
+ poco_check_ptr(pKey);
+ poco_check_ptr(pKey->impl());
+ setKey(pKey->impl()->getRSA());
+}
+
+
+int EVPPKey::passCB(char* buf, int size, int, void* pass)
+{
+ if (pass)
+ {
+ int len = (int)std::strlen((char*)pass);
+ if(len > size) len = size;
+ std::memcpy(buf, pass, len);
+ return len;
+ }
+ return 0;
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/KeyPair.cpp b/contrib/libs/poco/Crypto/src/KeyPair.cpp
new file mode 100644
index 0000000000..1c650806b3
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/KeyPair.cpp
@@ -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
diff --git a/contrib/libs/poco/Crypto/src/KeyPairImpl.cpp b/contrib/libs/poco/Crypto/src/KeyPairImpl.cpp
new file mode 100644
index 0000000000..c782f04270
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/KeyPairImpl.cpp
@@ -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
diff --git a/contrib/libs/poco/Crypto/src/OpenSSLInitializer.cpp b/contrib/libs/poco/Crypto/src/OpenSSLInitializer.cpp
new file mode 100644
index 0000000000..a3bc1d0143
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/OpenSSLInitializer.cpp
@@ -0,0 +1,190 @@
+//
+// OpenSSLInitializer.cpp
+//
+// Library: Crypto
+// Package: CryptoCore
+// Module: OpenSSLInitializer
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/RandomStream.h"
+#include "Poco/Thread.h"
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#if OPENSSL_VERSION_NUMBER >= 0x0907000L
+#include <openssl/conf.h>
+#endif
+#if defined(POCO_OS_FAMILY_WINDOWS)
+ #define POCO_STR_HELPER(x) #x
+ #define POCO_STR(x) POCO_STR_HELPER(x)
+ #if defined POCO_INTERNAL_OPENSSL_MSVC_VER
+ #define POCO_INTERNAL_OPENSSL_BUILD \
+ " (POCO internal build, MSVC version " \
+ POCO_STR(POCO_INTERNAL_OPENSSL_MSVC_VER) ")"
+ #else
+ #define POCO_INTERNAL_OPENSSL_BUILD ""
+ #endif
+ #pragma message (OPENSSL_VERSION_TEXT POCO_INTERNAL_OPENSSL_BUILD)
+#endif
+
+
+using Poco::RandomInputStream;
+using Poco::Thread;
+
+
+#if defined(_MSC_VER) && !defined(_DLL) && defined(POCO_INTERNAL_OPENSSL_MSVC_VER)
+
+ #if (POCO_MSVS_VERSION >= 2015)
+ FILE _iob[] = { *stdin, *stdout, *stderr };
+ extern "C" FILE * __cdecl __iob_func(void) { return _iob; }
+ #endif // (POCO_MSVS_VERSION >= 2015)
+
+ #if (POCO_MSVS_VERSION < 2012)
+ extern "C" __declspec(noreturn) void __cdecl __report_rangecheckfailure(void) { ::ExitProcess(1); }
+ #endif // (POCO_MSVS_VERSION < 2012)
+
+#endif // _MSC_VER && _MT && !POCO_EXTERNAL_OPENSSL && (POCO_MSVS_VERSION < 2013)
+
+
+namespace Poco {
+namespace Crypto {
+
+
+Poco::FastMutex* OpenSSLInitializer::_mutexes(0);
+Poco::AtomicCounter OpenSSLInitializer::_rc;
+
+
+OpenSSLInitializer::OpenSSLInitializer()
+{
+ initialize();
+}
+
+
+OpenSSLInitializer::~OpenSSLInitializer()
+{
+ try
+ {
+ uninitialize();
+ }
+ catch (...)
+ {
+ poco_unexpected();
+ }
+}
+
+
+void OpenSSLInitializer::initialize()
+{
+ if (++_rc == 1)
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x0907000L
+ OPENSSL_config(NULL);
+#endif
+ SSL_library_init();
+ SSL_load_error_strings();
+ OpenSSL_add_all_algorithms();
+
+ char seed[SEEDSIZE];
+ RandomInputStream rnd;
+ rnd.read(seed, sizeof(seed));
+ RAND_seed(seed, SEEDSIZE);
+
+ int nMutexes = CRYPTO_num_locks();
+ _mutexes = new Poco::FastMutex[nMutexes];
+ CRYPTO_set_locking_callback(&OpenSSLInitializer::lock);
+#ifndef POCO_OS_FAMILY_WINDOWS
+// Not needed on Windows (see SF #110: random unhandled exceptions when linking with ssl).
+// https://sourceforge.net/p/poco/bugs/110/
+//
+// From http://www.openssl.org/docs/crypto/threads.html :
+// "If the application does not register such a callback using CRYPTO_THREADID_set_callback(),
+// then a default implementation is used - on Windows and BeOS this uses the system's
+// default thread identifying APIs"
+ CRYPTO_set_id_callback(&OpenSSLInitializer::id);
+#endif
+ CRYPTO_set_dynlock_create_callback(&OpenSSLInitializer::dynlockCreate);
+ CRYPTO_set_dynlock_lock_callback(&OpenSSLInitializer::dynlock);
+ CRYPTO_set_dynlock_destroy_callback(&OpenSSLInitializer::dynlockDestroy);
+ }
+}
+
+
+void OpenSSLInitializer::uninitialize()
+{
+ if (--_rc == 0)
+ {
+ EVP_cleanup();
+ ERR_free_strings();
+ CRYPTO_set_locking_callback(0);
+#ifndef POCO_OS_FAMILY_WINDOWS
+ CRYPTO_set_id_callback(0);
+#endif
+ delete [] _mutexes;
+
+ CONF_modules_free();
+ }
+}
+
+
+void OpenSSLInitializer::lock(int mode, int n, const char* file, int line)
+{
+ if (mode & CRYPTO_LOCK)
+ _mutexes[n].lock();
+ else
+ _mutexes[n].unlock();
+}
+
+
+unsigned long OpenSSLInitializer::id()
+{
+ // Note: we use an old-style C cast here because
+ // neither static_cast<> nor reinterpret_cast<>
+ // work uniformly across all platforms.
+ return (unsigned long) Poco::Thread::currentTid();
+}
+
+
+struct CRYPTO_dynlock_value* OpenSSLInitializer::dynlockCreate(const char* file, int line)
+{
+ return new CRYPTO_dynlock_value;
+}
+
+
+void OpenSSLInitializer::dynlock(int mode, struct CRYPTO_dynlock_value* lock, const char* file, int line)
+{
+ poco_check_ptr (lock);
+
+ if (mode & CRYPTO_LOCK)
+ lock->_mutex.lock();
+ else
+ lock->_mutex.unlock();
+}
+
+
+void OpenSSLInitializer::dynlockDestroy(struct CRYPTO_dynlock_value* lock, const char* file, int line)
+{
+ delete lock;
+}
+
+
+void initializeCrypto()
+{
+ OpenSSLInitializer::initialize();
+}
+
+
+void uninitializeCrypto()
+{
+ OpenSSLInitializer::uninitialize();
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/PKCS12Container.cpp b/contrib/libs/poco/Crypto/src/PKCS12Container.cpp
new file mode 100644
index 0000000000..5c03a9ff85
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/PKCS12Container.cpp
@@ -0,0 +1,202 @@
+//
+// 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("PKCS12Container(istream&, const string&)");
+ load(pPKCS12, password);
+ }
+ else
+ {
+ throw Poco::NullPointerException("PKCS12Container(istream&, const string&)");
+ }
+}
+
+
+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("PKCS12Container(const string&, const string&)");
+ load(pPKCS12, password);
+ }
+ else
+ {
+ throw Poco::OpenFileException("PKCS12Container: " + path);
+ }
+}
+
+
+PKCS12Container::PKCS12Container(const PKCS12Container& other):
+ _pKey(EVPPKey::duplicate(other._pKey, &_pKey)),
+ _pX509Cert(new X509Certificate(*other._pX509Cert)),
+ _caCertList(other._caCertList),
+ _caCertNames(other._caCertNames),
+ _pkcsFriendlyName(other._pkcsFriendlyName)
+{
+}
+
+
+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;
+ _caCertNames = other._caCertNames;
+ _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)),
+ _caCertNames(std::move(other._caCertNames)),
+ _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);
+ _caCertNames = std::move(other._caCertNames);
+ _pkcsFriendlyName = std::move(other._pkcsFriendlyName);
+ }
+ return *this;
+}
+
+
+#endif // POCO_ENABLE_CPP11
+
+
+PKCS12Container::~PKCS12Container()
+{
+ if (_pKey) EVP_PKEY_free(_pKey);
+}
+
+
+std::string PKCS12Container::extractFriendlyName(X509* pCert)
+{
+ std::string friendlyName;
+ if(pCert)
+ {
+ STACK_OF(PKCS12_SAFEBAG)*pBags = 0;
+ PKCS12_SAFEBAG*pBag = PKCS12_add_cert(&pBags, pCert);
+ if(pBag)
+ {
+ char* pBuffer = PKCS12_get_friendlyname(pBag);
+ if(pBuffer)
+ {
+ friendlyName = pBuffer;
+ OPENSSL_free(pBuffer);
+ }
+ if(pBags) sk_PKCS12_SAFEBAG_pop_free(pBags, PKCS12_SAFEBAG_free);
+ }
+ else throw OpenSSLException("PKCS12Container::extractFriendlyName()");
+ }
+ else throw NullPointerException("PKCS12Container::extractFriendlyName()");
+
+ return friendlyName;
+}
+
+
+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)
+ {
+ _pX509Cert.reset(new X509Certificate(pCert, true));
+ _pkcsFriendlyName = extractFriendlyName(pCert);
+ }
+ else _pX509Cert.reset();
+
+ _caCertList.clear();
+ _caCertNames.clear();
+ if (pCA)
+ {
+ int certCount = sk_X509_num(pCA);
+ for (int i = 0; i < certCount; ++i)
+ {
+ X509* pX509 = sk_X509_value(pCA, i);
+ if (pX509)
+ {
+ _caCertList.push_back(X509Certificate(pX509, true));
+ _caCertNames.push_back(extractFriendlyName(pX509));
+ }
+ else throw OpenSSLException("PKCS12Container::load()");
+ }
+ }
+ }
+ else
+ {
+ throw OpenSSLException();
+ }
+ PKCS12_free(pPKCS12);
+ sk_X509_pop_free(pCA, X509_free);
+ if (pCert) X509_free(pCert);
+ poco_assert_dbg (_caCertList.size() == _caCertNames.size());
+ }
+ else
+ {
+ throw NullPointerException("PKCS12Container: struct PKCS12");
+ }
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/RSACipherImpl.cpp b/contrib/libs/poco/Crypto/src/RSACipherImpl.cpp
new file mode 100644
index 0000000000..5c2e493ed0
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/RSACipherImpl.cpp
@@ -0,0 +1,344 @@
+//
+// RSACipherImpl.cpp
+//
+// Library: Crypto
+// Package: RSA
+// Module: RSACipherImpl
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/RSACipherImpl.h"
+#include "Poco/Crypto/CryptoTransform.h"
+#include "Poco/Exception.h"
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <cstring>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+namespace
+{
+ void throwError()
+ {
+ unsigned long err;
+ std::string msg;
+
+ while ((err = ERR_get_error()))
+ {
+ if (!msg.empty())
+ msg.append("; ");
+ msg.append(ERR_error_string(err, 0));
+ }
+
+ throw Poco::IOException(msg);
+ }
+
+
+ int mapPaddingMode(RSAPaddingMode paddingMode)
+ {
+ switch (paddingMode)
+ {
+ case RSA_PADDING_PKCS1:
+ return RSA_PKCS1_PADDING;
+ case RSA_PADDING_PKCS1_OAEP:
+ return RSA_PKCS1_OAEP_PADDING;
+ case RSA_PADDING_SSLV23:
+ return RSA_SSLV23_PADDING;
+ case RSA_PADDING_NONE:
+ return RSA_NO_PADDING;
+ default:
+ poco_bugcheck();
+ return RSA_NO_PADDING;
+ }
+ }
+
+
+ class RSAEncryptImpl: public CryptoTransform
+ {
+ public:
+ RSAEncryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode);
+ ~RSAEncryptImpl();
+
+ std::size_t blockSize() const;
+ std::size_t maxDataSize() const;
+ std::string getTag(std::size_t);
+ void setTag(const std::string&);
+
+ std::streamsize transform(
+ const unsigned char* input,
+ std::streamsize inputLength,
+ unsigned char* output,
+ std::streamsize outputLength);
+
+ std::streamsize finalize(unsigned char* output, std::streamsize length);
+
+ private:
+ const RSA* _pRSA;
+ RSAPaddingMode _paddingMode;
+ std::streamsize _pos;
+ unsigned char* _pBuf;
+ };
+
+
+ RSAEncryptImpl::RSAEncryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode):
+ _pRSA(pRSA),
+ _paddingMode(paddingMode),
+ _pos(0),
+ _pBuf(0)
+ {
+ _pBuf = new unsigned char[blockSize()];
+ }
+
+
+ RSAEncryptImpl::~RSAEncryptImpl()
+ {
+ delete [] _pBuf;
+ }
+
+
+ std::size_t RSAEncryptImpl::blockSize() const
+ {
+ return RSA_size(_pRSA);
+ }
+
+
+ std::size_t RSAEncryptImpl::maxDataSize() const
+ {
+ std::size_t size = blockSize();
+ switch (_paddingMode)
+ {
+ case RSA_PADDING_PKCS1:
+ case RSA_PADDING_SSLV23:
+ size -= 11;
+ break;
+ case RSA_PADDING_PKCS1_OAEP:
+ size -= 41;
+ break;
+ default:
+ break;
+ }
+ return size;
+ }
+
+
+ std::string RSAEncryptImpl::getTag(std::size_t)
+ {
+ return std::string();
+ }
+
+
+ void RSAEncryptImpl::setTag(const std::string&)
+ {
+ }
+
+
+ std::streamsize RSAEncryptImpl::transform(
+ const unsigned char* input,
+ std::streamsize inputLength,
+ unsigned char* output,
+ std::streamsize outputLength)
+ {
+ // always fill up the buffer before writing!
+ std::streamsize maxSize = static_cast<std::streamsize>(maxDataSize());
+ std::streamsize rsaSize = static_cast<std::streamsize>(blockSize());
+ poco_assert_dbg(_pos <= maxSize);
+ poco_assert (outputLength >= rsaSize);
+ int rc = 0;
+ while (inputLength > 0)
+ {
+ // check how many data bytes we are missing to get the buffer full
+ poco_assert_dbg (maxSize >= _pos);
+ std::streamsize missing = maxSize - _pos;
+ if (missing == 0)
+ {
+ poco_assert (outputLength >= rsaSize);
+ int n = RSA_public_encrypt(static_cast<int>(maxSize), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
+ if (n == -1)
+ throwError();
+ rc += n;
+ output += n;
+ outputLength -= n;
+ _pos = 0;
+
+ }
+ else
+ {
+ if (missing > inputLength)
+ missing = inputLength;
+
+ std::memcpy(_pBuf + _pos, input, static_cast<std::size_t>(missing));
+ input += missing;
+ _pos += missing;
+ inputLength -= missing;
+ }
+ }
+ return rc;
+ }
+
+
+ std::streamsize RSAEncryptImpl::finalize(unsigned char* output, std::streamsize length)
+ {
+ poco_assert (length >= blockSize());
+ poco_assert (_pos <= maxDataSize());
+ int rc = 0;
+ if (_pos > 0)
+ {
+ rc = RSA_public_encrypt(static_cast<int>(_pos), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
+ if (rc == -1) throwError();
+ }
+ return rc;
+ }
+
+
+ class RSADecryptImpl: public CryptoTransform
+ {
+ public:
+ RSADecryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode);
+ ~RSADecryptImpl();
+
+ std::size_t blockSize() const;
+ std::string getTag(std::size_t);
+ void setTag(const std::string&);
+
+ std::streamsize transform(
+ const unsigned char* input,
+ std::streamsize inputLength,
+ unsigned char* output,
+ std::streamsize outputLength);
+
+ std::streamsize finalize(
+ unsigned char* output,
+ std::streamsize length);
+
+ private:
+ const RSA* _pRSA;
+ RSAPaddingMode _paddingMode;
+ std::streamsize _pos;
+ unsigned char* _pBuf;
+ };
+
+
+ RSADecryptImpl::RSADecryptImpl(const RSA* pRSA, RSAPaddingMode paddingMode):
+ _pRSA(pRSA),
+ _paddingMode(paddingMode),
+ _pos(0),
+ _pBuf(0)
+ {
+ _pBuf = new unsigned char[blockSize()];
+ }
+
+
+ RSADecryptImpl::~RSADecryptImpl()
+ {
+ delete [] _pBuf;
+ }
+
+
+ std::size_t RSADecryptImpl::blockSize() const
+ {
+ return RSA_size(_pRSA);
+ }
+
+
+ std::string RSADecryptImpl::getTag(std::size_t)
+ {
+ return std::string();
+ }
+
+
+ void RSADecryptImpl::setTag(const std::string&)
+ {
+ }
+
+
+ std::streamsize RSADecryptImpl::transform(
+ const unsigned char* input,
+ std::streamsize inputLength,
+ unsigned char* output,
+ std::streamsize outputLength)
+ {
+
+ // always fill up the buffer before decrypting!
+ std::streamsize rsaSize = static_cast<std::streamsize>(blockSize());
+ poco_assert_dbg(_pos <= rsaSize);
+ poco_assert (outputLength >= rsaSize);
+ int rc = 0;
+ while (inputLength > 0)
+ {
+ // check how many data bytes we are missing to get the buffer full
+ poco_assert_dbg (rsaSize >= _pos);
+ std::streamsize missing = rsaSize - _pos;
+ if (missing == 0)
+ {
+ int tmp = RSA_private_decrypt(static_cast<int>(rsaSize), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
+ if (tmp == -1)
+ throwError();
+ rc += tmp;
+ output += tmp;
+ outputLength -= tmp;
+ _pos = 0;
+
+ }
+ else
+ {
+ if (missing > inputLength)
+ missing = inputLength;
+
+ std::memcpy(_pBuf + _pos, input, static_cast<std::size_t>(missing));
+ input += missing;
+ _pos += missing;
+ inputLength -= missing;
+ }
+ }
+ return rc;
+ }
+
+
+ std::streamsize RSADecryptImpl::finalize(unsigned char* output, std::streamsize length)
+ {
+ poco_assert (length >= blockSize());
+ int rc = 0;
+ if (_pos > 0)
+ {
+ rc = RSA_private_decrypt(static_cast<int>(_pos), _pBuf, output, const_cast<RSA*>(_pRSA), mapPaddingMode(_paddingMode));
+ if (rc == -1)
+ throwError();
+ }
+ return rc;
+ }
+}
+
+
+RSACipherImpl::RSACipherImpl(const RSAKey& key, RSAPaddingMode paddingMode):
+ _key(key),
+ _paddingMode(paddingMode)
+{
+}
+
+
+RSACipherImpl::~RSACipherImpl()
+{
+}
+
+
+CryptoTransform* RSACipherImpl::createEncryptor()
+{
+ return new RSAEncryptImpl(_key.impl()->getRSA(), _paddingMode);
+}
+
+
+CryptoTransform* RSACipherImpl::createDecryptor()
+{
+ return new RSADecryptImpl(_key.impl()->getRSA(), _paddingMode);
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/RSADigestEngine.cpp b/contrib/libs/poco/Crypto/src/RSADigestEngine.cpp
new file mode 100644
index 0000000000..948aa25ac6
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/RSADigestEngine.cpp
@@ -0,0 +1,96 @@
+//
+// RSADigestEngine.cpp
+//
+// Library: Crypto
+// Package: RSA
+// Module: RSADigestEngine
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/RSADigestEngine.h"
+#include <openssl/rsa.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+RSADigestEngine::RSADigestEngine(const RSAKey& key, DigestType digestType):
+ _key(key),
+ _engine(digestType == DIGEST_MD5 ? "MD5" : "SHA1")
+{
+}
+
+RSADigestEngine::RSADigestEngine(const RSAKey& key, const std::string &name):
+ _key(key),
+ _engine(name)
+{
+}
+
+
+RSADigestEngine::~RSADigestEngine()
+{
+}
+
+
+std::size_t RSADigestEngine::digestLength() const
+{
+ return _engine.digestLength();
+}
+
+
+void RSADigestEngine::reset()
+{
+ _engine.reset();
+ _digest.clear();
+ _signature.clear();
+}
+
+
+const DigestEngine::Digest& RSADigestEngine::digest()
+{
+ if (_digest.empty())
+ {
+ _digest = _engine.digest();
+ }
+ return _digest;
+}
+
+
+const DigestEngine::Digest& RSADigestEngine::signature()
+{
+ if (_signature.empty())
+ {
+ digest();
+ _signature.resize(_key.size());
+ unsigned sigLen = static_cast<unsigned>(_signature.size());
+ RSA_sign(_engine.nid(), &_digest[0], static_cast<unsigned>(_digest.size()), &_signature[0], &sigLen, _key.impl()->getRSA());
+ // truncate _sig to sigLen
+ if (sigLen < _signature.size())
+ _signature.resize(sigLen);
+ }
+ return _signature;
+}
+
+
+bool RSADigestEngine::verify(const DigestEngine::Digest& sig)
+{
+ digest();
+ DigestEngine::Digest sigCpy = sig; // copy becausse RSA_verify can modify sigCpy
+ int ret = RSA_verify(_engine.nid(), &_digest[0], static_cast<unsigned>(_digest.size()), &sigCpy[0], static_cast<unsigned>(sigCpy.size()), _key.impl()->getRSA());
+ return ret != 0;
+}
+
+
+void RSADigestEngine::updateImpl(const void* data, std::size_t length)
+{
+ _engine.update(data, length);
+}
+
+
+} } // namespace Poco::Crypto
diff --git a/contrib/libs/poco/Crypto/src/RSAKey.cpp b/contrib/libs/poco/Crypto/src/RSAKey.cpp
new file mode 100644
index 0000000000..b81a0281bf
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/RSAKey.cpp
@@ -0,0 +1,87 @@
+//
+// RSAKey.cpp
+//
+// Library: Crypto
+// Package: RSA
+// Module: RSAKey
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/RSAKey.h"
+#include <openssl/rsa.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+RSAKey::RSAKey(const EVPPKey& key):
+ KeyPair(new RSAKeyImpl(key)),
+ _pImpl(KeyPair::impl().cast<RSAKeyImpl>())
+{
+}
+
+
+RSAKey::RSAKey(const X509Certificate& cert):
+ KeyPair(new RSAKeyImpl(cert)),
+ _pImpl(KeyPair::impl().cast<RSAKeyImpl>())
+{
+}
+
+
+RSAKey::RSAKey(const PKCS12Container& cont):
+ KeyPair(new RSAKeyImpl(cont)),
+ _pImpl(KeyPair::impl().cast<RSAKeyImpl>())
+{
+}
+
+
+RSAKey::RSAKey(KeyLength keyLength, Exponent exp):
+ KeyPair(new RSAKeyImpl(keyLength, (exp == EXP_LARGE) ? RSA_F4 : RSA_3)),
+ _pImpl(KeyPair::impl().cast<RSAKeyImpl>())
+{
+}
+
+
+RSAKey::RSAKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase):
+ KeyPair(new RSAKeyImpl(publicKeyFile, privateKeyFile, privateKeyPassphrase)),
+ _pImpl(KeyPair::impl().cast<RSAKeyImpl>())
+{
+}
+
+
+RSAKey::RSAKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase):
+ KeyPair(new RSAKeyImpl(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase)),
+ _pImpl(KeyPair::impl().cast<RSAKeyImpl>())
+{
+}
+
+
+RSAKey::~RSAKey()
+{
+}
+
+RSAKeyImpl::ByteVec RSAKey::modulus() const
+{
+ return _pImpl->modulus();
+}
+
+
+RSAKeyImpl::ByteVec RSAKey::encryptionExponent() const
+{
+ return _pImpl->encryptionExponent();
+}
+
+
+RSAKeyImpl::ByteVec RSAKey::decryptionExponent() const
+{
+ return _pImpl->decryptionExponent();
+}
+
+
+} } // namespace Poco::Crypto \ No newline at end of file
diff --git a/contrib/libs/poco/Crypto/src/RSAKeyImpl.cpp b/contrib/libs/poco/Crypto/src/RSAKeyImpl.cpp
new file mode 100644
index 0000000000..8aa3890b91
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/RSAKeyImpl.cpp
@@ -0,0 +1,386 @@
+//
+// RSAKeyImpl.cpp
+//
+// Library: Crypto
+// Package: RSA
+// Module: RSAKeyImpl
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/RSAKeyImpl.h"
+#include "Poco/Crypto/X509Certificate.h"
+#include "Poco/Crypto/PKCS12Container.h"
+#include "Poco/FileStream.h"
+#include "Poco/StreamCopier.h"
+#include <sstream>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L
+#include <openssl/bn.h>
+#endif
+
+
+namespace Poco {
+namespace Crypto {
+
+
+RSAKeyImpl::RSAKeyImpl(const EVPPKey& key):
+ KeyPairImpl("rsa", KT_RSA_IMPL),
+ _pRSA(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>((const EVP_PKEY*)key)))
+{
+ if (!_pRSA) throw OpenSSLException();
+}
+
+
+RSAKeyImpl::RSAKeyImpl(const X509Certificate& cert):
+ KeyPairImpl("rsa", KT_RSA_IMPL),
+ _pRSA(0)
+{
+ const X509* pCert = cert.certificate();
+ EVP_PKEY* pKey = X509_get_pubkey(const_cast<X509*>(pCert));
+ if (pKey)
+ {
+ _pRSA = EVP_PKEY_get1_RSA(pKey);
+ EVP_PKEY_free(pKey);
+ }
+ else
+ throw OpenSSLException("RSAKeyImpl(const X509Certificate&)");
+}
+
+
+RSAKeyImpl::RSAKeyImpl(const PKCS12Container& cont):
+ KeyPairImpl("rsa", KT_RSA_IMPL),
+ _pRSA(0)
+{
+ EVPPKey key = cont.getKey();
+ _pRSA = EVP_PKEY_get1_RSA(key);
+}
+
+
+RSAKeyImpl::RSAKeyImpl(int keyLength, unsigned long exponent): KeyPairImpl("rsa", KT_RSA_IMPL),
+ _pRSA(0)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L
+ _pRSA = RSA_new();
+ int ret = 0;
+ BIGNUM* bn = 0;
+ try
+ {
+ bn = BN_new();
+ BN_set_word(bn, exponent);
+ ret = RSA_generate_key_ex(_pRSA, keyLength, bn, 0);
+ BN_free(bn);
+ }
+ catch (...)
+ {
+ BN_free(bn);
+ throw;
+ }
+ if (!ret) throw Poco::InvalidArgumentException("Failed to create RSA context");
+#else
+ _pRSA = RSA_generate_key(keyLength, exponent, 0, 0);
+ if (!_pRSA) throw Poco::InvalidArgumentException("Failed to create RSA context");
+#endif
+}
+
+
+RSAKeyImpl::RSAKeyImpl(const std::string& publicKeyFile,
+ const std::string& privateKeyFile,
+ const std::string& privateKeyPassphrase): KeyPairImpl("rsa", KT_RSA_IMPL),
+ _pRSA(0)
+{
+ poco_assert_dbg(_pRSA == 0);
+
+ _pRSA = RSA_new();
+ if (!publicKeyFile.empty())
+ {
+ BIO* bio = BIO_new(BIO_s_file());
+ if (!bio) throw Poco::IOException("Cannot create BIO for reading public key", publicKeyFile);
+ int rc = BIO_read_filename(bio, publicKeyFile.c_str());
+ if (rc)
+ {
+ RSA* pubKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0);
+ if (!pubKey)
+ {
+ int rc = BIO_reset(bio);
+ // BIO_reset() normally returns 1 for success and 0 or -1 for failure.
+ // File BIOs are an exception, they return 0 for success and -1 for failure.
+ if (rc != 0) throw Poco::FileException("Failed to load public key", publicKeyFile);
+ pubKey = PEM_read_bio_RSA_PUBKEY(bio, &_pRSA, 0, 0);
+ }
+ BIO_free(bio);
+ if (!pubKey)
+ {
+ freeRSA();
+ throw Poco::FileException("Failed to load public key", publicKeyFile);
+ }
+ }
+ else
+ {
+ freeRSA();
+ throw Poco::FileNotFoundException("Public key file", publicKeyFile);
+ }
+ }
+
+ if (!privateKeyFile.empty())
+ {
+ BIO* bio = BIO_new(BIO_s_file());
+ if (!bio) throw Poco::IOException("Cannot create BIO for reading private key", privateKeyFile);
+ int rc = BIO_read_filename(bio, privateKeyFile.c_str());
+ if (rc)
+ {
+ RSA* privKey = 0;
+ if (privateKeyPassphrase.empty())
+ privKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, 0);
+ else
+ privKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, const_cast<char*>(privateKeyPassphrase.c_str()));
+ BIO_free(bio);
+ if (!privKey)
+ {
+ freeRSA();
+ throw Poco::FileException("Failed to load private key", privateKeyFile);
+ }
+ }
+ else
+ {
+ freeRSA();
+ throw Poco::FileNotFoundException("Private key file", privateKeyFile);
+ }
+ }
+}
+
+
+RSAKeyImpl::RSAKeyImpl(std::istream* pPublicKeyStream,
+ std::istream* pPrivateKeyStream,
+ const std::string& privateKeyPassphrase): KeyPairImpl("rsa", KT_RSA_IMPL),
+ _pRSA(0)
+{
+ poco_assert_dbg(_pRSA == 0);
+
+ _pRSA = RSA_new();
+ if (pPublicKeyStream)
+ {
+ std::string publicKeyData;
+ Poco::StreamCopier::copyToString(*pPublicKeyStream, publicKeyData);
+ BIO* bio = BIO_new_mem_buf(const_cast<char*>(publicKeyData.data()), static_cast<int>(publicKeyData.size()));
+ if (!bio) throw Poco::IOException("Cannot create BIO for reading public key");
+ RSA* publicKey = PEM_read_bio_RSAPublicKey(bio, &_pRSA, 0, 0);
+ if (!publicKey)
+ {
+ int rc = BIO_reset(bio);
+ // BIO_reset() normally returns 1 for success and 0 or -1 for failure.
+ // File BIOs are an exception, they return 0 for success and -1 for failure.
+ if (rc != 1) throw Poco::FileException("Failed to load public key");
+ publicKey = PEM_read_bio_RSA_PUBKEY(bio, &_pRSA, 0, 0);
+ }
+ BIO_free(bio);
+ if (!publicKey)
+ {
+ freeRSA();
+ throw Poco::FileException("Failed to load public key");
+ }
+ }
+
+ if (pPrivateKeyStream)
+ {
+ std::string privateKeyData;
+ Poco::StreamCopier::copyToString(*pPrivateKeyStream, privateKeyData);
+ BIO* bio = BIO_new_mem_buf(const_cast<char*>(privateKeyData.data()), static_cast<int>(privateKeyData.size()));
+ if (!bio) throw Poco::IOException("Cannot create BIO for reading private key");
+ RSA* privateKey = 0;
+ if (privateKeyPassphrase.empty())
+ privateKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, 0);
+ else
+ privateKey = PEM_read_bio_RSAPrivateKey(bio, &_pRSA, 0, const_cast<char*>(privateKeyPassphrase.c_str()));
+ BIO_free(bio);
+ if (!privateKey)
+ {
+ freeRSA();
+ throw Poco::FileException("Failed to load private key");
+ }
+ }
+}
+
+
+RSAKeyImpl::~RSAKeyImpl()
+{
+ freeRSA();
+}
+
+
+void RSAKeyImpl::freeRSA()
+{
+ if (_pRSA) RSA_free(_pRSA);
+ _pRSA = 0;
+}
+
+
+int RSAKeyImpl::size() const
+{
+ return RSA_size(_pRSA);
+}
+
+
+RSAKeyImpl::ByteVec RSAKeyImpl::modulus() const
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ const BIGNUM* n = 0;
+ const BIGNUM* e = 0;
+ const BIGNUM* d = 0;
+ RSA_get0_key(_pRSA, &n, &e, &d);
+ return convertToByteVec(n);
+#else
+ return convertToByteVec(_pRSA->n);
+#endif
+}
+
+
+RSAKeyImpl::ByteVec RSAKeyImpl::encryptionExponent() const
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ const BIGNUM* n = 0;
+ const BIGNUM* e = 0;
+ const BIGNUM* d = 0;
+ RSA_get0_key(_pRSA, &n, &e, &d);
+ return convertToByteVec(e);
+#else
+ return convertToByteVec(_pRSA->e);
+#endif
+}
+
+
+RSAKeyImpl::ByteVec RSAKeyImpl::decryptionExponent() const
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ const BIGNUM* n = 0;
+ const BIGNUM* e = 0;
+ const BIGNUM* d = 0;
+ RSA_get0_key(_pRSA, &n, &e, &d);
+ return convertToByteVec(d);
+#else
+ return convertToByteVec(_pRSA->d);
+#endif
+}
+
+
+void RSAKeyImpl::save(const std::string& publicKeyFile,
+ const std::string& privateKeyFile,
+ const std::string& privateKeyPassphrase) const
+{
+ 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())))
+ {
+ if (!PEM_write_bio_RSAPublicKey(bio, _pRSA))
+ 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())))
+ {
+ int rc = 0;
+ if (privateKeyPassphrase.empty())
+ rc = PEM_write_bio_RSAPrivateKey(bio, _pRSA, 0, 0, 0, 0, 0);
+ else
+ rc = PEM_write_bio_RSAPrivateKey(bio, _pRSA, 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 RSAKeyImpl::save(std::ostream* pPublicKeyStream,
+ std::ostream* pPrivateKeyStream,
+ const std::string& privateKeyPassphrase) const
+{
+ if (pPublicKeyStream)
+ {
+ BIO* bio = BIO_new(BIO_s_mem());
+ if (!bio) throw Poco::IOException("Cannot create BIO for writing public key");
+ if (!PEM_write_bio_RSAPublicKey(bio, _pRSA))
+ {
+ 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");
+ int rc = 0;
+ if (privateKeyPassphrase.empty())
+ rc = PEM_write_bio_RSAPrivateKey(bio, _pRSA, 0, 0, 0, 0, 0);
+ else
+ rc = PEM_write_bio_RSAPrivateKey(bio, _pRSA, 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);
+ }
+}
+
+
+RSAKeyImpl::ByteVec RSAKeyImpl::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 \ No newline at end of file
diff --git a/contrib/libs/poco/Crypto/src/X509Certificate.cpp b/contrib/libs/poco/Crypto/src/X509Certificate.cpp
new file mode 100644
index 0000000000..bea1e459ea
--- /dev/null
+++ b/contrib/libs/poco/Crypto/src/X509Certificate.cpp
@@ -0,0 +1,386 @@
+//
+// X509Certificate.cpp
+//
+// Library: Crypto
+// Package: Certificate
+// Module: X509Certificate
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Crypto/X509Certificate.h"
+#include "Poco/Crypto/CryptoException.h"
+#include "Poco/StreamCopier.h"
+#include "Poco/String.h"
+#include "Poco/DateTimeParser.h"
+#include "Poco/Format.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>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+X509Certificate::X509Certificate(std::istream& istr):
+ _pCert(0)
+{
+ load(istr);
+}
+
+
+X509Certificate::X509Certificate(const std::string& path):
+ _pCert(0)
+{
+ load(path);
+}
+
+
+X509Certificate::X509Certificate(X509* pCert):
+ _pCert(pCert)
+{
+ poco_check_ptr(_pCert);
+
+ init();
+}
+
+
+X509Certificate::X509Certificate(X509* pCert, bool shared):
+ _pCert(pCert)
+{
+ poco_check_ptr(_pCert);
+
+ if (shared)
+ {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ X509_up_ref(_pCert);
+#else
+ _pCert->references++;
+#endif
+ }
+
+ init();
+}
+
+
+X509Certificate::X509Certificate(const X509Certificate& cert):
+ _issuerName(cert._issuerName),
+ _subjectName(cert._subjectName),
+ _serialNumber(cert._serialNumber),
+ _pCert(cert._pCert)
+{
+ _pCert = X509_dup(_pCert);
+}
+
+
+X509Certificate& X509Certificate::operator = (const X509Certificate& cert)
+{
+ X509Certificate tmp(cert);
+ swap(tmp);
+ return *this;
+}
+
+
+void X509Certificate::swap(X509Certificate& cert)
+{
+ using std::swap;
+ swap(cert._issuerName, _issuerName);
+ swap(cert._subjectName, _subjectName);
+ swap(cert._serialNumber, _serialNumber);
+ swap(cert._pCert, _pCert);
+}
+
+
+X509Certificate::~X509Certificate()
+{
+ X509_free(_pCert);
+}
+
+
+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("Failed to load certificate from stream");
+
+ init();
+}
+
+
+void X509Certificate::load(const std::string& path)
+{
+ poco_assert (!_pCert);
+
+ BIO *pBIO = BIO_new(BIO_s_file());
+ if (!pBIO) throw Poco::IOException("Cannot create BIO for reading certificate file", path);
+ if (!BIO_read_filename(pBIO, path.c_str()))
+ {
+ 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();
+}
+
+
+void X509Certificate::save(std::ostream& stream) const
+{
+ BIO *pBIO = BIO_new(BIO_s_mem());
+ if (!pBIO) throw Poco::IOException("Cannot create BIO for writing certificate");
+ try
+ {
+ if (!PEM_write_bio_X509(pBIO, _pCert))
+ throw Poco::IOException("Failed to write certificate to stream");
+
+ char *pData;
+ long size;
+ size = BIO_get_mem_data(pBIO, &pData);
+ stream.write(pData, size);
+ }
+ catch (...)
+ {
+ BIO_free(pBIO);
+ throw;
+ }
+ BIO_free(pBIO);
+}
+
+
+void X509Certificate::save(const std::string& path) const
+{
+ BIO *pBIO = BIO_new(BIO_s_file());
+ if (!pBIO) throw Poco::IOException("Cannot create BIO for reading certificate file", path);
+ if (!BIO_write_filename(pBIO, const_cast<char*>(path.c_str())))
+ {
+ BIO_free(pBIO);
+ throw Poco::CreateFileException("Cannot create certificate file", path);
+ }
+ try
+ {
+ if (!PEM_write_bio_X509(pBIO, _pCert))
+ throw Poco::WriteFileException("Failed to write certificate to file", path);
+ }
+ catch (...)
+ {
+ BIO_free(pBIO);
+ throw;
+ }
+ BIO_free(pBIO);
+}
+
+
+void X509Certificate::init()
+{
+ char buffer[NAME_BUFFER_SIZE];
+ X509_NAME_oneline(X509_get_issuer_name(_pCert), buffer, sizeof(buffer));
+ _issuerName = buffer;
+ X509_NAME_oneline(X509_get_subject_name(_pCert), buffer, sizeof(buffer));
+ _subjectName = buffer;
+ BIGNUM* pBN = ASN1_INTEGER_to_BN(X509_get_serialNumber(const_cast<X509*>(_pCert)), 0);
+ if (pBN)
+ {
+ char* pSN = BN_bn2hex(pBN);
+ if (pSN)
+ {
+ _serialNumber = pSN;
+ OPENSSL_free(pSN);
+ }
+ BN_free(pBN);
+ }
+}
+
+
+std::string X509Certificate::commonName() const
+{
+ return subjectName(NID_COMMON_NAME);
+}
+
+
+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();
+}
+
+
+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();
+}
+
+
+void X509Certificate::extractNames(std::string& cmnName, std::set<std::string>& domainNames) const
+{
+ 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);
+ }
+
+ cmnName = commonName();
+ if (!cmnName.empty() && domainNames.empty())
+ {
+ domainNames.insert(cmnName);
+ }
+}
+
+
+Poco::DateTime X509Certificate::validFrom() const
+{
+ ASN1_TIME* certTime = X509_get_notBefore(_pCert);
+ std::string dateTime(reinterpret_cast<char*>(certTime->data));
+ int tzd;
+ return DateTimeParser::parse("%y%m%d%H%M%S", dateTime, tzd);
+}
+
+
+Poco::DateTime X509Certificate::expiresOn() const
+{
+ ASN1_TIME* certTime = X509_get_notAfter(_pCert);
+ std::string dateTime(reinterpret_cast<char*>(certTime->data));
+ int tzd;
+ return DateTimeParser::parse("%y%m%d%H%M%S", dateTime, tzd);
+}
+
+
+bool X509Certificate::issuedBy(const X509Certificate& issuerCertificate) const
+{
+ X509* pCert = const_cast<X509*>(_pCert);
+ X509* pIssuerCert = const_cast<X509*>(issuerCertificate.certificate());
+ EVP_PKEY* pIssuerPublicKey = X509_get_pubkey(pIssuerCert);
+ if (!pIssuerPublicKey) throw Poco::InvalidArgumentException("Issuer certificate has no public key");
+ int rc = X509_verify(pCert, pIssuerPublicKey);
+ EVP_PKEY_free(pIssuerPublicKey);
+ return rc == 1;
+}
+
+
+bool X509Certificate::equals(const X509Certificate& otherCertificate) const
+{
+ X509* pCert = const_cast<X509*>(_pCert);
+ X509* pOtherCert = const_cast<X509*>(otherCertificate.certificate());
+ return X509_cmp(pCert, pOtherCert) == 0;
+}
+
+
+std::string X509Certificate::signatureAlgorithm() const
+{
+ int sigNID = NID_undef;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
+ sigNID = X509_get_signature_nid(_pCert);
+#else
+ poco_check_ptr(_pCert->sig_alg);
+ sigNID = OBJ_obj2nid(_pCert->sig_alg->algorithm);
+#endif
+
+ if (sigNID != NID_undef)
+ {
+ const char* pAlgName = OBJ_nid2ln(sigNID);
+ if (pAlgName) return std::string(pAlgName);
+ else throw OpenSSLException(Poco::format("X509Certificate::"
+ "signatureAlgorithm(): OBJ_nid2ln(%d)", sigNID));
+ }
+ else
+ throw NotFoundException("X509Certificate::signatureAlgorithm()");
+
+ return "";
+}
+
+
+X509Certificate::List X509Certificate::readPEM(const std::string& pemFileName)
+{
+ List caCertList;
+ BIO* pBIO = BIO_new_file(pemFileName.c_str(), "r");
+ if (pBIO == NULL) throw OpenFileException("X509Certificate::readPEM()");
+ X509* x = PEM_read_bio_X509(pBIO, NULL, 0, NULL);
+ if (!x) throw OpenSSLException(Poco::format("X509Certificate::readPEM(%s)", pemFileName));
+ while(x)
+ {
+ caCertList.push_back(X509Certificate(x));
+ x = PEM_read_bio_X509(pBIO, NULL, 0, NULL);
+ }
+ BIO_free(pBIO);
+ return caCertList;
+}
+
+
+void X509Certificate::writePEM(const std::string& pemFileName, const List& list)
+{
+ BIO* pBIO = BIO_new_file(pemFileName.c_str(), "a");
+ if (pBIO == NULL) throw OpenFileException("X509Certificate::writePEM()");
+ List::const_iterator it = list.begin();
+ List::const_iterator end = list.end();
+ for (; it != end; ++it)
+ {
+ if (!PEM_write_bio_X509(pBIO, const_cast<X509*>(it->certificate())))
+ {
+ throw OpenSSLException("X509Certificate::writePEM()");
+ }
+ }
+ BIO_free(pBIO);
+}
+
+
+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