diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/poco/Crypto | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/poco/Crypto')
47 files changed, 7205 insertions, 0 deletions
diff --git a/contrib/libs/poco/Crypto/.yandex_meta/licenses.list.txt b/contrib/libs/poco/Crypto/.yandex_meta/licenses.list.txt new file mode 100644 index 0000000000..b188b98227 --- /dev/null +++ b/contrib/libs/poco/Crypto/.yandex_meta/licenses.list.txt @@ -0,0 +1,64 @@ +====================BSD-3-Clause==================== + remove advertising from BSD licensed parts + + +====================BSL-1.0==================== +- Changed license to Boost license + + +====================BSL-1.0==================== +// SPDX-License-Identifier: BSL-1.0 + + +====================BSL-1.0==================== +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------------------------- +Note: +Individual files contain the following tag instead of the full license text. + + SPDX-License-Identifier: BSL-1.0 + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ + +====================COPYRIGHT==================== +// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/Cipher.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/Cipher.h new file mode 100644 index 0000000000..fbe0c30ae8 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/Cipher.h @@ -0,0 +1,138 @@ +// +// Cipher.h +// +// Library: Crypto +// Package: Cipher +// Module: Cipher +// +// Definition of the Cipher class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_Cipher_INCLUDED +#define Crypto_Cipher_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include <istream> +#include <ostream> +#include <vector> + + +namespace Poco { +namespace Crypto { + + +class CryptoTransform; + + +class Crypto_API Cipher: public Poco::RefCountedObject + /// Represents the abstract base class from which all implementations of + /// symmetric/asymmetric encryption algorithms must inherit. Use the CipherFactory + /// class to obtain an instance of this class: + /// + /// CipherFactory& factory = CipherFactory::defaultFactory(); + /// // Creates a 256-bit AES cipher + /// Cipher* pCipher = factory.createCipher(CipherKey("aes-256")); + /// Cipher* pRSACipher = factory.createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL)); + /// + /// Check the different Key constructors on how to initialize/create + /// a key. The above example auto-generates random keys. + /// + /// Note that you won't be able to decrypt data encrypted with a random key + /// once the Cipher is destroyed unless you persist the generated key and IV. + /// An example usage for random keys is to encrypt data saved in a temporary + /// file. + /// + /// Once your key is set up, you can use the Cipher object to encrypt or + /// decrypt strings or, in conjunction with a CryptoInputStream or a + /// CryptoOutputStream, to encrypt streams of data. + /// + /// Since encrypted strings will contain arbitrary binary data that will cause + /// problems in applications that are not binary-safe (eg., when sending + /// encrypted data in e-mails), the encryptString() and decryptString() can + /// encode (or decode, respectively) encrypted data using a "transport encoding". + /// Supported encodings are Base64 and BinHex. + /// + /// The following example encrypts and decrypts a string utilizing Base64 + /// encoding: + /// + /// std::string plainText = "This is my secret information"; + /// std::string encrypted = pCipher->encryptString(plainText, Cipher::ENC_BASE64); + /// std::string decrypted = pCipher->decryptString(encrypted, Cipher::ENC_BASE64); + /// + /// In order to encrypt a stream of data (eg. to encrypt files), you can use + /// a CryptoStream: + /// + /// // Create an output stream that will encrypt all data going through it + /// // and write pass it to the underlying file stream. + /// Poco::FileOutputStream sink("encrypted.dat"); + /// CryptoOutputStream encryptor(sink, pCipher->createEncryptor()); + /// + /// Poco::FileInputStream source("source.txt"); + /// Poco::StreamCopier::copyStream(source, encryptor); + /// + /// // Always close output streams to flush all internal buffers + /// encryptor.close(); + /// sink.close(); +{ +public: + typedef Poco::AutoPtr<Cipher> Ptr; + typedef std::vector<unsigned char> ByteVec; + + enum Encoding + /// Transport encoding to use for encryptString() and decryptString(). + { + ENC_NONE = 0x00, /// Plain binary output + ENC_BASE64 = 0x01, /// Base64-encoded output + ENC_BINHEX = 0x02, /// BinHex-encoded output + ENC_BASE64_NO_LF = 0x81, /// Base64-encoded output, no linefeeds + ENC_BINHEX_NO_LF = 0x82 /// BinHex-encoded output, no linefeeds + + }; + + virtual ~Cipher(); + /// Destroys the Cipher. + + virtual const std::string& name() const = 0; + /// Returns the name of the Cipher. + + virtual CryptoTransform* createEncryptor() = 0; + /// Creates an encryptor object to be used with a CryptoStream. + + virtual CryptoTransform* createDecryptor() = 0; + /// Creates a decryptor object to be used with a CryptoStream. + + virtual std::string encryptString(const std::string& str, Encoding encoding = ENC_NONE); + /// Directly encrypt a string and encode it using the given encoding. + + virtual std::string decryptString(const std::string& str, Encoding encoding = ENC_NONE); + /// Directly decrypt a string that is encoded with the given encoding. + + virtual void encrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE); + /// Directly encrypts an input stream and encodes it using the given encoding. + + virtual void decrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE); + /// Directly decrypt an input stream that is encoded with the given encoding. + +protected: + Cipher(); + /// Creates a new Cipher object. + +private: + Cipher(const Cipher&); + Cipher& operator = (const Cipher&); +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_Cipher_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherFactory.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherFactory.h new file mode 100644 index 0000000000..36aa964a1e --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherFactory.h @@ -0,0 +1,75 @@ +// +// CipherFactory.h +// +// Library: Crypto +// Package: Cipher +// Module: CipherFactory +// +// Definition of the CipherFactory class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CipherFactory_INCLUDED +#define Crypto_CipherFactory_INCLUDED + + +#include "Poco/Crypto/Crypto.h" + + +namespace Poco { +namespace Crypto { + + +class Cipher; +class CipherKey; +class RSAKey; + + +class Crypto_API CipherFactory + /// A factory for Cipher objects. See the Cipher class for examples on how to + /// use the CipherFactory. +{ +public: + CipherFactory(); + /// Creates a new CipherFactory object. + + virtual ~CipherFactory(); + /// Destroys the CipherFactory. + + Cipher* createCipher(const CipherKey& key); + /// Creates a Cipher object for the given Cipher name. Valid cipher + /// names depend on the OpenSSL version the library is linked with; + /// see the output of + /// + /// openssl enc --help + /// + /// for a list of supported block and stream ciphers. + /// + /// Common examples are: + /// + /// * AES: "aes-128", "aes-256" + /// * DES: "des", "des3" + /// * Blowfish: "bf" + + Cipher* createCipher(const RSAKey& key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1); + /// Creates a RSACipher using the given RSA key and padding mode + /// for public key encryption/private key decryption. + + static CipherFactory& defaultFactory(); + /// Returns the default CipherFactory. + +private: + CipherFactory(const CipherFactory&); + CipherFactory& operator = (const CipherFactory&); +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CipherFactory_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherImpl.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherImpl.h new file mode 100644 index 0000000000..d6e8e0e79b --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherImpl.h @@ -0,0 +1,69 @@ +// +// CipherImpl.h +// +// Library: Crypto +// Package: Cipher +// Module: CipherImpl +// +// Definition of the CipherImpl class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CipherImpl_INCLUDED +#define Crypto_CipherImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/Cipher.h" +#include "Poco/Crypto/CipherKey.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include <openssl/evp.h> + + +namespace Poco { +namespace Crypto { + + +class CipherImpl: public Cipher + /// An implementation of the Cipher class for OpenSSL's crypto library. +{ +public: + CipherImpl(const CipherKey& key); + /// Creates a new CipherImpl object for the given CipherKey. + + virtual ~CipherImpl(); + /// Destroys the CipherImpl. + + const std::string& name() const; + /// Returns the name of the cipher. + + CryptoTransform* createEncryptor(); + /// Creates an encryptor object. + + CryptoTransform* createDecryptor(); + /// Creates a decryptor object. + +private: + CipherKey _key; + OpenSSLInitializer _openSSLInitializer; +}; + + +// +// Inlines +// +inline const std::string& CipherImpl::name() const +{ + return _key.name(); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CipherImpl_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherKey.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherKey.h new file mode 100644 index 0000000000..b102cc2310 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherKey.h @@ -0,0 +1,201 @@ +// +// CipherKey.h +// +// Library: Crypto +// Package: Cipher +// Module: CipherKey +// +// Definition of the CipherKey class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CipherKey_INCLUDED +#define Crypto_CipherKey_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/CipherKeyImpl.h" + + +namespace Poco { +namespace Crypto { + + +class Crypto_API CipherKey + /// CipherKey stores the key information for decryption/encryption of data. + /// To create a random key, using the following code: + /// + /// CipherKey key("aes-256"); + /// + /// Note that you won't be able to decrypt data encrypted with a random key + /// once the Cipher is destroyed unless you persist the generated key and IV. + /// An example usage for random keys is to encrypt data saved in a temporary + /// file. + /// + /// To create a key using a human-readable password + /// string, use the following code. We create a AES Cipher and + /// use a salt value to make the key more robust: + /// + /// std::string password = "secret"; + /// std::string salt("asdff8723lasdf(**923412"); + /// CipherKey key("aes-256", password, salt); + /// + /// You may also control the digest and the number of iterations used to generate the key + /// by specifying the specific values. Here we create a key with the same data as before, + /// except that we use 100 iterations instead of DEFAULT_ITERATION_COUNT, and sha1 instead of + /// the default md5: + /// + /// std::string password = "secret"; + /// std::string salt("asdff8723lasdf(**923412"); + /// std::string digest ("sha1"); + /// CipherKey key("aes-256", password, salt, 100, digest); + /// +{ +public: + typedef CipherKeyImpl::Mode Mode; + typedef CipherKeyImpl::ByteVec ByteVec; + + enum + { + DEFAULT_ITERATION_COUNT = 2000 + /// Default iteration count to use with + /// generateKey(). RSA security recommends + /// an iteration count of at least 1000. + }; + + CipherKey(const std::string& name, + const std::string& passphrase, + const std::string& salt = "", + int iterationCount = DEFAULT_ITERATION_COUNT, + const std::string& digest = "md5"); + /// Creates a new CipherKeyImpl object using the given + /// cipher name, passphrase, salt value, iteration count and digest. + + CipherKey(const std::string& name, + const ByteVec& key, + const ByteVec& iv); + /// Creates a new CipherKeyImpl object using the given cipher + /// name, key and initialization vector (IV). + /// + /// The size of the IV must match the cipher's expected + /// IV size (see ivSize()), except for GCM mode, which allows + /// a custom IV size. + + CipherKey(const std::string& name); + /// Creates a new CipherKeyImpl object. Autoinitializes key and + /// initialization vector. + + ~CipherKey(); + /// Destroys the CipherKeyImpl. + + const std::string& name() const; + /// Returns the name of the Cipher. + + int keySize() const; + /// Returns the key size of the Cipher. + + int blockSize() const; + /// Returns the block size of the Cipher. + + int ivSize() const; + /// Returns the IV size of the Cipher. + + Mode mode() const; + /// Returns the Cipher's mode of operation. + + const ByteVec& getKey() const; + /// Returns the key for the Cipher. + + void setKey(const ByteVec& key); + /// Sets the key for the Cipher. + + const ByteVec& getIV() const; + /// Returns the initialization vector (IV) for the Cipher. + + void setIV(const ByteVec& iv); + /// Sets the initialization vector (IV) for the Cipher. + /// + /// The size of the vector must match the cipher's expected + /// IV size (see ivSize()), except for GCM mode, which allows + /// a custom IV size. + + CipherKeyImpl::Ptr impl(); + /// Returns the impl object + +private: + CipherKeyImpl::Ptr _pImpl; +}; + + +// +// inlines +// +inline const std::string& CipherKey::name() const +{ + return _pImpl->name(); +} + + +inline int CipherKey::keySize() const +{ + return _pImpl->keySize(); +} + + +inline int CipherKey::blockSize() const +{ + return _pImpl->blockSize(); +} + + +inline int CipherKey::ivSize() const +{ + return _pImpl->ivSize(); +} + + +inline CipherKey::Mode CipherKey::mode() const +{ + return _pImpl->mode(); +} + + +inline const CipherKey::ByteVec& CipherKey::getKey() const +{ + return _pImpl->getKey(); +} + + +inline void CipherKey::setKey(const CipherKey::ByteVec& key) +{ + _pImpl->setKey(key); +} + + +inline const CipherKey::ByteVec& CipherKey::getIV() const +{ + return _pImpl->getIV(); +} + + +inline void CipherKey::setIV(const CipherKey::ByteVec& iv) +{ + _pImpl->setIV(iv); +} + + +inline CipherKeyImpl::Ptr CipherKey::impl() +{ + return _pImpl; +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CipherKey_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h new file mode 100644 index 0000000000..f7807aad9f --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CipherKeyImpl.h @@ -0,0 +1,168 @@ +// +// CipherKeyImpl.h +// +// Library: Crypto +// Package: Cipher +// Module: CipherKeyImpl +// +// Definition of the CipherKeyImpl class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CipherKeyImpl_INCLUDED +#define Crypto_CipherKeyImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include <vector> + + +struct evp_cipher_st; +typedef struct evp_cipher_st EVP_CIPHER; + + +namespace Poco { +namespace Crypto { + + +class CipherKeyImpl: public RefCountedObject + /// An implementation of the CipherKey class for OpenSSL's crypto library. +{ +public: + typedef std::vector<unsigned char> ByteVec; + typedef Poco::AutoPtr<CipherKeyImpl> Ptr; + + enum Mode + /// Cipher mode of operation. This mode determines how multiple blocks + /// are connected; this is essential to improve security. + { + MODE_STREAM_CIPHER, /// Stream cipher + MODE_ECB, /// Electronic codebook (plain concatenation) + MODE_CBC, /// Cipher block chaining (default) + MODE_CFB, /// Cipher feedback + MODE_OFB, /// Output feedback + MODE_CTR, /// Counter mode + MODE_GCM, /// Galois/Counter mode + MODE_CCM /// Counter with CBC-MAC + }; + + CipherKeyImpl(const std::string& name, + const std::string& passphrase, + const std::string& salt, + int iterationCount, + const std::string& digest); + /// Creates a new CipherKeyImpl object, using + /// the given cipher name, passphrase, salt value + /// and iteration count. + + CipherKeyImpl(const std::string& name, + const ByteVec& key, + const ByteVec& iv); + /// Creates a new CipherKeyImpl object, using the + /// given cipher name, key and initialization vector. + + CipherKeyImpl(const std::string& name); + /// Creates a new CipherKeyImpl object. Autoinitializes key + /// and initialization vector. + + virtual ~CipherKeyImpl(); + /// Destroys the CipherKeyImpl. + + const std::string& name() const; + /// Returns the name of the Cipher. + + int keySize() const; + /// Returns the key size of the Cipher. + + int blockSize() const; + /// Returns the block size of the Cipher. + + int ivSize() const; + /// Returns the IV size of the Cipher. + + Mode mode() const; + /// Returns the Cipher's mode of operation. + + const ByteVec& getKey() const; + /// Returns the key for the Cipher. + + void setKey(const ByteVec& key); + /// Sets the key for the Cipher. + + const ByteVec& getIV() const; + /// Returns the initialization vector (IV) for the Cipher. + + void setIV(const ByteVec& iv); + /// Sets the initialization vector (IV) for the Cipher. + + const EVP_CIPHER* cipher(); + /// Returns the cipher object + +private: + void generateKey(const std::string& passphrase, + const std::string& salt, + int iterationCount); + /// Generates key and IV from a password and optional salt string. + + void generateKey(); + /// Generates key and IV from random data. + + void getRandomBytes(ByteVec& vec, std::size_t count); + /// Stores random bytes in vec. + +private: + const EVP_CIPHER* _pCipher; + const EVP_MD* _pDigest; + std::string _name; + ByteVec _key; + ByteVec _iv; + OpenSSLInitializer _openSSLInitializer; +}; + + +// +// Inlines +// +inline const std::string& CipherKeyImpl::name() const +{ + return _name; +} + + +inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getKey() const +{ + return _key; +} + + +inline void CipherKeyImpl::setKey(const ByteVec& key) +{ + poco_assert(key.size() == static_cast<ByteVec::size_type>(keySize())); + _key = key; +} + + +inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getIV() const +{ + return _iv; +} + + +inline const EVP_CIPHER* CipherKeyImpl::cipher() +{ + return _pCipher; +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CipherKeyImpl_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/Crypto.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/Crypto.h new file mode 100644 index 0000000000..d6b3ede65c --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/Crypto.h @@ -0,0 +1,195 @@ +// +// Crypto.h +// +// Library: Crypto +// Package: CryptoCore +// Module: Crypto +// +// Basic definitions for the Poco Crypto library. +// This file must be the first file included by every other Crypto +// header file. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_Crypto_INCLUDED +#define Crypto_Crypto_INCLUDED + + +#define POCO_EXTERNAL_OPENSSL_DEFAULT 1 +#define POCO_EXTERNAL_OPENSSL_SLPRO 2 + + +#include "Poco/Foundation.h" +#include <openssl/opensslv.h> + + +#ifndef OPENSSL_VERSION_PREREQ + #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR) + #define OPENSSL_VERSION_PREREQ(maj, min) \ + ((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min)) + #else + #define OPENSSL_VERSION_PREREQ(maj, min) \ + (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20))) + #endif +#endif + + +enum RSAPaddingMode + /// The padding mode used for RSA public key encryption. +{ + RSA_PADDING_PKCS1, + /// PKCS #1 v1.5 padding. This currently is the most widely used mode. + + RSA_PADDING_PKCS1_OAEP, + /// EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty + /// encoding parameter. This mode is recommended for all new applications. + + RSA_PADDING_SSLV23, + /// PKCS #1 v1.5 padding with an SSL-specific modification that denotes + /// that the server is SSL3 capable. + + RSA_PADDING_NONE + /// Raw RSA encryption. This mode should only be used to implement cryptographically + /// sound padding modes in the application code. Encrypting user data directly with RSA + /// is insecure. +}; + + +// +// The following block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the Crypto_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// Crypto_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. +// +#if defined(_WIN32) + #if defined(POCO_DLL) + #if defined(Crypto_EXPORTS) + #define Crypto_API __declspec(dllexport) + #else + #define Crypto_API __declspec(dllimport) + #endif + #endif +#endif + + +#if !defined(Crypto_API) + #if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4) + #define Crypto_API __attribute__ ((visibility ("default"))) + #else + #define Crypto_API + #endif +#endif + + +// +// Automatically link Crypto and OpenSSL libraries. +// +#if defined(_MSC_VER) + #if !defined(POCO_NO_AUTOMATIC_LIBS) + #if defined(POCO_INTERNAL_OPENSSL_MSVC_VER) + #if defined(POCO_EXTERNAL_OPENSSL) + #pragma message("External OpenSSL defined but internal headers used - possible mismatch!") + #endif // POCO_EXTERNAL_OPENSSL + #if !defined(_DEBUG) + #define POCO_DEBUG_SUFFIX "" + #if !defined (_DLL) + #define POCO_STATIC_SUFFIX "mt" + #else // _DLL + #define POCO_STATIC_SUFFIX "" + #endif + #else // _DEBUG + #define POCO_DEBUG_SUFFIX "d" + #if !defined (_DLL) + #define POCO_STATIC_SUFFIX "mt" + #else // _DLL + #define POCO_STATIC_SUFFIX "" + #endif + #endif + #pragma comment(lib, "libcrypto" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib") + #pragma comment(lib, "libssl" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib") + #if !defined(_WIN64) && !defined (_DLL) && \ + (POCO_INTERNAL_OPENSSL_MSVC_VER == 120) && \ + (POCO_MSVC_VERSION < POCO_INTERNAL_OPENSSL_MSVC_VER) + #pragma comment(lib, "libPreVS2013CRT" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib") + #endif + #if !defined (_DLL) && (POCO_MSVS_VERSION >= 2015) + #pragma comment(lib, "legacy_stdio_definitions.lib") + #pragma comment(lib, "legacy_stdio_wide_specifiers.lib") + #endif + #elif defined(POCO_EXTERNAL_OPENSSL) + #if POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_SLPRO + #if defined(POCO_DLL) + #if OPENSSL_VERSION_PREREQ(1,1) + #pragma comment(lib, "libcrypto.lib") + #pragma comment(lib, "libssl.lib") + #else + #pragma comment(lib, "libeay32.lib") + #pragma comment(lib, "ssleay32.lib") + #endif + #else + #if OPENSSL_VERSION_PREREQ(1,1) + #if defined(_WIN64) + #pragma comment(lib, "libcrypto64" POCO_LIB_SUFFIX) + #pragma comment(lib, "libssl64" POCO_LIB_SUFFIX) + #else + #pragma comment(lib, "libcrypto32" POCO_LIB_SUFFIX) + #pragma comment(lib, "libssl32" POCO_LIB_SUFFIX) + #endif + #else + #pragma comment(lib, "libeay32" POCO_LIB_SUFFIX) + #pragma comment(lib, "ssleay32" POCO_LIB_SUFFIX) + #endif + #endif + #elif POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_DEFAULT + #if OPENSSL_VERSION_PREREQ(1,1) + #pragma comment(lib, "libcrypto.lib") + #pragma comment(lib, "libssl.lib") + #else + #pragma comment(lib, "libeay32.lib") + #pragma comment(lib, "ssleay32.lib") + #endif + #endif + #endif // POCO_INTERNAL_OPENSSL_MSVC_VER + #if !defined(Crypto_EXPORTS) + #pragma comment(lib, "PocoCrypto" POCO_LIB_SUFFIX) + #endif + #endif // POCO_NO_AUTOMATIC_LIBS +#endif + + +namespace Poco { +namespace Crypto { + + +void Crypto_API initializeCrypto(); + /// Initialize the Crypto library, as well as the underlying OpenSSL + /// libraries, by calling OpenSSLInitializer::initialize(). + /// + /// Should be called before using any class from the Crypto library. + /// The Crypto library will be initialized automatically, through + /// OpenSSLInitializer instances held by various Crypto classes + /// (Cipher, CipherKey, RSAKey, X509Certificate). + /// However, it is recommended to call initializeCrypto() + /// in any case at application startup. + /// + /// Can be called multiple times; however, for every call to + /// initializeCrypto(), a matching call to uninitializeCrypto() + /// must be performed. + + +void Crypto_API uninitializeCrypto(); + /// Uninitializes the Crypto library by calling + /// OpenSSLInitializer::uninitialize(). + + +} } // namespace Poco::Crypto + + +#endif // Crypto_Crypto_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoException.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoException.h new file mode 100644 index 0000000000..8bd5b011c4 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoException.h @@ -0,0 +1,56 @@ +// +// CryptoException.h +// +// +// Library: Crypto +// Package: Crypto +// Module: CryptoException +// +// Definition of the CryptoException class. +// +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CryptoException_INCLUDED +#define Crypto_CryptoException_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Exception.h" + + +namespace Poco { +namespace Crypto { + + +POCO_DECLARE_EXCEPTION(Crypto_API, CryptoException, Poco::Exception) + + +class Crypto_API OpenSSLException : public CryptoException +{ +public: + OpenSSLException(int code = 0); + OpenSSLException(const std::string& msg, int code = 0); + OpenSSLException(const std::string& msg, const std::string& arg, int code = 0); + OpenSSLException(const std::string& msg, const Poco::Exception& exc, int code = 0); + OpenSSLException(const OpenSSLException& exc); + ~OpenSSLException() noexcept; + OpenSSLException& operator = (const OpenSSLException& exc); + const char* name() const noexcept; + const char* className() const noexcept; + Poco::Exception* clone() const; + void rethrow() const; + +private: + void setExtMessage(); +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CryptoException_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoStream.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoStream.h new file mode 100644 index 0000000000..25a99a4ae5 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoStream.h @@ -0,0 +1,192 @@ +// +// CryptoStream.h +// +// Library: Crypto +// Package: Cipher +// Module: CryptoStream +// +// Definition of the CryptoStreamBuf, CryptoInputStream and CryptoOutputStream +// classes. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CryptoStream_INCLUDED +#define Crypto_CryptoStream_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/BufferedStreamBuf.h" +#include "Poco/Buffer.h" +#include <iostream> + + +namespace Poco { +namespace Crypto { + + +class CryptoTransform; +class Cipher; + + +class Crypto_API CryptoStreamBuf: public Poco::BufferedStreamBuf + /// This stream buffer performs cryptographic transformation on the data + /// going through it. +{ +public: + CryptoStreamBuf(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); + CryptoStreamBuf(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); + + virtual ~CryptoStreamBuf(); + + void close(); + /// Flushes all buffers and finishes the encryption. + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + CryptoTransform* _pTransform; + std::istream* _pIstr; + std::ostream* _pOstr; + bool _eof; + + Poco::Buffer<unsigned char> _buffer; + + CryptoStreamBuf(const CryptoStreamBuf&); + CryptoStreamBuf& operator = (const CryptoStreamBuf&); +}; + + +class Crypto_API CryptoIOS: public virtual std::ios + /// The base class for CryptoInputStream and CryptoOutputStream. + /// + /// This class is needed to ensure correct initialization order of the + /// stream buffer and base classes. +{ +public: + CryptoIOS(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); + CryptoIOS(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); + ~CryptoIOS(); + CryptoStreamBuf* rdbuf(); + +protected: + CryptoStreamBuf _buf; +}; + + +class Crypto_API CryptoInputStream: public CryptoIOS, public std::istream + /// This stream transforms all data passing through it using the given + /// CryptoTransform. + /// + /// Use a CryptoTransform object provided by Cipher::createEncrytor() or + /// Cipher::createDecryptor() to create an encrypting or decrypting stream, + /// respectively. +{ +public: + CryptoInputStream(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); + /// Create a new CryptoInputStream object. The CryptoInputStream takes the + /// ownership of the given CryptoTransform object. + + CryptoInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192); + /// Create a new encrypting CryptoInputStream object using the given cipher. + + ~CryptoInputStream(); + /// Destroys the CryptoInputStream. +}; + + +class Crypto_API CryptoOutputStream: public CryptoIOS, public std::ostream + /// This stream transforms all data passing through it using the given + /// CryptoTransform. + /// + /// Use a CryptoTransform object provided by Cipher::createEncrytor() or + /// Cipher::createDecryptor() to create an encrypting or decrypting stream, + /// respectively. + /// + /// After all data has been passed through the stream, close() must be called + /// to ensure completion of cryptographic transformation. +{ +public: + CryptoOutputStream(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192); + /// Create a new CryptoOutputStream object. The CryptoOutputStream takes the + /// ownership of the given CryptoTransform object. + + CryptoOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192); + /// Create a new decrypting CryptoOutputStream object using the given cipher. + + ~CryptoOutputStream(); + /// Destroys the CryptoOutputStream. + + void close(); + /// Flushes all buffers and finishes the encryption. +}; + + +class Crypto_API DecryptingInputStream: public CryptoIOS, public std::istream + /// This stream decrypts all data passing through it using the given + /// Cipher. +{ +public: + DecryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192); + /// Create a new DecryptingInputStream object using the given cipher. + + ~DecryptingInputStream(); + /// Destroys the DecryptingInputStream. +}; + + +class Crypto_API DecryptingOutputStream: public CryptoIOS, public std::ostream + /// This stream decrypts all data passing through it using the given + /// Cipher. +{ +public: + DecryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192); + /// Create a new DecryptingOutputStream object using the given cipher. + + ~DecryptingOutputStream(); + /// Destroys the DecryptingOutputStream. + + void close(); + /// Flushes all buffers and finishes the decryption. +}; + + +class Crypto_API EncryptingInputStream: public CryptoIOS, public std::istream + /// This stream encrypts all data passing through it using the given + /// Cipher. +{ +public: + EncryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192); + /// Create a new EncryptingInputStream object using the given cipher. + + ~EncryptingInputStream(); + /// Destroys the EncryptingInputStream. +}; + + +class Crypto_API EncryptingOutputStream: public CryptoIOS, public std::ostream + /// This stream encrypts all data passing through it using the given + /// Cipher. +{ +public: + EncryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192); + /// Create a new EncryptingOutputStream object using the given cipher. + + ~EncryptingOutputStream(); + /// Destroys the EncryptingOutputStream. + + void close(); + /// Flushes all buffers and finishes the encryption. +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CryptoStream_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoTransform.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoTransform.h new file mode 100644 index 0000000000..9fa3806c65 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/CryptoTransform.h @@ -0,0 +1,87 @@ +// +// CryptoTransform.h +// +// Library: Crypto +// Package: Cipher +// Module: CryptoTransform +// +// Definition of the CryptoTransform class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_CryptoTransform_INCLUDED +#define Crypto_CryptoTransform_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include <ios> + + +namespace Poco { +namespace Crypto { + + +class Crypto_API CryptoTransform + /// This interface represents the basic operations for cryptographic + /// transformations to be used with a CryptoInputStream or a + /// CryptoOutputStream. + /// + /// Implementations of this class are returned by the Cipher class to + /// perform encryption or decryption of data. +{ +public: + CryptoTransform(); + /// Creates a new CryptoTransform object. + + virtual ~CryptoTransform(); + /// Destroys the CryptoTransform. + + virtual std::size_t blockSize() const = 0; + /// Returns the block size for this CryptoTransform. + + virtual int setPadding(int padding); + /// Enables or disables padding. By default encryption operations are padded using standard block + /// padding and the padding is checked and removed when decrypting. If the padding parameter is zero then + /// no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of + /// the block size or an error will occur. + + virtual std::string getTag(std::size_t tagSize = 16) = 0; + /// Returns the GCM tag after encrypting using GCM mode. + /// + /// Must be called after finalize(). + + virtual void setTag(const std::string& tag) = 0; + /// Sets the GCM tag for authenticated decryption using GCM mode. + /// + /// Must be set before finalize() is called, otherwise + /// decryption will fail. + + virtual std::streamsize transform( + const unsigned char* input, + std::streamsize inputLength, + unsigned char* output, + std::streamsize outputLength) = 0; + /// Transforms a chunk of data. The inputLength is arbitrary and does not + /// need to be a multiple of the block size. The output buffer has a maximum + /// capacity of the given outputLength that must be at least + /// inputLength + blockSize() - 1 + /// Returns the number of bytes written to the output buffer. + + virtual std::streamsize finalize(unsigned char* output, std::streamsize length) = 0; + /// Finalizes the transformation. The output buffer must contain enough + /// space for at least two blocks, ie. + /// length >= 2*blockSize() + /// must be true. Returns the number of bytes written to the output + /// buffer. +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_CryptoTransform_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/DigestEngine.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/DigestEngine.h new file mode 100644 index 0000000000..8244a6ea8c --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/DigestEngine.h @@ -0,0 +1,80 @@ +// +// DigestEngine.h +// +// Library: Crypto +// Package: Digest +// Module: DigestEngine +// +// Definition of the DigestEngine class. +// +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_DigestEngine_INCLUDED +#define Crypto_DigestEngine_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/DigestEngine.h" +#include <openssl/evp.h> + + +namespace Poco { +namespace Crypto { + + +class Crypto_API DigestEngine: public Poco::DigestEngine + /// This class implements a Poco::DigestEngine for all + /// digest algorithms supported by OpenSSL. +{ +public: + DigestEngine(const std::string& name); + /// Creates a DigestEngine using the digest with the given name + /// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.). + /// See the OpenSSL documentation for a list of supported digest algorithms. + /// + /// Throws a Poco::NotFoundException if no algorithm with the given name exists. + + ~DigestEngine(); + /// Destroys the DigestEngine. + + const std::string& algorithm() const; + /// Returns the name of the digest algorithm. + + int nid() const; + /// Returns the NID (OpenSSL object identifier) of the digest algorithm. + + // DigestEngine + std::size_t digestLength() const; + void reset(); + const Poco::DigestEngine::Digest& digest(); + +protected: + void updateImpl(const void* data, std::size_t length); + +private: + std::string _name; + EVP_MD_CTX* _pContext; + Poco::DigestEngine::Digest _digest; + OpenSSLInitializer _openSSLInitializer; +}; + + +// +// inlines +// +inline const std::string& DigestEngine::algorithm() const +{ + return _name; +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_DigestEngine_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h new file mode 100644 index 0000000000..ed6fab442f --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/ECDSADigestEngine.h @@ -0,0 +1,101 @@ +// +// ECDSADigestEngine.h +// +// +// Library: Crypto +// Package: ECDSA +// Module: ECDSADigestEngine +// +// Definition of the ECDSADigestEngine class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_ECDSADigestEngine_INCLUDED +#define Crypto_ECDSADigestEngine_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/ECKey.h" +#include "Poco/DigestEngine.h" +#include "Poco/Crypto/DigestEngine.h" +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Crypto { + + +class Crypto_API ECDSADigestEngine: public Poco::DigestEngine + /// This class implements a Poco::DigestEngine that can be + /// used to compute a secure digital signature. + /// + /// First another Poco::Crypto::DigestEngine is created and + /// used to compute a cryptographic hash of the data to be + /// signed. Then, the hash value is encrypted, using + /// the ECDSA private key. + /// + /// To verify a signature, pass it to the verify() + /// member function. It will decrypt the signature + /// using the ECDSA public key and compare the resulting + /// hash with the actual hash of the data. +{ +public: + + ECDSADigestEngine(const ECKey& key, const std::string &name); + /// Creates the ECDSADigestEngine with the given ECDSA key, + /// using the hash algorithm with the given name + /// (e.g., "SHA1", "SHA256", "SHA512", etc.). + /// See the OpenSSL documentation for a list of supported digest algorithms. + /// + /// Throws a Poco::NotFoundException if no algorithm with the given name exists. + + ~ECDSADigestEngine(); + /// Destroys the ECDSADigestEngine. + + std::size_t digestLength() const; + /// Returns the length of the digest in bytes. + + void reset(); + /// Resets the engine so that a new + /// digest can be computed. + + const DigestEngine::Digest& digest(); + /// Finishes the computation of the digest + /// (the first time it's called) and + /// returns the message digest. + /// + /// Can be called multiple times. + + const DigestEngine::Digest& signature(); + /// Signs the digest using the ECDSADSA algorithm + /// and the private key (the first time it's + /// called) and returns the result. + /// + /// Can be called multiple times. + + bool verify(const DigestEngine::Digest& signature); + /// Verifies the data against the signature. + /// + /// Returns true if the signature can be verified, false otherwise. + +protected: + void updateImpl(const void* data, std::size_t length); + +private: + ECKey _key; + Poco::Crypto::DigestEngine _engine; + Poco::DigestEngine::Digest _digest; + Poco::DigestEngine::Digest _signature; +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_ECDSADigestEngine_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/ECKey.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/ECKey.h new file mode 100644 index 0000000000..14f2ac0a18 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/ECKey.h @@ -0,0 +1,136 @@ +// +// ECKey.h +// +// +// Library: Crypto +// Package: EC +// Module: ECKey +// +// Definition of the ECKey class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_ECKey_INCLUDED +#define Crypto_ECKey_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/KeyPair.h" +#include "Poco/Crypto/ECKeyImpl.h" + + +namespace Poco { +namespace Crypto { + + +class X509Certificate; +class PKCS12Container; + + +class Crypto_API ECKey : public KeyPair + /// This class stores an EC key pair, consisting + /// of private and public key. Storage of the private + /// key is optional. + /// + /// If a private key is available, the ECKey can be + /// used for decrypting data (encrypted with the public key) + /// or computing secure digital signatures. +{ +public: + ECKey(const EVPPKey& key); + /// Constructs ECKeyImpl by extracting the EC key. + + ECKey(const X509Certificate& cert); + /// Extracts the EC public key from the given certificate. + + ECKey(const PKCS12Container& cert); + /// Extracts the EC private key from the given certificate. + + ECKey(const std::string& eccGroup); + /// Creates the ECKey. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + ECKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = ""); + /// Creates the ECKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + ECKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = ""); + /// Creates the ECKey, by reading public and private key from the given streams and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + ~ECKey(); + /// Destroys the ECKey. + + ECKeyImpl::Ptr impl() const; + /// Returns the impl object. + + static std::string getCurveName(int nid = -1); + /// Returns elliptical curve name corresponding to + /// the given nid; if nid is not found, returns + /// empty string. + /// + /// If nid is -1, returns first curve name. + /// + /// If no curves are found, returns empty string; + + static int getCurveNID(std::string& name); + /// Returns the NID of the specified curve. + /// + /// If name is empty, returns the first curve NID + /// and updates the name accordingly. + + static bool hasCurve(const std::string& name); + /// Returns true if the named curve is found, + /// false otherwise. + +private: + ECKeyImpl::Ptr _pImpl; +}; + + +// +// inlines +// +inline ECKeyImpl::Ptr ECKey::impl() const +{ + return _pImpl; +} + + +inline std::string ECKey::getCurveName(int nid) +{ + return ECKeyImpl::getCurveName(nid); +} + + +inline int ECKey::getCurveNID(std::string& name) +{ + return ECKeyImpl::getCurveNID(name); +} + + +inline bool ECKey::hasCurve(const std::string& name) +{ + return ECKeyImpl::hasCurve(name); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_ECKey_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h new file mode 100644 index 0000000000..840764304d --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/ECKeyImpl.h @@ -0,0 +1,174 @@ +// +// ECKeyImpl.h +// +// +// Library: Crypto +// Package: EC +// Module: ECKeyImpl +// +// Definition of the ECKeyImpl class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_ECKeyImplImpl_INCLUDED +#define Crypto_ECKeyImplImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/EVPPKey.h" +#include "Poco/Crypto/KeyPairImpl.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include <istream> +#include <ostream> +#include <vector> +#include <openssl/objects.h> +#include <openssl/ec.h> + + +namespace Poco { +namespace Crypto { + + +class X509Certificate; +class PKCS12Container; + + +class ECKeyImpl: public KeyPairImpl + /// Elliptic Curve key clas implementation. +{ +public: + typedef Poco::AutoPtr<ECKeyImpl> Ptr; + typedef std::vector<unsigned char> ByteVec; + + ECKeyImpl(const EVPPKey& key); + /// Constructs ECKeyImpl by extracting the EC key. + + ECKeyImpl(const X509Certificate& cert); + /// Constructs ECKeyImpl by extracting the EC public key from the given certificate. + + ECKeyImpl(const PKCS12Container& cert); + /// Constructs ECKeyImpl by extracting the EC private key from the given certificate. + + ECKeyImpl(int eccGroup); + /// Creates the ECKey of the specified group. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + ECKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase); + /// Creates the ECKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. Can only by used for signing if + /// a private key is available. + + ECKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase); + /// Creates the ECKey. Can only by used for signing if pPrivKey + /// is not null. If a private key file is specified, you don't need to + /// specify a public key file. OpenSSL will auto-create it from the private key. + + ~ECKeyImpl(); + /// Destroys the ECKeyImpl. + + EC_KEY* getECKey(); + /// Returns the OpenSSL EC key. + + const EC_KEY* getECKey() const; + /// Returns the OpenSSL EC key. + + int size() const; + /// Returns the EC key length in bits. + + int groupId() const; + /// Returns the EC key group integer Id. + + std::string groupName() const; + /// Returns the EC key group name. + + void save(const std::string& publicKeyFile, + const std::string& privateKeyFile = "", + const std::string& privateKeyPassphrase = "") const; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + void save(std::ostream* pPublicKeyStream, + std::ostream* pPrivateKeyStream = 0, + const std::string& privateKeyPassphrase = "") const; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + static std::string getCurveName(int nid = -1); + /// Returns elliptical curve name corresponding to + /// the given nid; if nid is not found, returns + /// empty string. + /// + /// If nid is -1, returns first curve name. + /// + /// If no curves are found, returns empty string; + + static int getCurveNID(std::string& name); + /// Returns the NID of the specified curve. + /// + /// If name is empty, returns the first curve NID + /// and updates the name accordingly. + + static bool hasCurve(const std::string& name); + /// Returns true if the named curve is found, + /// false otherwise. + +private: + void checkEC(const std::string& method, const std::string& func) const; + void freeEC(); + + EC_KEY* _pEC; +}; + + +// +// inlines +// +inline EC_KEY* ECKeyImpl::getECKey() +{ + return _pEC; +} + + +inline const EC_KEY* ECKeyImpl::getECKey() const +{ + return _pEC; +} + + +inline std::string ECKeyImpl::groupName() const +{ + return OBJ_nid2sn(groupId()); +} + + +inline void ECKeyImpl::save(const std::string& publicKeyFile, + const std::string& privateKeyFile, + const std::string& privateKeyPassphrase) const +{ + EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase); +} + + +inline void ECKeyImpl::save(std::ostream* pPublicKeyStream, + std::ostream* pPrivateKeyStream, + const std::string& privateKeyPassphrase) const +{ + EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_ECKeyImplImpl_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/EVPPKey.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/EVPPKey.h new file mode 100644 index 0000000000..fbcdad5b19 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/EVPPKey.h @@ -0,0 +1,354 @@ +// +// EVPPKey.h +// +// +// Library: Crypto +// Package: CryptoCore +// Module: EVPPKey +// +// Definition of the EVPPKey class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_EVPPKeyImpl_INCLUDED +#define Crypto_EVPPKeyImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/CryptoException.h" +#include "Poco/StreamCopier.h" +#include <openssl/ec.h> +#include <openssl/rsa.h> +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <sstream> +#include <typeinfo> + + +namespace Poco { +namespace Crypto { + + +class ECKey; +class RSAKey; + + +class Crypto_API EVPPKey + /// Utility class for conversion of native keys to EVP. + /// Currently, only RSA and EC keys are supported. +{ +public: + explicit EVPPKey(const std::string& ecCurveName); + /// Constructs EVPPKey from ECC curve name. + /// + /// Only EC keys can be wrapped by an EVPPKey + /// created using this constructor. + + explicit EVPPKey(const char* ecCurveName); + /// Constructs EVPPKey from ECC curve name. + /// + /// Only EC keys can be wrapped by an EVPPKey + /// created using this constructor. + + explicit EVPPKey(EVP_PKEY* pEVPPKey); + /// Constructs EVPPKey from EVP_PKEY pointer. + /// The content behind the supplied pointer is internally duplicated. + + template<typename K> + explicit EVPPKey(K* pKey): _pEVPPKey(EVP_PKEY_new()) + /// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY), + /// or a Poco wrapper (RSAKey, ECKey) key pointer. + { + if (!_pEVPPKey) throw OpenSSLException(); + setKey(pKey); + } + + EVPPKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = ""); + /// Creates the EVPPKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. Can only by used for signing if + /// a private key is available. + + EVPPKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase = ""); + /// Creates the EVPPKey. Can only by used for signing if pPrivKey + /// is not null. If a private key file is specified, you don't need to + /// specify a public key file. OpenSSL will auto-create it from the private key. + + EVPPKey(const EVPPKey& other); + /// Copy constructor. + + EVPPKey& operator=(const EVPPKey& other); + /// Assignment operator. + +#ifdef POCO_ENABLE_CPP11 + + EVPPKey(EVPPKey&& other); + /// Move constructor. + + EVPPKey& operator=(EVPPKey&& other); + /// Assignment move operator. + +#endif // POCO_ENABLE_CPP11 + + ~EVPPKey(); + /// Destroys the EVPPKey. + + bool operator == (const EVPPKey& other) const; + /// Comparison operator. + /// Returns true if public key components and parameters + /// of the other key are equal to this key. + /// + /// Works as expected when one key contains only public key, + /// while the other one contains private (thus also public) key. + + bool operator != (const EVPPKey& other) const; + /// Comparison operator. + /// Returns true if public key components and parameters + /// of the other key are different from this key. + /// + /// Works as expected when one key contains only public key, + /// while the other one contains private (thus also public) key. + + void save(const std::string& publicKeyFile, const std::string& privateKeyFile = "", const std::string& privateKeyPassphrase = "") const; + /// Exports the public and/or private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + void save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "") const; + /// Exports the public and/or private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + int type() const; + /// Retuns the EVPPKey type NID. + + bool isSupported(int type) const; + /// Returns true if OpenSSL type is supported + + operator const EVP_PKEY*() const; + /// Returns const pointer to the OpenSSL EVP_PKEY structure. + + operator EVP_PKEY*(); + /// Returns pointer to the OpenSSL EVP_PKEY structure. + + static EVP_PKEY* duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey); + /// Duplicates pFromKey into *pToKey and returns + // the pointer to duplicated EVP_PKEY. + +private: + EVPPKey(); + + static int type(const EVP_PKEY* pEVPPKey); + void newECKey(const char* group); + void duplicate(EVP_PKEY* pEVPPKey); + + void setKey(ECKey* pKey); + void setKey(RSAKey* pKey); + void setKey(EC_KEY* pKey); + void setKey(RSA* pKey); + static int passCB(char* buf, int size, int, void* pass); + + typedef EVP_PKEY* (*PEM_read_FILE_Key_fn)(FILE*, EVP_PKEY**, pem_password_cb*, void*); + typedef EVP_PKEY* (*PEM_read_BIO_Key_fn)(BIO*, EVP_PKEY**, pem_password_cb*, void*); + typedef void* (*EVP_PKEY_get_Key_fn)(EVP_PKEY*); + + // The following load*() functions are used by both native and EVP_PKEY type key + // loading from BIO/FILE. + // When used for EVP key loading, getFunc is null (ie. native key is not extracted + // from the loaded EVP_PKEY). + template <typename K, typename F> + static bool loadKey(K** ppKey, + PEM_read_FILE_Key_fn readFunc, + F getFunc, + const std::string& keyFile, + const std::string& pass = "") + { + poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) || + ((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc)); + poco_check_ptr (ppKey); + poco_assert_dbg (!*ppKey); + + FILE* pFile = 0; + if (!keyFile.empty()) + { + if (!getFunc) *ppKey = (K*)EVP_PKEY_new(); + EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey; + if (pKey) + { + pFile = fopen(keyFile.c_str(), "r"); + if (pFile) + { + pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB; + void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str(); + if (readFunc(pFile, &pKey, pCB, pPassword)) + { + fclose(pFile); pFile = 0; + if(getFunc) + { + *ppKey = (K*)getFunc(pKey); + EVP_PKEY_free(pKey); + } + else + { + poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*)); + *ppKey = (K*)pKey; + } + if(!*ppKey) goto error; + return true; + } + goto error; + } + else + { + if (getFunc) EVP_PKEY_free(pKey); + throw IOException("ECKeyImpl, cannot open file", keyFile); + } + } + else goto error; + } + return false; + + error: + if (pFile) fclose(pFile); + throw OpenSSLException("EVPKey::loadKey(string)"); + } + + template <typename K, typename F> + static bool loadKey(K** ppKey, + PEM_read_BIO_Key_fn readFunc, + F getFunc, + std::istream* pIstr, + const std::string& pass = "") + { + poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) || + ((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc)); + poco_check_ptr(ppKey); + poco_assert_dbg(!*ppKey); + + BIO* pBIO = 0; + if (pIstr) + { + std::ostringstream ostr; + Poco::StreamCopier::copyStream(*pIstr, ostr); + std::string key = ostr.str(); + pBIO = BIO_new_mem_buf(const_cast<char*>(key.data()), static_cast<int>(key.size())); + if (pBIO) + { + if (!getFunc) *ppKey = (K*)EVP_PKEY_new(); + EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey; + if (pKey) + { + pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB; + void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str(); + if (readFunc(pBIO, &pKey, pCB, pPassword)) + { + BIO_free(pBIO); pBIO = 0; + if (getFunc) + { + *ppKey = (K*)getFunc(pKey); + EVP_PKEY_free(pKey); + } + else + { + poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*)); + *ppKey = (K*)pKey; + } + if (!*ppKey) goto error; + return true; + } + if (getFunc) EVP_PKEY_free(pKey); + goto error; + } + else goto error; + } + else goto error; + } + return false; + + error: + if (pBIO) BIO_free(pBIO); + throw OpenSSLException("EVPKey::loadKey(stream)"); + } + + EVP_PKEY* _pEVPPKey; + + friend class ECKeyImpl; + friend class RSAKeyImpl; +}; + + +// +// inlines +// + + +inline bool EVPPKey::operator == (const EVPPKey& other) const +{ + poco_check_ptr (other._pEVPPKey); + poco_check_ptr (_pEVPPKey); + return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey)); +} + + +inline bool EVPPKey::operator != (const EVPPKey& other) const +{ + return !(other == *this); +} + + +inline int EVPPKey::type(const EVP_PKEY* pEVPPKey) +{ + if (!pEVPPKey) return NID_undef; + + return EVP_PKEY_type(EVP_PKEY_id(pEVPPKey)); +} + + +inline int EVPPKey::type() const +{ + return type(_pEVPPKey); +} + + +inline bool EVPPKey::isSupported(int type) const +{ + return type == EVP_PKEY_EC || type == EVP_PKEY_RSA; +} + + +inline EVPPKey::operator const EVP_PKEY*() const +{ + return _pEVPPKey; +} + + +inline EVPPKey::operator EVP_PKEY*() +{ + return _pEVPPKey; +} + + +inline void EVPPKey::setKey(EC_KEY* pKey) +{ + if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pKey)) + throw OpenSSLException(); +} + + +inline void EVPPKey::setKey(RSA* pKey) +{ + if (!EVP_PKEY_set1_RSA(_pEVPPKey, pKey)) + throw OpenSSLException(); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_EVPPKeyImpl_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/KeyPair.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/KeyPair.h new file mode 100644 index 0000000000..b9a705f8f1 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/KeyPair.h @@ -0,0 +1,133 @@ +// +// KeyPair.h +// +// +// Library: Crypto +// Package: CryptoCore +// Module: KeyPair +// +// Definition of the KeyPair class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_KeyPair_INCLUDED +#define Crypto_KeyPair_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/KeyPairImpl.h" + + +namespace Poco { +namespace Crypto { + + +class X509Certificate; + + +class Crypto_API KeyPair + /// This is a parent class for classes storing a key pair, consisting + /// of private and public key. Storage of the private key is optional. + /// + /// If a private key is available, the KeyPair can be + /// used for decrypting data (encrypted with the public key) + /// or computing secure digital signatures. +{ +public: + enum Type + { + KT_RSA = KeyPairImpl::KT_RSA_IMPL, + KT_EC = KeyPairImpl::KT_EC_IMPL + }; + + explicit KeyPair(KeyPairImpl::Ptr pKeyPairImpl = 0); + /// Extracts the RSA public key from the given certificate. + + virtual ~KeyPair(); + /// Destroys the KeyPair. + + virtual int size() const; + /// Returns the RSA modulus size. + + virtual void save(const std::string& publicKeyPairFile, + const std::string& privateKeyPairFile = "", + const std::string& privateKeyPairPassphrase = "") const; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + virtual void save(std::ostream* pPublicKeyPairStream, + std::ostream* pPrivateKeyPairStream = 0, + const std::string& privateKeyPairPassphrase = "") const; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + KeyPairImpl::Ptr impl() const; + /// Returns the impl object. + + const std::string& name() const; + /// Returns key pair name + + Type type() const; + /// Returns key pair type + +private: + KeyPairImpl::Ptr _pImpl; +}; + + +// +// inlines +// + +inline int KeyPair::size() const +{ + return _pImpl->size(); +} + + +inline void KeyPair::save(const std::string& publicKeyFile, + const std::string& privateKeyFile, + const std::string& privateKeyPassphrase) const +{ + _pImpl->save(publicKeyFile, privateKeyFile, privateKeyPassphrase); +} + + +inline void KeyPair::save(std::ostream* pPublicKeyStream, + std::ostream* pPrivateKeyStream, + const std::string& privateKeyPassphrase) const +{ + _pImpl->save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase); +} + + +inline const std::string& KeyPair::name() const +{ + return _pImpl->name(); +} + +inline KeyPairImpl::Ptr KeyPair::impl() const +{ + return _pImpl; +} + + +inline KeyPair::Type KeyPair::type() const +{ + return (KeyPair::Type)impl()->type(); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_KeyPair_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h new file mode 100644 index 0000000000..e6320df044 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/KeyPairImpl.h @@ -0,0 +1,107 @@ +// +// KeyPairImpl.h +// +// +// Library: Crypto +// Package: CryptoCore +// Module: KeyPairImpl +// +// Definition of the KeyPairImpl class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_KeyPairImplImpl_INCLUDED +#define Crypto_KeyPairImplImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include <string> +#include <vector> + + +namespace Poco { +namespace Crypto { + + +class KeyPairImpl: public Poco::RefCountedObject + /// Class KeyPairImpl +{ +public: + enum Type + { + KT_RSA_IMPL = 0, + KT_EC_IMPL + }; + + typedef Poco::AutoPtr<KeyPairImpl> Ptr; + typedef std::vector<unsigned char> ByteVec; + + KeyPairImpl(const std::string& name, Type type); + /// Create KeyPairImpl with specified type and name. + + virtual ~KeyPairImpl(); + /// Destroys the KeyPairImpl. + + virtual int size() const = 0; + /// Returns the key size. + + virtual void save(const std::string& publicKeyFile, + const std::string& privateKeyFile = "", + const std::string& privateKeyPassphrase = "") const = 0; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + virtual void save(std::ostream* pPublicKeyStream, + std::ostream* pPrivateKeyStream = 0, + const std::string& privateKeyPassphrase = "") const = 0; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + + const std::string& name() const; + /// Returns key pair name + + Type type() const; + /// Returns key pair type + +private: + KeyPairImpl(); + + std::string _name; + Type _type; + OpenSSLInitializer _openSSLInitializer; +}; + + +// +// inlines +// + + +inline const std::string& KeyPairImpl::name() const +{ + return _name; +} + + +inline KeyPairImpl::Type KeyPairImpl::type() const +{ + return _type; +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_KeyPairImplImpl_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h new file mode 100644 index 0000000000..42c97ae465 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/OpenSSLInitializer.h @@ -0,0 +1,115 @@ +// +// OpenSSLInitializer.h +// +// Library: Crypto +// Package: CryptoCore +// Module: OpenSSLInitializer +// +// Definition of the OpenSSLInitializer class. +// +// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_OpenSSLInitializer_INCLUDED +#define Crypto_OpenSSLInitializer_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Mutex.h" +#include "Poco/AtomicCounter.h" +#include <openssl/crypto.h> + +#if defined(OPENSSL_FIPS) && OPENSSL_VERSION_NUMBER < 0x010001000L +#include <openssl/fips.h> +#endif + + +extern "C" +{ + struct CRYPTO_dynlock_value + { + Poco::FastMutex _mutex; + }; +} + + +namespace Poco { +namespace Crypto { + + +class Crypto_API OpenSSLInitializer + /// Initalizes the OpenSSL library. + /// + /// The class ensures the earliest initialization and the + /// latest shutdown of the OpenSSL library. +{ +public: + OpenSSLInitializer(); + /// Automatically initialize OpenSSL on startup. + + ~OpenSSLInitializer(); + /// Automatically shut down OpenSSL on exit. + + static void initialize(); + /// Initializes the OpenSSL machinery. + + static void uninitialize(); + /// Shuts down the OpenSSL machinery. + + static bool isFIPSEnabled(); + // Returns true if FIPS mode is enabled, false otherwise. + + static void enableFIPSMode(bool enabled); + // Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything. + +protected: + enum + { + SEEDSIZE = 256 + }; + + // OpenSSL multithreading support + static void lock(int mode, int n, const char* file, int line); + static unsigned long id(); + static struct CRYPTO_dynlock_value* dynlockCreate(const char* file, int line); + static void dynlock(int mode, struct CRYPTO_dynlock_value* lock, const char* file, int line); + static void dynlockDestroy(struct CRYPTO_dynlock_value* lock, const char* file, int line); + +private: + static Poco::FastMutex* _mutexes; + static Poco::AtomicCounter _rc; +}; + + +// +// inlines +// +inline bool OpenSSLInitializer::isFIPSEnabled() +{ +#ifdef OPENSSL_FIPS + return FIPS_mode() ? true : false; +#else + return false; +#endif +} + +#ifdef OPENSSL_FIPS +inline void OpenSSLInitializer::enableFIPSMode(bool enabled) +{ + FIPS_mode_set(enabled); +} +#else +inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/) +{ +} +#endif + + +} } // namespace Poco::Crypto + + +#endif // Crypto_OpenSSLInitializer_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/PKCS12Container.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/PKCS12Container.h new file mode 100644 index 0000000000..63cc224d8c --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/PKCS12Container.h @@ -0,0 +1,159 @@ +// +// PKCS12Container.h +// +// Library: Crypto +// Package: Certificate +// Module: PKCS12Container +// +// Definition of the PKCS12Container class. +// +// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_PKCS12Container_INCLUDED +#define Crypto_PKCS12Container_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/Crypto/X509Certificate.h" +#include "Poco/Crypto/EVPPKey.h" +#include "Poco/Path.h" +#include <memory> +#include <istream> +#include <openssl/pkcs12.h> + + +namespace Poco { +namespace Crypto { + + +class Crypto_API PKCS12Container + /// This class implements PKCS#12 container functionality. +{ +public: + typedef X509Certificate::List CAList; + typedef std::vector<std::string> CANameList; + + explicit PKCS12Container(std::istream& istr, const std::string& password = ""); + /// Creates the PKCS12Container object from a stream. + + explicit PKCS12Container(const std::string& path, const std::string& password = ""); + /// Creates the PKCS12Container object from a file. + + PKCS12Container(const PKCS12Container& cont); + /// Copy constructor. + + PKCS12Container& operator = (const PKCS12Container& cont); + /// Assignment operator. + +#ifdef POCO_ENABLE_CPP11 + + PKCS12Container(PKCS12Container&& cont); + /// Move constructor. + + PKCS12Container& operator = (PKCS12Container&& cont); + /// Move assignment operator. + +#endif // POCO_ENABLE_CPP11 + + ~PKCS12Container(); + /// Destroys the PKCS12Container. + + bool hasKey() const; + /// Returns true if container contains the key. + + EVPPKey getKey() const; + /// Return key as openssl EVP_PKEY wrapper object. + + bool hasX509Certificate() const; + /// Returns true if container has X509 certificate. + + const X509Certificate& getX509Certificate() const; + /// Returns the X509 certificate. + /// Throws NotFoundException if there is no certificate. + + const CAList& getCACerts() const; + /// Returns the list of CA certificates in this container. + + const std::string& getFriendlyName() const; + /// Returns the friendly name of the certificate bag. + + const CANameList& getFriendlyNamesCA() const; + /// Returns a list of CA certificates friendly names. + +private: + void load(PKCS12* pPKCS12, const std::string& password = ""); + std::string extractFriendlyName(X509* pCert); + +#ifdef POCO_ENABLE_CPP11 + typedef std::unique_ptr<X509Certificate> CertPtr; +#else + typedef std::auto_ptr<X509Certificate> CertPtr; +#endif // #ifdef POCO_ENABLE_CPP11 + + OpenSSLInitializer _openSSLInitializer; + EVP_PKEY* _pKey; + CertPtr _pX509Cert; + CAList _caCertList; + CANameList _caCertNames; + std::string _pkcsFriendlyName; +}; + + +// +// inlines +// + +inline bool PKCS12Container::hasX509Certificate() const +{ + return _pX509Cert.get() != 0; +} + + +inline const X509Certificate& PKCS12Container::getX509Certificate() const +{ + if (!hasX509Certificate()) + throw NotFoundException("PKCS12Container X509 certificate"); + return *_pX509Cert; +} + + +inline const std::string& PKCS12Container::getFriendlyName() const +{ + return _pkcsFriendlyName; +} + + +inline const PKCS12Container::CAList& PKCS12Container::getCACerts() const +{ + return _caCertList; +} + + +inline const PKCS12Container::CANameList& PKCS12Container::getFriendlyNamesCA() const +{ + return _caCertNames; +} + + +inline bool PKCS12Container::hasKey() const +{ + return _pKey != 0; +} + + +inline EVPPKey PKCS12Container::getKey() const +{ + return EVPPKey(_pKey); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_PKCS12Container_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h new file mode 100644 index 0000000000..2ebc38e3b5 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSACipherImpl.h @@ -0,0 +1,77 @@ +// +// RSACipherImpl.h +// +// Library: Crypto +// Package: RSA +// Module: RSACipherImpl +// +// Definition of the RSACipherImpl class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_RSACipherImpl_INCLUDED +#define Crypto_RSACipherImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/Cipher.h" +#include "Poco/Crypto/RSAKey.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include <openssl/evp.h> + + +namespace Poco { +namespace Crypto { + + +class RSACipherImpl: public Cipher + /// An implementation of the Cipher class for + /// asymmetric (public-private key) encryption + /// based on the the RSA algorithm in OpenSSL's + /// crypto library. + /// + /// Encryption is using the public key, decryption + /// requires the private key. +{ +public: + RSACipherImpl(const RSAKey& key, RSAPaddingMode paddingMode); + /// Creates a new RSACipherImpl object for the given RSAKey + /// and using the given padding mode. + + virtual ~RSACipherImpl(); + /// Destroys the RSACipherImpl. + + const std::string& name() const; + /// Returns the name of the Cipher. + + CryptoTransform* createEncryptor(); + /// Creates an encryptor object. + + CryptoTransform* createDecryptor(); + /// Creates a decryptor object. + +private: + RSAKey _key; + RSAPaddingMode _paddingMode; + OpenSSLInitializer _openSSLInitializer; +}; + + +// +// Inlines +// +inline const std::string& RSACipherImpl::name() const +{ + return _key.name(); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_RSACipherImpl_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h new file mode 100644 index 0000000000..7c4d386050 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSADigestEngine.h @@ -0,0 +1,111 @@ +// +// RSADigestEngine.h +// +// Library: Crypto +// Package: RSA +// Module: RSADigestEngine +// +// Definition of the RSADigestEngine class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_RSADigestEngine_INCLUDED +#define Crypto_RSADigestEngine_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/RSAKey.h" +#include "Poco/DigestEngine.h" +#include "Poco/Crypto/DigestEngine.h" +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Crypto { + + +class Crypto_API RSADigestEngine: public Poco::DigestEngine + /// This class implements a Poco::DigestEngine that can be + /// used to compute a secure digital signature. + /// + /// First another Poco::Crypto::DigestEngine is created and + /// used to compute a cryptographic hash of the data to be + /// signed. Then, the hash value is encrypted, using + /// the RSA private key. + /// + /// To verify a signature, pass it to the verify() + /// member function. It will decrypt the signature + /// using the RSA public key and compare the resulting + /// hash with the actual hash of the data. +{ +public: + enum DigestType + { + DIGEST_MD5, + DIGEST_SHA1 + }; + + //@ deprecated + RSADigestEngine(const RSAKey& key, DigestType digestType = DIGEST_SHA1); + /// Creates the RSADigestEngine with the given RSA key, + /// using the MD5 or SHA-1 hash algorithm. + /// Kept for backward compatibility + + RSADigestEngine(const RSAKey& key, const std::string &name); + /// Creates the RSADigestEngine with the given RSA key, + /// using the hash algorithm with the given name + /// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.). + /// See the OpenSSL documentation for a list of supported digest algorithms. + /// + /// Throws a Poco::NotFoundException if no algorithm with the given name exists. + + ~RSADigestEngine(); + /// Destroys the RSADigestEngine. + + std::size_t digestLength() const; + /// Returns the length of the digest in bytes. + + void reset(); + /// Resets the engine so that a new + /// digest can be computed. + + const DigestEngine::Digest& digest(); + /// Finishes the computation of the digest + /// (the first time it's called) and + /// returns the message digest. + /// + /// Can be called multiple times. + + const DigestEngine::Digest& signature(); + /// Signs the digest using the RSA algorithm + /// and the private key (the first time it's + /// called) and returns the result. + /// + /// Can be called multiple times. + + bool verify(const DigestEngine::Digest& signature); + /// Verifies the data against the signature. + /// + /// Returns true if the signature can be verified, false otherwise. + +protected: + void updateImpl(const void* data, std::size_t length); + +private: + RSAKey _key; + Poco::Crypto::DigestEngine _engine; + Poco::DigestEngine::Digest _digest; + Poco::DigestEngine::Digest _signature; +}; + + +} } // namespace Poco::Crypto + + +#endif // Crypto_RSADigestEngine_INCLUDED diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/RSAKey.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSAKey.h new file mode 100644 index 0000000000..ad9163ed42 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSAKey.h @@ -0,0 +1,125 @@ +// +// RSAKey.h +// +// Library: Crypto +// Package: RSA +// Module: RSAKey +// +// Definition of the RSAKey class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_RSAKey_INCLUDED +#define Crypto_RSAKey_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/KeyPair.h" +#include "Poco/Crypto/RSAKeyImpl.h" + + +namespace Poco { +namespace Crypto { + + +class X509Certificate; +class PKCS12Container; + + +class Crypto_API RSAKey : public KeyPair + /// This class stores an RSA key pair, consisting + /// of private and public key. Storage of the private + /// key is optional. + /// + /// If a private key is available, the RSAKey can be + /// used for decrypting data (encrypted with the public key) + /// or computing secure digital signatures. +{ +public: + enum KeyLength + { + KL_512 = 512, + KL_1024 = 1024, + KL_2048 = 2048, + KL_4096 = 4096 + }; + + enum Exponent + { + EXP_SMALL = 0, + EXP_LARGE + }; + + RSAKey(const EVPPKey& key); + /// Constructs ECKeyImpl by extracting the EC key. + + RSAKey(const X509Certificate& cert); + /// Extracts the RSA public key from the given certificate. + + RSAKey(const PKCS12Container& cert); + /// Extracts the RSA private key from the given certificate. + + RSAKey(KeyLength keyLength, Exponent exp); + /// Creates the RSAKey. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + RSAKey(const std::string& publicKeyFile, + const std::string& privateKeyFile = "", + const std::string& privateKeyPassphrase = ""); + /// Creates the RSAKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + RSAKey(std::istream* pPublicKeyStream, + std::istream* pPrivateKeyStream = 0, + const std::string& privateKeyPassphrase = ""); + /// Creates the RSAKey, by reading public and private key from the given streams and + /// using the given passphrase for the private key. + /// + /// Cannot be used for signing or decryption unless a private key is available. + /// + /// If a private key is specified, you don't need to specify a public key file. + /// OpenSSL will auto-create the public key from the private key. + + ~RSAKey(); + /// Destroys the RSAKey. + + RSAKeyImpl::ByteVec modulus() const; + /// Returns the RSA modulus. + + RSAKeyImpl::ByteVec encryptionExponent() const; + /// Returns the RSA encryption exponent. + + RSAKeyImpl::ByteVec decryptionExponent() const; + /// Returns the RSA decryption exponent. + + RSAKeyImpl::Ptr impl() const; + /// Returns the impl object. + +private: + RSAKeyImpl::Ptr _pImpl; +}; + + +// +// inlines +// +inline RSAKeyImpl::Ptr RSAKey::impl() const +{ + return _pImpl; +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_RSAKey_INCLUDED
\ No newline at end of file diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h new file mode 100644 index 0000000000..035881636b --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/RSAKeyImpl.h @@ -0,0 +1,141 @@ +// +// RSAKeyImpl.h +// +// Library: Crypto +// Package: RSA +// Module: RSAKeyImpl +// +// Definition of the RSAKeyImpl class. +// +// Copyright (c) 2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_RSAKeyImplImpl_INCLUDED +#define Crypto_RSAKeyImplImpl_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/EVPPKey.h" +#include "Poco/Crypto/KeyPairImpl.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include <istream> +#include <ostream> +#include <vector> + + +struct bignum_st; +struct rsa_st; +typedef struct bignum_st BIGNUM; +typedef struct rsa_st RSA; + + +namespace Poco { +namespace Crypto { + + +class X509Certificate; +class PKCS12Container; + + +class RSAKeyImpl: public KeyPairImpl + /// class RSAKeyImpl +{ +public: + typedef Poco::AutoPtr<RSAKeyImpl> Ptr; + typedef std::vector<unsigned char> ByteVec; + + RSAKeyImpl(const EVPPKey& key); + /// Constructs ECKeyImpl by extracting the EC key. + + RSAKeyImpl(const X509Certificate& cert); + /// Extracts the RSA public key from the given certificate. + + RSAKeyImpl(const PKCS12Container& cert); + /// Extracts the EC private key from the given certificate. + + RSAKeyImpl(int keyLength, unsigned long exponent); + /// Creates the RSAKey. Creates a new public/private keypair using the given parameters. + /// Can be used to sign data and verify signatures. + + RSAKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase); + /// Creates the RSAKey, by reading public and private key from the given files and + /// using the given passphrase for the private key. Can only by used for signing if + /// a private key is available. + + RSAKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase); + /// Creates the RSAKey. Can only by used for signing if pPrivKey + /// is not null. If a private key file is specified, you don't need to + /// specify a public key file. OpenSSL will auto-create it from the private key. + + ~RSAKeyImpl(); + /// Destroys the RSAKeyImpl. + + RSA* getRSA(); + /// Returns the OpenSSL RSA object. + + const RSA* getRSA() const; + /// Returns the OpenSSL RSA object. + + int size() const; + /// Returns the RSA modulus size. + + ByteVec modulus() const; + /// Returns the RSA modulus. + + ByteVec encryptionExponent() const; + /// Returns the RSA encryption exponent. + + ByteVec decryptionExponent() const; + /// Returns the RSA decryption exponent. + + void save(const std::string& publicKeyFile, + const std::string& privateKeyFile = "", + const std::string& privateKeyPassphrase = "") const; + /// Exports the public and private keys to the given files. + /// + /// If an empty filename is specified, the corresponding key + /// is not exported. + + void save(std::ostream* pPublicKeyStream, + std::ostream* pPrivateKeyStream = 0, + const std::string& privateKeyPassphrase = "") const; + /// Exports the public and private key to the given streams. + /// + /// If a null pointer is passed for a stream, the corresponding + /// key is not exported. + +private: + RSAKeyImpl(); + + void freeRSA(); + static ByteVec convertToByteVec(const BIGNUM* bn); + + RSA* _pRSA; +}; + + +// +// inlines +// +inline RSA* RSAKeyImpl::getRSA() +{ + return _pRSA; +} + + +inline const RSA* RSAKeyImpl::getRSA() const +{ + return _pRSA; +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_RSAKeyImplImpl_INCLUDED
\ No newline at end of file diff --git a/contrib/libs/poco/Crypto/include/Poco/Crypto/X509Certificate.h b/contrib/libs/poco/Crypto/include/Poco/Crypto/X509Certificate.h new file mode 100644 index 0000000000..ccdab1ce37 --- /dev/null +++ b/contrib/libs/poco/Crypto/include/Poco/Crypto/X509Certificate.h @@ -0,0 +1,245 @@ +// +// X509Certificate.h +// +// Library: Crypto +// Package: Certificate +// Module: X509Certificate +// +// Definition of the X509Certificate class. +// +// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Crypto_X509Certificate_INCLUDED +#define Crypto_X509Certificate_INCLUDED + + +#include "Poco/Crypto/Crypto.h" +#include "Poco/Crypto/OpenSSLInitializer.h" +#include "Poco/DateTime.h" +#include "Poco/SharedPtr.h" +#include <vector> +#include <set> +#include <istream> +#include <openssl/ssl.h> + + +namespace Poco { +namespace Crypto { + + +class Crypto_API X509Certificate + /// This class represents a X509 Certificate. +{ +public: + typedef std::vector<X509Certificate> List; + + enum NID + /// Name identifier for extracting information from + /// a certificate subject's or issuer's distinguished name. + { + NID_COMMON_NAME = 13, + NID_COUNTRY = 14, + NID_LOCALITY_NAME = 15, + NID_STATE_OR_PROVINCE = 16, + NID_ORGANIZATION_NAME = 17, + NID_ORGANIZATION_UNIT_NAME = 18, + NID_PKCS9_EMAIL_ADDRESS = 48, + NID_SERIAL_NUMBER = 105 + }; + + explicit X509Certificate(std::istream& istr); + /// Creates the X509Certificate object by reading + /// a certificate in PEM format from a stream. + + explicit X509Certificate(const std::string& path); + /// Creates the X509Certificate object by reading + /// a certificate in PEM format from a file. + + explicit X509Certificate(X509* pCert); + /// Creates the X509Certificate from an existing + /// OpenSSL certificate. Ownership is taken of + /// the certificate. + + X509Certificate(X509* pCert, bool shared); + /// Creates the X509Certificate from an existing + /// OpenSSL certificate. Ownership is taken of + /// the certificate. If shared is true, the + /// certificate's reference count is incremented. + + X509Certificate(const X509Certificate& cert); + /// Creates the certificate by copying another one. + + X509Certificate& operator = (const X509Certificate& cert); + /// Assigns a certificate. + + void swap(X509Certificate& cert); + /// Exchanges the certificate with another one. + + ~X509Certificate(); + /// Destroys the X509Certificate. + + long version() const; + /// Returns the version of the certificate. + + const std::string& serialNumber() const; + /// Returns the certificate serial number as a + /// string in decimal encoding. + + const std::string& issuerName() const; + /// Returns the certificate issuer's distinguished name. + + std::string issuerName(NID nid) const; + /// Extracts the information specified by the given + /// NID (name identifier) from the certificate issuer's + /// distinguished name. + + const std::string& subjectName() const; + /// Returns the certificate subject's distinguished name. + + std::string subjectName(NID nid) const; + /// Extracts the information specified by the given + /// NID (name identifier) from the certificate subject's + /// distinguished name. + + std::string commonName() const; + /// Returns the common name stored in the certificate + /// subject's distinguished name. + + void extractNames(std::string& commonName, std::set<std::string>& domainNames) const; + /// Extracts the common name and the alias domain names from the + /// certificate. + + Poco::DateTime validFrom() const; + /// Returns the date and time the certificate is valid from. + + Poco::DateTime expiresOn() const; + /// Returns the date and time the certificate expires. + + void save(std::ostream& stream) const; + /// Writes the certificate to the given stream. + /// The certificate is written in PEM format. + + void save(const std::string& path) const; + /// Writes the certificate to the file given by path. + /// The certificate is written in PEM format. + + bool issuedBy(const X509Certificate& issuerCertificate) const; + /// Checks whether the certificate has been issued by + /// the issuer given by issuerCertificate. This can be + /// used to validate a certificate chain. + /// + /// Verifies if the certificate has been signed with the + /// issuer's private key, using the public key from the issuer + /// certificate. + /// + /// Returns true if verification against the issuer certificate + /// was successful, false otherwise. + + bool equals(const X509Certificate& otherCertificate) const; + /// Checks whether the certificate is equal to + /// the other certificate, by comparing the hashes + /// of both certificates. + /// + /// Returns true if both certificates are identical, + /// otherwise false. + + const X509* certificate() const; + /// Returns the underlying OpenSSL certificate. + + X509* dup() const; + /// Duplicates and returns the underlying OpenSSL certificate. Note that + /// the caller assumes responsibility for the lifecycle of the created + /// certificate. + + std::string signatureAlgorithm() const; + /// Returns the certificate signature algorithm long name. + + void print(std::ostream& out) const; + /// Prints the certificate information to ostream. + + static List readPEM(const std::string& pemFileName); + /// Reads and returns a list of certificates from + /// the specified PEM file. + + static void writePEM(const std::string& pemFileName, const List& list); + /// Writes the list of certificates to the specified PEM file. + +protected: + void load(std::istream& stream); + /// Loads the certificate from the given stream. The + /// certificate must be in PEM format. + + void load(const std::string& path); + /// Loads the certificate from the given file. The + /// certificate must be in PEM format. + + void init(); + /// Extracts issuer and subject name from the certificate. + +private: + enum + { + NAME_BUFFER_SIZE = 256 + }; + + std::string _issuerName; + std::string _subjectName; + std::string _serialNumber; + X509* _pCert; + OpenSSLInitializer _openSSLInitializer; +}; + + +// +// inlines +// + + +inline long X509Certificate::version() const +{ + // This is defined by standards (X.509 et al) to be + // one less than the certificate version. + // So, eg. a version 3 certificate will return 2. + return X509_get_version(_pCert) + 1; +} + + +inline const std::string& X509Certificate::serialNumber() const +{ + return _serialNumber; +} + + +inline const std::string& X509Certificate::issuerName() const +{ + return _issuerName; +} + + +inline const std::string& X509Certificate::subjectName() const +{ + return _subjectName; +} + + +inline const X509* X509Certificate::certificate() const +{ + return _pCert; +} + + +inline X509* X509Certificate::dup() const +{ + return X509_dup(_pCert); +} + + +} } // namespace Poco::Crypto + + +#endif // Crypto_X509Certificate_INCLUDED 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 diff --git a/contrib/libs/poco/Crypto/ya.make b/contrib/libs/poco/Crypto/ya.make new file mode 100644 index 0000000000..cf58950785 --- /dev/null +++ b/contrib/libs/poco/Crypto/ya.make @@ -0,0 +1,57 @@ +# Generated by devtools/yamaker. + +LIBRARY() + +OWNER( + orivej + g:cpp-contrib +) + +LICENSE( + BSD-3-Clause AND + BSL-1.0 +) + +LICENSE_TEXTS(.yandex_meta/licenses.list.txt) + +PEERDIR( + contrib/libs/openssl + contrib/libs/poco/Foundation +) + +ADDINCL( + GLOBAL contrib/libs/poco/Crypto/include + contrib/libs/poco/Crypto/src + contrib/libs/poco/Foundation/include +) + +NO_COMPILER_WARNINGS() + +NO_UTIL() + +SRCS( + src/Cipher.cpp + src/CipherFactory.cpp + src/CipherImpl.cpp + src/CipherKey.cpp + src/CipherKeyImpl.cpp + src/CryptoException.cpp + src/CryptoStream.cpp + src/CryptoTransform.cpp + src/DigestEngine.cpp + src/ECDSADigestEngine.cpp + src/ECKey.cpp + src/ECKeyImpl.cpp + src/EVPPKey.cpp + src/KeyPair.cpp + src/KeyPairImpl.cpp + src/OpenSSLInitializer.cpp + src/PKCS12Container.cpp + src/RSACipherImpl.cpp + src/RSADigestEngine.cpp + src/RSAKey.cpp + src/RSAKeyImpl.cpp + src/X509Certificate.cpp +) + +END() |