1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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>
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
);
31 static void HMAC_CTX_free(HMAC_CTX
* pContext
)
33 HMAC_CTX_cleanup(pContext
);
42 void operator()(EVP_CIPHER_CTX
* p
) { EVP_CIPHER_CTX_free(p
); }
47 SAL_WNODEPRECATED_DECLARATIONS_PUSH
// 'HMAC_CTX_free' is deprecated
49 operator()(HMAC_CTX
* 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
;
63 CryptoImplementationOpenSSL() = default;
65 virtual ~CryptoImplementationOpenSSL()
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)
82 EVP_EncryptInit_ex(mpContext
.get(), cipher
, nullptr, key
.data(), nullptr);
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)
98 const size_t nMinKeySize
= EVP_CIPHER_key_length(pCipher
);
99 if (key
.size() < nMinKeySize
)
100 key
.resize(nMinKeySize
, 0);
103 EVP_DecryptInit_ex(mpContext
.get(), pCipher
, nullptr, key
.data(), nullptr);
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;
123 case CryptoHashType::SHA1
:
126 case CryptoHashType::SHA256
:
127 aEvpMd
= EVP_sha256();
129 case CryptoHashType::SHA384
:
130 aEvpMd
= EVP_sha384();
132 case CryptoHashType::SHA512
:
133 aEvpMd
= EVP_sha512();
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
)
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();
159 sal_uInt32
decryptUpdate(std::vector
<sal_uInt8
>& output
, std::vector
<sal_uInt8
>& input
,
160 sal_uInt32 inputLength
) override
164 int outputLength
= 0;
165 (void)EVP_DecryptUpdate(mpContext
.get(), output
.data(), &outputLength
, input
.data(),
170 sal_uInt32
encryptUpdate(std::vector
<sal_uInt8
>& output
, std::vector
<sal_uInt8
>& input
,
171 sal_uInt32 inputLength
) override
175 int outputLength
= 0;
176 (void)EVP_EncryptUpdate(mpContext
.get(), output
.data(), &outputLength
, input
.data(),
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
)
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: */