xref: /trunk/main/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx (revision a5b190bfa3e1bed4623e2958a8877664a3b5506c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_xmlsecurity.hxx"
31 
32 //todo before commit:  nssrenam.h is not delivered!!!
33 #ifndef __nssrenam_h_
34 #define CERT_NewTempCertificate __CERT_NewTempCertificate
35 #endif /* __nssrenam_h_ */
36 
37 #include "cert.h"
38 #include "secerr.h"
39 #include "ocsp.h"
40 
41 #include <sal/config.h>
42 #include "securityenvironment_nssimpl.hxx"
43 #include "x509certificate_nssimpl.hxx"
44 #include <rtl/uuid.h>
45 #include "../diagnose.hxx"
46 
47 #include <sal/types.h>
48 //For reasons that escape me, this is what xmlsec does when size_t is not 4
49 #if SAL_TYPES_SIZEOFPOINTER != 4
50 #    define XMLSEC_NO_SIZE_T
51 #endif
52 #include <xmlsec/xmlsec.h>
53 #include <xmlsec/keysmngr.h>
54 #include <xmlsec/crypto.h>
55 #include <xmlsec/base64.h>
56 #include <xmlsec/strings.h>
57 
58 #include <tools/string.hxx>
59 #include <rtl/ustrbuf.hxx>
60 #include <comphelper/processfactory.hxx>
61 #include <cppuhelper/servicefactory.hxx>
62 #include <comphelper/docpasswordrequest.hxx>
63 #include <xmlsecurity/biginteger.hxx>
64 #include <rtl/logfile.h>
65 #include <com/sun/star/task/XInteractionHandler.hpp>
66 #include <vector>
67 #include "boost/scoped_array.hpp"
68 
69 #include "secerror.hxx"
70 
71 // MM : added for password exception
72 #include <com/sun/star/security/NoPasswordException.hpp>
73 namespace csss = ::com::sun::star::security;
74 using namespace xmlsecurity;
75 using namespace ::com::sun::star::security;
76 using namespace com::sun::star;
77 using namespace ::com::sun::star::uno ;
78 using namespace ::com::sun::star::lang ;
79 using ::com::sun::star::lang::XMultiServiceFactory ;
80 using ::com::sun::star::lang::XSingleServiceFactory ;
81 using ::rtl::OUString ;
82 
83 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
84 using ::com::sun::star::security::XCertificate ;
85 
86 extern X509Certificate_NssImpl* NssCertToXCert( CERTCertificate* cert ) ;
87 extern X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* ) ;
88 
89 
90 struct UsageDescription
91 {
92     SECCertificateUsage usage;
93     char const* description;
94 
95     UsageDescription()
96     : usage( certificateUsageCheckAllUsages )
97     , description( NULL )
98     {}
99 
100     UsageDescription( SECCertificateUsage i_usage, char const* i_description )
101     : usage( i_usage )
102     , description( i_description )
103     {}
104 
105     UsageDescription( const UsageDescription& aDescription )
106     : usage( aDescription.usage )
107     , description( aDescription.description )
108     {}
109 
110     UsageDescription& operator =( const UsageDescription& aDescription )
111     {
112         usage = aDescription.usage;
113         description = aDescription.description;
114         return *this;
115     }
116 };
117 
118 
119 
120 char* GetPasswordFunction( PK11SlotInfo* pSlot, PRBool bRetry, void* /*arg*/ )
121 {
122     uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() );
123     if ( xMSF.is() )
124     {
125         uno::Reference < task::XInteractionHandler > xInteractionHandler(
126             xMSF->createInstance( rtl::OUString::createFromAscii("com.sun.star.task.InteractionHandler") ), uno::UNO_QUERY );
127 
128         if ( xInteractionHandler.is() )
129         {
130             task::PasswordRequestMode eMode = bRetry ? task::PasswordRequestMode_PASSWORD_REENTER : task::PasswordRequestMode_PASSWORD_ENTER;
131             ::comphelper::DocPasswordRequest* pPasswordRequest = new ::comphelper::DocPasswordRequest(
132                 ::comphelper::DocPasswordRequestType_STANDARD, eMode, ::rtl::OUString::createFromAscii(PK11_GetTokenName(pSlot)) );
133 
134             uno::Reference< task::XInteractionRequest > xRequest( pPasswordRequest );
135             xInteractionHandler->handle( xRequest );
136 
137             if ( pPasswordRequest->isPassword() )
138             {
139                 ByteString aPassword = ByteString( String( pPasswordRequest->getPassword() ), gsl_getSystemTextEncoding() );
140                 sal_uInt16 nLen = aPassword.Len();
141                 char* pPassword = (char*) PORT_Alloc( nLen+1 ) ;
142                 pPassword[nLen] = 0;
143                 memcpy( pPassword, aPassword.GetBuffer(), nLen );
144                 return pPassword;
145             }
146         }
147     }
148     return NULL;
149 }
150 
151 SecurityEnvironment_NssImpl :: SecurityEnvironment_NssImpl( const Reference< XMultiServiceFactory >& ) :
152 m_pHandler( NULL ) , m_tSymKeyList() , m_tPubKeyList() , m_tPriKeyList() {
153 
154     PK11_SetPasswordFunc( GetPasswordFunction ) ;
155 }
156 
157 SecurityEnvironment_NssImpl :: ~SecurityEnvironment_NssImpl() {
158 
159     PK11_SetPasswordFunc( NULL ) ;
160 
161     for (CIT_SLOTS i = m_Slots.begin(); i != m_Slots.end(); i++)
162     {
163         PK11_FreeSlot(*i);
164     }
165 
166     if( !m_tSymKeyList.empty()  ) {
167         std::list< PK11SymKey* >::iterator symKeyIt ;
168 
169         for( symKeyIt = m_tSymKeyList.begin() ; symKeyIt != m_tSymKeyList.end() ; symKeyIt ++ )
170             PK11_FreeSymKey( *symKeyIt ) ;
171     }
172 
173     if( !m_tPubKeyList.empty()  ) {
174         std::list< SECKEYPublicKey* >::iterator pubKeyIt ;
175 
176         for( pubKeyIt = m_tPubKeyList.begin() ; pubKeyIt != m_tPubKeyList.end() ; pubKeyIt ++ )
177             SECKEY_DestroyPublicKey( *pubKeyIt ) ;
178     }
179 
180     if( !m_tPriKeyList.empty()  ) {
181         std::list< SECKEYPrivateKey* >::iterator priKeyIt ;
182 
183         for( priKeyIt = m_tPriKeyList.begin() ; priKeyIt != m_tPriKeyList.end() ; priKeyIt ++ )
184             SECKEY_DestroyPrivateKey( *priKeyIt ) ;
185     }
186 }
187 
188 /* XInitialization */
189 void SAL_CALL SecurityEnvironment_NssImpl :: initialize( const Sequence< Any >& ) throw( Exception, RuntimeException ) {
190     // TBD
191 } ;
192 
193 /* XServiceInfo */
194 OUString SAL_CALL SecurityEnvironment_NssImpl :: getImplementationName() throw( RuntimeException ) {
195     return impl_getImplementationName() ;
196 }
197 
198 /* XServiceInfo */
199 sal_Bool SAL_CALL SecurityEnvironment_NssImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) {
200     Sequence< OUString > seqServiceNames = getSupportedServiceNames() ;
201     const OUString* pArray = seqServiceNames.getConstArray() ;
202     for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) {
203         if( *( pArray + i ) == serviceName )
204             return sal_True ;
205     }
206     return sal_False ;
207 }
208 
209 /* XServiceInfo */
210 Sequence< OUString > SAL_CALL SecurityEnvironment_NssImpl :: getSupportedServiceNames() throw( RuntimeException ) {
211     return impl_getSupportedServiceNames() ;
212 }
213 
214 //Helper for XServiceInfo
215 Sequence< OUString > SecurityEnvironment_NssImpl :: impl_getSupportedServiceNames() {
216     ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
217     Sequence< OUString > seqServiceNames( 1 ) ;
218     seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.SecurityEnvironment" ) ;
219     return seqServiceNames ;
220 }
221 
222 OUString SecurityEnvironment_NssImpl :: impl_getImplementationName() throw( RuntimeException ) {
223     return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.SecurityEnvironment_NssImpl" ) ;
224 }
225 
226 //Helper for registry
227 Reference< XInterface > SAL_CALL SecurityEnvironment_NssImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) {
228     return Reference< XInterface >( *new SecurityEnvironment_NssImpl( aServiceManager ) ) ;
229 }
230 
231 Reference< XSingleServiceFactory > SecurityEnvironment_NssImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) {
232     //Reference< XSingleServiceFactory > xFactory ;
233     //xFactory = ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName , impl_createInstance , impl_getSupportedServiceNames ) ;
234     //return xFactory ;
235     return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ;
236 }
237 
238 /* XUnoTunnel */
239 sal_Int64 SAL_CALL SecurityEnvironment_NssImpl :: getSomething( const Sequence< sal_Int8 >& aIdentifier )
240     throw( RuntimeException )
241 {
242     if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) {
243         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this));
244     }
245     return 0 ;
246 }
247 
248 /* XUnoTunnel extension */
249 const Sequence< sal_Int8>& SecurityEnvironment_NssImpl :: getUnoTunnelId() {
250     static Sequence< sal_Int8 >* pSeq = 0 ;
251     if( !pSeq ) {
252         ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
253         if( !pSeq ) {
254             static Sequence< sal_Int8> aSeq( 16 ) ;
255             rtl_createUuid( ( sal_uInt8* )aSeq.getArray() , 0 , sal_True ) ;
256             pSeq = &aSeq ;
257         }
258     }
259     return *pSeq ;
260 }
261 
262 /* XUnoTunnel extension */
263 SecurityEnvironment_NssImpl* SecurityEnvironment_NssImpl :: getImplementation( const Reference< XInterface > xObj ) {
264     Reference< XUnoTunnel > xUT( xObj , UNO_QUERY ) ;
265     if( xUT.is() ) {
266         return reinterpret_cast<SecurityEnvironment_NssImpl*>(
267             sal::static_int_cast<sal_uIntPtr>(xUT->getSomething( getUnoTunnelId() ))) ;
268     } else
269         return NULL ;
270 }
271 
272 
273 ::rtl::OUString SecurityEnvironment_NssImpl::getSecurityEnvironmentInformation() throw( ::com::sun::star::uno::RuntimeException )
274 {
275     rtl::OUString result;
276     ::rtl::OUStringBuffer buff;
277     for (CIT_SLOTS is = m_Slots.begin(); is != m_Slots.end(); is++)
278     {
279         buff.append(rtl::OUString::createFromAscii(PK11_GetTokenName(*is)));
280         buff.appendAscii("\n");
281     }
282     return buff.makeStringAndClear();
283 }
284 
285 void SecurityEnvironment_NssImpl::addCryptoSlot( PK11SlotInfo* aSlot) throw( Exception , RuntimeException )
286 {
287     PK11_ReferenceSlot(aSlot);
288     m_Slots.push_back(aSlot);
289 }
290 
291 CERTCertDBHandle* SecurityEnvironment_NssImpl :: getCertDb() throw( Exception , RuntimeException ) {
292     return m_pHandler ;
293 }
294 
295 //Could we have multiple cert dbs?
296 void SecurityEnvironment_NssImpl :: setCertDb( CERTCertDBHandle* aCertDb ) throw( Exception , RuntimeException ) {
297     m_pHandler = aCertDb ;
298 }
299 
300 void SecurityEnvironment_NssImpl :: adoptSymKey( PK11SymKey* aSymKey ) throw( Exception , RuntimeException ) {
301     PK11SymKey* symkey ;
302     std::list< PK11SymKey* >::iterator keyIt ;
303 
304     if( aSymKey != NULL ) {
305         //First try to find the key in the list
306         for( keyIt = m_tSymKeyList.begin() ; keyIt != m_tSymKeyList.end() ; keyIt ++ ) {
307             if( *keyIt == aSymKey )
308                 return ;
309         }
310 
311         //If we do not find the key in the list, add a new node
312         symkey = PK11_ReferenceSymKey( aSymKey ) ;
313         if( symkey == NULL )
314             throw RuntimeException() ;
315 
316         try {
317             m_tSymKeyList.push_back( symkey ) ;
318         } catch ( Exception& ) {
319             PK11_FreeSymKey( symkey ) ;
320         }
321     }
322 }
323 
324 void SecurityEnvironment_NssImpl :: rejectSymKey( PK11SymKey* aSymKey ) throw( Exception , RuntimeException ) {
325     PK11SymKey* symkey ;
326     std::list< PK11SymKey* >::iterator keyIt ;
327 
328     if( aSymKey != NULL ) {
329         for( keyIt = m_tSymKeyList.begin() ; keyIt != m_tSymKeyList.end() ; keyIt ++ ) {
330             if( *keyIt == aSymKey ) {
331                 symkey = *keyIt ;
332                 PK11_FreeSymKey( symkey ) ;
333                 m_tSymKeyList.erase( keyIt ) ;
334                 break ;
335             }
336         }
337     }
338 }
339 
340 PK11SymKey* SecurityEnvironment_NssImpl :: getSymKey( unsigned int position ) throw( Exception , RuntimeException ) {
341     PK11SymKey* symkey ;
342     std::list< PK11SymKey* >::iterator keyIt ;
343     unsigned int pos ;
344 
345     symkey = NULL ;
346     for( pos = 0, keyIt = m_tSymKeyList.begin() ; pos < position && keyIt != m_tSymKeyList.end() ; pos ++ , keyIt ++ ) ;
347 
348     if( pos == position && keyIt != m_tSymKeyList.end() )
349         symkey = *keyIt ;
350 
351     return symkey ;
352 }
353 
354 void SecurityEnvironment_NssImpl :: adoptPubKey( SECKEYPublicKey* aPubKey ) throw( Exception , RuntimeException ) {
355     SECKEYPublicKey*    pubkey ;
356     std::list< SECKEYPublicKey* >::iterator keyIt ;
357 
358     if( aPubKey != NULL ) {
359         //First try to find the key in the list
360         for( keyIt = m_tPubKeyList.begin() ; keyIt != m_tPubKeyList.end() ; keyIt ++ ) {
361             if( *keyIt == aPubKey )
362                 return ;
363         }
364 
365         //If we do not find the key in the list, add a new node
366         pubkey = SECKEY_CopyPublicKey( aPubKey ) ;
367         if( pubkey == NULL )
368             throw RuntimeException() ;
369 
370         try {
371             m_tPubKeyList.push_back( pubkey ) ;
372         } catch ( Exception& ) {
373             SECKEY_DestroyPublicKey( pubkey ) ;
374         }
375     }
376 }
377 
378 void SecurityEnvironment_NssImpl :: rejectPubKey( SECKEYPublicKey* aPubKey ) throw( Exception , RuntimeException ) {
379     SECKEYPublicKey*    pubkey ;
380     std::list< SECKEYPublicKey* >::iterator keyIt ;
381 
382     if( aPubKey != NULL ) {
383         for( keyIt = m_tPubKeyList.begin() ; keyIt != m_tPubKeyList.end() ; keyIt ++ ) {
384             if( *keyIt == aPubKey ) {
385                 pubkey = *keyIt ;
386                 SECKEY_DestroyPublicKey( pubkey ) ;
387                 m_tPubKeyList.erase( keyIt ) ;
388                 break ;
389             }
390         }
391     }
392 }
393 
394 SECKEYPublicKey* SecurityEnvironment_NssImpl :: getPubKey( unsigned int position ) throw( Exception , RuntimeException ) {
395     SECKEYPublicKey* pubkey ;
396     std::list< SECKEYPublicKey* >::iterator keyIt ;
397     unsigned int pos ;
398 
399     pubkey = NULL ;
400     for( pos = 0, keyIt = m_tPubKeyList.begin() ; pos < position && keyIt != m_tPubKeyList.end() ; pos ++ , keyIt ++ ) ;
401 
402     if( pos == position && keyIt != m_tPubKeyList.end() )
403         pubkey = *keyIt ;
404 
405     return pubkey ;
406 }
407 
408 void SecurityEnvironment_NssImpl :: adoptPriKey( SECKEYPrivateKey* aPriKey ) throw( Exception , RuntimeException ) {
409     SECKEYPrivateKey*   prikey ;
410     std::list< SECKEYPrivateKey* >::iterator keyIt ;
411 
412     if( aPriKey != NULL ) {
413         //First try to find the key in the list
414         for( keyIt = m_tPriKeyList.begin() ; keyIt != m_tPriKeyList.end() ; keyIt ++ ) {
415             if( *keyIt == aPriKey )
416                 return ;
417         }
418 
419         //If we do not find the key in the list, add a new node
420         prikey = SECKEY_CopyPrivateKey( aPriKey ) ;
421         if( prikey == NULL )
422             throw RuntimeException() ;
423 
424         try {
425             m_tPriKeyList.push_back( prikey ) ;
426         } catch ( Exception& ) {
427             SECKEY_DestroyPrivateKey( prikey ) ;
428         }
429     }
430 }
431 
432 void SecurityEnvironment_NssImpl :: rejectPriKey( SECKEYPrivateKey* aPriKey ) throw( Exception , RuntimeException ) {
433     SECKEYPrivateKey*   prikey ;
434     std::list< SECKEYPrivateKey* >::iterator keyIt ;
435 
436     if( aPriKey != NULL ) {
437         for( keyIt = m_tPriKeyList.begin() ; keyIt != m_tPriKeyList.end() ; keyIt ++ ) {
438             if( *keyIt == aPriKey ) {
439                 prikey = *keyIt ;
440                 SECKEY_DestroyPrivateKey( prikey ) ;
441                 m_tPriKeyList.erase( keyIt ) ;
442                 break ;
443             }
444         }
445     }
446 }
447 
448 SECKEYPrivateKey* SecurityEnvironment_NssImpl :: getPriKey( unsigned int position ) throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException )  {
449     SECKEYPrivateKey* prikey ;
450     std::list< SECKEYPrivateKey* >::iterator keyIt ;
451     unsigned int pos ;
452 
453     prikey = NULL ;
454     for( pos = 0, keyIt = m_tPriKeyList.begin() ; pos < position && keyIt != m_tPriKeyList.end() ; pos ++ , keyIt ++ ) ;
455 
456     if( pos == position && keyIt != m_tPriKeyList.end() )
457         prikey = *keyIt ;
458 
459     return prikey ;
460 }
461 
462 void SecurityEnvironment_NssImpl::updateSlots()
463 {
464     //In case new tokens are present then we can obtain the corresponding slot
465     PK11SlotList * soltList = NULL;
466     PK11SlotListElement * soltEle = NULL;
467     PK11SlotInfo * pSlot = NULL;
468     PK11SymKey * pSymKey = NULL;
469 
470     osl::MutexGuard guard(m_mutex);
471 
472     m_Slots.clear();
473     m_tSymKeyList.clear();
474 
475     soltList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL ) ;
476     if( soltList != NULL )
477     {
478         for( soltEle = soltList->head ; soltEle != NULL; soltEle = soltEle->next )
479         {
480             pSlot = soltEle->slot ;
481 
482             if(pSlot != NULL)
483             {
484                 RTL_LOGFILE_TRACE2( "XMLSEC: Found a slot: SlotName=%s, TokenName=%s", PK11_GetSlotName(pSlot), PK11_GetTokenName(pSlot) );
485 
486 //The following code which is commented out checks if a slot, that is a smart card for example, is
487 //              able to generate a symmetric key of type CKM_DES3_CBC. If this fails then this token
488 //              will not be used. This key is possibly used for the encryption service. However, all
489 //              interfaces and services used for public key signature and encryption are not published
490 //              and the encryption is not used in OOo. Therefore it does not do any harm to remove
491 //              this code, hence allowing smart cards which cannot generate this type of key.
492 //
493 //              By doing this, the encryption may fail if a smart card is being used which does not
494 //              support this key generation.
495 //
496                 pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC, NULL, 128, NULL ) ;
497 //              if( pSymKey == NULL )
498 //              {
499 //                  PK11_FreeSlot( pSlot ) ;
500 //                  RTL_LOGFILE_TRACE( "XMLSEC: Error - pSymKey is NULL" );
501 //                  continue;
502 //              }
503                 addCryptoSlot(pSlot);
504                 PK11_FreeSlot( pSlot ) ;
505                 pSlot = NULL;
506 
507                 if (pSymKey != NULL)
508                 {
509                     adoptSymKey( pSymKey ) ;
510                     PK11_FreeSymKey( pSymKey ) ;
511                     pSymKey = NULL;
512                 }
513 
514             }// end of if(pSlot != NULL)
515         }// end of for
516     }// end of if( soltList != NULL )
517 
518 }
519 
520 
521 Sequence< Reference < XCertificate > >
522 SecurityEnvironment_NssImpl::getPersonalCertificates() throw( SecurityException , RuntimeException )
523 {
524     sal_Int32 length ;
525     X509Certificate_NssImpl* xcert ;
526     std::list< X509Certificate_NssImpl* > certsList ;
527 
528     updateSlots();
529     //firstly, we try to find private keys in slot
530     for (CIT_SLOTS is = m_Slots.begin(); is != m_Slots.end(); is++)
531     {
532         PK11SlotInfo *slot = *is;
533         SECKEYPrivateKeyList* priKeyList ;
534         SECKEYPrivateKeyListNode* curPri ;
535 
536         if( PK11_NeedLogin(slot ) ) {
537             SECStatus nRet = PK11_Authenticate(slot, PR_TRUE, NULL);
538             //PK11_Authenticate may fail in case the a slot has not been initialized.
539             //this is the case if the user has a new profile, so that they have never
540             //added a personal certificate.
541             if( nRet != SECSuccess && PORT_GetError() != SEC_ERROR_IO) {
542                 throw NoPasswordException();
543             }
544         }
545 
546         priKeyList = PK11_ListPrivateKeysInSlot(slot) ;
547         if( priKeyList != NULL ) {
548             for( curPri = PRIVKEY_LIST_HEAD( priKeyList );
549                 !PRIVKEY_LIST_END( curPri, priKeyList ) && curPri != NULL ;
550                 curPri = PRIVKEY_LIST_NEXT( curPri ) ) {
551                 xcert = NssPrivKeyToXCert( curPri->key ) ;
552                 if( xcert != NULL )
553                     certsList.push_back( xcert ) ;
554             }
555         }
556 
557         SECKEY_DestroyPrivateKeyList( priKeyList ) ;
558     }
559 
560     //secondly, we try to find certificate from registered private keys.
561     if( !m_tPriKeyList.empty()  ) {
562         std::list< SECKEYPrivateKey* >::iterator priKeyIt ;
563 
564         for( priKeyIt = m_tPriKeyList.begin() ; priKeyIt != m_tPriKeyList.end() ; priKeyIt ++ ) {
565             xcert = NssPrivKeyToXCert( *priKeyIt ) ;
566             if( xcert != NULL )
567                 certsList.push_back( xcert ) ;
568         }
569     }
570 
571     length = certsList.size() ;
572     if( length != 0 ) {
573         int i ;
574         std::list< X509Certificate_NssImpl* >::iterator xcertIt ;
575         Sequence< Reference< XCertificate > > certSeq( length ) ;
576 
577         for( i = 0, xcertIt = certsList.begin(); xcertIt != certsList.end(); xcertIt ++, i++ ) {
578             certSeq[i] = *xcertIt ;
579         }
580 
581         return certSeq ;
582     }
583 
584     return Sequence< Reference < XCertificate > > ();
585 }
586 
587 Reference< XCertificate > SecurityEnvironment_NssImpl :: getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& serialNumber ) throw( SecurityException , RuntimeException )
588 {
589     X509Certificate_NssImpl* xcert = NULL;
590 
591     if( m_pHandler != NULL ) {
592         CERTIssuerAndSN issuerAndSN ;
593         CERTCertificate* cert ;
594         CERTName* nmIssuer ;
595         char* chIssuer ;
596         SECItem* derIssuer ;
597         PRArenaPool* arena ;
598 
599         arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE ) ;
600         if( arena == NULL )
601             throw RuntimeException() ;
602 
603                 /*
604                  * mmi : because MS Crypto use the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise
605                  *      it, so the 'S' tag should be changed to 'ST' tag
606                  *
607                  * PS  : it can work, but inside libxmlsec, the 'S' tag is till used to find cert in NSS engine, so it
608                  *       is not useful at all. (comment out now)
609                  */
610 
611                 /*
612                 sal_Int32 nIndex = 0;
613                 OUString newIssuerName;
614                 do
615                 {
616                     OUString aToken = issuerName.getToken( 0, ',', nIndex ).trim();
617                     if (aToken.compareToAscii("S=",2) == 0)
618                     {
619                         newIssuerName+=OUString::createFromAscii("ST=");
620                         newIssuerName+=aToken.copy(2);
621                     }
622                     else
623                     {
624                         newIssuerName+=aToken;
625                     }
626 
627                     if (nIndex >= 0)
628                     {
629                         newIssuerName+=OUString::createFromAscii(",");
630                     }
631                 } while ( nIndex >= 0 );
632                 */
633 
634                 /* end */
635 
636         //Create cert info from issue and serial
637         rtl::OString ostr = rtl::OUStringToOString( issuerName , RTL_TEXTENCODING_UTF8 ) ;
638         chIssuer = PL_strndup( ( char* )ostr.getStr(), ( int )ostr.getLength() ) ;
639         nmIssuer = CERT_AsciiToName( chIssuer ) ;
640         if( nmIssuer == NULL ) {
641             PL_strfree( chIssuer ) ;
642             PORT_FreeArena( arena, PR_FALSE ) ;
643 
644             /*
645              * i40394
646              *
647              * mmi : no need to throw exception
648              *       just return "no found"
649              */
650             //throw RuntimeException() ;
651             return NULL;
652         }
653 
654         derIssuer = SEC_ASN1EncodeItem( arena, NULL, ( void* )nmIssuer, SEC_ASN1_GET( CERT_NameTemplate ) ) ;
655         if( derIssuer == NULL ) {
656             PL_strfree( chIssuer ) ;
657             CERT_DestroyName( nmIssuer ) ;
658             PORT_FreeArena( arena, PR_FALSE ) ;
659             throw RuntimeException() ;
660         }
661 
662         memset( &issuerAndSN, 0, sizeof( issuerAndSN ) ) ;
663 
664         issuerAndSN.derIssuer.data = derIssuer->data ;
665         issuerAndSN.derIssuer.len = derIssuer->len ;
666 
667         issuerAndSN.serialNumber.data = ( unsigned char* )&serialNumber[0] ;
668         issuerAndSN.serialNumber.len = serialNumber.getLength() ;
669 
670         cert = CERT_FindCertByIssuerAndSN( m_pHandler, &issuerAndSN ) ;
671         if( cert != NULL ) {
672             xcert = NssCertToXCert( cert ) ;
673         } else {
674             xcert = NULL ;
675         }
676 
677         PL_strfree( chIssuer ) ;
678         CERT_DestroyName( nmIssuer ) ;
679         //SECITEM_FreeItem( derIssuer, PR_FALSE ) ;
680         CERT_DestroyCertificate( cert ) ;
681         PORT_FreeArena( arena, PR_FALSE ) ;
682     } else {
683         xcert = NULL ;
684     }
685 
686     return xcert ;
687 }
688 
689 Reference< XCertificate > SecurityEnvironment_NssImpl :: getCertificate( const OUString& issuerName, const OUString& serialNumber ) throw( SecurityException , RuntimeException ) {
690     Sequence< sal_Int8 > serial = numericStringToBigInteger( serialNumber ) ;
691     return getCertificate( issuerName, serial ) ;
692 }
693 
694 Sequence< Reference < XCertificate > > SecurityEnvironment_NssImpl :: buildCertificatePath( const Reference< XCertificate >& begin ) throw( SecurityException , RuntimeException ) {
695     const X509Certificate_NssImpl* xcert ;
696     const CERTCertificate* cert ;
697     CERTCertList* certChain ;
698 
699     Reference< XUnoTunnel > xCertTunnel( begin, UNO_QUERY ) ;
700     if( !xCertTunnel.is() ) {
701         throw RuntimeException() ;
702     }
703 
704     xcert = reinterpret_cast<X509Certificate_NssImpl*>(
705         sal::static_int_cast<sal_uIntPtr>(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ;
706     if( xcert == NULL ) {
707         throw RuntimeException() ;
708     }
709 
710     cert = xcert->getNssCert() ;
711     if( cert != NULL ) {
712         int64 timeboundary ;
713 
714         //Get the system clock time
715         timeboundary = PR_Now() ;
716 
717         certChain = CERT_GetCertChainFromCert( ( CERTCertificate* )cert, timeboundary, certUsageAnyCA ) ;
718     } else {
719         certChain = NULL ;
720     }
721 
722     if( certChain != NULL ) {
723         X509Certificate_NssImpl* pCert ;
724         CERTCertListNode* node ;
725         int len ;
726 
727         for( len = 0, node = CERT_LIST_HEAD( certChain ); !CERT_LIST_END( node, certChain ); node = CERT_LIST_NEXT( node ), len ++ ) ;
728         Sequence< Reference< XCertificate > > xCertChain( len ) ;
729 
730         for( len = 0, node = CERT_LIST_HEAD( certChain ); !CERT_LIST_END( node, certChain ); node = CERT_LIST_NEXT( node ), len ++ ) {
731             pCert = new X509Certificate_NssImpl() ;
732             if( pCert == NULL ) {
733                 CERT_DestroyCertList( certChain ) ;
734                 throw RuntimeException() ;
735             }
736 
737             pCert->setCert( node->cert ) ;
738 
739             xCertChain[len] = pCert ;
740         }
741 
742         CERT_DestroyCertList( certChain ) ;
743 
744         return xCertChain ;
745     }
746 
747     return Sequence< Reference < XCertificate > >();
748 }
749 
750 Reference< XCertificate > SecurityEnvironment_NssImpl :: createCertificateFromRaw( const Sequence< sal_Int8 >& rawCertificate ) throw( SecurityException , RuntimeException ) {
751     X509Certificate_NssImpl* xcert ;
752 
753     if( rawCertificate.getLength() > 0 ) {
754         xcert = new X509Certificate_NssImpl() ;
755         if( xcert == NULL )
756             throw RuntimeException() ;
757 
758         xcert->setRawCert( rawCertificate ) ;
759     } else {
760         xcert = NULL ;
761     }
762 
763     return xcert ;
764 }
765 
766 Reference< XCertificate > SecurityEnvironment_NssImpl :: createCertificateFromAscii( const OUString& asciiCertificate ) throw( SecurityException , RuntimeException ) {
767     xmlChar* chCert ;
768     xmlSecSize certSize ;
769 
770     rtl::OString oscert = rtl::OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ;
771 
772     chCert = xmlStrndup( ( const xmlChar* )oscert.getStr(), ( int )oscert.getLength() ) ;
773 
774     certSize = xmlSecBase64Decode( chCert, ( xmlSecByte* )chCert, xmlStrlen( chCert ) ) ;
775 
776     Sequence< sal_Int8 > rawCert( certSize ) ;
777     for( unsigned int i = 0 ; i < certSize ; i ++ )
778         rawCert[i] = *( chCert + i ) ;
779 
780     xmlFree( chCert ) ;
781 
782     return createCertificateFromRaw( rawCert ) ;
783 }
784 
785 sal_Int32 SecurityEnvironment_NssImpl ::
786 verifyCertificate( const Reference< csss::XCertificate >& aCert,
787                    const Sequence< Reference< csss::XCertificate > >&  intermediateCerts )
788     throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException )
789 {
790     sal_Int32 validity = csss::CertificateValidity::INVALID;
791     const X509Certificate_NssImpl* xcert ;
792     const CERTCertificate* cert ;
793     ::std::vector<CERTCertificate*> vecTmpNSSCertificates;
794     Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ;
795     if( !xCertTunnel.is() ) {
796         throw RuntimeException() ;
797     }
798 
799     xmlsec_trace("Start verification of certificate: \n %s \n",
800               OUStringToOString(
801                   aCert->getSubjectName(), osl_getThreadTextEncoding()).getStr());
802 
803     xcert = reinterpret_cast<X509Certificate_NssImpl*>(
804        sal::static_int_cast<sal_uIntPtr>(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ;
805     if( xcert == NULL ) {
806         throw RuntimeException() ;
807     }
808 
809     //CERT_PKIXVerifyCert does not take a db as argument. It will therefore
810     //internally use CERT_GetDefaultCertDB
811     //Make sure m_pHandler is the default DB
812     OSL_ASSERT(m_pHandler == CERT_GetDefaultCertDB());
813     CERTCertDBHandle * certDb = m_pHandler != NULL ? m_pHandler : CERT_GetDefaultCertDB();
814     cert = xcert->getNssCert() ;
815     if( cert != NULL )
816     {
817 
818         //prepare the intermediate certificates
819         for (sal_Int32 i = 0; i < intermediateCerts.getLength(); i++)
820         {
821             Sequence<sal_Int8> der = intermediateCerts[i]->getEncoded();
822             SECItem item;
823             item.type = siBuffer;
824             item.data = (unsigned char*)der.getArray();
825             item.len = der.getLength();
826 
827             CERTCertificate* certTmp = CERT_NewTempCertificate(certDb, &item,
828                                            NULL     /* nickname */,
829                                            PR_FALSE /* isPerm */,
830                                            PR_TRUE  /* copyDER */);
831              if (!certTmp)
832              {
833                  xmlsec_trace("Failed to add a temporary certificate: %s",
834                            OUStringToOString(intermediateCerts[i]->getIssuerName(),
835                                              osl_getThreadTextEncoding()).getStr());
836 
837              }
838              else
839              {
840                  xmlsec_trace("Added temporary certificate: %s",
841                            certTmp->subjectName ? certTmp->subjectName : "");
842                  vecTmpNSSCertificates.push_back(certTmp);
843              }
844         }
845 
846 
847         SECStatus status ;
848 
849         CERTVerifyLog log;
850         log.arena = PORT_NewArena(512);
851         log.head = log.tail = NULL;
852         log.count = 0;
853 
854         CERT_EnableOCSPChecking(certDb);
855         CERT_DisableOCSPDefaultResponder(certDb);
856         CERTValOutParam cvout[5];
857         CERTValInParam cvin[3];
858 
859         cvin[0].type = cert_pi_useAIACertFetch;
860         cvin[0].value.scalar.b = PR_TRUE;
861 
862         PRUint64 revFlagsLeaf[2];
863         PRUint64 revFlagsChain[2];
864         CERTRevocationFlags rev;
865         rev.leafTests.number_of_defined_methods = 2;
866         rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf;
867         //the flags are defined in cert.h
868         //We check both leaf and chain.
869         //It is enough if one revocation method has fresh info,
870         //but at least one must have some. Otherwise validation fails.
871         //!!! using leaf test and CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE
872         // when validating a root certificate will result in "revoked". Usually
873         //there is no revocation information available for the root cert because
874         //it must be trusted anyway and it does itself issue revocation information.
875         //When we use the flag here and OOo shows the certification path then the root
876         //cert is invalid while all other can be valid. It would probably best if
877         //this interface method returned the whole chain.
878         //Otherwise we need to check if the certificate is self-signed and if it is
879         //then not use the flag when doing the leaf-test.
880         rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
881             CERT_REV_M_TEST_USING_THIS_METHOD
882             | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
883         rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
884             CERT_REV_M_TEST_USING_THIS_METHOD
885             | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
886         rev.leafTests.number_of_preferred_methods = 0;
887         rev.leafTests.preferred_methods = NULL;
888         rev.leafTests.cert_rev_method_independent_flags =
889             CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
890 //            | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
891 
892         rev.chainTests.number_of_defined_methods = 2;
893         rev.chainTests.cert_rev_flags_per_method = revFlagsChain;
894         rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
895             CERT_REV_M_TEST_USING_THIS_METHOD
896             | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
897         rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
898             CERT_REV_M_TEST_USING_THIS_METHOD
899             | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
900         rev.chainTests.number_of_preferred_methods = 0;
901         rev.chainTests.preferred_methods = NULL;
902         rev.chainTests.cert_rev_method_independent_flags =
903             CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
904 //            | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
905 
906 
907         cvin[1].type = cert_pi_revocationFlags;
908         cvin[1].value.pointer.revocation = &rev;
909         // does not work, not implemented yet in 3.12.4
910 //         cvin[2].type = cert_pi_keyusage;
911 //         cvin[2].value.scalar.ui = KU_DIGITAL_SIGNATURE;
912         cvin[2].type = cert_pi_end;
913 
914         cvout[0].type = cert_po_trustAnchor;
915         cvout[0].value.pointer.cert = NULL;
916         cvout[1].type = cert_po_errorLog;
917         cvout[1].value.pointer.log = &log;
918         cvout[2].type = cert_po_end;
919 
920         // We check SSL server certificates, CA certificates and signing sertificates.
921         //
922         // ToDo check keyusage, looking at CERT_KeyUsageAndTypeForCertUsage (
923         // mozilla/security/nss/lib/certdb/certdb.c indicates that
924         // certificateUsageSSLClient, certificateUsageSSLServer and certificateUsageSSLCA
925         // are sufficient. They cover the key usages for digital signature, key agreement
926         // and encipherment and certificate signature
927 
928         //never use the following usages because they are not checked properly
929         // certificateUsageUserCertImport
930         // certificateUsageVerifyCA
931         // certificateUsageAnyCA
932         // certificateUsageProtectedObjectSigner
933 
934         UsageDescription arUsages[5];
935         arUsages[0] = UsageDescription( certificateUsageSSLClient, "certificateUsageSSLClient"  );
936         arUsages[1] = UsageDescription( certificateUsageSSLServer, "certificateUsageSSLServer"  );
937         arUsages[2] = UsageDescription( certificateUsageSSLCA, "certificateUsageSSLCA"  );
938         arUsages[3] = UsageDescription( certificateUsageEmailSigner, "certificateUsageEmailSigner" );
939         arUsages[4] = UsageDescription( certificateUsageEmailRecipient, "certificateUsageEmailRecipient" );
940 
941         int numUsages = sizeof(arUsages) / sizeof(UsageDescription);
942         for (int i = 0; i < numUsages; i++)
943         {
944             xmlsec_trace("Testing usage %d of %d: %s (0x%x)", i + 1,
945                       numUsages, arUsages[i].description, (int) arUsages[i].usage);
946 
947             status = CERT_PKIXVerifyCert(const_cast<CERTCertificate *>(cert), arUsages[i].usage,
948                                          cvin, cvout, NULL);
949             if( status == SECSuccess )
950             {
951                 xmlsec_trace("CERT_PKIXVerifyCert returned SECSuccess.");
952                 //When an intermediate or root certificate is checked then we expect the usage
953                 //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog
954                 //the button "This certificate can identify websites" is checked. If for example only
955                 //"This certificate can identify mail users" is set then the end certificate can
956                 //be validated and the returned usage will conain certificateUsageEmailRecipient.
957                 //But checking directly the root or intermediate certificate will fail. In the
958                 //certificate path view the end certificate will be shown as valid but the others
959                 //will be displayed as invalid.
960 
961                 validity = csss::CertificateValidity::VALID;
962                 xmlsec_trace("Certificate is valid.\n");
963                 CERTCertificate * issuerCert = cvout[0].value.pointer.cert;
964                 if (issuerCert)
965                 {
966                     xmlsec_trace("Root certificate: %s", issuerCert->subjectName);
967                     CERT_DestroyCertificate(issuerCert);
968                 };
969 
970                 break;
971             }
972             else
973             {
974                 PRIntn err = PR_GetError();
975                 xmlsec_trace("Error: , %d = %s", err, getCertError(err));
976 
977                 /* Display validation results */
978                 if ( log.count > 0)
979                 {
980                     CERTVerifyLogNode *node = NULL;
981                     printChainFailure(&log);
982 
983                     for (node = log.head; node; node = node->next) {
984                         if (node->cert)
985                             CERT_DestroyCertificate(node->cert);
986                     }
987                     log.head = log.tail = NULL;
988                     log.count = 0;
989                 }
990                 xmlsec_trace("Certificate is invalid.\n");
991             }
992         }
993 
994     }
995     else
996     {
997         validity = ::com::sun::star::security::CertificateValidity::INVALID ;
998     }
999 
1000     //Destroying the temporary certificates
1001     std::vector<CERTCertificate*>::const_iterator cert_i;
1002     for (cert_i = vecTmpNSSCertificates.begin(); cert_i != vecTmpNSSCertificates.end(); cert_i++)
1003     {
1004         xmlsec_trace("Destroying temporary certificate");
1005         CERT_DestroyCertificate(*cert_i);
1006     }
1007     return validity ;
1008 }
1009 
1010 sal_Int32 SecurityEnvironment_NssImpl::getCertificateCharacters(
1011     const ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificate >& aCert ) throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException ) {
1012     sal_Int32 characters ;
1013     const X509Certificate_NssImpl* xcert ;
1014     const CERTCertificate* cert ;
1015 
1016     Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ;
1017     if( !xCertTunnel.is() ) {
1018         throw RuntimeException() ;
1019     }
1020 
1021     xcert = reinterpret_cast<X509Certificate_NssImpl*>(
1022         sal::static_int_cast<sal_uIntPtr>(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ;
1023     if( xcert == NULL ) {
1024         throw RuntimeException() ;
1025     }
1026 
1027     cert = xcert->getNssCert() ;
1028 
1029     characters = 0x00000000 ;
1030 
1031     //Firstly, find out whether or not the cert is self-signed.
1032     if( SECITEM_CompareItem( &(cert->derIssuer), &(cert->derSubject) ) == SECEqual ) {
1033         characters |= ::com::sun::star::security::CertificateCharacters::SELF_SIGNED ;
1034     } else {
1035         characters &= ~ ::com::sun::star::security::CertificateCharacters::SELF_SIGNED ;
1036     }
1037 
1038     //Secondly, find out whether or not the cert has a private key.
1039 
1040     /*
1041      * i40394
1042      *
1043      * mmi : need to check whether the cert's slot is valid first
1044      */
1045     SECKEYPrivateKey* priKey = NULL;
1046 
1047     if (cert->slot != NULL)
1048     {
1049         priKey = PK11_FindPrivateKeyFromCert( cert->slot, ( CERTCertificate* )cert, NULL ) ;
1050     }
1051     if(priKey == NULL)
1052     {
1053         for (CIT_SLOTS is = m_Slots.begin(); is != m_Slots.end(); is++)
1054         {
1055             priKey = PK11_FindPrivateKeyFromCert(*is, (CERTCertificate*)cert, NULL);
1056             if (priKey)
1057                 break;
1058         }
1059     }
1060     if( priKey != NULL ) {
1061         characters |=  ::com::sun::star::security::CertificateCharacters::HAS_PRIVATE_KEY ;
1062 
1063         SECKEY_DestroyPrivateKey( priKey ) ;
1064     } else {
1065         characters &= ~ ::com::sun::star::security::CertificateCharacters::HAS_PRIVATE_KEY ;
1066     }
1067 
1068     return characters ;
1069 }
1070 
1071 X509Certificate_NssImpl* NssCertToXCert( CERTCertificate* cert )
1072 {
1073     X509Certificate_NssImpl* xcert ;
1074 
1075     if( cert != NULL ) {
1076         xcert = new X509Certificate_NssImpl() ;
1077         if( xcert == NULL ) {
1078             xcert = NULL ;
1079         } else {
1080             xcert->setCert( cert ) ;
1081         }
1082     } else {
1083         xcert = NULL ;
1084     }
1085 
1086     return xcert ;
1087 }
1088 
1089 X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* priKey )
1090 {
1091     CERTCertificate* cert ;
1092     X509Certificate_NssImpl* xcert ;
1093 
1094     if( priKey != NULL ) {
1095         cert = PK11_GetCertFromPrivateKey( priKey ) ;
1096 
1097         if( cert != NULL ) {
1098             xcert = NssCertToXCert( cert ) ;
1099         } else {
1100             xcert = NULL ;
1101         }
1102 
1103         CERT_DestroyCertificate( cert ) ;
1104     } else {
1105         xcert = NULL ;
1106     }
1107 
1108     return xcert ;
1109 }
1110 
1111 
1112 /* Native methods */
1113 xmlSecKeysMngrPtr SecurityEnvironment_NssImpl::createKeysManager() throw( Exception, RuntimeException ) {
1114 
1115     unsigned int i ;
1116     CERTCertDBHandle* handler = NULL ;
1117     PK11SymKey* symKey = NULL ;
1118     SECKEYPublicKey* pubKey = NULL ;
1119     SECKEYPrivateKey* priKey = NULL ;
1120     xmlSecKeysMngrPtr pKeysMngr = NULL ;
1121 
1122     handler = this->getCertDb() ;
1123 
1124     /*-
1125      * The following lines is based on the private version of xmlSec-NSS
1126      * crypto engine
1127      */
1128     int cSlots = m_Slots.size();
1129     boost::scoped_array<PK11SlotInfo*> sarSlots(new PK11SlotInfo*[cSlots]);
1130     PK11SlotInfo**  slots = sarSlots.get();
1131     int count = 0;
1132     for (CIT_SLOTS islots = m_Slots.begin();islots != m_Slots.end(); islots++, count++)
1133         slots[count] = *islots;
1134 
1135     pKeysMngr = xmlSecNssAppliedKeysMngrCreate(slots, cSlots, handler ) ;
1136     if( pKeysMngr == NULL )
1137         throw RuntimeException() ;
1138 
1139     /*-
1140      * Adopt symmetric key into keys manager
1141      */
1142     for( i = 0 ; ( symKey = this->getSymKey( i ) ) != NULL ; i ++ ) {
1143         if( xmlSecNssAppliedKeysMngrSymKeyLoad( pKeysMngr, symKey ) < 0 ) {
1144             throw RuntimeException() ;
1145         }
1146     }
1147 
1148     /*-
1149      * Adopt asymmetric public key into keys manager
1150      */
1151     for( i = 0 ; ( pubKey = this->getPubKey( i ) ) != NULL ; i ++ ) {
1152         if( xmlSecNssAppliedKeysMngrPubKeyLoad( pKeysMngr, pubKey ) < 0 ) {
1153             throw RuntimeException() ;
1154         }
1155     }
1156 
1157     /*-
1158      * Adopt asymmetric private key into keys manager
1159      */
1160     for( i = 0 ; ( priKey = this->getPriKey( i ) ) != NULL ; i ++ ) {
1161         if( xmlSecNssAppliedKeysMngrPriKeyLoad( pKeysMngr, priKey ) < 0 ) {
1162             throw RuntimeException() ;
1163         }
1164     }
1165     return pKeysMngr ;
1166 }
1167 void SecurityEnvironment_NssImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) throw( Exception, RuntimeException ) {
1168     if( pKeysMngr != NULL ) {
1169         xmlSecKeysMngrDestroy( pKeysMngr ) ;
1170     }
1171 }
1172