xref: /AOO41X/main/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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