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 = 0;
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