Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : *
9 : */
10 :
11 : #include "oox/crypto/CryptTools.hxx"
12 : #include <com/sun/star/uno/RuntimeException.hpp>
13 :
14 : namespace oox {
15 : namespace core {
16 :
17 : using namespace std;
18 :
19 0 : Crypto::Crypto(CryptoType type)
20 : : mType(type)
21 : #if USE_TLS_NSS
22 : , mContext(NULL)
23 : , mSecParam(NULL)
24 0 : , mSymKey(NULL)
25 : #endif
26 : {
27 : #if USE_TLS_NSS
28 : // Initialize NSS, database functions are not needed
29 0 : NSS_NoDB_Init(NULL);
30 : #endif // USE_TLS_NSS
31 0 : }
32 :
33 0 : Crypto::~Crypto()
34 : {
35 : #if USE_TLS_OPENSSL
36 : EVP_CIPHER_CTX_cleanup( &mContext );
37 : #endif
38 : #if USE_TLS_NSS
39 0 : PK11_DestroyContext( mContext, PR_TRUE );
40 0 : PK11_FreeSymKey( mSymKey );
41 0 : SECITEM_FreeItem( mSecParam, PR_TRUE );
42 : #endif
43 0 : }
44 :
45 : #if USE_TLS_OPENSSL
46 : const EVP_CIPHER* Crypto::getCipher(CryptoType type)
47 : {
48 : switch(type)
49 : {
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;
58 : }
59 : return NULL;
60 : }
61 : #endif
62 :
63 : #if USE_TLS_NSS
64 0 : void Crypto::setupContext(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type, CK_ATTRIBUTE_TYPE operation)
65 : {
66 0 : CK_MECHANISM_TYPE mechanism = static_cast<CK_ULONG>(-1);
67 :
68 : SECItem ivItem;
69 0 : ivItem.type = siBuffer;
70 0 : if(iv.empty())
71 0 : ivItem.data = NULL;
72 : else
73 0 : ivItem.data = &iv[0];
74 0 : ivItem.len = iv.size();
75 :
76 0 : SECItem* pIvItem = NULL;
77 :
78 0 : switch(type)
79 : {
80 : case AES_128_ECB:
81 0 : mechanism = CKM_AES_ECB;
82 0 : break;
83 : case AES_128_CBC:
84 0 : mechanism = CKM_AES_CBC;
85 0 : pIvItem = &ivItem;
86 0 : break;
87 : case AES_256_CBC:
88 0 : mechanism = CKM_AES_CBC;
89 0 : pIvItem = &ivItem;
90 0 : break;
91 : default:
92 0 : break;
93 : }
94 :
95 0 : PK11SlotInfo* pSlot( PK11_GetBestSlot( mechanism, NULL ) );
96 :
97 0 : if (!pSlot)
98 0 : throw css::uno::RuntimeException("NSS Slot failure", css::uno::Reference<css::uno::XInterface>());
99 :
100 : SECItem keyItem;
101 0 : keyItem.type = siBuffer;
102 0 : keyItem.data = &key[0];
103 0 : keyItem.len = key.size();
104 :
105 0 : mSymKey = PK11_ImportSymKey( pSlot, mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL );
106 0 : mSecParam = PK11_ParamFromIV( mechanism, pIvItem );
107 0 : mContext = PK11_CreateContextBySymKey( mechanism, operation, mSymKey, mSecParam );
108 0 : }
109 : #endif // USE_TLS_NSS
110 :
111 : // DECRYPT
112 :
113 0 : Decrypt::Decrypt(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type) :
114 0 : Crypto(type)
115 : {
116 : #if USE_TLS_OPENSSL
117 : EVP_CIPHER_CTX_init( &mContext );
118 :
119 : const EVP_CIPHER* cipher = getCipher(type);
120 :
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
127 :
128 : #if USE_TLS_NSS
129 0 : setupContext(key, iv, type, CKA_DECRYPT);
130 : #endif // USE_TLS_NSS
131 0 : }
132 :
133 0 : sal_uInt32 Decrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, sal_uInt32 inputLength)
134 : {
135 0 : int outputLength = 0;
136 :
137 0 : sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
138 :
139 : #if USE_TLS_OPENSSL
140 : (void)EVP_DecryptUpdate( &mContext, &output[0], &outputLength, &input[0], actualInputLength );
141 : #endif // USE_TLS_OPENSSL
142 :
143 : #if USE_TLS_NSS
144 0 : (void)PK11_CipherOp( mContext, &output[0], &outputLength, actualInputLength, &input[0], actualInputLength );
145 : #endif // USE_TLS_NSS
146 :
147 0 : return static_cast<sal_uInt32>(outputLength);
148 : }
149 :
150 0 : sal_uInt32 Decrypt::aes128ecb(vector<sal_uInt8>& output, vector<sal_uInt8>& input, vector<sal_uInt8>& key)
151 : {
152 0 : sal_uInt32 outputLength = 0;
153 0 : vector<sal_uInt8> iv;
154 0 : Decrypt crypto(key, iv, Crypto::AES_128_ECB);
155 0 : outputLength = crypto.update(output, input);
156 0 : return outputLength;
157 : }
158 :
159 : // ENCRYPT
160 :
161 0 : Encrypt::Encrypt(vector<sal_uInt8>& key, vector<sal_uInt8>& iv, CryptoType type) :
162 0 : Crypto(type)
163 : {
164 : #if USE_TLS_OPENSSL
165 : EVP_CIPHER_CTX_init( &mContext );
166 :
167 : const EVP_CIPHER* cipher = getCipher(type);
168 :
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
175 :
176 : #if USE_TLS_NSS
177 0 : setupContext(key, iv, type, CKA_ENCRYPT);
178 : #endif // USE_TLS_NSS
179 0 : }
180 :
181 0 : sal_uInt32 Encrypt::update(vector<sal_uInt8>& output, vector<sal_uInt8>& input, sal_uInt32 inputLength)
182 : {
183 0 : int outputLength = 0;
184 :
185 0 : sal_uInt32 actualInputLength = inputLength == 0 || inputLength > input.size() ? input.size() : inputLength;
186 :
187 : #if USE_TLS_OPENSSL
188 : (void)EVP_EncryptUpdate( &mContext, &output[0], &outputLength, &input[0], actualInputLength );
189 : #endif // USE_TLS_OPENSSL
190 :
191 : #if USE_TLS_NSS
192 0 : (void)PK11_CipherOp( mContext, &output[0], &outputLength, actualInputLength, &input[0], actualInputLength );
193 : #endif // USE_TLS_NSS
194 :
195 0 : return static_cast<sal_uInt32>(outputLength);
196 : }
197 :
198 : // Digest
199 :
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
208 :
209 : namespace
210 : {
211 :
212 : #if USE_TLS_OPENSSL
213 : const EVP_MD* lclOpenSSLgetEngine(Digest::DigestType eType)
214 : {
215 : switch(eType)
216 : {
217 : case Digest::SHA1:
218 : return EVP_sha1();
219 : case Digest::SHA512:
220 : return EVP_sha512();
221 : default:
222 : break;
223 : }
224 : return NULL;
225 : }
226 : #endif
227 :
228 : #if USE_TLS_NSS
229 0 : HASH_HashType lclNSSgetHashType(Digest::DigestType eType)
230 : {
231 0 : switch(eType)
232 : {
233 : case Digest::SHA1:
234 0 : return HASH_AlgSHA1;
235 : case Digest::SHA512:
236 0 : return HASH_AlgSHA512;
237 : default:
238 0 : break;
239 : }
240 0 : return HASH_AlgNULL;
241 : }
242 : #endif
243 :
244 : }
245 :
246 0 : Digest::Digest(DigestType eType) :
247 0 : meType(eType)
248 : {
249 : #if USE_TLS_OPENSSL
250 : mpContext = EVP_MD_CTX_create();
251 : EVP_DigestInit_ex(mpContext, lclOpenSSLgetEngine(eType), NULL);
252 : #endif
253 :
254 : #if USE_TLS_NSS
255 0 : NSS_NoDB_Init(NULL);
256 0 : mpContext = HASH_Create(lclNSSgetHashType(eType));
257 0 : HASH_Begin(mpContext);
258 : #endif
259 0 : }
260 :
261 0 : Digest::~Digest()
262 : {
263 : #if USE_TLS_OPENSSL
264 : if(mpContext)
265 : EVP_MD_CTX_destroy(mpContext);
266 : #endif
267 :
268 : #if USE_TLS_NSS
269 0 : if(mpContext)
270 0 : HASH_Destroy(mpContext);
271 : #endif
272 0 : }
273 :
274 0 : sal_uInt32 Digest::getLength()
275 : {
276 0 : switch(meType)
277 : {
278 : case SHA1:
279 0 : return DIGEST_LENGTH_SHA1;
280 : case SHA512:
281 0 : return DIGEST_LENGTH_SHA512;
282 : default:
283 0 : break;
284 : }
285 0 : return 0;
286 : }
287 :
288 0 : bool Digest::update(std::vector<sal_uInt8>& input)
289 : {
290 : #if USE_TLS_OPENSSL
291 : EVP_DigestUpdate(mpContext, &input[0], input.size());
292 : #endif
293 : #if USE_TLS_NSS
294 0 : HASH_Update(mpContext, &input[0], input.size());
295 : #endif
296 0 : return true;
297 : }
298 :
299 0 : bool Digest::finalize(std::vector<sal_uInt8>& digest)
300 : {
301 0 : digest.clear();
302 :
303 : #if USE_TLS_OPENSSL
304 : unsigned int digestWrittenLength;
305 : digest.resize(getLength(), 0);
306 : EVP_DigestFinal_ex(mpContext, &digest[0], &digestWrittenLength);
307 : #endif
308 :
309 : #if USE_TLS_NSS
310 : unsigned int digestWrittenLength;
311 0 : unsigned int digestLength = static_cast<unsigned int>(getLength());
312 0 : digest.resize(digestLength, 0);
313 0 : HASH_End(mpContext, &digest[0], &digestWrittenLength, digestLength);
314 : #endif
315 0 : return true;
316 : }
317 :
318 0 : bool Digest::sha1(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
319 : {
320 0 : bool aResult = false;
321 :
322 0 : Digest aDigest(SHA1);
323 0 : aDigest.update(input);
324 0 : aDigest.finalize(output);
325 0 : aResult = true;
326 0 : return aResult;
327 : }
328 :
329 0 : bool Digest::sha512(vector<sal_uInt8>& output, vector<sal_uInt8>& input)
330 : {
331 0 : bool aResult = false;
332 :
333 0 : Digest aDigest(SHA512);
334 0 : aDigest.update(input);
335 0 : aDigest.finalize(output);
336 0 : aResult = true;
337 0 : return aResult;
338 : }
339 :
340 : } // namespace core
341 : } // namespace oox
342 :
343 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|