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