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