1111 lines
39 KiB
C++
1111 lines
39 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <sal/config.h>
|
|
|
|
#include <cstddef>
|
|
#include <string.h>
|
|
|
|
#include <xmlsec/base64.h>
|
|
|
|
#if !defined WIN32_LEAN_AND_MEAN
|
|
# define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <Windows.h>
|
|
#include <WinCrypt.h>
|
|
#include <sal/macros.h>
|
|
#include <osl/thread.h>
|
|
#include "securityenvironment_mscryptimpl.hxx"
|
|
|
|
#include "x509certificate_mscryptimpl.hxx"
|
|
#include <comphelper/servicehelper.hxx>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/uno/XComponentContext.hpp>
|
|
#include <cppuhelper/supportsservice.hxx>
|
|
#include "akmngr.hxx"
|
|
|
|
#include <biginteger.hxx>
|
|
|
|
#include <comphelper/sequence.hxx>
|
|
#include <comphelper/windowserrorstring.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <rtl/locale.h>
|
|
#include <rtl/ref.hxx>
|
|
#include <osl/nlsupport.h>
|
|
#include <osl/process.h>
|
|
#include <o3tl/char16_t2wchar_t.hxx>
|
|
#include <svl/cryptosign.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::lang ;
|
|
|
|
using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
|
|
using ::com::sun::star::security::XCertificate ;
|
|
|
|
static rtl::Reference<X509Certificate_MSCryptImpl> MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ;
|
|
|
|
namespace {
|
|
|
|
struct CertErrorToString{
|
|
DWORD error;
|
|
char const * name;
|
|
};
|
|
|
|
}
|
|
|
|
CertErrorToString const arErrStrings[] =
|
|
{
|
|
{ 0x00000000, "CERT_TRUST_NO_ERROR"},
|
|
{ 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"},
|
|
{ 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"},
|
|
{ 0x00000004, "CERT_TRUST_IS_REVOKED" },
|
|
{ 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" },
|
|
{ 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"},
|
|
{ 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"},
|
|
{ 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"},
|
|
{ 0x00000080, "CERT_TRUST_IS_CYCLIC"},
|
|
{ 0x00000100, "CERT_TRUST_INVALID_EXTENSION"},
|
|
{ 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"},
|
|
{ 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"},
|
|
{ 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"},
|
|
{ 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"},
|
|
{ 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"},
|
|
{ 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"},
|
|
{ 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"},
|
|
{ 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"},
|
|
{ 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"},
|
|
{ 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"},
|
|
{ 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"},
|
|
//Chain errors
|
|
{ 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"},
|
|
{ 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"},
|
|
{ 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"},
|
|
{ 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"}
|
|
};
|
|
|
|
static void traceTrustStatus(DWORD err)
|
|
{
|
|
if (err == 0)
|
|
SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[0].name);
|
|
for (auto const & arErrStringIter : arErrStrings)
|
|
{
|
|
if (arErrStringIter.error & err)
|
|
SAL_INFO("xmlsecurity.xmlsec", " " << arErrStringIter.name);
|
|
}
|
|
}
|
|
|
|
SecurityEnvironment_MSCryptImpl::SecurityEnvironment_MSCryptImpl( const uno::Reference< uno::XComponentContext >& xContext ) : m_hProv( 0 ) , m_pszContainer( nullptr ) , m_hKeyStore( nullptr ), m_hCertStore( nullptr ), m_hMySystemStore(nullptr), m_hRootSystemStore(nullptr), m_hTrustSystemStore(nullptr), m_hCaSystemStore(nullptr), m_bEnableDefault( false ){
|
|
|
|
m_xServiceManager.set(xContext, uno::UNO_QUERY);
|
|
}
|
|
|
|
SecurityEnvironment_MSCryptImpl::~SecurityEnvironment_MSCryptImpl() {
|
|
|
|
if( m_hProv != 0 ) {
|
|
CryptReleaseContext( m_hProv, 0 ) ;
|
|
m_hProv = 0 ;
|
|
}
|
|
|
|
if( m_pszContainer != nullptr ) {
|
|
//TODO: Don't know whether or not it should be released now.
|
|
m_pszContainer = nullptr ;
|
|
}
|
|
|
|
if( m_hCertStore != nullptr ) {
|
|
CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
|
|
m_hCertStore = nullptr ;
|
|
}
|
|
|
|
if( m_hKeyStore != nullptr ) {
|
|
CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
|
|
m_hKeyStore = nullptr ;
|
|
}
|
|
|
|
//i120675, close the store handles
|
|
if( m_hMySystemStore != nullptr ) {
|
|
CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hMySystemStore = nullptr ;
|
|
}
|
|
|
|
if( m_hRootSystemStore != nullptr ) {
|
|
CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hRootSystemStore = nullptr ;
|
|
}
|
|
|
|
if( m_hTrustSystemStore != nullptr ) {
|
|
CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hTrustSystemStore = nullptr ;
|
|
}
|
|
|
|
if( m_hCaSystemStore != nullptr ) {
|
|
CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hCaSystemStore = nullptr ;
|
|
}
|
|
}
|
|
|
|
/* XServiceInfo */
|
|
OUString SAL_CALL SecurityEnvironment_MSCryptImpl::getImplementationName() {
|
|
return "com.sun.star.xml.crypto.SecurityEnvironment";
|
|
}
|
|
|
|
/* XServiceInfo */
|
|
sal_Bool SAL_CALL SecurityEnvironment_MSCryptImpl::supportsService( const OUString& serviceName) {
|
|
return cppu::supportsService(this, serviceName);
|
|
}
|
|
/* XServiceInfo */
|
|
uno::Sequence< OUString > SAL_CALL SecurityEnvironment_MSCryptImpl::getSupportedServiceNames() {
|
|
return { "com.sun.star.xml.crypto.SecurityEnvironment" };
|
|
}
|
|
|
|
HCRYPTPROV SecurityEnvironment_MSCryptImpl::getCryptoProvider() {
|
|
return m_hProv ;
|
|
}
|
|
|
|
void SecurityEnvironment_MSCryptImpl::setCryptoProvider( HCRYPTPROV aProv ) {
|
|
if( m_hProv != 0 ) {
|
|
CryptReleaseContext( m_hProv, 0 ) ;
|
|
m_hProv = 0 ;
|
|
}
|
|
|
|
if( aProv != 0 ) {
|
|
m_hProv = aProv ;
|
|
}
|
|
}
|
|
|
|
LPCTSTR SecurityEnvironment_MSCryptImpl::getKeyContainer() {
|
|
return m_pszContainer ;
|
|
}
|
|
|
|
void SecurityEnvironment_MSCryptImpl::setKeyContainer( LPCTSTR aKeyContainer ) {
|
|
//TODO: Don't know whether or not it should be copied.
|
|
m_pszContainer = aKeyContainer ;
|
|
}
|
|
|
|
|
|
HCERTSTORE SecurityEnvironment_MSCryptImpl::getCryptoSlot() {
|
|
return m_hKeyStore ;
|
|
}
|
|
|
|
void SecurityEnvironment_MSCryptImpl::setCryptoSlot( HCERTSTORE aSlot) {
|
|
if( m_hKeyStore != nullptr ) {
|
|
CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
|
|
m_hKeyStore = nullptr ;
|
|
}
|
|
|
|
if( aSlot != nullptr ) {
|
|
m_hKeyStore = CertDuplicateStore( aSlot ) ;
|
|
}
|
|
}
|
|
|
|
HCERTSTORE SecurityEnvironment_MSCryptImpl::getCertDb() {
|
|
return m_hCertStore ;
|
|
}
|
|
|
|
void SecurityEnvironment_MSCryptImpl::setCertDb( HCERTSTORE aCertDb ) {
|
|
if( m_hCertStore != nullptr ) {
|
|
CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
|
|
m_hCertStore = nullptr ;
|
|
}
|
|
|
|
if( aCertDb != nullptr ) {
|
|
m_hCertStore = CertDuplicateStore( aCertDb ) ;
|
|
}
|
|
}
|
|
|
|
#ifdef SAL_LOG_INFO
|
|
|
|
// Based on sample code from MSDN
|
|
|
|
static OUString get_system_name(const void *pvSystemStore,
|
|
DWORD dwFlags)
|
|
{
|
|
LPCWSTR ppwszSystemName;
|
|
if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
|
|
{
|
|
_CERT_SYSTEM_STORE_RELOCATE_PARA const * pRelocatePara;
|
|
pRelocatePara = static_cast<_CERT_SYSTEM_STORE_RELOCATE_PARA const *>(pvSystemStore);
|
|
ppwszSystemName = pRelocatePara->pwszSystemStore;
|
|
}
|
|
else
|
|
{
|
|
ppwszSystemName = static_cast<LPCWSTR>(pvSystemStore);
|
|
}
|
|
return OUString(o3tl::toU(ppwszSystemName));
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
static BOOL WINAPI cert_enum_physical_store_callback(const void *,
|
|
DWORD dwFlags,
|
|
LPCWSTR pwszStoreName,
|
|
PCERT_PHYSICAL_STORE_INFO,
|
|
void *,
|
|
void *)
|
|
{
|
|
OUString name(o3tl::toU(pwszStoreName));
|
|
if (dwFlags & CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG)
|
|
name += " (implicitly created)";
|
|
SAL_INFO("xmlsecurity.xmlsec", " Physical store: " << name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL WINAPI cert_enum_system_store_callback(const void *pvSystemStore,
|
|
DWORD dwFlags,
|
|
PCERT_SYSTEM_STORE_INFO,
|
|
void *,
|
|
void *)
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "System store: " << get_system_name(pvSystemStore, dwFlags));
|
|
|
|
if (!CertEnumPhysicalStore(pvSystemStore,
|
|
dwFlags,
|
|
nullptr,
|
|
cert_enum_physical_store_callback))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
if (!(ERROR_FILE_NOT_FOUND == dwErr ||
|
|
ERROR_NOT_SUPPORTED == dwErr))
|
|
{
|
|
SAL_WARN("xmlsecurity.xmlsec", "CertEnumPhysicalStore failed:" << WindowsErrorString(GetLastError()));
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
//Methods from XSecurityEnvironment
|
|
uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::getPersonalCertificates()
|
|
{
|
|
sal_Int32 length ;
|
|
rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
|
|
std::vector< rtl::Reference<X509Certificate_MSCryptImpl> > certsList ;
|
|
PCCERT_CONTEXT pCertContext = nullptr;
|
|
|
|
//firstly, we try to find private keys in given key store.
|
|
if( m_hKeyStore != nullptr ) {
|
|
pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext );
|
|
while (pCertContext)
|
|
{
|
|
xcert = MswcryCertContextToXCert( pCertContext ) ;
|
|
if( xcert.is() )
|
|
certsList.push_back( xcert ) ;
|
|
pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext );
|
|
}
|
|
}
|
|
|
|
//Thirdly, we try to find certificate from system default key store.
|
|
if( m_bEnableDefault ) {
|
|
HCERTSTORE hSystemKeyStore ;
|
|
DWORD dwKeySpec;
|
|
NCRYPT_KEY_HANDLE hCryptKey;
|
|
|
|
#ifdef SAL_LOG_INFO
|
|
CertEnumSystemStore(CERT_SYSTEM_STORE_CURRENT_USER, nullptr, nullptr, cert_enum_system_store_callback);
|
|
#endif
|
|
|
|
hSystemKeyStore = CertOpenSystemStoreW( 0, L"MY" ) ;
|
|
if( hSystemKeyStore != nullptr ) {
|
|
pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
|
|
while (pCertContext)
|
|
{
|
|
// for checking whether the certificate is a personal certificate or not.
|
|
DWORD dwFlags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG;
|
|
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hCryptKey;
|
|
if(!(CryptAcquireCertificatePrivateKey(pCertContext,
|
|
dwFlags,
|
|
nullptr,
|
|
phCryptProvOrNCryptKey,
|
|
&dwKeySpec,
|
|
nullptr)))
|
|
{
|
|
// Not Privatekey found. SKIP this one.
|
|
pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
|
|
continue;
|
|
}
|
|
// then TODO : Check the personal cert is valid or not.
|
|
|
|
xcert = MswcryCertContextToXCert( pCertContext ) ;
|
|
if( xcert.is() )
|
|
certsList.push_back( xcert ) ;
|
|
pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
|
|
}
|
|
}
|
|
|
|
CertCloseStore( hSystemKeyStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
}
|
|
|
|
length = certsList.size() ;
|
|
if( length != 0 ) {
|
|
int i = 0;
|
|
uno::Sequence< uno::Reference< XCertificate > > certSeq( length ) ;
|
|
auto pcertSeq = certSeq.getArray();
|
|
|
|
for( const auto& rXCert : certsList ) {
|
|
pcertSeq[i] = rXCert ;
|
|
++i;
|
|
}
|
|
|
|
return certSeq ;
|
|
}
|
|
|
|
return uno::Sequence< uno::Reference< XCertificate > >() ;
|
|
}
|
|
|
|
|
|
uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const uno::Sequence< sal_Int8 >& serialNumber ) {
|
|
unsigned int i ;
|
|
rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
|
|
PCCERT_CONTEXT pCertContext = nullptr ;
|
|
HCERTSTORE hCertStore = nullptr ;
|
|
CRYPT_INTEGER_BLOB cryptSerialNumber ;
|
|
CERT_INFO certInfo ;
|
|
|
|
// for correct encoding
|
|
rtl_Locale *pLocale = nullptr ;
|
|
osl_getProcessLocale( &pLocale ) ;
|
|
|
|
//Create cert info from issue and serial
|
|
LPCWSTR pszName = o3tl::toW( issuerName.getStr() );
|
|
|
|
if( ! ( CertStrToNameW(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
|
|
pszName ,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
|
|
nullptr ,
|
|
nullptr ,
|
|
&certInfo.Issuer.cbData, nullptr ) )
|
|
) {
|
|
return nullptr ;
|
|
}
|
|
|
|
certInfo.Issuer.pbData = static_cast<BYTE*>(malloc( certInfo.Issuer.cbData ));
|
|
if(!certInfo.Issuer.pbData)
|
|
throw uno::RuntimeException() ;
|
|
|
|
if( ! ( CertStrToNameW(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
|
|
pszName ,
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
|
|
nullptr ,
|
|
certInfo.Issuer.pbData ,
|
|
&certInfo.Issuer.cbData, nullptr ) )
|
|
) {
|
|
free( certInfo.Issuer.pbData ) ;
|
|
return nullptr ;
|
|
}
|
|
|
|
//Get the SerialNumber
|
|
cryptSerialNumber.cbData = serialNumber.getLength() ;
|
|
cryptSerialNumber.pbData = static_cast<BYTE*>(malloc( cryptSerialNumber.cbData));
|
|
if (!cryptSerialNumber.pbData)
|
|
{
|
|
free( certInfo.Issuer.pbData ) ;
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
for( i = 0; i < cryptSerialNumber.cbData; i ++ )
|
|
cryptSerialNumber.pbData[i] = serialNumber[ cryptSerialNumber.cbData - i - 1 ] ;
|
|
|
|
certInfo.SerialNumber.cbData = cryptSerialNumber.cbData ;
|
|
certInfo.SerialNumber.pbData = cryptSerialNumber.pbData ;
|
|
|
|
// Get the Cert from all store.
|
|
for( i = 0 ; i < 6 ; i ++ )
|
|
{
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
if(m_hKeyStore == nullptr) continue ;
|
|
hCertStore = m_hKeyStore ;
|
|
break;
|
|
case 1:
|
|
if(m_hCertStore == nullptr) continue ;
|
|
hCertStore = m_hCertStore ;
|
|
break;
|
|
case 2:
|
|
hCertStore = CertOpenSystemStoreW( 0, L"MY" ) ;
|
|
if(hCertStore == nullptr || !m_bEnableDefault) continue ;
|
|
break;
|
|
case 3:
|
|
hCertStore = CertOpenSystemStoreW( 0, L"Root" ) ;
|
|
if(hCertStore == nullptr || !m_bEnableDefault) continue ;
|
|
break;
|
|
case 4:
|
|
hCertStore = CertOpenSystemStoreW( 0, L"Trust" ) ;
|
|
if(hCertStore == nullptr || !m_bEnableDefault) continue ;
|
|
break;
|
|
case 5:
|
|
hCertStore = CertOpenSystemStoreW( 0, L"CA" ) ;
|
|
if(hCertStore == nullptr || !m_bEnableDefault) continue ;
|
|
break;
|
|
default:
|
|
i=6;
|
|
continue;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* This code reserved for remind us there are another way to find one cert by
|
|
* IssuerName&serialnumber. You can use the code to replaced the function
|
|
* CertFindCertificateInStore IF and ONLY IF you must find one special cert in
|
|
* certStore but can not be found by CertFindCertificateInStore , then , you
|
|
* should also change the same part in libxmlsec/.../src/mscrypto/x509vfy.c#875.
|
|
* By Chandler Peng(chandler.peng@sun.com)
|
|
*****/
|
|
/*******************************************************************************
|
|
pCertContext = NULL ;
|
|
found = 0;
|
|
do{
|
|
// 1. enum the certs has same string in the issuer string.
|
|
pCertContext = CertEnumCertificatesInStore( hCertStore , pCertContext ) ;
|
|
if( pCertContext != NULL )
|
|
{
|
|
// 2. check the cert's issuer name .
|
|
char* issuer = NULL ;
|
|
DWORD cbIssuer = 0 ;
|
|
|
|
cbIssuer = CertNameToStr(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
|
|
&( pCertContext->pCertInfo->Issuer ),
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
|
|
NULL, 0
|
|
) ;
|
|
|
|
if( cbIssuer == 0 ) continue ; // discard this cert;
|
|
|
|
issuer = (char *)malloc( cbIssuer ) ;
|
|
if( issuer == NULL ) // discard this cert;
|
|
{
|
|
free( cryptSerialNumber.pbData) ;
|
|
free( certInfo.Issuer.pbData ) ;
|
|
CertFreeCertificateContext( pCertContext ) ;
|
|
if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
throw RuntimeException() ;
|
|
}
|
|
|
|
cbIssuer = CertNameToStr(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
|
|
&( pCertContext->pCertInfo->Issuer ),
|
|
CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
|
|
issuer, cbIssuer
|
|
) ;
|
|
|
|
if( cbIssuer <= 0 )
|
|
{
|
|
free( issuer ) ;
|
|
continue ;// discard this cert;
|
|
}
|
|
|
|
if(strncmp(pszName , issuer , cbIssuer) != 0)
|
|
{
|
|
free( issuer ) ;
|
|
continue ;// discard this cert;
|
|
}
|
|
free( issuer ) ;
|
|
|
|
// 3. check the serial number.
|
|
if( memcmp( cryptSerialNumber.pbData , pCertContext->pCertInfo->SerialNumber.pbData , cryptSerialNumber.cbData ) != 0 )
|
|
{
|
|
continue ;// discard this cert;
|
|
}
|
|
|
|
// 4. confirm and break;
|
|
found = 1;
|
|
break ;
|
|
}
|
|
|
|
}while(pCertContext);
|
|
|
|
if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
if( found != 0 ) break; // Found the certificate.
|
|
********************************************************************************/
|
|
|
|
pCertContext = CertFindCertificateInStore(
|
|
hCertStore,
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0,
|
|
CERT_FIND_SUBJECT_CERT,
|
|
&certInfo,
|
|
nullptr
|
|
) ;
|
|
|
|
if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
if( pCertContext != nullptr ) break ; // Found the certificate.
|
|
|
|
}
|
|
|
|
free(cryptSerialNumber.pbData);
|
|
free(certInfo.Issuer.pbData);
|
|
|
|
if( pCertContext != nullptr ) {
|
|
xcert = MswcryCertContextToXCert(pCertContext);
|
|
CertFreeCertificateContext(pCertContext);
|
|
}
|
|
|
|
return xcert ;
|
|
}
|
|
|
|
uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const OUString& serialNumber ) {
|
|
uno::Sequence< sal_Int8 > serial = xmlsecurity::numericStringToBigInteger( serialNumber ) ;
|
|
return getCertificate( issuerName, serial ) ;
|
|
}
|
|
|
|
uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::buildCertificatePath( const uno::Reference< XCertificate >& begin ) {
|
|
PCCERT_CHAIN_CONTEXT pChainContext ;
|
|
PCCERT_CONTEXT pCertContext ;
|
|
|
|
CERT_ENHKEY_USAGE enhKeyUsage ;
|
|
CERT_USAGE_MATCH certUsage ;
|
|
CERT_CHAIN_PARA chainPara ;
|
|
|
|
enhKeyUsage.cUsageIdentifier = 0 ;
|
|
enhKeyUsage.rgpszUsageIdentifier = nullptr ;
|
|
certUsage.dwType = USAGE_MATCH_TYPE_AND ;
|
|
certUsage.Usage = enhKeyUsage ;
|
|
chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ;
|
|
chainPara.RequestedUsage = certUsage ;
|
|
|
|
const auto* xcert = dynamic_cast<X509Certificate_MSCryptImpl*>(begin.get());
|
|
if( xcert == nullptr ) {
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
|
|
pCertContext = xcert->getMswcryCert() ;
|
|
|
|
pChainContext = nullptr ;
|
|
|
|
bool bChain = false;
|
|
if( pCertContext != nullptr )
|
|
{
|
|
HCERTSTORE hAdditionalStore = nullptr;
|
|
HCERTSTORE hCollectionStore = nullptr;
|
|
if (m_hCertStore && m_hKeyStore)
|
|
{
|
|
//Merge m_hCertStore and m_hKeyStore into one store.
|
|
hCollectionStore = CertOpenStore(
|
|
CERT_STORE_PROV_COLLECTION ,
|
|
0 ,
|
|
0 ,
|
|
0 ,
|
|
nullptr
|
|
) ;
|
|
if (hCollectionStore != nullptr)
|
|
{
|
|
CertAddStoreToCollection (
|
|
hCollectionStore ,
|
|
m_hCertStore ,
|
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
|
|
0) ;
|
|
CertAddStoreToCollection (
|
|
hCollectionStore ,
|
|
m_hKeyStore,
|
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
|
|
0) ;
|
|
hAdditionalStore = hCollectionStore;
|
|
}
|
|
|
|
}
|
|
|
|
//if the merge of both stores failed then we add only m_hCertStore
|
|
if (hAdditionalStore == nullptr && m_hCertStore)
|
|
hAdditionalStore = m_hCertStore;
|
|
else if (hAdditionalStore == nullptr && m_hKeyStore)
|
|
hAdditionalStore = m_hKeyStore;
|
|
else
|
|
hAdditionalStore = nullptr;
|
|
|
|
//CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST
|
|
bChain = CertGetCertificateChain(
|
|
nullptr ,
|
|
pCertContext ,
|
|
nullptr , //use current system time
|
|
hAdditionalStore,
|
|
&chainPara ,
|
|
CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME ,
|
|
nullptr ,
|
|
&pChainContext);
|
|
if (!bChain)
|
|
pChainContext = nullptr;
|
|
|
|
//Close the additional store
|
|
CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
}
|
|
|
|
if(bChain && pChainContext != nullptr && pChainContext->cChain > 0 )
|
|
{
|
|
PCCERT_CONTEXT pCertInChain ;
|
|
PCERT_SIMPLE_CHAIN pCertChain ;
|
|
rtl::Reference<X509Certificate_MSCryptImpl> pCert ;
|
|
|
|
pCertChain = pChainContext->rgpChain[0] ;
|
|
if( pCertChain->cElement ) {
|
|
uno::Sequence< uno::Reference< XCertificate > > xCertChain( pCertChain->cElement ) ;
|
|
auto pxCertChain = xCertChain.getArray();
|
|
|
|
for( unsigned int i = 0 ; i < pCertChain->cElement ; i ++ ) {
|
|
if( pCertChain->rgpElement[i] )
|
|
pCertInChain = pCertChain->rgpElement[i]->pCertContext ;
|
|
else
|
|
pCertInChain = nullptr ;
|
|
|
|
if( pCertInChain != nullptr ) {
|
|
pCert = MswcryCertContextToXCert( pCertInChain ) ;
|
|
if( pCert.is() )
|
|
pxCertChain[i] = pCert ;
|
|
}
|
|
}
|
|
|
|
CertFreeCertificateChain( pChainContext ) ;
|
|
pChainContext = nullptr ;
|
|
|
|
return xCertChain ;
|
|
}
|
|
}
|
|
if (pChainContext)
|
|
CertFreeCertificateChain(pChainContext);
|
|
|
|
return uno::Sequence< uno::Reference < XCertificate > >();
|
|
}
|
|
|
|
uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::createCertificateFromRaw( const uno::Sequence< sal_Int8 >& rawCertificate ) {
|
|
rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
|
|
|
|
if( rawCertificate.getLength() > 0 ) {
|
|
xcert = new X509Certificate_MSCryptImpl() ;
|
|
xcert->setRawCert( rawCertificate ) ;
|
|
}
|
|
|
|
return xcert ;
|
|
}
|
|
|
|
uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::createCertificateFromAscii( const OUString& asciiCertificate )
|
|
{
|
|
OString oscert = OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ;
|
|
xmlChar* chCert = xmlStrndup( reinterpret_cast<const xmlChar*>(oscert.getStr()), static_cast<int>(oscert.getLength()) ) ;
|
|
xmlSecSize certSize;
|
|
int nRet = xmlSecBase64Decode_ex( chCert, reinterpret_cast<xmlSecByte*>(chCert), xmlStrlen( chCert ), &certSize ) ;
|
|
if (nRet < 0 || certSize == 0)
|
|
{
|
|
xmlFree(chCert);
|
|
return nullptr;
|
|
}
|
|
|
|
uno::Sequence<sal_Int8> rawCert(comphelper::arrayToSequence<sal_Int8>(chCert, certSize));
|
|
|
|
xmlFree( chCert ) ;
|
|
|
|
return createCertificateFromRaw( rawCert ) ;
|
|
}
|
|
|
|
static HCERTSTORE getCertStoreForIntermediatCerts(
|
|
const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts)
|
|
{
|
|
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, nullptr);
|
|
if (store == nullptr)
|
|
return nullptr;
|
|
|
|
for (const auto& i : seqCerts)
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << i->getSubjectName());
|
|
|
|
uno::Sequence<sal_Int8> data = i->getEncoded();
|
|
PCCERT_CONTEXT cert = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(&data[0]), data.getLength());
|
|
//Adding the certificate creates a copy and not just increases the ref count
|
|
//Therefore we free later the certificate that we now add
|
|
CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_ALWAYS, nullptr);
|
|
CertFreeCertificateContext(cert);
|
|
}
|
|
return store;
|
|
}
|
|
|
|
static bool CheckUnitTestStore(PCCERT_CHAIN_CONTEXT const pChainContext, DWORD ignoreFlags)
|
|
{
|
|
bool ret = false;
|
|
static char const*const pVar = getenv("LIBO_TEST_CRYPTOAPI_PKCS7");
|
|
if (!pVar)
|
|
{
|
|
return ret;
|
|
}
|
|
if (pChainContext->cChain == 0)
|
|
{
|
|
return ret;
|
|
}
|
|
PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0];
|
|
// check if untrusted root is the only problem
|
|
if (pSimpleChain->TrustStatus.dwErrorStatus & ~(CERT_TRUST_IS_UNTRUSTED_ROOT | ignoreFlags))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
// leak this store, re-opening is a waste of time in tests
|
|
static HCERTSTORE const hExtra = CertOpenStore(
|
|
CERT_STORE_PROV_FILENAME_A,
|
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
|
0,
|
|
CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
|
|
OString(OString::Concat(pVar) + "/test.p7b").getStr());
|
|
assert(hExtra != nullptr);
|
|
if (pSimpleChain->cElement < 1)
|
|
{
|
|
SAL_WARN("xmlsecurity.xmlsec", "unexpected empty chain");
|
|
return ret;
|
|
}
|
|
PCCERT_CONTEXT const pRoot(pSimpleChain->rgpElement[pSimpleChain->cElement-1]->pCertContext);
|
|
PCCERT_CONTEXT const pIssuerCert = CertFindCertificateInStore(
|
|
hExtra,
|
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
|
0,
|
|
CERT_FIND_SUBJECT_NAME,
|
|
&pRoot->pCertInfo->Subject,
|
|
nullptr);
|
|
if (pIssuerCert)
|
|
{
|
|
// check that it signed itself
|
|
DWORD flags = CERT_STORE_SIGNATURE_FLAG;
|
|
bool result = CertVerifySubjectCertificateContext(pRoot, pIssuerCert, &flags);
|
|
if (result && flags == 0)
|
|
{
|
|
ret = true;
|
|
}
|
|
}
|
|
CertFreeCertificateContext(pIssuerCert);
|
|
return ret;
|
|
}
|
|
|
|
//We return only valid or invalid, as long as the API documentation expresses
|
|
//explicitly that all validation steps are carried out even if one or several
|
|
//errors occur. See also
|
|
//http://wiki.openoffice.org/wiki/Certificate_Path_Validation#Validation_status
|
|
sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate(
|
|
const uno::Reference< css::security::XCertificate >& aCert,
|
|
const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts)
|
|
{
|
|
sal_Int32 validity = css::security::CertificateValidity::INVALID;
|
|
PCCERT_CHAIN_CONTEXT pChainContext = nullptr;
|
|
PCCERT_CONTEXT pCertContext = nullptr;
|
|
|
|
SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName());
|
|
|
|
const auto* xcert = dynamic_cast<X509Certificate_MSCryptImpl*>(aCert.get());
|
|
if( xcert == nullptr ) {
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
|
|
pCertContext = xcert->getMswcryCert() ;
|
|
|
|
CERT_ENHKEY_USAGE enhKeyUsage ;
|
|
CERT_USAGE_MATCH certUsage ;
|
|
CERT_CHAIN_PARA chainPara = {};
|
|
|
|
//Prepare parameter for CertGetCertificateChain
|
|
enhKeyUsage.cUsageIdentifier = 0 ;
|
|
enhKeyUsage.rgpszUsageIdentifier = nullptr ;
|
|
certUsage.dwType = USAGE_MATCH_TYPE_AND ;
|
|
certUsage.Usage = enhKeyUsage ;
|
|
chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ;
|
|
chainPara.RequestedUsage = certUsage ;
|
|
|
|
|
|
HCERTSTORE hCollectionStore = nullptr;
|
|
HCERTSTORE hIntermediateCertsStore = nullptr;
|
|
bool bChain = false;
|
|
if( pCertContext != nullptr )
|
|
{
|
|
hIntermediateCertsStore =
|
|
getCertStoreForIntermediatCerts(seqCerts);
|
|
|
|
//Merge m_hCertStore and m_hKeyStore and the store of the intermediate
|
|
//certificates into one store.
|
|
hCollectionStore = CertOpenStore(
|
|
CERT_STORE_PROV_COLLECTION ,
|
|
0 ,
|
|
0 ,
|
|
0 ,
|
|
nullptr
|
|
) ;
|
|
if (hCollectionStore != nullptr)
|
|
{
|
|
CertAddStoreToCollection (
|
|
hCollectionStore ,
|
|
m_hCertStore ,
|
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
|
|
0) ;
|
|
CertAddStoreToCollection (
|
|
hCollectionStore ,
|
|
m_hKeyStore,
|
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
|
|
0) ;
|
|
CertAddStoreToCollection (
|
|
hCollectionStore,
|
|
hIntermediateCertsStore,
|
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
|
|
0);
|
|
|
|
}
|
|
|
|
//CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST
|
|
//We do not check revocation of the root. In most cases there are none.
|
|
//Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN
|
|
SAL_INFO("xmlsecurity.xmlsec", "Verifying cert using revocation information.");
|
|
bChain = CertGetCertificateChain(
|
|
nullptr ,
|
|
pCertContext ,
|
|
nullptr , //use current system time
|
|
hCollectionStore,
|
|
&chainPara ,
|
|
CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
|
|
nullptr ,
|
|
&pChainContext);
|
|
|
|
if (bChain && pChainContext->cChain > 0)
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "Overall error status (all chains):");
|
|
traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus);
|
|
//highest quality chains come first
|
|
PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0];
|
|
SAL_INFO("xmlsecurity.xmlsec", "Error status of first chain:");
|
|
traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus);
|
|
|
|
//CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate
|
|
//has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed.
|
|
DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
|
|
CERT_TRUST_IS_OFFLINE_REVOCATION;
|
|
DWORD otherErrorsMask = ~revocationFlags;
|
|
if (!(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask)
|
|
|| CheckUnitTestStore(pChainContext, revocationFlags))
|
|
|
|
{
|
|
//No errors except maybe those caused by missing revocation information
|
|
//Check if there are errors
|
|
if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags)
|
|
{
|
|
//No revocation information. Because MSDN documentation is not
|
|
//clear about if all other tests are performed if an error occurs,
|
|
//we test again, without requiring revocation checking.
|
|
CertFreeCertificateChain(pChainContext);
|
|
pChainContext = nullptr;
|
|
SAL_INFO("xmlsecurity.xmlsec", "Checking again but without requiring revocation information.");
|
|
bChain = CertGetCertificateChain(
|
|
nullptr ,
|
|
pCertContext ,
|
|
nullptr , //use current system time
|
|
hCollectionStore,
|
|
&chainPara ,
|
|
0,
|
|
nullptr ,
|
|
&pChainContext);
|
|
if (bChain
|
|
&& pChainContext->cChain > 0
|
|
&& pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid.");
|
|
validity = css::security::CertificateValidity::VALID;
|
|
}
|
|
else if (CheckUnitTestStore(pChainContext, 0))
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "root certificate found in extra test store");
|
|
validity = css::security::CertificateValidity::VALID;
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//valid and revocation information available
|
|
SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid.");
|
|
validity = css::security::CertificateValidity::VALID;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//invalid
|
|
SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid.");
|
|
validity = css::security::CertificateValidity::INVALID ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChain failed.");
|
|
}
|
|
}
|
|
|
|
if (pChainContext)
|
|
{
|
|
CertFreeCertificateChain(pChainContext);
|
|
pChainContext = nullptr;
|
|
}
|
|
|
|
//Close the additional store, do not destroy the contained certs
|
|
CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
//Close the temporary store containing the intermediate certificates and make
|
|
//sure all certificates are deleted.
|
|
CertCloseStore(hIntermediateCertsStore, CERT_CLOSE_STORE_CHECK_FLAG);
|
|
|
|
return validity ;
|
|
}
|
|
|
|
sal_Int32 SecurityEnvironment_MSCryptImpl::getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& aCert ) {
|
|
sal_Int32 characters ;
|
|
PCCERT_CONTEXT pCertContext ;
|
|
|
|
const auto* xcert = dynamic_cast<X509Certificate_MSCryptImpl*>(aCert.get());
|
|
if( xcert == nullptr ) {
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
|
|
pCertContext = xcert->getMswcryCert() ;
|
|
|
|
characters = 0x00000000 ;
|
|
|
|
//Firstly, make sentence whether or not the cert is self-signed.
|
|
if( CertCompareCertificateName( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->Subject), &(pCertContext->pCertInfo->Issuer) ) ) {
|
|
characters |= css::security::CertificateCharacters::SELF_SIGNED ;
|
|
} else {
|
|
characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ;
|
|
}
|
|
|
|
//Secondly, make sentence whether or not the cert has a private key.
|
|
{
|
|
BOOL fCallerFreeProv ;
|
|
DWORD dwKeySpec ;
|
|
NCRYPT_KEY_HANDLE hKey = 0;
|
|
DWORD dwFlags = CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG;
|
|
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hKey;
|
|
if( CryptAcquireCertificatePrivateKey( pCertContext ,
|
|
dwFlags,
|
|
nullptr ,
|
|
phCryptProvOrNCryptKey,
|
|
&dwKeySpec,
|
|
&fCallerFreeProv )
|
|
) {
|
|
characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
|
|
|
|
if (hKey && fCallerFreeProv)
|
|
NCryptFreeObject(hKey);
|
|
} else {
|
|
characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
|
|
}
|
|
}
|
|
return characters ;
|
|
}
|
|
|
|
void SecurityEnvironment_MSCryptImpl::enableDefaultCrypt( bool enable ) {
|
|
m_bEnableDefault = enable ;
|
|
}
|
|
|
|
bool SecurityEnvironment_MSCryptImpl::defaultEnabled() {
|
|
return m_bEnableDefault ;
|
|
}
|
|
|
|
static rtl::Reference<X509Certificate_MSCryptImpl> MswcryCertContextToXCert( PCCERT_CONTEXT cert )
|
|
{
|
|
rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
|
|
|
|
if( cert != nullptr ) {
|
|
xcert = new X509Certificate_MSCryptImpl() ;
|
|
xcert->setMswcryCert( cert ) ;
|
|
}
|
|
|
|
return xcert ;
|
|
}
|
|
|
|
OUString SecurityEnvironment_MSCryptImpl::getSecurityEnvironmentInformation()
|
|
{
|
|
return "Microsoft Crypto API";
|
|
}
|
|
|
|
xmlSecKeysMngrPtr SecurityEnvironment_MSCryptImpl::createKeysManager() {
|
|
|
|
/*-
|
|
* The following lines is based on the of xmlsec-mscrypto crypto engine
|
|
*/
|
|
xmlSecKeysMngrPtr pKeysMngr = xmlsecurity::MSCryptoAppliedKeysMngrCreate() ;
|
|
if( pKeysMngr == nullptr )
|
|
throw uno::RuntimeException() ;
|
|
|
|
/*-
|
|
* Adopt system default certificate store.
|
|
*/
|
|
if( defaultEnabled() ) {
|
|
//Add system key store into the keys manager.
|
|
m_hMySystemStore = CertOpenSystemStoreW( 0, L"MY" ) ;
|
|
if( m_hMySystemStore != nullptr ) {
|
|
if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptKeyStore( pKeysMngr, m_hMySystemStore ) < 0 ) {
|
|
CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hMySystemStore = nullptr;
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
m_hMySystemStore = nullptr;
|
|
}
|
|
|
|
//Add system root store into the keys manager.
|
|
m_hRootSystemStore = CertOpenSystemStoreW( 0, L"Root" ) ;
|
|
if( m_hRootSystemStore != nullptr ) {
|
|
if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptTrustedStore( pKeysMngr, m_hRootSystemStore ) < 0 ) {
|
|
CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hRootSystemStore = nullptr;
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
m_hRootSystemStore = nullptr;
|
|
}
|
|
|
|
//Add system trusted store into the keys manager.
|
|
m_hTrustSystemStore = CertOpenSystemStoreW( 0, L"Trust" ) ;
|
|
if( m_hTrustSystemStore != nullptr ) {
|
|
if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hTrustSystemStore ) < 0 ) {
|
|
CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hTrustSystemStore = nullptr;
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
m_hTrustSystemStore = nullptr;
|
|
}
|
|
|
|
//Add system CA store into the keys manager.
|
|
m_hCaSystemStore = CertOpenSystemStoreW( 0, L"CA" ) ;
|
|
if( m_hCaSystemStore != nullptr ) {
|
|
if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hCaSystemStore ) < 0 ) {
|
|
CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
|
|
m_hCaSystemStore = nullptr;
|
|
throw uno::RuntimeException() ;
|
|
}
|
|
m_hCaSystemStore = nullptr;
|
|
}
|
|
}
|
|
|
|
return pKeysMngr ;
|
|
}
|
|
void SecurityEnvironment_MSCryptImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) {
|
|
if( pKeysMngr != nullptr ) {
|
|
xmlSecKeysMngrDestroy( pKeysMngr ) ;
|
|
}
|
|
}
|
|
|
|
extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
|
|
com_sun_star_xml_crypto_SecurityEnvironment_get_implementation(
|
|
uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
|
|
{
|
|
return cppu::acquire(new SecurityEnvironment_MSCryptImpl(pCtx));
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|