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