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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
30 
31 #ifdef _MSC_VER
32 #pragma warning(push,1)
33 #endif
34 #include "Windows.h"
35 #include "WinCrypt.h"
36 #ifdef _MSC_VER
37 #pragma warning(pop)
38 #endif
39 #include <sal/config.h>
40 #include <osl/thread.h>
41 #include "securityenvironment_mscryptimpl.hxx"
42 
43 #ifndef _X509CERTIFICATE_NSSIMPL_HXX_
44 #include "x509certificate_mscryptimpl.hxx"
45 #endif
46 #include <rtl/uuid.h>
47 
48 #include <xmlsec/xmlsec.h>
49 #include <xmlsec/keysmngr.h>
50 #include <xmlsec/crypto.h>
51 #include <xmlsec/base64.h>
52 
53 #include <xmlsecurity/biginteger.hxx>
54 
55 #include "xmlsec/keysmngr.h"
56 #include "xmlsec/mscrypto/akmngr.h"
57 
58 //CP : added by CP
59 #include <rtl/locale.h>
60 #include <osl/nlsupport.h>
61 #include <osl/process.h>
62 
63 //CP : end
64 #include <rtl/memory.h>
65 
66 #include "../diagnose.hxx"
67 
68 using namespace xmlsecurity;
69 using namespace ::com::sun::star::uno ;
70 using namespace ::com::sun::star::lang ;
71 using ::com::sun::star::lang::XMultiServiceFactory ;
72 using ::com::sun::star::lang::XSingleServiceFactory ;
73 using ::rtl::OUString ;
74 
75 using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
76 using ::com::sun::star::security::XCertificate ;
77 namespace css = ::com::sun::star;
78 
79 extern X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ;
80 
81 struct CertErrorToString{
82     DWORD error;
83     char * name;
84 };
85 
86 CertErrorToString arErrStrings[] =
87 {
88     { 0x00000000, "CERT_TRUST_NO_ERROR"},
89     { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"},
90     { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"},
91     { 0x00000004, "CERT_TRUST_IS_REVOKED" },
92     { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" },
93     { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"},
94     { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"},
95     { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"},
96     { 0x00000080, "CERT_TRUST_IS_CYCLIC"},
97     { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"},
98     { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"},
99     { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"},
100     { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"},
101     { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"},
102     { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"},
103     { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"},
104     { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"},
105     { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"},
106     { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"},
107     { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"},
108     { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"},
109     //Chain errors
110     { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"},
111     { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"},
112     { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"},
113     { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"}
114 };
115 
116 void traceTrustStatus(DWORD err)
117 {
118     int numErrors = sizeof(arErrStrings) / sizeof(CertErrorToString);
119     xmlsec_trace("The certificate error status is: ");
120     if (err == 0)
121         xmlsec_trace("%s", arErrStrings[0].name);
122     for (int i = 1; i < numErrors; i++)
123     {
124         if (arErrStrings[i].error & err)
125             xmlsec_trace("%s", arErrStrings[i].name);
126     }
127 }
128 
129 SecurityEnvironment_MSCryptImpl :: SecurityEnvironment_MSCryptImpl( const Reference< XMultiServiceFactory >& aFactory ) : m_hProv( NULL ) , m_pszContainer( NULL ) , m_hKeyStore( NULL ), m_hCertStore( NULL ), m_tSymKeyList() , m_tPubKeyList() , m_tPriKeyList(), m_xServiceManager( aFactory ), m_bEnableDefault( sal_False ) {
130 
131 }
132 
133 SecurityEnvironment_MSCryptImpl :: ~SecurityEnvironment_MSCryptImpl() {
134 
135 	if( m_hProv != NULL ) {
136 		CryptReleaseContext( m_hProv, 0 ) ;
137 		m_hProv = NULL ;
138 	}
139 
140 	if( m_pszContainer != NULL ) {
141 		//TODO: Don't know whether or not it should be released now.
142 		m_pszContainer = NULL ;
143 	}
144 
145 	if( m_hCertStore != NULL ) {
146 		CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
147 		m_hCertStore = NULL ;
148 	}
149 
150 	if( m_hKeyStore != NULL ) {
151 		CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
152 		m_hKeyStore = NULL ;
153 	}
154 
155 	if( !m_tSymKeyList.empty()  ) {
156 		std::list< HCRYPTKEY >::iterator symKeyIt ;
157 
158 		for( symKeyIt = m_tSymKeyList.begin() ; symKeyIt != m_tSymKeyList.end() ; symKeyIt ++ )
159 			CryptDestroyKey( *symKeyIt ) ;
160 	}
161 
162 	if( !m_tPubKeyList.empty()  ) {
163 		std::list< HCRYPTKEY >::iterator pubKeyIt ;
164 
165 		for( pubKeyIt = m_tPubKeyList.begin() ; pubKeyIt != m_tPubKeyList.end() ; pubKeyIt ++ )
166 			CryptDestroyKey( *pubKeyIt ) ;
167 	}
168 
169 	if( !m_tPriKeyList.empty()  ) {
170 		std::list< HCRYPTKEY >::iterator priKeyIt ;
171 
172 		for( priKeyIt = m_tPriKeyList.begin() ; priKeyIt != m_tPriKeyList.end() ; priKeyIt ++ )
173 			CryptDestroyKey( *priKeyIt ) ;
174 	}
175 
176 }
177 
178 /* XInitialization */
179 void SAL_CALL SecurityEnvironment_MSCryptImpl :: initialize( const Sequence< Any >& /*aArguments*/ ) throw( Exception, RuntimeException ) {
180 	//TODO
181 } ;
182 
183 /* XServiceInfo */
184 OUString SAL_CALL SecurityEnvironment_MSCryptImpl :: getImplementationName() throw( RuntimeException ) {
185 	return impl_getImplementationName() ;
186 }
187 
188 /* XServiceInfo */
189 sal_Bool SAL_CALL SecurityEnvironment_MSCryptImpl :: supportsService( const OUString& serviceName) throw( RuntimeException ) {
190 	Sequence< OUString > seqServiceNames = getSupportedServiceNames() ;
191 	const OUString* pArray = seqServiceNames.getConstArray() ;
192 	for( sal_Int32 i = 0 ; i < seqServiceNames.getLength() ; i ++ ) {
193 		if( *( pArray + i ) == serviceName )
194 			return sal_True ;
195 	}
196 	return sal_False ;
197 }
198 
199 /* XServiceInfo */
200 Sequence< OUString > SAL_CALL SecurityEnvironment_MSCryptImpl :: getSupportedServiceNames() throw( RuntimeException ) {
201 	return impl_getSupportedServiceNames() ;
202 }
203 
204 //Helper for XServiceInfo
205 Sequence< OUString > SecurityEnvironment_MSCryptImpl :: impl_getSupportedServiceNames() {
206 	::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
207 	Sequence< OUString > seqServiceNames( 1 ) ;
208 	seqServiceNames.getArray()[0] = OUString::createFromAscii( "com.sun.star.xml.crypto.SecurityEnvironment" ) ;
209 	return seqServiceNames ;
210 }
211 
212 OUString SecurityEnvironment_MSCryptImpl :: impl_getImplementationName() throw( RuntimeException ) {
213 	return OUString::createFromAscii( "com.sun.star.xml.security.bridge.xmlsec.SecurityEnvironment_MSCryptImpl" ) ;
214 }
215 
216 //Helper for registry
217 Reference< XInterface > SAL_CALL SecurityEnvironment_MSCryptImpl :: impl_createInstance( const Reference< XMultiServiceFactory >& aServiceManager ) throw( RuntimeException ) {
218 	return Reference< XInterface >( *new SecurityEnvironment_MSCryptImpl( aServiceManager ) ) ;
219 }
220 
221 Reference< XSingleServiceFactory > SecurityEnvironment_MSCryptImpl :: impl_createFactory( const Reference< XMultiServiceFactory >& aServiceManager ) {
222 	return ::cppu::createSingleFactory( aServiceManager , impl_getImplementationName() , impl_createInstance , impl_getSupportedServiceNames() ) ;
223 }
224 
225 /* XUnoTunnel */
226 sal_Int64 SAL_CALL SecurityEnvironment_MSCryptImpl :: getSomething( const Sequence< sal_Int8 >& aIdentifier )
227 	throw( RuntimeException )
228 {
229 	if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) {
230 		return ( sal_Int64 )this ;
231 	}
232 	return 0 ;
233 }
234 
235 /* XUnoTunnel extension */
236 const Sequence< sal_Int8>& SecurityEnvironment_MSCryptImpl :: getUnoTunnelId() {
237 	static Sequence< sal_Int8 >* pSeq = 0 ;
238 	if( !pSeq ) {
239 		::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ) ;
240 		if( !pSeq ) {
241 			static Sequence< sal_Int8> aSeq( 16 ) ;
242 			rtl_createUuid( ( sal_uInt8* )aSeq.getArray() , 0 , sal_True ) ;
243 			pSeq = &aSeq ;
244 		}
245 	}
246 	return *pSeq ;
247 }
248 
249 /* XUnoTunnel extension */
250 SecurityEnvironment_MSCryptImpl* SecurityEnvironment_MSCryptImpl :: getImplementation( const Reference< XInterface > xObj ) {
251 	Reference< XUnoTunnel > xUT( xObj , UNO_QUERY ) ;
252 	if( xUT.is() ) {
253 		return ( SecurityEnvironment_MSCryptImpl* )xUT->getSomething( getUnoTunnelId() ) ;
254 	} else
255 		return NULL ;
256 }
257 
258 /* Native methods */
259 HCRYPTPROV SecurityEnvironment_MSCryptImpl :: getCryptoProvider() throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) {
260 	return m_hProv ;
261 }
262 
263 void SecurityEnvironment_MSCryptImpl :: setCryptoProvider( HCRYPTPROV aProv ) throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) {
264 	if( m_hProv != NULL ) {
265 		CryptReleaseContext( m_hProv, 0 ) ;
266 		m_hProv = NULL ;
267 	}
268 
269 	if( aProv != NULL ) {
270 		/*- Replaced by direct adopt for WINNT support ----
271 		if( !CryptContextAddRef( aProv, NULL, NULL ) )
272 			throw Exception() ;
273 		else
274 			m_hProv = aProv ;
275 		----*/
276 		m_hProv = aProv ;
277 	}
278 }
279 
280 LPCTSTR SecurityEnvironment_MSCryptImpl :: getKeyContainer() throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) {
281 	return m_pszContainer ;
282 }
283 
284 void SecurityEnvironment_MSCryptImpl :: setKeyContainer( LPCTSTR aKeyContainer ) throw( ::com::sun::star::uno::Exception , ::com::sun::star::uno::RuntimeException ) {
285 	//TODO: Don't know whether or not it should be copied.
286 	m_pszContainer = aKeyContainer ;
287 }
288 
289 
290 HCERTSTORE SecurityEnvironment_MSCryptImpl :: getCryptoSlot() throw( Exception , RuntimeException ) {
291 	return m_hKeyStore ;
292 }
293 
294 void SecurityEnvironment_MSCryptImpl :: setCryptoSlot( HCERTSTORE aSlot) throw( Exception , RuntimeException ) {
295 	if( m_hKeyStore != NULL ) {
296 		CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
297 		m_hKeyStore = NULL ;
298 	}
299 
300 	if( aSlot != NULL ) {
301 		m_hKeyStore = CertDuplicateStore( aSlot ) ;
302 	}
303 }
304 
305 HCERTSTORE SecurityEnvironment_MSCryptImpl :: getCertDb() throw( Exception , RuntimeException ) {
306 	return m_hCertStore ;
307 }
308 
309 void SecurityEnvironment_MSCryptImpl :: setCertDb( HCERTSTORE aCertDb ) throw( Exception , RuntimeException ) {
310 	if( m_hCertStore != NULL ) {
311 		CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
312 		m_hCertStore = NULL ;
313 	}
314 
315 	if( aCertDb != NULL ) {
316 		m_hCertStore = CertDuplicateStore( aCertDb ) ;
317 	}
318 }
319 
320 void SecurityEnvironment_MSCryptImpl :: adoptSymKey( HCRYPTKEY aSymKey ) throw( Exception , RuntimeException ) {
321 	HCRYPTKEY	symkey ;
322 	std::list< HCRYPTKEY >::iterator keyIt ;
323 
324 	if( aSymKey != NULL ) {
325 		//First try to find the key in the list
326 		for( keyIt = m_tSymKeyList.begin() ; keyIt != m_tSymKeyList.end() ; keyIt ++ ) {
327 			if( *keyIt == aSymKey )
328 				return ;
329 		}
330 
331 		//If we do not find the key in the list, add a new node
332 		/*- Replaced with directly adopt for WINNT 4.0 support ----
333 		if( !CryptDuplicateKey( aSymKey, NULL, 0, &symkey ) )
334 			throw RuntimeException() ;
335 		----*/
336 		symkey = aSymKey ;
337 
338 		try {
339 			m_tSymKeyList.push_back( symkey ) ;
340 		} catch ( Exception& ) {
341 			CryptDestroyKey( symkey ) ;
342 		}
343 	}
344 }
345 
346 void SecurityEnvironment_MSCryptImpl :: rejectSymKey( HCRYPTKEY aSymKey ) throw( Exception , RuntimeException ) {
347 	HCRYPTKEY symkey ;
348 	std::list< HCRYPTKEY >::iterator keyIt ;
349 
350 	if( aSymKey != NULL ) {
351 		for( keyIt = m_tSymKeyList.begin() ; keyIt != m_tSymKeyList.end() ; keyIt ++ ) {
352 			if( *keyIt == aSymKey ) {
353 				symkey = *keyIt ;
354 				CryptDestroyKey( symkey ) ;
355 				m_tSymKeyList.erase( keyIt ) ;
356 				break ;
357 			}
358 		}
359 	}
360 }
361 
362 HCRYPTKEY SecurityEnvironment_MSCryptImpl :: getSymKey( unsigned int position ) throw( Exception , RuntimeException ) {
363 	HCRYPTKEY symkey ;
364 	std::list< HCRYPTKEY >::iterator keyIt ;
365 	unsigned int pos ;
366 
367 	symkey = NULL ;
368 	for( pos = 0, keyIt = m_tSymKeyList.begin() ; pos < position && keyIt != m_tSymKeyList.end() ; pos ++ , keyIt ++ ) ;
369 
370 	if( pos == position && keyIt != m_tSymKeyList.end() )
371 		symkey = *keyIt ;
372 
373 	return symkey ;
374 }
375 
376 void SecurityEnvironment_MSCryptImpl :: adoptPubKey( HCRYPTKEY aPubKey ) throw( Exception , RuntimeException ) {
377 	HCRYPTKEY	pubkey ;
378 	std::list< HCRYPTKEY >::iterator keyIt ;
379 
380 	if( aPubKey != NULL ) {
381 		//First try to find the key in the list
382 		for( keyIt = m_tPubKeyList.begin() ; keyIt != m_tPubKeyList.end() ; keyIt ++ ) {
383 			if( *keyIt == aPubKey )
384 				return ;
385 		}
386 
387 		//If we do not find the key in the list, add a new node
388 		/*- Replaced with directly adopt for WINNT 4.0 support ----
389 		if( !CryptDuplicateKey( aPubKey, NULL, 0, &pubkey ) )
390 			throw RuntimeException() ;
391 		----*/
392 		pubkey = aPubKey ;
393 
394 		try {
395 			m_tPubKeyList.push_back( pubkey ) ;
396 		} catch ( Exception& ) {
397 			CryptDestroyKey( pubkey ) ;
398 		}
399 	}
400 }
401 
402 void SecurityEnvironment_MSCryptImpl :: rejectPubKey( HCRYPTKEY aPubKey ) throw( Exception , RuntimeException ) {
403 	HCRYPTKEY pubkey ;
404 	std::list< HCRYPTKEY >::iterator keyIt ;
405 
406 	if( aPubKey != NULL ) {
407 		for( keyIt = m_tPubKeyList.begin() ; keyIt != m_tPubKeyList.end() ; keyIt ++ ) {
408 			if( *keyIt == aPubKey ) {
409 				pubkey = *keyIt ;
410 				CryptDestroyKey( pubkey ) ;
411 				m_tPubKeyList.erase( keyIt ) ;
412 				break ;
413 			}
414 		}
415 	}
416 }
417 
418 HCRYPTKEY SecurityEnvironment_MSCryptImpl :: getPubKey( unsigned int position ) throw( Exception , RuntimeException ) {
419 	HCRYPTKEY pubkey ;
420 	std::list< HCRYPTKEY >::iterator keyIt ;
421 	unsigned int pos ;
422 
423 	pubkey = NULL ;
424 	for( pos = 0, keyIt = m_tPubKeyList.begin() ; pos < position && keyIt != m_tPubKeyList.end() ; pos ++ , keyIt ++ ) ;
425 
426 	if( pos == position && keyIt != m_tPubKeyList.end() )
427 		pubkey = *keyIt ;
428 
429 	return pubkey ;
430 }
431 
432 void SecurityEnvironment_MSCryptImpl :: adoptPriKey( HCRYPTKEY aPriKey ) throw( Exception , RuntimeException ) {
433 	HCRYPTKEY	prikey ;
434 	std::list< HCRYPTKEY >::iterator keyIt ;
435 
436 	if( aPriKey != NULL ) {
437 		//First try to find the key in the list
438 		for( keyIt = m_tPriKeyList.begin() ; keyIt != m_tPriKeyList.end() ; keyIt ++ ) {
439 			if( *keyIt == aPriKey )
440 				return ;
441 		}
442 
443 		//If we do not find the key in the list, add a new node
444 		/*- Replaced with directly adopt for WINNT 4.0 support ----
445 		if( !CryptDuplicateKey( aPriKey, NULL, 0, &prikey ) )
446 			throw RuntimeException() ;
447 		----*/
448 		prikey = aPriKey ;
449 
450 		try {
451 			m_tPriKeyList.push_back( prikey ) ;
452 		} catch ( Exception& ) {
453 			CryptDestroyKey( prikey ) ;
454 		}
455 	}
456 }
457 
458 void SecurityEnvironment_MSCryptImpl :: rejectPriKey( HCRYPTKEY aPriKey ) throw( Exception , RuntimeException ) {
459 	HCRYPTKEY	prikey ;
460 	std::list< HCRYPTKEY >::iterator keyIt ;
461 
462 	if( aPriKey != NULL ) {
463 		for( keyIt = m_tPriKeyList.begin() ; keyIt != m_tPriKeyList.end() ; keyIt ++ ) {
464 			if( *keyIt == aPriKey ) {
465 				prikey = *keyIt ;
466 				CryptDestroyKey( prikey ) ;
467 				m_tPriKeyList.erase( keyIt ) ;
468 				break ;
469 			}
470 		}
471 	}
472 }
473 
474 HCRYPTKEY SecurityEnvironment_MSCryptImpl :: getPriKey( unsigned int position ) throw( Exception , RuntimeException ) {
475 	HCRYPTKEY prikey ;
476 	std::list< HCRYPTKEY >::iterator keyIt ;
477 	unsigned int pos ;
478 
479 	prikey = NULL ;
480 	for( pos = 0, keyIt = m_tPriKeyList.begin() ; pos < position && keyIt != m_tPriKeyList.end() ; pos ++ , keyIt ++ ) ;
481 
482 	if( pos == position && keyIt != m_tPriKeyList.end() )
483 		prikey = *keyIt ;
484 
485 	return prikey ;
486 }
487 
488 //Methods from XSecurityEnvironment
489 Sequence< Reference < XCertificate > > SecurityEnvironment_MSCryptImpl :: getPersonalCertificates() throw( SecurityException , RuntimeException )
490 {
491 	sal_Int32 length ;
492 	X509Certificate_MSCryptImpl* xcert ;
493 	std::list< X509Certificate_MSCryptImpl* > certsList ;
494 	PCCERT_CONTEXT pCertContext = NULL;
495 
496 	//firstly, we try to find private keys in given key store.
497 	if( m_hKeyStore != NULL ) {
498 		pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext );
499 		while (pCertContext)
500         {
501 			xcert = MswcryCertContextToXCert( pCertContext ) ;
502 			if( xcert != NULL )
503 				certsList.push_back( xcert ) ;
504             pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext );
505 		}
506 	}
507 
508 	//secondly, we try to find certificate from registered private keys.
509 	if( !m_tPriKeyList.empty()  ) {
510 		//TODO: Don't know whether or not it is necessary ans possible.
511 	}
512 
513 	//Thirdly, we try to find certificate from system default key store.
514 	if( m_bEnableDefault ) {
515 		HCERTSTORE hSystemKeyStore ;
516 		DWORD      dwKeySpec;
517 		HCRYPTPROV hCryptProv;
518 
519 		/*
520 		hSystemKeyStore = CertOpenStore(
521 				CERT_STORE_PROV_SYSTEM ,
522 				0 ,
523 				NULL ,
524 				CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG ,
525 				L"MY"
526 			) ;
527 		*/
528 		hSystemKeyStore = CertOpenSystemStore( 0, "MY" ) ;
529 		if( hSystemKeyStore != NULL ) {
530 			pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
531 			while (pCertContext)
532             {
533 				// Add By CP for checking whether the certificate is a personal certificate or not.
534 				if(!(CryptAcquireCertificatePrivateKey(pCertContext,
535 						CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
536 						NULL,
537 						&hCryptProv,
538 						&dwKeySpec,
539 						NULL)))
540 				{
541 					// Not Privatekey found. SKIP this one; By CP
542                     pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
543 					continue;
544 				}
545 				// then TODO : Check the personal cert is valid or not.
546 
547 				// end CP
548 				xcert = MswcryCertContextToXCert( pCertContext ) ;
549 				if( xcert != NULL )
550 					certsList.push_back( xcert ) ;
551                 pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
552 			}
553 		}
554 
555 		CertCloseStore( hSystemKeyStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
556 	}
557 
558 	length = certsList.size() ;
559 	if( length != 0 ) {
560 		int i ;
561 		std::list< X509Certificate_MSCryptImpl* >::iterator xcertIt ;
562 		Sequence< Reference< XCertificate > > certSeq( length ) ;
563 
564 		for( i = 0, xcertIt = certsList.begin(); xcertIt != certsList.end(); xcertIt ++, i++ ) {
565 			certSeq[i] = *xcertIt ;
566 		}
567 
568 		return certSeq ;
569 	}
570 
571 	return Sequence< Reference< XCertificate > >() ;
572 }
573 
574 
575 Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& serialNumber ) throw( SecurityException , RuntimeException ) {
576 	unsigned int i ;
577 //	sal_Int8 found = 0 ;
578 	LPSTR	pszName ;
579 	X509Certificate_MSCryptImpl *xcert = NULL ;
580 	PCCERT_CONTEXT pCertContext = NULL ;
581 	HCERTSTORE hCertStore = NULL ;
582 	CRYPT_INTEGER_BLOB cryptSerialNumber ;
583 	CERT_INFO certInfo ;
584 
585 	// By CP , for correct encoding
586 	sal_uInt16 encoding ;
587 	rtl_Locale *pLocale = NULL ;
588 	osl_getProcessLocale( &pLocale ) ;
589 	encoding = osl_getTextEncodingFromLocale( pLocale ) ;
590 	// CP end
591 
592 	//Create cert info from issue and serial
593 	rtl::OString oissuer = rtl::OUStringToOString( issuerName , encoding ) ;
594 	pszName = ( char* )oissuer.getStr() ;
595 
596 	if( ! ( CertStrToName(
597 		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
598 		pszName ,
599 		CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
600 		NULL ,
601 		NULL ,
602 		&certInfo.Issuer.cbData, NULL ) )
603 	) {
604 		return NULL ;
605 	}
606 
607     certInfo.Issuer.pbData = ( BYTE* )malloc( certInfo.Issuer.cbData );
608 	if(!certInfo.Issuer.pbData)
609 		throw RuntimeException() ;
610 
611 	if( ! ( CertStrToName(
612 		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
613 		pszName ,
614 		CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
615 		NULL ,
616 		( BYTE* )certInfo.Issuer.pbData ,
617 		&certInfo.Issuer.cbData, NULL ) )
618 	) {
619 		free( certInfo.Issuer.pbData ) ;
620 		return NULL ;
621 	}
622 
623 	//Get the SerialNumber
624 	cryptSerialNumber.cbData = serialNumber.getLength() ;
625     cryptSerialNumber.pbData = ( BYTE* )malloc( cryptSerialNumber.cbData);
626 	if (!cryptSerialNumber.pbData)
627 	{
628 		free( certInfo.Issuer.pbData ) ;
629 		throw RuntimeException() ;
630 	}
631 	for( i = 0; i < cryptSerialNumber.cbData; i ++ )
632 		cryptSerialNumber.pbData[i] = serialNumber[ cryptSerialNumber.cbData - i - 1 ] ;
633 
634 	certInfo.SerialNumber.cbData = cryptSerialNumber.cbData ;
635 	certInfo.SerialNumber.pbData = cryptSerialNumber.pbData ;
636 
637 	// Get the Cert from all store.
638 	for( i = 0 ; i < 6 ; i ++ )
639 	{
640 		switch(i)
641 		{
642 		case 0:
643 			if(m_hKeyStore == NULL) continue ;
644 			hCertStore = m_hKeyStore ;
645 			break;
646 		case 1:
647 			if(m_hCertStore == NULL) continue ;
648 			hCertStore = m_hCertStore ;
649 			break;
650 		case 2:
651 			hCertStore = CertOpenSystemStore( 0, "MY" ) ;
652 			if(hCertStore == NULL || !m_bEnableDefault) continue ;
653 			break;
654 		case 3:
655 			hCertStore = CertOpenSystemStore( 0, "Root" ) ;
656 			if(hCertStore == NULL || !m_bEnableDefault) continue ;
657 			break;
658 		case 4:
659 			hCertStore = CertOpenSystemStore( 0, "Trust" ) ;
660 			if(hCertStore == NULL || !m_bEnableDefault) continue ;
661 			break;
662 		case 5:
663 			hCertStore = CertOpenSystemStore( 0, "CA" ) ;
664 			if(hCertStore == NULL || !m_bEnableDefault) continue ;
665 			break;
666 		default:
667 			i=6;
668 			continue;
669 		}
670 
671 /*******************************************************************************
672  * This code reserved for remind us there are another way to find one cert by
673  * IssuerName&serialnumber. You can use the code to replaced the function
674  * CertFindCertificateInStore IF and ONLY IF you must find one special cert in
675  * certStore but can not be found by CertFindCertificateInStore , then , you
676  * should also change the same part in libxmlsec/.../src/mscrypto/x509vfy.c#875.
677  * By Chandler Peng(chandler.peng@sun.com)
678  *****/
679 /*******************************************************************************
680 		pCertContext = NULL ;
681 		found = 0;
682 		do{
683 			//	1. enum the certs has same string in the issuer string.
684 			pCertContext = CertEnumCertificatesInStore( hCertStore , pCertContext ) ;
685 			if( pCertContext != NULL )
686 			{
687 				// 2. check the cert's issuer name .
688 				char* issuer = NULL ;
689 				DWORD cbIssuer = 0 ;
690 
691 				cbIssuer = CertNameToStr(
692 					X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
693 					&( pCertContext->pCertInfo->Issuer ),
694 					CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
695 					NULL, 0
696 				) ;
697 
698 				if( cbIssuer == 0 ) continue ; // discard this cert;
699 
700 				issuer = (char *)malloc( cbIssuer ) ;
701 				if( issuer == NULL )  // discard this cert;
702 				{
703 					free( cryptSerialNumber.pbData) ;
704 					free( certInfo.Issuer.pbData ) ;
705 					CertFreeCertificateContext( pCertContext ) ;
706 					if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
707 					throw RuntimeException() ;
708 				}
709 
710 				cbIssuer = CertNameToStr(
711 					X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
712 					&( pCertContext->pCertInfo->Issuer ),
713 					CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
714 					issuer, cbIssuer
715 				) ;
716 
717 				if( cbIssuer <= 0 )
718 				{
719 					free( issuer ) ;
720 					continue ;// discard this cert;
721 				}
722 
723 				if(strncmp(pszName , issuer , cbIssuer) != 0)
724 				{
725 					free( issuer ) ;
726 					continue ;// discard this cert;
727 				}
728 				free( issuer ) ;
729 
730 				// 3. check the serial number.
731 				if( memcmp( cryptSerialNumber.pbData , pCertContext->pCertInfo->SerialNumber.pbData  , cryptSerialNumber.cbData ) != 0 )
732 				{
733 					continue ;// discard this cert;
734 				}
735 
736 				// 4. confirm and break;
737 				found = 1;
738 				break ;
739 			}
740 
741 		}while(pCertContext);
742 
743 		if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
744 		if( found != 0 ) break; // Found the certificate.
745 ********************************************************************************/
746 
747 		pCertContext = CertFindCertificateInStore(
748 			hCertStore,
749 			X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
750 			0,
751 			CERT_FIND_SUBJECT_CERT,
752 			&certInfo,
753 			NULL
754 		) ;
755 
756 		if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
757 		if( pCertContext != NULL ) break ; // Found the certificate.
758 
759 	}
760 
761 	if( cryptSerialNumber.pbData ) free( cryptSerialNumber.pbData ) ;
762 	if( certInfo.Issuer.pbData ) free( certInfo.Issuer.pbData ) ;
763 
764 	if( pCertContext != NULL ) {
765 		xcert = MswcryCertContextToXCert( pCertContext ) ;
766 		if( pCertContext ) CertFreeCertificateContext( pCertContext ) ;
767 	} else {
768 		xcert = NULL ;
769 	}
770 
771 	return xcert ;
772 }
773 
774 Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: getCertificate( const OUString& issuerName, const OUString& serialNumber ) throw( SecurityException , RuntimeException ) {
775 	Sequence< sal_Int8 > serial = numericStringToBigInteger( serialNumber ) ;
776 	return getCertificate( issuerName, serial ) ;
777 }
778 
779 Sequence< Reference < XCertificate > > SecurityEnvironment_MSCryptImpl :: buildCertificatePath( const Reference< XCertificate >& begin ) throw( SecurityException , RuntimeException ) {
780 	PCCERT_CHAIN_CONTEXT pChainContext ;
781 	PCCERT_CONTEXT pCertContext ;
782 	const X509Certificate_MSCryptImpl* xcert ;
783 
784 	CERT_ENHKEY_USAGE	enhKeyUsage ;
785 	CERT_USAGE_MATCH	certUsage ;
786 	CERT_CHAIN_PARA		chainPara ;
787 
788 	enhKeyUsage.cUsageIdentifier = 0 ;
789 	enhKeyUsage.rgpszUsageIdentifier = NULL ;
790 	certUsage.dwType = USAGE_MATCH_TYPE_AND ;
791 	certUsage.Usage = enhKeyUsage ;
792 	chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ;
793 	chainPara.RequestedUsage = certUsage ;
794 
795 	Reference< XUnoTunnel > xCertTunnel( begin, UNO_QUERY ) ;
796 	if( !xCertTunnel.is() ) {
797 		throw RuntimeException() ;
798 	}
799 
800 	xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ;
801 	if( xcert == NULL ) {
802 		throw RuntimeException() ;
803 	}
804 
805 	pCertContext = xcert->getMswcryCert() ;
806 
807 	pChainContext = NULL ;
808 
809     BOOL bChain = FALSE;
810     if( pCertContext != NULL )
811     {
812         HCERTSTORE hAdditionalStore = NULL;
813         HCERTSTORE hCollectionStore = NULL;
814         if (m_hCertStore && m_hKeyStore)
815         {
816             //Merge m_hCertStore and m_hKeyStore into one store.
817             hCollectionStore = CertOpenStore(
818 				CERT_STORE_PROV_COLLECTION ,
819 				0 ,
820 				NULL ,
821 				0 ,
822 				NULL
823                 ) ;
824             if (hCollectionStore != NULL)
825             {
826                 CertAddStoreToCollection (
827  					hCollectionStore ,
828  					m_hCertStore ,
829  					CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
830  					0) ;
831                 CertAddStoreToCollection (
832  					hCollectionStore ,
833  					m_hCertStore ,
834  					CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
835  					0) ;
836                 hAdditionalStore = hCollectionStore;
837             }
838 
839         }
840 
841         //if the merge of both stores failed then we add only m_hCertStore
842         if (hAdditionalStore == NULL && m_hCertStore)
843             hAdditionalStore = m_hCertStore;
844         else if (hAdditionalStore == NULL && m_hKeyStore)
845             hAdditionalStore = m_hKeyStore;
846         else
847             hAdditionalStore = NULL;
848 
849         //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST
850     	bChain = CertGetCertificateChain(
851 		    NULL ,
852 		    pCertContext ,
853 		    NULL , //use current system time
854 		    hAdditionalStore,
855 		    &chainPara ,
856 		    CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME ,
857 		    NULL ,
858 		    &pChainContext);
859         if (!bChain)
860 			pChainContext = NULL;
861 
862         //Close the additional store
863        CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG);
864     }
865 
866 	if(bChain &&  pChainContext != NULL && pChainContext->cChain > 0 )
867     {
868 		PCCERT_CONTEXT pCertInChain ;
869 		PCERT_SIMPLE_CHAIN pCertChain ;
870 		X509Certificate_MSCryptImpl* pCert ;
871 
872 		pCertChain = pChainContext->rgpChain[0] ;
873 		if( pCertChain->cElement ) {
874 			Sequence< Reference< XCertificate > > xCertChain( pCertChain->cElement ) ;
875 
876 			for( unsigned int i = 0 ; i < pCertChain->cElement ; i ++ ) {
877 				if( pCertChain->rgpElement[i] )
878 					pCertInChain = pCertChain->rgpElement[i]->pCertContext ;
879 				else
880 					pCertInChain = NULL ;
881 
882 				if( pCertInChain != NULL ) {
883 					pCert = MswcryCertContextToXCert( pCertInChain ) ;
884 					if( pCert != NULL )
885 						xCertChain[i] = pCert ;
886 				}
887 			}
888 
889 			CertFreeCertificateChain( pChainContext ) ;
890 			pChainContext = NULL ;
891 
892 			return xCertChain ;
893 		}
894 	}
895     if (pChainContext)
896         CertFreeCertificateChain(pChainContext);
897 
898 	return Sequence< Reference < XCertificate > >();
899 }
900 
901 Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: createCertificateFromRaw( const Sequence< sal_Int8 >& rawCertificate ) throw( SecurityException , RuntimeException ) {
902 	X509Certificate_MSCryptImpl* xcert ;
903 
904 	if( rawCertificate.getLength() > 0 ) {
905 		xcert = new X509Certificate_MSCryptImpl() ;
906 		if( xcert == NULL )
907 			throw RuntimeException() ;
908 
909 		xcert->setRawCert( rawCertificate ) ;
910 	} else {
911 		xcert = NULL ;
912 	}
913 
914 	return xcert ;
915 }
916 
917 Reference< XCertificate > SecurityEnvironment_MSCryptImpl :: createCertificateFromAscii( const OUString& asciiCertificate ) throw( SecurityException , RuntimeException ) {
918 	xmlChar* chCert ;
919 	xmlSecSize certSize ;
920 
921 	rtl::OString oscert = rtl::OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ;
922 
923 	chCert = xmlStrndup( ( const xmlChar* )oscert.getStr(), ( int )oscert.getLength() ) ;
924 
925 	certSize = xmlSecBase64Decode( chCert, ( xmlSecByte* )chCert, xmlStrlen( chCert ) ) ;
926 
927 	Sequence< sal_Int8 > rawCert( certSize ) ;
928 	for( unsigned int i = 0 ; i < certSize ; i ++ )
929 		rawCert[i] = *( chCert + i ) ;
930 
931 	xmlFree( chCert ) ;
932 
933 	return createCertificateFromRaw( rawCert ) ;
934 }
935 
936 
937 HCERTSTORE getCertStoreForIntermediatCerts(
938     const Sequence< Reference< ::com::sun::star::security::XCertificate > >& seqCerts)
939 {
940     HCERTSTORE store = NULL;
941     store = CertOpenStore(
942         CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
943     if (store == NULL)
944         return NULL;
945 
946     for (int i = 0; i < seqCerts.getLength(); i++)
947     {
948         xmlsec_trace("Added temporary certificate: \n%s",
949                      OUStringToOString(seqCerts[i]->getSubjectName(),
950                                        osl_getThreadTextEncoding()).getStr());
951 
952 
953         Sequence<sal_Int8> data = seqCerts[i]->getEncoded();
954         PCCERT_CONTEXT cert = CertCreateCertificateContext(
955             X509_ASN_ENCODING, ( const BYTE* )&data[0], data.getLength());
956         //Adding the certificate creates a copy and not just increases the ref count
957         //Therefore we free later the certificate that we now add
958         CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_ALWAYS, NULL);
959         CertFreeCertificateContext(cert);
960     }
961     return store;
962 }
963 
964 //We return only valid or invalid, as long as the API documentation expresses
965 //explicitly that all validation steps are carried out even if one or several
966 //errors occur. See also
967 //http://wiki.services.openoffice.org/wiki/Certificate_Path_Validation#Validation_status
968 sal_Int32 SecurityEnvironment_MSCryptImpl :: verifyCertificate(
969     const Reference< ::com::sun::star::security::XCertificate >& aCert,
970     const Sequence< Reference< ::com::sun::star::security::XCertificate > >& seqCerts)
971     throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException )
972 {
973 	sal_Int32 validity = 0;
974 	PCCERT_CHAIN_CONTEXT pChainContext = NULL;
975 	PCCERT_CONTEXT pCertContext = NULL;
976 	const X509Certificate_MSCryptImpl* xcert = NULL;
977 
978 	Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ;
979 	if( !xCertTunnel.is() ) {
980 		throw RuntimeException() ;
981 	}
982 
983     xmlsec_trace("Start verification of certificate: \n %s",
984                  OUStringToOString(
985                      aCert->getSubjectName(), osl_getThreadTextEncoding()).getStr());
986 
987 	xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ;
988 	if( xcert == NULL ) {
989 		throw RuntimeException() ;
990 	}
991 
992 	pCertContext = xcert->getMswcryCert() ;
993 
994 	CERT_ENHKEY_USAGE	enhKeyUsage ;
995 	CERT_USAGE_MATCH	certUsage ;
996 	CERT_CHAIN_PARA		chainPara ;
997     rtl_zeroMemory(&chainPara, sizeof(CERT_CHAIN_PARA));
998 
999     //Prepare parameter for CertGetCertificateChain
1000 	enhKeyUsage.cUsageIdentifier = 0 ;
1001 	enhKeyUsage.rgpszUsageIdentifier = NULL ;
1002 	certUsage.dwType = USAGE_MATCH_TYPE_AND ;
1003 	certUsage.Usage = enhKeyUsage ;
1004 	chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ;
1005 	chainPara.RequestedUsage = certUsage ;
1006 
1007 
1008     HCERTSTORE hCollectionStore = NULL;
1009     HCERTSTORE hIntermediateCertsStore = NULL;
1010 	BOOL bChain = FALSE;
1011 	if( pCertContext != NULL )
1012     {
1013         hIntermediateCertsStore =
1014             getCertStoreForIntermediatCerts(seqCerts);
1015 
1016         //Merge m_hCertStore and m_hKeyStore and the store of the intermediate
1017         //certificates into one store.
1018         hCollectionStore = CertOpenStore(
1019 			CERT_STORE_PROV_COLLECTION ,
1020 			0 ,
1021 			NULL ,
1022 			0 ,
1023 			NULL
1024             ) ;
1025         if (hCollectionStore != NULL)
1026         {
1027             CertAddStoreToCollection (
1028 				hCollectionStore ,
1029 				m_hCertStore ,
1030 				CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
1031 				0) ;
1032             CertAddStoreToCollection (
1033 				hCollectionStore ,
1034 				m_hCertStore ,
1035 				CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
1036 				0) ;
1037             CertAddStoreToCollection (
1038                 hCollectionStore,
1039                 hIntermediateCertsStore,
1040                 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
1041                 0);
1042 
1043         }
1044 
1045         //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST
1046         //We do not check revocation of the root. In most cases there are none.
1047         //Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN
1048         xmlsec_trace("Verifying cert using revocation information.");
1049         bChain = CertGetCertificateChain(
1050             NULL ,
1051             pCertContext ,
1052             NULL , //use current system time
1053             hCollectionStore,
1054             &chainPara ,
1055             CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
1056             NULL ,
1057         	&pChainContext);
1058 
1059         if (bChain && pChainContext->cChain > 0)
1060         {
1061             xmlsec_trace("Overall error status (all chains):");
1062             traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus);
1063             //highest quality chains come first
1064             PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0];
1065             xmlsec_trace("Error status of first chain: ");
1066             traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus);
1067 
1068             //CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate
1069             //has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed.
1070             DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
1071                 CERT_TRUST_IS_OFFLINE_REVOCATION;
1072             DWORD otherErrorsMask = ~revocationFlags;
1073             if( !(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask))
1074 
1075             {
1076                 //No errors except maybe those caused by missing revocation information
1077                 //Check if there are errors
1078                 if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags)
1079                 {
1080                     //No revocation information. Because MSDN documentation is not
1081                     //clear about if all other tests are performed if an error occurrs,
1082                     //we test again, without requiring revocation checking.
1083                     CertFreeCertificateChain(pChainContext);
1084                     pChainContext = NULL;
1085                     xmlsec_trace("Checking again but without requiring revocation information.");
1086                     bChain = CertGetCertificateChain(
1087                         NULL ,
1088                         pCertContext ,
1089                         NULL , //use current system time
1090                         hCollectionStore,
1091                         &chainPara ,
1092                         0,
1093                         NULL ,
1094                         &pChainContext);
1095                     if (bChain
1096                         && pChainContext->cChain > 0
1097                         && pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
1098                     {
1099                         xmlsec_trace("Certificate is valid.\n");
1100                         validity = ::com::sun::star::security::CertificateValidity::VALID;
1101                     }
1102                     else
1103                     {
1104                         xmlsec_trace("Certificate is invalid.\n");
1105                     }
1106                 }
1107                 else
1108                 {
1109                     //valid and revocation information available
1110                     xmlsec_trace("Certificate is valid.\n");
1111                     validity = ::com::sun::star::security::CertificateValidity::VALID;
1112                 }
1113             }
1114             else
1115             {
1116                 //invalid
1117                 xmlsec_trace("Certificate is invalid.\n");
1118                 validity = ::com::sun::star::security::CertificateValidity::INVALID ;
1119             }
1120         }
1121         else
1122         {
1123             xmlsec_trace("CertGetCertificateChaine failed.\n");
1124         }
1125     }
1126 
1127     if (pChainContext)
1128     {
1129         CertFreeCertificateChain(pChainContext);
1130         pChainContext = NULL;
1131     }
1132 
1133     //Close the additional store, do not destroy the contained certs
1134     CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG);
1135     //Close the temporary store containing the intermediate certificates and make
1136     //sure all certificates are deleted.
1137     CertCloseStore(hIntermediateCertsStore, CERT_CLOSE_STORE_CHECK_FLAG);
1138 
1139 	return validity ;
1140 }
1141 
1142 sal_Int32 SecurityEnvironment_MSCryptImpl :: getCertificateCharacters( const ::com::sun::star::uno::Reference< ::com::sun::star::security::XCertificate >& aCert ) throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException ) {
1143 	sal_Int32 characters ;
1144 	PCCERT_CONTEXT pCertContext ;
1145 	const X509Certificate_MSCryptImpl* xcert ;
1146 
1147 	Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY ) ;
1148 	if( !xCertTunnel.is() ) {
1149 		throw RuntimeException() ;
1150 	}
1151 
1152 	xcert = ( X509Certificate_MSCryptImpl* )xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() ) ;
1153 	if( xcert == NULL ) {
1154 		throw RuntimeException() ;
1155 	}
1156 
1157 	pCertContext = xcert->getMswcryCert() ;
1158 
1159 	characters = 0x00000000 ;
1160 
1161 	//Firstly, make sentence whether or not the cert is self-signed.
1162 	if( CertCompareCertificateName( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->Subject), &(pCertContext->pCertInfo->Issuer) ) ) {
1163 		characters |= ::com::sun::star::security::CertificateCharacters::SELF_SIGNED ;
1164 	} else {
1165 		characters &= ~ ::com::sun::star::security::CertificateCharacters::SELF_SIGNED ;
1166 	}
1167 
1168 	//Secondly, make sentence whether or not the cert has a private key.
1169 	{
1170 		BOOL	fCallerFreeProv ;
1171 		DWORD	dwKeySpec ;
1172 		HCRYPTPROV	hProv ;
1173 		if( CryptAcquireCertificatePrivateKey( pCertContext ,
1174 				   0 ,
1175 				   NULL ,
1176 				   &( hProv ) ,
1177 				   &( dwKeySpec ) ,
1178 				   &( fCallerFreeProv ) )
1179 		) {
1180 			characters |=  ::com::sun::star::security::CertificateCharacters::HAS_PRIVATE_KEY ;
1181 
1182 			if( hProv != NULL && fCallerFreeProv )
1183 				CryptReleaseContext( hProv, 0 ) ;
1184 		} else {
1185 			characters &= ~ ::com::sun::star::security::CertificateCharacters::HAS_PRIVATE_KEY ;
1186 		}
1187 	}
1188 	return characters ;
1189 }
1190 
1191 void SecurityEnvironment_MSCryptImpl :: enableDefaultCrypt( sal_Bool enable ) throw( Exception, RuntimeException ) {
1192 	m_bEnableDefault = enable ;
1193 }
1194 
1195 sal_Bool SecurityEnvironment_MSCryptImpl :: defaultEnabled() throw( Exception, RuntimeException ) {
1196 	return m_bEnableDefault ;
1197 }
1198 
1199 X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert )
1200 {
1201 	X509Certificate_MSCryptImpl* xcert ;
1202 
1203 	if( cert != NULL ) {
1204 		xcert = new X509Certificate_MSCryptImpl() ;
1205 		if( xcert != NULL ) {
1206 			xcert->setMswcryCert( cert ) ;
1207 		}
1208 	} else {
1209 		xcert = NULL ;
1210 	}
1211 
1212 	return xcert ;
1213 }
1214 
1215 ::rtl::OUString SecurityEnvironment_MSCryptImpl::getSecurityEnvironmentInformation() throw( ::com::sun::star::uno::RuntimeException )
1216 {
1217 	return rtl::OUString::createFromAscii("Microsoft Crypto API");
1218 }
1219 
1220 /* Native methods */
1221 xmlSecKeysMngrPtr SecurityEnvironment_MSCryptImpl :: createKeysManager() throw( Exception, RuntimeException ) {
1222 
1223 	unsigned int i ;
1224 	HCRYPTKEY symKey ;
1225 	HCRYPTKEY pubKey ;
1226 	HCRYPTKEY priKey ;
1227 	xmlSecKeysMngrPtr pKeysMngr = NULL ;
1228 
1229 	/*-
1230 	 * The following lines is based on the of xmlsec-mscrypto crypto engine
1231 	 */
1232 	pKeysMngr = xmlSecMSCryptoAppliedKeysMngrCreate( m_hKeyStore , m_hCertStore ) ;
1233 	if( pKeysMngr == NULL )
1234 		throw RuntimeException() ;
1235 
1236 	/*-
1237 	 * Adopt symmetric key into keys manager
1238 	 */
1239 	for( i = 0 ; ( symKey = getSymKey( i ) ) != NULL ; i ++ ) {
1240 		if( xmlSecMSCryptoAppliedKeysMngrSymKeyLoad( pKeysMngr, symKey ) < 0 ) {
1241 			throw RuntimeException() ;
1242 		}
1243 	}
1244 
1245 	/*-
1246 	 * Adopt asymmetric public key into keys manager
1247 	 */
1248 	for( i = 0 ; ( pubKey = getPubKey( i ) ) != NULL ; i ++ ) {
1249 		if( xmlSecMSCryptoAppliedKeysMngrPubKeyLoad( pKeysMngr, pubKey ) < 0 ) {
1250 			throw RuntimeException() ;
1251 		}
1252 	}
1253 
1254 	/*-
1255 	 * Adopt asymmetric private key into keys manager
1256 	 */
1257 	for( i = 0 ; ( priKey = getPriKey( i ) ) != NULL ; i ++ ) {
1258 		if( xmlSecMSCryptoAppliedKeysMngrPriKeyLoad( pKeysMngr, priKey ) < 0 ) {
1259 			throw RuntimeException() ;
1260 		}
1261 	}
1262 
1263 	/*-
1264 	 * Adopt system default certificate store.
1265 	 */
1266 	if( defaultEnabled() ) {
1267 		HCERTSTORE hSystemStore ;
1268 
1269 		//Add system key store into the keys manager.
1270 		hSystemStore = CertOpenSystemStore( 0, "MY" ) ;
1271 		if( hSystemStore != NULL ) {
1272 			if( xmlSecMSCryptoAppliedKeysMngrAdoptKeyStore( pKeysMngr, hSystemStore ) < 0 ) {
1273 				CertCloseStore( hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
1274 				throw RuntimeException() ;
1275 			}
1276 		}
1277 
1278 		//Add system root store into the keys manager.
1279 		hSystemStore = CertOpenSystemStore( 0, "Root" ) ;
1280 		if( hSystemStore != NULL ) {
1281 			if( xmlSecMSCryptoAppliedKeysMngrAdoptTrustedStore( pKeysMngr, hSystemStore ) < 0 ) {
1282 				CertCloseStore( hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
1283 				throw RuntimeException() ;
1284 			}
1285 		}
1286 
1287 		//Add system trusted store into the keys manager.
1288 		hSystemStore = CertOpenSystemStore( 0, "Trust" ) ;
1289 		if( hSystemStore != NULL ) {
1290 			if( xmlSecMSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, hSystemStore ) < 0 ) {
1291 				CertCloseStore( hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
1292 				throw RuntimeException() ;
1293 			}
1294 		}
1295 
1296 		//Add system CA store into the keys manager.
1297 		hSystemStore = CertOpenSystemStore( 0, "CA" ) ;
1298 		if( hSystemStore != NULL ) {
1299 			if( xmlSecMSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, hSystemStore ) < 0 ) {
1300 				CertCloseStore( hSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
1301 				throw RuntimeException() ;
1302 			}
1303 		}
1304 	}
1305 
1306 	return pKeysMngr ;
1307 }
1308 void SecurityEnvironment_MSCryptImpl :: destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) throw( Exception, RuntimeException ) {
1309 	if( pKeysMngr != NULL ) {
1310 		xmlSecKeysMngrDestroy( pKeysMngr ) ;
1311 	}
1312 }
1313