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