Branch libreoffice-5-0-4
[LibreOffice.git] / oox / source / crypto / CryptTools.cxx
blobf5b0769adb195e6adf93c4bfb1f6a7203b6995ab
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 <com/sun/star/uno/RuntimeException.hpp>
14 namespace oox {
15 namespace core {
17 using namespace std;
19 Crypto::Crypto(CryptoType type)
20 : mType(type)
21 #if USE_TLS_NSS
22 , mContext(NULL)
23 , mSecParam(NULL)
24 , mSymKey(NULL)
25 #endif
27 #if USE_TLS_NSS
28 // Initialize NSS, database functions are not needed
29 NSS_NoDB_Init(NULL);
30 #endif // USE_TLS_NSS
33 Crypto::~Crypto()
35 #if USE_TLS_OPENSSL
36 EVP_CIPHER_CTX_cleanup( &mContext );
37 #endif
38 #if USE_TLS_NSS
39 PK11_DestroyContext( mContext, PR_TRUE );
40 PK11_FreeSymKey( mSymKey );
41 SECITEM_FreeItem( mSecParam, PR_TRUE );
42 #endif
45 #if USE_TLS_OPENSSL
46 const EVP_CIPHER* Crypto::getCipher(CryptoType type)
48 switch(type)
50 case AES_128_ECB:
51 return EVP_aes_128_ecb();
52 case AES_128_CBC:
53 return EVP_aes_128_cbc();
54 case AES_256_CBC:
55 return EVP_aes_256_cbc();
56 default:
57 break;
59 return NULL;
61 #endif
63 #if USE_TLS_NSS
64 void Crypto::setupContext(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type, CK_ATTRIBUTE_TYPE operation)
66 CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1);
68 SECItem ivItem;
69 ivItem.type = siBuffer;
70 if(iv.empty())
71 ivItem.data = NULL;
72 else
73 ivItem.data = &iv[0];
74 ivItem.len = iv.size();
76 SECItem* pIvItem = NULL;
78 switch(type)
80 case AES_128_ECB:
81 mechanism = CKM_AES_ECB;
82 break;
83 case AES_128_CBC:
84 mechanism = CKM_AES_CBC;
85 pIvItem = &ivItem;
86 break;
87 case AES_256_CBC:
88 mechanism = CKM_AES_CBC;
89 pIvItem = &ivItem;
90 break;
91 default:
92 break;
95 PK11SlotInfo* pSlot( PK11_GetBestSlot( mechanism, NULL ) );
97 if (!pSlot)
98 throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
100 SECItem keyItem;
101 keyItem.type = siBuffer;
102 keyItem.data = &key[0];
103 keyItem.len = key.size();
105 mSymKey = PK11_ImportSymKey( pSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL );
106 mSecParam = PK11_ParamFromIV( mechanism, pIvItem );
107 mContext = PK11_CreateContextBySymKey( mechanism, operation, mSymKey, mSecParam );
109 #endif // USE_TLS_NSS
111 // DECRYPT
113 Decrypt::Decrypt(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type) :
114 Crypto(type)
116 #if USE_TLS_OPENSSL
117 EVP_CIPHER_CTX_init( &mContext );
119 const EVP_CIPHER* cipher = getCipher(type);
121 if (iv.empty())
122 EVP_DecryptInit_ex( &mContext, cipher, NULL, &key[0], 0 );
123 else
124 EVP_DecryptInit_ex( &mContext, cipher, NULL, &key[0], &iv[0] );
125 EVP_CIPHER_CTX_set_padding( &mContext, 0 );
126 #endif
128 #if USE_TLS_NSS
129 setupContext(key, iv, type, CKA_DECRYPT);
130 #endif // USE_TLS_NSS
133 sal_uInt32 Decrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, sal_uInt32 inputLength)
135 int outputLength = 0;
137 sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
139 #if USE_TLS_OPENSSL
140 (void)EVP_DecryptUpdate( &mContext, &output[0], &outputLength, &input[0], actualInputLength );
141 #endif // USE_TLS_OPENSSL
143 #if USE_TLS_NSS
144 (void)PK11_CipherOp( mContext, &output[0], &outputLength, actualInputLength, &input[0], actualInputLength );
145 #endif // USE_TLS_NSS
147 return static_cast<sal_uInt32>(outputLength);
150 sal_uInt32 Decrypt::aes128ecb(vector<sal_uInt8>& output, vector<sal_uInt8>& input, vector<sal_uInt8>& key)
152 sal_uInt32 outputLength = 0;
153 vector<sal_uInt8> iv;
154 Decrypt crypto(key, iv, Crypto::AES_128_ECB);
155 outputLength = crypto.update(output, input);
156 return outputLength;
159 // ENCRYPT
161 Encrypt::Encrypt(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type) :
162 Crypto(type)
164 #if USE_TLS_OPENSSL
165 EVP_CIPHER_CTX_init( &mContext );
167 const EVP_CIPHER* cipher = getCipher(type);
169 if (iv.empty())
170 EVP_EncryptInit_ex( &mContext, cipher, NULL, &key[0], 0 );
171 else
172 EVP_EncryptInit_ex( &mContext, cipher, NULL, &key[0], &iv[0] );
173 EVP_CIPHER_CTX_set_padding( &mContext, 0 );
174 #endif
176 #if USE_TLS_NSS
177 setupContext(key, iv, type, CKA_ENCRYPT);
178 #endif // USE_TLS_NSS
181 sal_uInt32 Encrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, sal_uInt32 inputLength)
183 int outputLength = 0;
185 sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
187 #if USE_TLS_OPENSSL
188 (void)EVP_EncryptUpdate( &mContext, &output[0], &outputLength, &input[0], actualInputLength );
189 #endif // USE_TLS_OPENSSL
191 #if USE_TLS_NSS
192 (void)PK11_CipherOp( mContext, &output[0], &outputLength, actualInputLength, &input[0], actualInputLength );
193 #endif // USE_TLS_NSS
195 return static_cast<sal_uInt32>(outputLength);
198 // Digest
200 #if USE_TLS_OPENSSL
201 const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA_DIGEST_LENGTH;
202 const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_DIGEST_LENGTH;
203 #endif
204 #if USE_TLS_NSS
205 const sal_uInt32 Digest::DIGEST_LENGTH_SHA1 = SHA1_LENGTH;
206 const sal_uInt32 Digest::DIGEST_LENGTH_SHA512 = SHA512_LENGTH;
207 #endif
209 namespace
212 #if USE_TLS_OPENSSL
213 const EVP_MD* lclOpenSSLgetEngine(Digest::DigestType eType)
215 switch(eType)
217 case Digest::SHA1:
218 return EVP_sha1();
219 case Digest::SHA512:
220 return EVP_sha512();
221 default:
222 break;
224 return NULL;
226 #endif
228 #if USE_TLS_NSS
229 HASH_HashType lclNSSgetHashType(Digest::DigestType eType)
231 switch(eType)
233 case Digest::SHA1:
234 return HASH_AlgSHA1;
235 case Digest::SHA512:
236 return HASH_AlgSHA512;
237 default:
238 break;
240 return HASH_AlgNULL;
242 #endif
246 Digest::Digest(DigestType eType) :
247 meType(eType)
249 #if USE_TLS_OPENSSL
250 mpContext = EVP_MD_CTX_create();
251 EVP_DigestInit_ex(mpContext, lclOpenSSLgetEngine(eType), NULL);
252 #endif
254 #if USE_TLS_NSS
255 NSS_NoDB_Init(NULL);
256 mpContext = HASH_Create(lclNSSgetHashType(eType));
257 HASH_Begin(mpContext);
258 #endif
261 Digest::~Digest()
263 #if USE_TLS_OPENSSL
264 if(mpContext)
265 EVP_MD_CTX_destroy(mpContext);
266 #endif
268 #if USE_TLS_NSS
269 if(mpContext)
270 HASH_Destroy(mpContext);
271 #endif
274 sal_uInt32 Digest::getLength()
276 switch(meType)
278 case SHA1:
279 return DIGEST_LENGTH_SHA1;
280 case SHA512:
281 return DIGEST_LENGTH_SHA512;
282 default:
283 break;
285 return 0;
288 bool Digest::update(std::vector<sal_uInt8>& input)
290 #if USE_TLS_OPENSSL
291 EVP_DigestUpdate(mpContext, &input[0], input.size());
292 #endif
293 #if USE_TLS_NSS
294 HASH_Update(mpContext, &input[0], input.size());
295 #endif
296 return true;
299 bool Digest::finalize(std::vector<sal_uInt8>& digest)
301 digest.clear();
303 #if USE_TLS_OPENSSL
304 unsigned int digestWrittenLength;
305 digest.resize(getLength(), 0);
306 EVP_DigestFinal_ex(mpContext, &digest[0], &digestWrittenLength);
307 #endif
309 #if USE_TLS_NSS
310 unsigned int digestWrittenLength;
311 unsigned int digestLength = static_cast<unsigned int>(getLength());
312 digest.resize(digestLength, 0);
313 HASH_End(mpContext, &digest[0], &digestWrittenLength, digestLength);
314 #endif
315 return true;
318 bool Digest::sha1(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
320 bool aResult = false;
322 Digest aDigest(SHA1);
323 aDigest.update(input);
324 aDigest.finalize(output);
325 aResult = true;
326 return aResult;
329 bool Digest::sha512(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
331 bool aResult = false;
333 Digest aDigest(SHA512);
334 aDigest.update(input);
335 aDigest.finalize(output);
336 aResult = true;
337 return aResult;
340 } // namespace core
341 } // namespace oox
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */