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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <com/sun/star/lang/IllegalArgumentException.hpp>
21 #include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
22 #include <com/sun/star/xml/crypto/DigestID.hpp>
23 #include <com/sun/star/xml/crypto/CipherID.hpp>
24 #include <com/sun/star/xml/crypto/NSSInitializer.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <officecfg/Office/Common.hxx>
28 #include <sal/types.h>
29 #include <rtl/bootstrap.hxx>
30 #include <rtl/string.hxx>
31 #include <osl/file.hxx>
32 #include <osl/thread.h>
33 #include <sal/log.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <unotools/tempfile.hxx>
36 #include <salhelper/singletonref.hxx>
37 #include <comphelper/sequence.hxx>
38
39 #include <nss/nssinitializer.hxx>
40
41 #include "digestcontext.hxx"
42 #include "ciphercontext.hxx"
43
44 #include <memory>
45 #include <vector>
46
47 #include <nss.h>
48 #include <pk11pub.h>
49 #include <secmod.h>
50 #include <prerror.h>
51 #include <prinit.h>
52
53 namespace cssu = css::uno;
54 namespace cssl = css::lang;
55
56 using namespace com::sun::star;
57
58 #define ROOT_CERTS "Root Certs for OpenOffice.org"
59
60 extern "C" {
61
62 static void nsscrypto_finalize();
63
64 }
65
66 namespace
67 {
68
69 class InitNSSPrivate
70 {
71 private:
72 std::unique_ptr<utl::TempFile> m_pTempFileDatabaseDirectory;
73
74 public:
getTempDatabasePath()75 OUString getTempDatabasePath()
76 {
77 if (!m_pTempFileDatabaseDirectory)
78 {
79 m_pTempFileDatabaseDirectory.reset(new utl::TempFile(nullptr, true));
80 m_pTempFileDatabaseDirectory->EnableKillingFile();
81 }
82 return m_pTempFileDatabaseDirectory->GetFileName();
83 }
84
reset()85 void reset()
86 {
87 if (m_pTempFileDatabaseDirectory)
88 {
89 m_pTempFileDatabaseDirectory.reset();
90 }
91 }
92 };
93
getInitNSSPrivate()94 salhelper::SingletonRef<InitNSSPrivate>* getInitNSSPrivate()
95 {
96 static salhelper::SingletonRef<InitNSSPrivate> aInitNSSPrivate;
97 return &aInitNSSPrivate;
98 }
99
100 bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init );
101
102 #ifdef XMLSEC_CRYPTO_NSS
103
deleteRootsModule()104 void deleteRootsModule()
105 {
106 SECMODModule *RootsModule = nullptr;
107 SECMODModuleList *list = SECMOD_GetDefaultModuleList();
108 SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
109 SECMOD_GetReadLock(lock);
110
111 while (!RootsModule && list)
112 {
113 SECMODModule *module = list->module;
114
115 for (int i=0; i < module->slotCount; i++)
116 {
117 PK11SlotInfo *slot = module->slots[i];
118 if (PK11_IsPresent(slot))
119 {
120 if (PK11_HasRootCerts(slot))
121 {
122 SAL_INFO("xmlsecurity.xmlsec", "The root certificates module \"" << module->commonName << "\" is already loaded: " << module->dllName);
123
124 RootsModule = SECMOD_ReferenceModule(module);
125 break;
126 }
127 }
128 }
129 list = list->next;
130 }
131 SECMOD_ReleaseReadLock(lock);
132
133 if (!RootsModule)
134 return;
135
136 PRInt32 modType;
137 if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType))
138 {
139 SAL_INFO("xmlsecurity.xmlsec", "Deleted module \"" << RootsModule->commonName << "\".");
140 }
141 else
142 {
143 SAL_INFO("xmlsecurity.xmlsec", "Failed to delete \"" << RootsModule->commonName << "\": " << RootsModule->dllName);
144 }
145 SECMOD_DestroyModule(RootsModule);
146 RootsModule = nullptr;
147 }
148
149 #endif
150
lcl_pathExists(const OUString & sPath)151 bool lcl_pathExists(const OUString& sPath)
152 {
153 if (sPath.isEmpty())
154 return false;
155
156 ::osl::DirectoryItem aPathItem;
157 OUString sURL;
158 osl::FileBase::getFileURLFromSystemPath(sPath, sURL);
159 if (::osl::FileBase::E_None == ::osl::DirectoryItem::get(sURL, aPathItem))
160 {
161 ::osl::FileStatus aStatus = osl_FileStatus_Mask_Validate;
162 if (::osl::FileBase::E_None == aPathItem.getFileStatus(aStatus))
163 return true;
164 }
165
166 return false;
167 }
168
169 } // namespace
170
getMozillaCurrentProfile(const css::uno::Reference<css::uno::XComponentContext> & rxContext,bool bSetActive)171 const OUString & ONSSInitializer::getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive)
172 {
173 if (m_bIsNSSinitialized)
174 return m_sNSSPath;
175 if (bSetActive)
176 m_bIsNSSinitialized = true;
177
178 // first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER"
179 const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER");
180 if (pEnv)
181 {
182 SAL_INFO(
183 "xmlsecurity.xmlsec",
184 "Using Mozilla profile from MOZILLA_CERTIFICATE_FOLDER=" << pEnv);
185 m_sNSSPath = OStringToOUString(pEnv, osl_getThreadTextEncoding());
186 }
187
188 // second, try to get saved user-preference
189 if (m_sNSSPath.isEmpty())
190 {
191 try
192 {
193 OUString sUserSetCertPath =
194 officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());
195
196 if (lcl_pathExists(sUserSetCertPath))
197 {
198 SAL_INFO(
199 "xmlsecurity.xmlsec",
200 "Using Mozilla profile from /org.openoffice.Office.Common/"
201 "Security/Scripting/CertDir: " << sUserSetCertPath);
202 m_sNSSPath = sUserSetCertPath;
203 }
204 }
205 catch (const uno::Exception &)
206 {
207 TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:");
208 }
209 }
210
211 // third, dig around to see if there's one default available
212 mozilla::MozillaProductType productTypes[3] = {
213 mozilla::MozillaProductType_Thunderbird,
214 mozilla::MozillaProductType_Firefox,
215 mozilla::MozillaProductType_Mozilla };
216
217 uno::Reference<uno::XInterface> xInstance = rxContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", rxContext);
218 OSL_ENSURE( xInstance.is(), "failed to create instance" );
219
220 uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY);
221 OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" );
222
223 if (xMozillaBootstrap.is())
224 {
225 for (int i=0; i<int(SAL_N_ELEMENTS(productTypes)); ++i)
226 {
227 OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]);
228
229 if (!profile.isEmpty())
230 {
231 OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypes[i], profile);
232 if (m_sNSSPath.isEmpty())
233 {
234 SAL_INFO("xmlsecurity.xmlsec", "Using Mozilla profile " << sProfilePath);
235 m_sNSSPath = sProfilePath;
236 }
237 break;
238 }
239 }
240 }
241
242 SAL_INFO_IF(m_sNSSPath.isEmpty(), "xmlsecurity.xmlsec", "No Mozilla profile found");
243 return m_sNSSPath;
244 }
245
getNSSProfiles()246 css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL ONSSInitializer::getNSSProfiles()
247 {
248 ONSSInitializer::getMozillaCurrentProfile(m_xContext);
249
250 std::vector<xml::crypto::NSSProfile> aProfileList;
251 aProfileList.reserve(10);
252
253 mozilla::MozillaProductType productTypes[3] = {
254 mozilla::MozillaProductType_Thunderbird,
255 mozilla::MozillaProductType_Firefox,
256 mozilla::MozillaProductType_Mozilla };
257
258 uno::Reference<uno::XInterface> xInstance = m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", m_xContext);
259 OSL_ENSURE(xInstance.is(), "failed to create instance" );
260
261 uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY);
262
263 if (xMozillaBootstrap.is())
264 {
265 for (int i=0; i<int(SAL_N_ELEMENTS(productTypes)); ++i)
266 {
267 uno::Sequence<OUString> aProductProfileList;
268 xMozillaBootstrap->getProfileList(productTypes[i], aProductProfileList);
269 for (const auto& sProfile : std::as_const(aProductProfileList))
270 aProfileList.push_back({sProfile, xMozillaBootstrap->getProfilePath(productTypes[i], sProfile), productTypes[i]});
271 }
272 }
273
274 OUString sUserSelect;
275 try
276 {
277 sUserSelect = officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());;
278 if (!lcl_pathExists(sUserSelect))
279 sUserSelect = OUString();
280 }
281 catch (const uno::Exception &)
282 {
283 TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:");
284 }
285 aProfileList.push_back({"MANUAL", sUserSelect, mozilla::MozillaProductType_Default});
286
287 const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER");
288 aProfileList.push_back({"MOZILLA_CERTIFICATE_FOLDER",
289 pEnv ? OStringToOUString(pEnv, osl_getThreadTextEncoding()) : OUString(),
290 mozilla::MozillaProductType_Default});
291
292 return comphelper::containerToSequence(aProfileList);
293 }
294
295 bool ONSSInitializer::m_bIsNSSinitialized = false;
296 OUString ONSSInitializer::m_sNSSPath;
297
getNSSPath()298 OUString SAL_CALL ONSSInitializer::getNSSPath()
299 {
300 ONSSInitializer::getMozillaCurrentProfile(m_xContext);
301 return m_sNSSPath;
302 };
303
getIsNSSinitialized()304 sal_Bool SAL_CALL ONSSInitializer::getIsNSSinitialized()
305 {
306 return m_bIsNSSinitialized;
307 }
308
ONSSInitializer(const css::uno::Reference<css::uno::XComponentContext> & rxContext)309 ONSSInitializer::ONSSInitializer(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
310 : m_xContext(rxContext)
311 {
312 }
313
ONSSInitializer()314 ONSSInitializer::ONSSInitializer()
315 {
316 }
317
318 namespace
319 {
320
321 //Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write
322 //the roots certificate module (libnssckbi.so), which they use, into the
323 //profile. This module will then already be loaded during NSS_Init (and the
324 //other init functions). This fails in two cases. First, FF3 was used to create
325 //the profile, or possibly used that profile before, and second the profile was
326 //used on a different platform.
327 //
328 //Then one needs to add the roots module oneself. This should be done with
329 //SECMOD_LoadUserModule rather than SECMOD_AddNewModule. The latter would write
330 //the location of the roots module to the profile, which makes FF2 and TB2 use
331 //it instead of their own module.
332 //
333 //When using SYSTEM_NSS then the libnss3.so lib is typically found in /usr/lib.
334 //This folder may, however, NOT contain the roots certificate module. That is,
335 //just providing the library name in SECMOD_LoadUserModule or
336 //SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH
337 //contains an FF or TB installation.
338 //ATTENTION: DO NOT call this function directly instead use initNSS
339 //return true - whole initialization was successful
340 //param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite
341 //was successful and therefore NSS_Shutdown should be called when terminating.
nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const & rxContext,bool & out_nss_init)342 bool nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const & rxContext, bool & out_nss_init)
343 {
344 // this method must be called only once, no need for additional lock
345 OString sCertDir;
346
347 #ifdef XMLSEC_CRYPTO_NSS
348 sCertDir = OUStringToOString(ONSSInitializer::getMozillaCurrentProfile(rxContext, true), osl_getThreadTextEncoding());
349 #else
350 (void) rxContext;
351 #endif
352 SAL_INFO("xmlsecurity.xmlsec", "Using profile: " << sCertDir );
353
354 PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
355
356 bool bSuccess = false;
357 // there might be no profile
358 if (!sCertDir.isEmpty())
359 {
360 if (sCertDir.indexOf(':') == -1) //might be env var with explicit prefix
361 {
362 OUString sCertDirURL;
363 osl::FileBase::getFileURLFromSystemPath(
364 OStringToOUString(sCertDir, osl_getThreadTextEncoding()),
365 sCertDirURL);
366 osl::DirectoryItem item;
367 if (osl::FileBase::E_NOENT != osl::DirectoryItem::get(sCertDirURL + "/cert8.db", item) &&
368 osl::FileBase::E_NOENT == osl::DirectoryItem::get(sCertDirURL + "/cert9.db", item))
369 {
370 SAL_INFO("xmlsecurity.xmlsec", "nsscrypto_initialize: trying to avoid profile migration");
371 sCertDir = "dbm:" + sCertDir;
372 }
373 }
374 if (NSS_InitReadWrite(sCertDir.getStr()) != SECSuccess)
375 {
376 SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with profile failed.");
377 int errlen = PR_GetErrorTextLength();
378 if (errlen > 0)
379 {
380 std::unique_ptr<char[]> const error(new char[errlen + 1]);
381 PR_GetErrorText(error.get());
382 SAL_INFO("xmlsecurity.xmlsec", error.get());
383 }
384 }
385 else
386 {
387 bSuccess = true;
388 }
389 }
390
391 if (!bSuccess) // Try to create a database in temp dir
392 {
393 SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
394 OUString rString = (*getInitNSSPrivate())->getTempDatabasePath();
395
396 if (NSS_InitReadWrite(rString.toUtf8().getStr()) != SECSuccess)
397 {
398 SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
399 int errlen = PR_GetErrorTextLength();
400 if(errlen > 0)
401 {
402 std::unique_ptr<char[]> const error(new char[errlen + 1]);
403 PR_GetErrorText(error.get());
404 SAL_INFO("xmlsecurity.xmlsec", error.get());
405 }
406 return false;
407 }
408 // Initialize and set empty password if needed
409 PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
410 if (pSlot)
411 {
412 if (PK11_NeedUserInit(pSlot))
413 PK11_InitPin(pSlot, nullptr, nullptr);
414 PK11_FreeSlot(pSlot);
415 }
416 }
417 out_nss_init = true;
418
419 #ifdef XMLSEC_CRYPTO_NSS
420 bool return_value = true;
421
422 #if defined SYSTEM_NSS || defined IOS // The statically linked nss on iOS acts as a "system" nss in this regards
423 if (!SECMOD_HasRootCerts())
424 #endif
425 {
426 deleteRootsModule();
427
428 #ifdef IOS // Use statically linked NSS
429 OUString rootModulePath("NSSCKBI");
430
431 if (true)
432 #else
433 #if defined SYSTEM_NSS || defined ANDROID
434 OUString rootModule("libnssckbi" SAL_DLLEXTENSION);
435 #else
436 OUString rootModule("${LO_LIB_DIR}/libnssckbi" SAL_DLLEXTENSION);
437 #endif
438 ::rtl::Bootstrap::expandMacros(rootModule);
439
440 OUString rootModulePath;
441 if (::osl::File::E_None == ::osl::File::getSystemPathFromFileURL(rootModule, rootModulePath))
442 #endif
443 {
444 OString ospath = OUStringToOString(rootModulePath, osl_getThreadTextEncoding());
445 OString aStr = "name=\"" ROOT_CERTS "\" library=\"" + ospath + "\"";
446
447 SECMODModule * RootsModule =
448 SECMOD_LoadUserModule(
449 const_cast<char*>(aStr.getStr()),
450 nullptr, // no parent
451 PR_FALSE); // do not recurse
452
453 if (RootsModule)
454 {
455
456 bool found = RootsModule->loaded;
457
458 SECMOD_DestroyModule(RootsModule);
459 RootsModule = nullptr;
460 if (found)
461 SAL_INFO("xmlsecurity.xmlsec", "Added new root certificate module " ROOT_CERTS " contained in " << ospath);
462 else
463 {
464 SAL_INFO("xmlsecurity.xmlsec", "FAILED to load the new root certificate module " ROOT_CERTS "contained in " << ospath);
465 return_value = false;
466 }
467 }
468 else
469 {
470 SAL_INFO("xmlsecurity.xmlsec", "FAILED to add new root certificate module " ROOT_CERTS " contained in " << ospath);
471 return_value = false;
472
473 }
474 }
475 else
476 {
477 SAL_INFO("xmlsecurity.xmlsec", "Adding new root certificate module failed.");
478 return_value = false;
479 }
480 }
481
482 return return_value;
483 #else
484 return true;
485 #endif
486 }
487
488 } // namespace
489
490 // must be extern "C" because we pass the function pointer to atexit
nsscrypto_finalize()491 extern "C" void nsscrypto_finalize()
492 {
493 SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS);
494
495 if (RootsModule)
496 {
497
498 if (SECSuccess == SECMOD_UnloadUserModule(RootsModule))
499 {
500 SAL_INFO("xmlsecurity.xmlsec", "Unloaded module \"" ROOT_CERTS "\".");
501 }
502 else
503 {
504 SAL_INFO("xmlsecurity.xmlsec", "Failed unloading module \"" ROOT_CERTS "\".");
505 }
506 SECMOD_DestroyModule(RootsModule);
507 }
508 else
509 {
510 SAL_INFO("xmlsecurity.xmlsec", "Unloading module \"" ROOT_CERTS "\" failed because it was not found.");
511 }
512 PK11_LogoutAll();
513 (void)NSS_Shutdown();
514
515 (*getInitNSSPrivate())->reset();
516 }
517
518
~ONSSInitializer()519 ONSSInitializer::~ONSSInitializer()
520 {
521 }
522
initNSS(const css::uno::Reference<css::uno::XComponentContext> & rxContext)523 bool ONSSInitializer::initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext )
524 {
525 static bool gbInitialized = [&rxContext]()
526 {
527 bool bNSSInit = false;
528 bool bInitialized = nsscrypto_initialize( rxContext, bNSSInit );
529 if (bNSSInit)
530 atexit(nsscrypto_finalize);
531 return bInitialized;
532 }();
533 return gbInitialized;
534 }
535
getDigestContext(::sal_Int32 nDigestID,const css::uno::Sequence<css::beans::NamedValue> & aParams)536 css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams )
537 {
538 SECOidTag nNSSDigestID = SEC_OID_UNKNOWN;
539 sal_Int32 nDigestLength = 0;
540 bool b1KData = false;
541 if ( nDigestID == css::xml::crypto::DigestID::SHA256
542 || nDigestID == css::xml::crypto::DigestID::SHA256_1K )
543 {
544 nNSSDigestID = SEC_OID_SHA256;
545 nDigestLength = 32;
546 b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K );
547 }
548 else if ( nDigestID == css::xml::crypto::DigestID::SHA1
549 || nDigestID == css::xml::crypto::DigestID::SHA1_1K )
550 {
551 nNSSDigestID = SEC_OID_SHA1;
552 nDigestLength = 20;
553 b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K );
554 }
555 else if ( nDigestID == css::xml::crypto::DigestID::SHA512
556 || nDigestID == css::xml::crypto::DigestID::SHA512_1K )
557 {
558 nNSSDigestID = SEC_OID_SHA512;
559 nDigestLength = 64;
560 b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA512_1K );
561 }
562 else
563 throw css::lang::IllegalArgumentException("Unexpected digest requested.", css::uno::Reference< css::uno::XInterface >(), 1 );
564
565 if ( aParams.hasElements() )
566 throw css::lang::IllegalArgumentException("Unexpected arguments provided for digest creation.", css::uno::Reference< css::uno::XInterface >(), 2 );
567
568 css::uno::Reference< css::xml::crypto::XDigestContext > xResult;
569 if( initNSS( m_xContext ) )
570 {
571 PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID );
572 if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess )
573 xResult = new ODigestContext( pContext, nDigestLength, b1KData );
574 }
575
576 return xResult;
577 }
578
getCipherContext(::sal_Int32 nCipherID,const css::uno::Sequence<::sal_Int8> & aKey,const css::uno::Sequence<::sal_Int8> & aInitializationVector,sal_Bool bEncryption,const css::uno::Sequence<css::beans::NamedValue> & aParams)579 css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams )
580 {
581 CK_MECHANISM_TYPE nNSSCipherID = 0;
582 bool bW3CPadding = false;
583 if ( nCipherID != css::xml::crypto::CipherID::AES_CBC_W3C_PADDING )
584 throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1 );
585
586 nNSSCipherID = CKM_AES_CBC;
587 bW3CPadding = true;
588
589 if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 )
590 throw css::lang::IllegalArgumentException("Unexpected key length.", css::uno::Reference< css::uno::XInterface >(), 2 );
591
592 if ( aParams.hasElements() )
593 throw css::lang::IllegalArgumentException("Unexpected arguments provided for cipher creation.", css::uno::Reference< css::uno::XInterface >(), 5 );
594
595 css::uno::Reference< css::xml::crypto::XCipherContext > xResult;
596 if( initNSS( m_xContext ) )
597 {
598 if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) )
599 throw css::lang::IllegalArgumentException("Unexpected length of initialization vector.", css::uno::Reference< css::uno::XInterface >(), 3 );
600
601 xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding );
602 }
603
604 return xResult;
605 }
606
607 /* XServiceInfo */
getImplementationName()608 OUString SAL_CALL ONSSInitializer::getImplementationName()
609 {
610 return "com.sun.star.xml.crypto.NSSInitializer";
611 }
612
supportsService(const OUString & rServiceName)613 sal_Bool SAL_CALL ONSSInitializer::supportsService( const OUString& rServiceName )
614 {
615 return cppu::supportsService(this, rServiceName);
616 }
617
getSupportedServiceNames()618 cssu::Sequence< OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames( )
619 {
620 return { NSS_SERVICE_NAME };
621 }
622
623 #ifndef XMLSEC_CRYPTO_NSS
624 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_xml_crypto_NSSInitializer_get_implementation(uno::XComponentContext * pCtx,uno::Sequence<uno::Any> const &)625 com_sun_star_xml_crypto_NSSInitializer_get_implementation(
626 uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
627 {
628 return cppu::acquire(new ONSSInitializer(pCtx));
629 }
630 #endif
631
632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
633