Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / oox / source / crypto / CryptTools.cxx
blob1de9fafc80e09ded7fca7e2e774e5e90610f246e
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/.
9 */
11 #include <oox/crypto/CryptTools.hxx>
12 #include <filter/msfilter/mscodec.hxx>
13 #include <com/sun/star/uno/RuntimeException.hpp>
15 namespace oox {
16 namespace core {
18 Crypto::Crypto()
19 #if USE_TLS_NSS
20 : mContext(nullptr)
21 , mSecParam(nullptr)
22 , mSymKey(nullptr)
23 #endif
25 #if USE_TLS_NSS
26 // Initialize NSS, database functions are not needed
27 NSS_NoDB_Init(nullptr);
28 #endif // USE_TLS_NSS
31 Crypto::~Crypto()
33 #if USE_TLS_OPENSSL
34 EVP_CIPHER_CTX_cleanup( &mContext );
35 #endif
36 #if USE_TLS_NSS
37 if (mContext)
38 PK11_DestroyContext(mContext, PR_TRUE);
39 if (mSymKey)
40 PK11_FreeSymKey(mSymKey);
41 if (mSecParam)
42 SECITEM_FreeItem(mSecParam, PR_TRUE);
43 #endif
46 #if USE_TLS_OPENSSL
47 const EVP_CIPHER* Crypto::getCipher(CryptoType type)
49 switch(type)
51 case AES_128_ECB:
52 return EVP_aes_128_ecb();
53 case AES_128_CBC:
54 return EVP_aes_128_cbc();
55 case AES_256_CBC:
56 return EVP_aes_256_cbc();
57 default:
58 break;
60 return NULL;
62 #endif
64 #if USE_TLS_NSS
65 void Crypto::setupContext(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type, CK_ATTRIBUTE_TYPE operation)
67 CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1);
69 SECItem ivItem;
70 ivItem.type = siBuffer;
71 if(iv.empty())
72 ivItem.data = nullptr;
73 else
74 ivItem.data = iv.data();
75 ivItem.len = iv.size();
77 SECItem* pIvItem = nullptr;
79 switch(type)
81 case AES_128_ECB:
82 mechanism = CKM_AES_ECB;
83 break;
84 case AES_128_CBC:
85 mechanism = CKM_AES_CBC;
86 pIvItem = &ivItem;
87 break;
88 case AES_256_CBC:
89 mechanism = CKM_AES_CBC;
90 pIvItem = &ivItem;
91 break;
92 default:
93 break;
96 PK11SlotInfo* pSlot(PK11_GetBestSlot(mechanism, nullptr));
98 if (!pSlot)
99 throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
101 SECItem keyItem;
102 keyItem.type = siBuffer;
103 keyItem.data = key.data();
104 keyItem.len = key.size();
106 mSymKey = PK11_ImportSymKey(pSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr);
107 if (!mSymKey)
108 throw css::uno::RuntimeException("NSS SymKey failure", css::uno::Reference<css::uno::XInterface>());
110 mSecParam = PK11_ParamFromIV(mechanism, pIvItem);
111 mContext = PK11_CreateContextBySymKey(mechanism, operation, mSymKey, mSecParam);
113 #endif // USE_TLS_NSS
115 // DECRYPT
117 Decrypt::Decrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type)
118 : Crypto()
120 #if USE_TLS_OPENSSL + USE_TLS_NSS == 0
121 (void)key;
122 (void)iv;
123 (void)type;
124 #endif
126 #if USE_TLS_OPENSSL
127 EVP_CIPHER_CTX_init(&mContext);
129 const EVP_CIPHER* cipher = getCipher(type);
131 const size_t nMinKeySize = EVP_CIPHER_key_length(cipher);
132 if (key.size() < nMinKeySize)
133 key.resize(nMinKeySize, 0);
135 if (iv.empty())
136 EVP_DecryptInit_ex(&mContext, cipher, nullptr, key.data(), 0);
137 else
139 const size_t nMinIVSize = EVP_CIPHER_iv_length(cipher);
140 if (iv.size() < nMinIVSize)
141 iv.resize(nMinIVSize, 0);
143 EVP_DecryptInit_ex(&mContext, cipher, nullptr, key.data(), iv.data());
145 EVP_CIPHER_CTX_set_padding(&mContext, 0);
146 #endif
148 #if USE_TLS_NSS
149 setupContext(key, iv, type, CKA_DECRYPT);
150 #endif // USE_TLS_NSS
153 sal_uInt32 Decrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength)
155 int outputLength = 0;
157 #if USE_TLS_OPENSSL + USE_TLS_NSS > 0
158 sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
159 #else
160 (void)output;
161 (void)input;
162 (void)inputLength;
163 #endif
165 #if USE_TLS_OPENSSL
166 (void)EVP_DecryptUpdate(&mContext, output.data(), &outputLength, input.data(), actualInputLength);
167 #endif // USE_TLS_OPENSSL
169 #if USE_TLS_NSS
170 if (!mContext)
171 return 0;
172 (void)PK11_CipherOp( mContext, output.data(), &outputLength, actualInputLength, input.data(), actualInputLength );
173 #endif // USE_TLS_NSS
175 return static_cast<sal_uInt32>(outputLength);
178 sal_uInt32 Decrypt::aes128ecb(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, std::vector<sal_uInt8>& key)
180 sal_uInt32 outputLength = 0;
181 std::vector<sal_uInt8> iv;
182 Decrypt crypto(key, iv, Crypto::AES_128_ECB);
183 outputLength = crypto.update(output, input);
184 return outputLength;
187 // ENCRYPT
189 Encrypt::Encrypt(std::vector<sal_uInt8>& key, std::vector<sal_uInt8>& iv, CryptoType type)
190 : Crypto()
192 #if USE_TLS_OPENSSL + USE_TLS_NSS == 0
193 (void)key;
194 (void)iv;
195 (void)type;
196 #endif
198 #if USE_TLS_OPENSSL
199 EVP_CIPHER_CTX_init(&mContext);
201 const EVP_CIPHER* cipher = getCipher(type);
203 if (iv.empty())
204 EVP_EncryptInit_ex(&mContext, cipher, nullptr, key.data(), 0);
205 else
206 EVP_EncryptInit_ex(&mContext, cipher, nullptr, key.data(), iv.data());
207 EVP_CIPHER_CTX_set_padding(&mContext, 0);
208 #endif
210 #if USE_TLS_NSS
211 setupContext(key, iv, type, CKA_ENCRYPT);
212 #endif // USE_TLS_NSS
215 sal_uInt32 Encrypt::update(std::vector<sal_uInt8>& output, std::vector<sal_uInt8>& input, sal_uInt32 inputLength)
217 int outputLength = 0;
219 #if USE_TLS_OPENSSL + USE_TLS_NSS > 0
220 sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
221 #else
222 (void)output;
223 (void)input;
224 (void)inputLength;
225 #endif
227 #if USE_TLS_OPENSSL
228 (void)EVP_EncryptUpdate(&mContext, output.data(), &outputLength, input.data(), actualInputLength);
229 #endif // USE_TLS_OPENSSL
231 #if USE_TLS_NSS
232 (void)PK11_CipherOp(mContext, output.data(), &outputLength, actualInputLength, input.data(), actualInputLength);
233 #endif // USE_TLS_NSS
235 return static_cast<sal_uInt32>(outputLength);
238 } // namespace core
239 } // namespace oox
241 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */