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