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