tdf#164972 Fix white-on-white themed scrollbars on windows
[LibreOffice.git] / comphelper / source / crypto / Crypto_OpenSSL.cxx
blob37c5ff44e2224c4da00dcb466ae27d4a05b2a5e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <comphelper/crypto/Crypto.hxx>
11 #include <sal/types.h>
12 #include <config_oox.h>
14 #include <openssl/evp.h>
15 #include <openssl/sha.h>
16 #include <openssl/hmac.h>
18 namespace comphelper
20 namespace
22 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
24 static HMAC_CTX* HMAC_CTX_new(void)
26 HMAC_CTX* pContext = new HMAC_CTX;
27 HMAC_CTX_init(pContext);
28 return pContext;
31 static void HMAC_CTX_free(HMAC_CTX* pContext)
33 HMAC_CTX_cleanup(pContext);
34 delete pContext;
36 #endif
38 namespace
40 struct cipher_delete
42 void operator()(EVP_CIPHER_CTX* p) { EVP_CIPHER_CTX_free(p); }
45 struct hmac_delete
47 SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_free' is deprecated
48 void
49 operator()(HMAC_CTX* p)
51 HMAC_CTX_free(p);
53 SAL_WNODEPRECATED_DECLARATIONS_POP
57 class CryptoImplementationOpenSSL : public ICryptoImplementation
59 std::unique_ptr<EVP_CIPHER_CTX, cipher_delete> mpContext;
60 std::unique_ptr<HMAC_CTX, hmac_delete> mpHmacContext;
62 public:
63 CryptoImplementationOpenSSL() = default;
65 virtual ~CryptoImplementationOpenSSL()
67 if (mpContext)
68 EVP_CIPHER_CTX_cleanup(mpContext.get());
71 void setupEncryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
72 CryptoType eType) override
74 mpContext.reset(EVP_CIPHER_CTX_new());
75 EVP_CIPHER_CTX_init(mpContext.get());
77 const EVP_CIPHER* cipher = getCipher(eType);
78 if (cipher == nullptr)
79 return;
81 if (iv.empty())
82 EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), nullptr);
83 else
84 EVP_EncryptInit_ex(mpContext.get(), cipher, nullptr, key.data(), iv.data());
85 EVP_CIPHER_CTX_set_padding(mpContext.get(), 0);
88 void setupDecryptContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv,
89 CryptoType eType) override
91 mpContext.reset(EVP_CIPHER_CTX_new());
92 EVP_CIPHER_CTX_init(mpContext.get());
94 const EVP_CIPHER* pCipher = getCipher(eType);
95 if (pCipher == nullptr)
96 return;
98 const size_t nMinKeySize = EVP_CIPHER_key_length(pCipher);
99 if (key.size() < nMinKeySize)
100 key.resize(nMinKeySize, 0);
102 if (iv.empty())
103 EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), nullptr);
104 else
106 const size_t nMinIVSize = EVP_CIPHER_iv_length(pCipher);
107 if (iv.size() < nMinIVSize)
108 iv.resize(nMinIVSize, 0);
110 EVP_DecryptInit_ex(mpContext.get(), pCipher, nullptr, key.data(), iv.data());
112 EVP_CIPHER_CTX_set_padding(mpContext.get(), 0);
115 void setupCryptoHashContext(std::vector<sal_uInt8>& rKey, CryptoHashType eType) override
117 SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_CTX_new' is deprecated
118 mpHmacContext.reset(HMAC_CTX_new());
119 SAL_WNODEPRECATED_DECLARATIONS_POP
120 const EVP_MD* aEvpMd = nullptr;
121 switch (eType)
123 case CryptoHashType::SHA1:
124 aEvpMd = EVP_sha1();
125 break;
126 case CryptoHashType::SHA256:
127 aEvpMd = EVP_sha256();
128 break;
129 case CryptoHashType::SHA384:
130 aEvpMd = EVP_sha384();
131 break;
132 case CryptoHashType::SHA512:
133 aEvpMd = EVP_sha512();
134 break;
136 SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Init_ex' is deprecated
137 HMAC_Init_ex(mpHmacContext.get(), rKey.data(), rKey.size(), aEvpMd, nullptr);
138 SAL_WNODEPRECATED_DECLARATIONS_POP
141 static const EVP_CIPHER* getCipher(CryptoType type)
143 switch (type)
145 case CryptoType::AES_128_ECB:
146 return EVP_aes_128_ecb();
147 case CryptoType::AES_256_ECB:
148 return EVP_aes_256_ecb();
149 case CryptoType::AES_128_CBC:
150 return EVP_aes_128_cbc();
151 case CryptoType::AES_256_CBC:
152 return EVP_aes_256_cbc();
153 default:
154 break;
156 return nullptr;
159 sal_uInt32 decryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
160 sal_uInt32 inputLength) override
162 if (!mpContext)
163 return 0;
164 int outputLength = 0;
165 (void)EVP_DecryptUpdate(mpContext.get(), output.data(), &outputLength, input.data(),
166 inputLength);
167 return outputLength;
170 sal_uInt32 encryptUpdate(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input,
171 sal_uInt32 inputLength) override
173 if (!mpContext)
174 return 0;
175 int outputLength = 0;
176 (void)EVP_EncryptUpdate(mpContext.get(), output.data(), &outputLength, input.data(),
177 inputLength);
178 return sal_uInt32(outputLength);
181 bool cryptoHashUpdate(std::vector<sal_uInt8>& rInput, sal_uInt32 nInputLength) override
183 SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Update' is deprecated
184 return HMAC_Update(mpHmacContext.get(), rInput.data(), nInputLength)
185 != 0;
186 SAL_WNODEPRECATED_DECLARATIONS_POP
189 bool cryptoHashFinalize(std::vector<sal_uInt8>& rHash) override
191 unsigned int nSizeWritten = 0;
192 SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'HMAC_Final' is deprecated
193 (void) HMAC_Final(mpHmacContext.get(), rHash.data(), &nSizeWritten);
194 SAL_WNODEPRECATED_DECLARATIONS_POP
195 return nSizeWritten == rHash.size();
199 } // anonymous namespace
201 std::shared_ptr<ICryptoImplementation> ICryptoImplementation::createInstance()
203 return std::shared_ptr<ICryptoImplementation>(new CryptoImplementationOpenSSL);
206 } // namespace comphelper
208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */