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