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