summaryrefslogtreecommitdiffstats
path: root/xmlsecurity/source/xmlsec/mscrypt
diff options
context:
space:
mode:
Diffstat (limited to 'xmlsecurity/source/xmlsec/mscrypt')
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx229
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx56
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/oid.hxx153
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx131
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx66
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx1118
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx173
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx173
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx71
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx786
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx96
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx155
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx312
13 files changed, 3519 insertions, 0 deletions
diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx
new file mode 100644
index 000000000..ec3cecd4a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <xmlsec-wrapper.h>
+
+#include "akmngr.hxx"
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscng/crypto.h>
+#include <xmlsec/mscng/keysstore.h>
+#include <xmlsec/mscng/x509.h>
+#include <svl/cryptosign.hxx>
+
+namespace xmlsecurity
+{
+
+/**
+ * MSCryptoAppliedKeysMngrCreate:
+ *
+ * Create and load key store and certificate database into keys manager
+ *
+ * Returns keys manager pointer on success or NULL otherwise.
+ */
+xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate()
+{
+ xmlSecKeysMngrPtr keyMngr = nullptr ;
+ xmlSecKeyStorePtr keyStore = nullptr ;
+
+ keyStore = xmlSecKeyStoreCreate(xmlSecMSCngKeysStoreId);
+ if (keyStore == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return nullptr ;
+ }
+
+ keyMngr = xmlSecKeysMngrCreate() ;
+ if (keyMngr == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+
+ xmlSecKeyStoreDestroy(keyStore) ;
+ return nullptr ;
+ }
+
+ /*-
+ * Add key store to manager, from now on keys manager destroys the store if
+ * needed
+ */
+ if (xmlSecKeysMngrAdoptKeysStore(keyMngr, keyStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(keyStore)),
+ "xmlSecKeysMngrAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+
+ xmlSecKeyStoreDestroy(keyStore) ;
+ xmlSecKeysMngrDestroy(keyMngr) ;
+ return nullptr ;
+ }
+
+ /*-
+ * Initialize crypto library specific data in keys manager
+ */
+ if (xmlSecMSCngKeysMngrInit(keyMngr) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecMSCngKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ xmlSecKeysMngrDestroy(keyMngr);
+ return nullptr;
+ }
+
+ /*-
+ * Set certificate database to X509 key data store
+ */
+ /*-
+ * At present, MS Crypto engine do not provide a way to setup a cert store.
+ */
+
+ /*-
+ * Set the getKey callback
+ */
+ keyMngr->getKey = xmlSecKeysMngrGetKey ;
+
+ return keyMngr ;
+}
+
+int
+MSCryptoAppliedKeysMngrAdoptKeyStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE keyStore
+)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2(mngr != nullptr, -1) ;
+ xmlSecAssert2(keyStore != nullptr, -1) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId);
+ if (x509Store == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return -1 ;
+ }
+
+ if (xmlSecMSCngX509StoreAdoptKeyStore(x509Store, keyStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)),
+ "xmlSecMSCngX509StoreAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+
+ return 0 ;
+}
+
+int
+MSCryptoAppliedKeysMngrAdoptTrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE trustedStore
+)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2(mngr != nullptr, -1) ;
+ xmlSecAssert2(trustedStore != nullptr, -1) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId);
+ if (x509Store == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return -1 ;
+ }
+
+ if (xmlSecMSCngX509StoreAdoptTrustedStore(x509Store, trustedStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)),
+ "xmlSecMSCngX509StoreAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+
+ return 0 ;
+}
+
+int
+MSCryptoAppliedKeysMngrAdoptUntrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE untrustedStore
+)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2(mngr != nullptr, -1) ;
+ xmlSecAssert2(untrustedStore != nullptr, -1) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId);
+ if (x509Store == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return -1 ;
+ }
+
+ if (xmlSecMSCngX509StoreAdoptUntrustedStore(x509Store, untrustedStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)),
+ "xmlSecMSCngX509StoreAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+
+ return 0 ;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx
new file mode 100644
index 000000000..e5942ba2a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 .
+ */
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+
+namespace xmlsecurity
+{
+
+xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate();
+
+int
+MSCryptoAppliedKeysMngrAdoptKeyStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE keyStore
+) ;
+
+int
+MSCryptoAppliedKeysMngrAdoptTrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE trustedStore
+) ;
+
+int
+MSCryptoAppliedKeysMngrAdoptUntrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE untrustedStore
+) ;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/oid.hxx b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx
new file mode 100644
index 000000000..ce573d882
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx
@@ -0,0 +1,153 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/macros.h>
+
+typedef struct {
+ char const *oid;
+ char const *desc;
+} OIDItem;
+
+OIDItem OIDs[] = {
+ {"1.2.840.113549", "RSA Data Security Inc."},
+ {"1.2.840.113549.1", "PKCS"},
+ {"1.2.840.113549.2", "RSA digest algorithm"},
+ {"1.2.840.113549.3", "RSA cipher algorithm"},
+ {"1.2.840.113549.1.1", "PKCS #1"},
+ {"1.2.840.113549.1.2", "Unknown"},
+ {"1.2.840.113549.1.3", "Unknown"},
+ {"1.2.840.113549.1.4", "Unknown"},
+ {"1.2.840.113549.1.5", "PKCS #5"},
+ {"1.2.840.113549.1.6", "Unknown"},
+ {"1.2.840.113549.1.7", "PKCS #7"},
+ {"1.2.840.113549.1.8", "Unknown"},
+ {"1.2.840.113549.1.9", "PKCS #9"},
+ {"1.2.840.113549.1.10", "Unknown"},
+ {"1.2.840.113549.1.12", "PKCS #12"},
+ {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"},
+ {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"},
+ {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"},
+ {"1.2.840.113549.1.1.1", "PKCS #1 RSA Encryption"},
+ {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"},
+ {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"},
+ {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"},
+ {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"},
+ {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"},
+ {"1.2.840.113549.1.3.1", "Unknown"},
+ {"1.2.840.113549.1.7.1", "PKCS #7 Data"},
+ {"1.2.840.113549.1.7.2", "PKCS #7 Signed Data"},
+ {"1.2.840.113549.1.7.3", "PKCS #7 Enveloped Data"},
+ {"1.2.840.113549.1.7.4", "PKCS #7 Signed and Enveloped Data"},
+ {"1.2.840.113549.1.7.5", "PKCS #7 Digested Data"},
+ {"1.2.840.113549.1.7.6", "PKCS #7 Encrypted Data"},
+ {"1.2.840.113549.1.9.1", "PKCS #9 Email Address"},
+ {"1.2.840.113549.1.9.2", "PKCS #9 Unstructured Name"},
+ {"1.2.840.113549.1.9.3", "PKCS #9 Content Type"},
+ {"1.2.840.113549.1.9.4", "PKCS #9 Message Digest"},
+ {"1.2.840.113549.1.9.5", "PKCS #9 Signing Time"},
+ {"1.2.840.113549.1.9.6", "PKCS #9 Counter Signature"},
+ {"1.2.840.113549.1.9.7", "PKCS #9 Challenge Password"},
+ {"1.2.840.113549.1.9.8", "PKCS #9 Unstructured Address"},
+ {"1.2.840.113549.1.9.9", "PKCS #9 Extended Certificate Attributes"},
+ {"1.2.840.113549.1.9.15", "PKCS #9 S/MIME Capabilities"},
+ {"1.2.840.113549.1.9.15.1", "Unknown"},
+ {"1.2.840.113549.3.2", "RC2-CBC"},
+ {"1.2.840.113549.3.4", "RC4"},
+ {"1.2.840.113549.3.7", "DES-EDE3-CBC"},
+ {"1.2.840.113549.3.9", "RC5-CBCPad"},
+ {"1.2.840.10046", "ANSI X9.42"},
+ {"1.2.840.10046.2.1", "Diffie-Hellman Public Key Algorithm"},
+ {"1.2.840.10040", "ANSI X9.57"},
+ {"1.2.840.10040.4.1", "ANSI X9.57 DSA Signature"},
+ {"1.2.840.10040.4.3", "ANSI X9.57 Algorithm DSA Signature with SHA-1 Digest"},
+ {"2.5", "Directory"},
+ {"2.5.8", "X.500-defined algorithms"},
+ {"2.5.8.1", "X.500-defined encryption algorithms"},
+ {"2.5.8.2", "Unknown"},
+ {"2.5.8.3", "Unknown"},
+ {"2.5.8.1.1", "RSA Encryption Algorithm"},
+ {"1.3.14", "Open Systems Implementors Workshop"},
+ {"1.3.14.3.2", "OIW SECSIG Algorithm"},
+ {"1.3.14.3.2.2", "Unknown"},
+ {"1.3.14.3.2.3", "Unknown"},
+ {"1.3.14.3.2.4", "Unknown"},
+ {"1.3.14.3.2.6", "DES-ECB"},
+ {"1.3.14.3.2.7", "DES-CBC"},
+ {"1.3.14.3.2.8", "DES-OFB"},
+ {"1.3.14.3.2.9", "DES-CFB"},
+ {"1.3.14.3.2.10", "DES-MAC"},
+ {"1.3.14.3.2.11", "Unknown"},
+ {"1.3.14.3.2.12", "Unknown"},
+ {"1.3.14.3.2.13", "Unknown"},
+ {"1.3.14.3.2.14", "Unknown"},
+ {"1.3.14.3.2.15", "ISO SHA with RSA Signature"},
+ {"1.3.14.3.2.16", "Unknown"},
+ {"1.3.14.3.2.17", "DES-EDE"},
+ {"1.3.14.3.2.18", "Unknown"},
+ {"1.3.14.3.2.19", "Unknown"},
+ {"1.3.14.3.2.20", "Unknown"},
+ {"1.3.14.3.2.21", "Unknown"},
+ {"1.3.14.3.2.22", "Unknown"},
+ {"1.3.14.3.2.23", "Unknown"},
+ {"1.3.14.3.2.24", "Unknown"},
+ {"1.3.14.3.2.25", "Unknown"},
+ {"1.3.14.3.2.26", "SHA-1"},
+ {"1.3.14.3.2.27", "Forgezza DSA Signature with SHA-1 Digest"},
+ {"1.3.14.3.2.28", "Unknown"},
+ {"1.3.14.3.2.29", "Unknown"},
+ {"1.3.14.7.2", "Unknown"},
+ {"1.3.14.7.2.1", "Unknown"},
+ {"1.3.14.7.2.2", "Unknown"},
+ {"1.3.14.7.2.3", "Unknown"},
+ {"1.3.14.7.2.2.1", "Unknown"},
+ {"1.3.14.7.2.3.1", "Unknown"},
+ {"2.16.840.1.101.2.1", "US DOD Infosec"},
+ {"2.16.840.1.101.2.1.1.1", "Unknown"},
+ {"2.16.840.1.101.2.1.1.2", "MISSI DSS Algorithm (Old)"},
+ {"2.16.840.1.101.2.1.1.3", "Unknown"},
+ {"2.16.840.1.101.2.1.1.4", "Skipjack CBC64"},
+ {"2.16.840.1.101.2.1.1.5", "Unknown"},
+ {"2.16.840.1.101.2.1.1.6", "Unknown"},
+ {"2.16.840.1.101.2.1.1.7", "Unknown"},
+ {"2.16.840.1.101.2.1.1.8", "Unknown"},
+ {"2.16.840.1.101.2.1.1.9", "Unknown"},
+ {"2.16.840.1.101.2.1.1.10", "MISSI KEA Algorithm"},
+ {"2.16.840.1.101.2.1.1.11", "Unknown"},
+ {"2.16.840.1.101.2.1.1.12", "MISSI KEA and DSS Algorithm (Old)"},
+ {"2.16.840.1.101.2.1.1.13", "Unknown"},
+ {"2.16.840.1.101.2.1.1.14", "Unknown"},
+ {"2.16.840.1.101.2.1.1.15", "Unknown"},
+ {"2.16.840.1.101.2.1.1.16", "Unknown"},
+ {"2.16.840.1.101.2.1.1.17", "Unknown"},
+ {"2.16.840.1.101.2.1.1.18", "Unknown"},
+ {"2.16.840.1.101.2.1.1.19", "MISSI DSS Algorithm"},
+ {"2.16.840.1.101.2.1.1.20", "MISSI KEA and DSS Algorithm"},
+ {"2.16.840.1.101.2.1.1.21", "Unknown"},
+ {"1.2.643.2.2.35.0", "GOST_R_34.10-2001_Test"},
+ {"1.2.643.2.2.35.1", "GOST_R_34.10-2001_Sign_DH_PRO"},
+ {"1.2.643.2.2.35.2", "GOST_R_34.10-2001_Sign_DH_CARD"},
+ {"1.2.643.2.2.35.3", "GOST_R_34.10-2001_Sign_DH"},
+ {"1.2.643.2.2.36.0", "GOST_R_34.10-2001_Sign_DH_PRO"}
+};
+
+const int nOID = SAL_N_ELEMENTS(OIDs);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx
new file mode 100644
index 000000000..6ded5fa0c
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx
@@ -0,0 +1,131 @@
+/* -*- 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 <memory>
+
+#include <rtl/uuid.h>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/security/ExtAltNameType.hpp>
+#include <com/sun/star/security/CertAltNameEntry.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <comphelper/sequence.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+#include "sanextension_mscryptimpl.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::security ;
+
+using ::com::sun::star::security::XCertificateExtension ;
+
+
+SanExtensionImpl::SanExtensionImpl() :
+ m_critical( false )
+{
+}
+
+SanExtensionImpl::~SanExtensionImpl() {
+}
+
+
+//Methods from XCertificateExtension
+sal_Bool SAL_CALL SanExtensionImpl::isCritical() {
+ return m_critical ;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL SanExtensionImpl::getExtensionId() {
+ return m_xExtnId ;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL SanExtensionImpl::getExtensionValue() {
+ return m_xExtnValue ;
+}
+
+//Methods from XSanExtension
+css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL SanExtensionImpl::getAlternativeNames(){
+
+ if (!m_Entries.hasElements())
+ {
+ CERT_ALT_NAME_INFO *subjectName;
+ DWORD size;
+ CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, reinterpret_cast<unsigned char*>(m_xExtnValue.getArray()), m_xExtnValue.getLength(), CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, nullptr,&subjectName, &size);
+
+ auto arrCertAltNameEntry = std::make_unique<CertAltNameEntry[]>(subjectName->cAltEntry);
+
+ for (unsigned int i = 0; i < static_cast<unsigned int>(subjectName->cAltEntry); i++){
+ PCERT_ALT_NAME_ENTRY pEntry = &subjectName->rgAltEntry[i];
+
+ switch(pEntry->dwAltNameChoice) {
+ case CERT_ALT_NAME_OTHER_NAME :
+ {
+ arrCertAltNameEntry[i].Type = ExtAltNameType_OTHER_NAME;
+ PCERT_OTHER_NAME pOtherName = pEntry->pOtherName;
+
+ css::beans::NamedValue otherNameProp;
+ otherNameProp.Name = OUString::createFromAscii(pOtherName->pszObjId);
+
+ Sequence< sal_Int8 > otherName( comphelper::arrayToSequence<sal_Int8>(
+ pOtherName->Value.pbData, pOtherName->Value.cbData) );
+ otherNameProp.Value <<= otherName;
+
+ arrCertAltNameEntry[i].Value <<= otherNameProp;
+ break;
+ }
+ case CERT_ALT_NAME_RFC822_NAME :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_RFC822_NAME;
+ arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszRfc822Name));
+ break;
+ case CERT_ALT_NAME_DNS_NAME :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_DNS_NAME;
+ arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszDNSName));
+ break;
+ case CERT_ALT_NAME_DIRECTORY_NAME :
+ {
+ arrCertAltNameEntry[i].Type = ExtAltNameType_DIRECTORY_NAME;
+ break;
+ }
+ case CERT_ALT_NAME_URL :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_URL;
+ arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszURL));
+ break;
+ case CERT_ALT_NAME_IP_ADDRESS :
+ {
+ arrCertAltNameEntry[i].Type = ExtAltNameType_IP_ADDRESS;
+
+ Sequence< sal_Int8 > ipAddress( comphelper::arrayToSequence<sal_Int8>(
+ pEntry->IPAddress.pbData, pEntry->IPAddress.cbData) );
+ arrCertAltNameEntry[i].Value <<= ipAddress;
+ break;
+ }
+ case CERT_ALT_NAME_REGISTERED_ID :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_REGISTERED_ID;
+ arrCertAltNameEntry[i].Value <<= OUString::createFromAscii(pEntry->pszRegisteredID);
+ break;
+ }
+ }
+ m_Entries = ::comphelper::arrayToSequence< css::security::CertAltNameEntry >(arrCertAltNameEntry.get(), subjectName->cAltEntry);
+ }
+
+ return m_Entries;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx
new file mode 100644
index 000000000..6c65c84f8
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx
@@ -0,0 +1,66 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <Windows.h>
+#include <WinCrypt.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/XCertificateExtension.hpp>
+#include <com/sun/star/security/XSanExtension.hpp>
+#include <com/sun/star/security/CertAltNameEntry.hpp>
+
+class SanExtensionImpl : public ::cppu::WeakImplHelper<
+ css::security::XSanExtension >
+{
+ private:
+ bool m_critical ;
+ css::uno::Sequence< sal_Int8 > m_xExtnId ;
+ css::uno::Sequence< sal_Int8 > m_xExtnValue ;
+
+ css::uno::Sequence< css::security::CertAltNameEntry > m_Entries;
+
+ public:
+ SanExtensionImpl() ;
+ virtual ~SanExtensionImpl() override;
+
+ //Methods from XCertificateExtension
+ virtual sal_Bool SAL_CALL isCritical() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override;
+
+ //Methods from XSanExtension
+
+ virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override;
+
+ //Helper method
+ void setCertExtn( unsigned char* value, unsigned int vlen, unsigned char* id, unsigned int idlen, bool critical ) ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
new file mode 100644
index 000000000..f198f839f
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
@@ -0,0 +1,1118 @@
+/* -*- 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>
+
+#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 <xmlsec-wrapper.h>
+#include "akmngr.hxx"
+
+#include <biginteger.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::lang::XMultiServiceFactory ;
+using ::com::sun::star::lang::XSingleServiceFactory ;
+
+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 (std::size_t i = 1; i < SAL_N_ELEMENTS(arErrStrings); i++)
+ {
+ if (arErrStrings[i].error & err)
+ SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[i].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" };
+}
+
+/* XUnoTunnel */
+UNO3_GETIMPLEMENTATION_IMPL(SecurityEnvironment_MSCryptImpl);
+
+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 ;
+
+ uno::Reference< XUnoTunnel > xCertTunnel( begin, uno::UNO_QUERY_THROW ) ;
+ const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel);
+ 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 = xmlSecBase64Decode( chCert, chCert, xmlStrlen( chCert ) ) ;
+
+ uno::Sequence< sal_Int8 > rawCert( certSize ) ;
+ auto rawCertRange = asNonConstRange(rawCert);
+ for( xmlSecSize i = 0 ; i < certSize ; i ++ )
+ rawCertRange[i] = *( chCert + i ) ;
+
+ 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 (int i = 0; i < seqCerts.getLength(); i++)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << seqCerts[i]->getSubjectName());
+
+ uno::Sequence<sal_Int8> data = seqCerts[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;
+
+ uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ;
+
+ SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName());
+
+ const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel);
+ 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 ;
+
+ uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ;
+ const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel);
+ 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: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx
new file mode 100644
index 000000000..a4ae45742
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx
@@ -0,0 +1,173 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/security/CertificateCharacters.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+#include <vector>
+#include <xmlsec-wrapper.h>
+
+#include <sal/types.h>
+
+
+class SecurityEnvironment_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XSecurityEnvironment ,
+ css::lang::XServiceInfo,
+ css::lang::XUnoTunnel >
+{
+ private:
+ //crypto provider and key container
+ HCRYPTPROV m_hProv ;
+ LPCTSTR m_pszContainer ;
+
+ //Key store
+ HCERTSTORE m_hKeyStore ;
+
+ //Certificate store
+ HCERTSTORE m_hCertStore ;
+
+ // i120675, save the store handles
+ HCERTSTORE m_hMySystemStore;
+ HCERTSTORE m_hRootSystemStore;
+ HCERTSTORE m_hTrustSystemStore;
+ HCERTSTORE m_hCaSystemStore;
+
+ //Enable default system cryptography setting
+ bool m_bEnableDefault ;
+
+ //Service manager
+ css::uno::Reference< css::lang::XMultiServiceFactory > m_xServiceManager ;
+
+ public:
+ explicit SecurityEnvironment_MSCryptImpl( const css::uno::Reference< css::uno::XComponentContext >& xContext ) ;
+ virtual ~SecurityEnvironment_MSCryptImpl() override;
+
+ //Methods from XSecurityEnvironment
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override
+ { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); }
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate(
+ const OUString& issuerName,
+ const css::uno::Sequence< sal_Int8 >& serialNumber ) override;
+
+ /// @throws css::uno::SecurityException
+ /// @throws css::uno::RuntimeException
+ virtual css::uno::Reference< css::security::XCertificate > getCertificate(
+ const OUString& issuerName,
+ const OUString& serialNumber ) ;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath(
+ const css::uno::Reference< css::security::XCertificate >& beginCert ) override;
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw(
+ const css::uno::Sequence< sal_Int8 >& rawCertificate ) override;
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii(
+ const OUString& asciiCertificate ) override;
+
+ virtual ::sal_Int32 SAL_CALL verifyCertificate(
+ const css::uno::Reference< css::security::XCertificate >& xCert,
+ const css::uno::Sequence< css::uno::Reference<
+ css::security::XCertificate > >& intermediateCertificates) override;
+
+ virtual ::sal_Int32 SAL_CALL getCertificateCharacters(
+ const css::uno::Reference< css::security::XCertificate >& xCert ) override;
+
+ virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override;
+
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //Methods from XUnoTunnel
+ UNO3_GETIMPLEMENTATION_DECL(SecurityEnvironment_MSCryptImpl)
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ HCRYPTPROV getCryptoProvider() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCryptoProvider( HCRYPTPROV aProv ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ LPCTSTR getKeyContainer() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setKeyContainer( LPCTSTR aKeyContainer ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ HCERTSTORE getCryptoSlot() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCryptoSlot( HCERTSTORE aKeyStore ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ HCERTSTORE getCertDb() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCertDb( HCERTSTORE aCertDb ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void enableDefaultCrypt( bool enable ) ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ bool defaultEnabled() ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ xmlSecKeysMngrPtr createKeysManager() ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx
new file mode 100644
index 000000000..08143f992
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx
@@ -0,0 +1,173 @@
+/* -*- 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 <xmlsec-wrapper.h>
+
+#include "seinitializer_mscryptimpl.hxx"
+
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include <xmlsec/mscng/app.h>
+#include <com/sun/star/xml/crypto/SecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/XMLSecurityContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <svl/cryptosign.hxx>
+
+using namespace com::sun::star;
+namespace cssl = com::sun::star::lang;
+namespace cssxc = com::sun::star::xml::crypto;
+
+SEInitializer_MSCryptImpl::SEInitializer_MSCryptImpl(
+ const uno::Reference< uno::XComponentContext > &rxContext)
+ :mxContext( rxContext )
+{
+}
+
+SEInitializer_MSCryptImpl::~SEInitializer_MSCryptImpl()
+{
+}
+
+/* XSEInitializer */
+uno::Reference< cssxc::XXMLSecurityContext > SAL_CALL
+ SEInitializer_MSCryptImpl::createSecurityContext(
+ const OUString& sCertDB )
+{
+ const char* n_pCertStore ;
+ HCERTSTORE n_hStoreHandle ;
+ OString sCertDir;
+
+ //Initialize the crypto engine
+ if( sCertDB.getLength() > 0 )
+ {
+ sCertDir = OString(sCertDB.getStr(), sCertDB.getLength(), RTL_TEXTENCODING_ASCII_US);
+ n_pCertStore = sCertDir.getStr();
+ n_hStoreHandle = CertOpenSystemStoreW( 0, o3tl::toW(sCertDB.getStr())) ;
+ if( n_hStoreHandle == nullptr )
+ {
+ return nullptr;
+ }
+ }
+ else
+ {
+ n_pCertStore = nullptr ;
+ n_hStoreHandle = nullptr ;
+ }
+
+ xmlSecMSCngAppInit(n_pCertStore);
+
+ try {
+ /* Build Security Environment */
+ uno::Reference< cssxc::XSecurityEnvironment > xSecEnv = cssxc::SecurityEnvironment::create( mxContext );
+
+ /* Setup key slot and certDb */
+ uno::Reference< cssl::XUnoTunnel > xSecEnvTunnel( xSecEnv, uno::UNO_QUERY_THROW );
+ SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecEnvTunnel);
+ if( pSecEnv == nullptr )
+ {
+ if( n_hStoreHandle != nullptr )
+ {
+ CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ }
+
+ xmlSecMSCngAppShutdown();
+ return nullptr;
+ }
+
+ if( n_hStoreHandle != nullptr )
+ {
+ pSecEnv->setCryptoSlot( n_hStoreHandle ) ;
+ pSecEnv->setCertDb( n_hStoreHandle ) ;
+ }
+ else
+ {
+ pSecEnv->enableDefaultCrypt( true ) ;
+ }
+
+ /* Build XML Security Context */
+ uno::Reference< cssxc::XXMLSecurityContext > xSecCtx = cssxc::XMLSecurityContext::create( mxContext );
+
+ xSecCtx->setDefaultSecurityEnvironmentIndex(xSecCtx->addSecurityEnvironment( xSecEnv )) ;
+ return xSecCtx;
+ }
+ catch( uno::Exception& )
+ {
+ if( n_hStoreHandle != nullptr )
+ {
+ CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ }
+
+ xmlSecMSCngAppShutdown();
+ return nullptr;
+ }
+}
+
+void SAL_CALL SEInitializer_MSCryptImpl::freeSecurityContext( const uno::Reference< cssxc::XXMLSecurityContext >&)
+{
+ /*
+ uno::Reference< cssxc::XSecurityEnvironment > xSecEnv
+ = securityContext->getSecurityEnvironment();
+
+ if( xSecEnv.is() )
+ {
+ uno::Reference< cssl::XUnoTunnel > xEnvTunnel( xSecEnv , uno::UNO_QUERY ) ;
+ if (auto pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xEnvTunnel))
+ {
+ HCERTSTORE n_hStoreHandle = pSecEnv->getCryptoSlot();
+
+ if( n_hStoreHandle != NULL )
+ {
+ CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ pSecEnv->setCryptoSlot( NULL ) ;
+ pSecEnv->setCertDb( NULL ) ;
+ }
+
+ xmlSecMSCryptoAppShutdown() ;
+ }
+ }
+ */
+
+ xmlSecMSCngAppShutdown();
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SEInitializer_MSCryptImpl::getImplementationName()
+{
+ return "com.sun.star.xml.crypto.SEInitializer";
+}
+
+sal_Bool SAL_CALL SEInitializer_MSCryptImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL SEInitializer_MSCryptImpl::getSupportedServiceNames()
+{
+ return { "com.sun.star.xml.crypto.SEInitializer" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_SEInitializer_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SEInitializer_MSCryptImpl(pCtx));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx
new file mode 100644
index 000000000..182ba5e5a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx
@@ -0,0 +1,71 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <libxml/tree.h>
+
+class SEInitializer_MSCryptImpl : public cppu::WeakImplHelper
+<
+ css::xml::crypto::XSEInitializer,
+ css::lang::XServiceInfo
+>
+/****** SEInitializer_MSCryptImpl.hxx/CLASS SEInitializer_MSCryptImpl ***********
+ *
+ * NAME
+ * SEInitializer_MSCryptImpl -- Class to initialize a Security Context
+ * instance
+ *
+ * FUNCTION
+ * Use this class to initialize a XmlSec based Security Context
+ * instance. After this instance is used up, use this class to free this
+ * instance.
+ ******************************************************************************/
+{
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+
+public:
+ explicit SEInitializer_MSCryptImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext);
+ virtual ~SEInitializer_MSCryptImpl() override;
+
+ /* XSEInitializer */
+ virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext >
+ SAL_CALL createSecurityContext( const OUString& certDB ) override;
+
+ virtual void SAL_CALL freeSecurityContext( const css::uno::Reference<
+ css::xml::crypto::XXMLSecurityContext >& securityContext ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
new file mode 100644
index 000000000..5e0ca9094
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
@@ -0,0 +1,786 @@
+/* -*- 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 <string.h>
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/windowserrorstring.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include "x509certificate_mscryptimpl.hxx"
+#include <certificateextension_xmlsecimpl.hxx>
+#include <biginteger.hxx>
+#include "sanextension_mscryptimpl.hxx"
+
+#include "oid.hxx"
+
+#include <rtl/locale.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/nlsupport.h>
+#include <osl/process.h>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+#include <memory>
+#include <string_view>
+#include <utility>
+#include <vector>
+#include <tools/time.hxx>
+#include <svl/sigstruct.hxx>
+
+using namespace com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::security ;
+
+using ::com::sun::star::security::XCertificate ;
+using ::com::sun::star::util::DateTime ;
+
+/*Returns the index within rRawString where sTypeName starts and where it ends.
+ The starting index is pair.first. The ending index in pair.second points
+ one char after the last character of the type.
+ sTypeName can be
+ "S" or "CN" (without ""). Do not use spaces at the beginning of the type name.
+ If the type name is not found then pair.first and pair.second are -1.
+*/
+static std::pair< sal_Int32, sal_Int32 >
+findTypeInDN(const OUString& rRawString, std::u16string_view sTypeName)
+{
+ std::pair< sal_Int32, sal_Int32 > retVal;
+ bool bInEscape = false;
+ bool bInValue = false;
+ bool bFound = false;
+ sal_Int32 nTypeNameStart = 0;
+ sal_Int32 length = rRawString.getLength();
+
+ for (sal_Int32 i = 0; i < length; i++)
+ {
+ sal_Unicode c = rRawString[i];
+
+ if (c == '=')
+ {
+ if (! bInValue)
+ {
+ OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart);
+ sType = sType.trim();
+ if (sType.equalsIgnoreAsciiCase(sTypeName))
+ {
+ bFound = true;
+ break;
+ }
+ }
+ }
+ else if (c == '"')
+ {
+ if (!bInEscape)
+ {
+ //If this is the quote is the first of the couple which enclose the
+ //whole value, because the value contains special characters
+ //then we just drop it. That is, this character must be followed by
+ //a character which is not '"'.
+ if ( i + 1 < length && rRawString[i+1] == '"')
+ bInEscape = true;
+ else
+ bInValue = !bInValue; //value is enclosed in " "
+ }
+ else
+ {
+ //This quote is escaped by a preceding quote and therefore is
+ //part of the value
+ bInEscape = false;
+ }
+ }
+ else if (c == ',' || c == '+')
+ {
+ //The comma separate the attribute value pairs.
+ //If the comma is not part of a value (the value would then be enclosed in '"'),
+ //then we have reached the end of the value
+ if (!bInValue)
+ {
+ //The next char is the start of the new type
+ nTypeNameStart = i + 1;
+ }
+ }
+ }
+
+ //Found the Type Name, but there can still be spaces after the last comma
+ //and the beginning of the type.
+ if (bFound)
+ {
+ while (true)
+ {
+ sal_Unicode c = rRawString[nTypeNameStart];
+ if (c != ' ' && c != '\t')
+ //found
+ break;
+ nTypeNameStart ++;
+ }
+ // search end (one after last letter)
+ sal_Int32 nTypeNameEnd = nTypeNameStart;
+ nTypeNameEnd++;
+ while (true)
+ {
+ sal_Unicode c = rRawString[nTypeNameEnd];
+ if (c == ' ' || c == '\t' || c == '=')
+ break;
+ nTypeNameEnd++;
+ }
+ retVal = std::make_pair(nTypeNameStart, nTypeNameEnd);
+ }
+ else
+ {
+ retVal = std::make_pair(-1, -1);
+ }
+ return retVal;
+}
+
+
+/*
+ MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise
+ it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary
+ anymore, because we provide always the signers certificate when signing. So libmlsec can find
+ the private key based on the provided certificate (X509Certificate element) and does not need
+ the issuer name (X509IssuerName element). The issuer name in the xml signature has also no
+ effect for the signature nor the certificate validation.
+ In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain
+ strings for type names. Instead it uses OIDs.
+ */
+
+static OUString replaceTagSWithTagST(OUString const & oldDN)
+{
+ std::pair<sal_Int32, sal_Int32 > pairIndex = findTypeInDN(oldDN, u"S");
+
+ if (pairIndex.first != -1)
+ {
+ return OUString::Concat(oldDN.subView(0, pairIndex.first))+"ST"
+ +oldDN.subView(pairIndex.second);
+ }
+ return oldDN;
+}
+/* end */
+
+X509Certificate_MSCryptImpl::X509Certificate_MSCryptImpl() :
+ m_pCertContext( nullptr )
+{
+}
+
+X509Certificate_MSCryptImpl::~X509Certificate_MSCryptImpl() {
+ if( m_pCertContext != nullptr ) {
+ CertFreeCertificateContext( m_pCertContext ) ;
+ }
+}
+
+//Methods from XCertificate
+sal_Int16 SAL_CALL X509Certificate_MSCryptImpl::getVersion() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ return static_cast<char>(m_pCertContext->pCertInfo->dwVersion) ;
+ } else {
+ return -1 ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSerialNumber() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ Sequence< sal_Int8 > serial( m_pCertContext->pCertInfo->SerialNumber.cbData ) ;
+ auto serialRange = asNonConstRange(serial);
+ for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SerialNumber.cbData ; i ++ )
+ serialRange[i] = *( m_pCertContext->pCertInfo->SerialNumber.pbData + m_pCertContext->pCertInfo->SerialNumber.cbData - i - 1 ) ;
+
+ return serial ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getIssuerName() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ DWORD cchIssuer = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Issuer ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ nullptr, 0
+ ) ;
+
+ // Here the cbIssuer count the last 0x00 , take care.
+ if( cchIssuer != 0 ) {
+ auto issuer = std::make_unique<wchar_t[]>(cchIssuer);
+
+ cchIssuer = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Issuer ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ issuer.get(), cchIssuer
+ ) ;
+
+ if( cchIssuer <= 0 ) {
+ throw RuntimeException() ;
+ }
+
+ if(issuer.get()[cchIssuer -1] == 0) cchIssuer--; //delimit the last 0x00;
+ OUString xIssuer(o3tl::toU(issuer.get()), cchIssuer) ;
+
+ return replaceTagSWithTagST(xIssuer);
+ } else {
+ return OUString() ;
+ }
+ } else {
+ return OUString() ;
+ }
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectName()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ DWORD cchSubject = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Subject ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ nullptr, 0
+ ) ;
+
+ if( cchSubject != 0 )
+ {
+ auto subject = std::make_unique<wchar_t[]>(cchSubject);
+
+ cchSubject = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Subject ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ subject.get(), cchSubject
+ ) ;
+
+ if( cchSubject <= 0 ) {
+ throw RuntimeException() ;
+ }
+
+ OUString xSubject(o3tl::toU(subject.get()));
+
+ return replaceTagSWithTagST(xSubject);
+ } else
+ {
+ return OUString() ;
+ }
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+css::util::DateTime SAL_CALL X509Certificate_MSCryptImpl::getNotValidBefore() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ SYSTEMTIME explTime ;
+ DateTime dateTime ;
+ FILETIME localFileTime;
+
+ if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotBefore ), &localFileTime))
+ {
+ if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
+ //Convert the time to readable local time
+ dateTime.NanoSeconds = explTime.wMilliseconds * ::tools::Time::nanoPerMilli ;
+ dateTime.Seconds = explTime.wSecond ;
+ dateTime.Minutes = explTime.wMinute ;
+ dateTime.Hours = explTime.wHour ;
+ dateTime.Day = explTime.wDay ;
+ dateTime.Month = explTime.wMonth ;
+ dateTime.Year = explTime.wYear ;
+ }
+ }
+
+ return dateTime ;
+ } else {
+ return DateTime() ;
+ }
+}
+
+css::util::DateTime SAL_CALL X509Certificate_MSCryptImpl::getNotValidAfter() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ SYSTEMTIME explTime ;
+ DateTime dateTime ;
+ FILETIME localFileTime;
+
+ if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotAfter ), &localFileTime))
+ {
+ if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
+ //Convert the time to readable local time
+ dateTime.NanoSeconds = explTime.wMilliseconds * ::tools::Time::nanoPerMilli ;
+ dateTime.Seconds = explTime.wSecond ;
+ dateTime.Minutes = explTime.wMinute ;
+ dateTime.Hours = explTime.wHour ;
+ dateTime.Day = explTime.wDay ;
+ dateTime.Month = explTime.wMonth ;
+ dateTime.Year = explTime.wYear ;
+ }
+ }
+
+ return dateTime ;
+ } else {
+ return DateTime() ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getIssuerUniqueID() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ Sequence< sal_Int8 > issuerUid( m_pCertContext->pCertInfo->IssuerUniqueId.cbData ) ;
+ auto issuerUidRange = asNonConstRange(issuerUid);
+ for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->IssuerUniqueId.cbData; i ++ )
+ issuerUidRange[i] = *( m_pCertContext->pCertInfo->IssuerUniqueId.pbData + i ) ;
+
+ return issuerUid ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectUniqueID() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ Sequence< sal_Int8 > subjectUid( m_pCertContext->pCertInfo->SubjectUniqueId.cbData ) ;
+ auto subjectUidRange = asNonConstRange(subjectUid);
+ for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SubjectUniqueId.cbData; i ++ )
+ subjectUidRange[i] = *( m_pCertContext->pCertInfo->SubjectUniqueId.pbData + i ) ;
+
+ return subjectUid ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL X509Certificate_MSCryptImpl::getExtensions() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) {
+ rtl::Reference<CertificateExtension_XmlSecImpl> xExtn ;
+ Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ;
+ auto pExtns = xExtns.getArray();
+
+ for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
+ CERT_EXTENSION* pExtn = &(m_pCertContext->pCertInfo->rgExtension[i]) ;
+
+
+ OUString objId = OUString::createFromAscii( pExtn->pszObjId );
+
+ if ( objId == "2.5.29.17" )
+ xExtn = reinterpret_cast<CertificateExtension_XmlSecImpl*>(new SanExtensionImpl());
+ else
+ xExtn = new CertificateExtension_XmlSecImpl;
+
+ xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast<unsigned char*>(pExtn->pszObjId), strlen( pExtn->pszObjId ), pExtn->fCritical ) ;
+
+ pExtns[i] = xExtn ;
+ }
+
+ return xExtns ;
+ } else {
+ return Sequence< Reference< XCertificateExtension > >();
+ }
+}
+
+css::uno::Reference< css::security::XCertificateExtension > SAL_CALL X509Certificate_MSCryptImpl::findCertificateExtension( const css::uno::Sequence< sal_Int8 >& /*oid*/ ) {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) {
+ rtl::Reference<CertificateExtension_XmlSecImpl> xExtn ;
+
+ for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
+ CERT_EXTENSION* pExtn = &( m_pCertContext->pCertInfo->rgExtension[i] ) ;
+
+ //TODO: Compare the oid
+ if( false ) {
+ xExtn = new CertificateExtension_XmlSecImpl;
+ xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast<unsigned char*>(pExtn->pszObjId), strlen( pExtn->pszObjId ), pExtn->fCritical ) ;
+ }
+ }
+
+ return xExtn ;
+ } else {
+ return nullptr ;
+ }
+}
+
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getEncoded() {
+ if( m_pCertContext != nullptr && m_pCertContext->cbCertEncoded > 0 ) {
+ Sequence< sal_Int8 > rawCert( m_pCertContext->cbCertEncoded ) ;
+ auto prawCert = rawCert.getArray();
+
+ for( unsigned int i = 0 ; i < m_pCertContext->cbCertEncoded ; i ++ )
+ prawCert[i] = *( m_pCertContext->pbCertEncoded + i ) ;
+
+ return rawCert ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+//Helper methods
+void X509Certificate_MSCryptImpl::setMswcryCert( const CERT_CONTEXT* cert ) {
+ if( m_pCertContext != nullptr ) {
+ CertFreeCertificateContext( m_pCertContext ) ;
+ m_pCertContext = nullptr ;
+ }
+
+ if( cert != nullptr ) {
+ m_pCertContext = CertDuplicateCertificateContext( cert ) ;
+ }
+}
+
+const CERT_CONTEXT* X509Certificate_MSCryptImpl::getMswcryCert() const {
+ if( m_pCertContext != nullptr ) {
+ return m_pCertContext ;
+ } else {
+ return nullptr ;
+ }
+}
+
+void X509Certificate_MSCryptImpl::setRawCert( Sequence< sal_Int8 > const & rawCert ) {
+ if( m_pCertContext != nullptr ) {
+ CertFreeCertificateContext( m_pCertContext ) ;
+ m_pCertContext = nullptr ;
+ }
+
+ if( rawCert.getLength() != 0 ) {
+ m_pCertContext = CertCreateCertificateContext( X509_ASN_ENCODING, reinterpret_cast<const sal_uInt8*>(&rawCert[0]), rawCert.getLength() ) ;
+ }
+}
+
+/* XUnoTunnel */
+UNO3_GETIMPLEMENTATION_IMPL(X509Certificate_MSCryptImpl);
+
+static OUString findOIDDescription(char const *oid)
+{
+ OUString ouOID = OUString::createFromAscii( oid );
+ for (int i=0; i<nOID; i++)
+ {
+ OUString item = OUString::createFromAscii( OIDs[i].oid );
+ if (ouOID == item)
+ {
+ return OUString::createFromAscii( OIDs[i].desc );
+ }
+ }
+
+ return OUString() ;
+}
+
+static css::uno::Sequence< sal_Int8 > getThumbprint(const CERT_CONTEXT* pCertContext, DWORD dwPropId)
+{
+ if( pCertContext != nullptr )
+ {
+ DWORD cbData = dwPropId == CERT_SHA256_HASH_PROP_ID ? 32 : 20;
+ unsigned char fingerprint[32];
+ if (CertGetCertificateContextProperty(pCertContext, dwPropId, fingerprint, &cbData))
+ {
+ Sequence< sal_Int8 > thumbprint( cbData ) ;
+ auto pthumbprint = thumbprint.getArray();
+ for( unsigned int i = 0 ; i < cbData ; i ++ )
+ {
+ pthumbprint[i] = fingerprint[i];
+ }
+
+ return thumbprint;
+ }
+ else
+ {
+ DWORD e = GetLastError();
+ cbData = e;
+ }
+ }
+
+ return Sequence< sal_Int8 >();
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyAlgorithm()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm;
+ return findOIDDescription( algorithm.pszObjId ) ;
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyValue()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ CRYPT_BIT_BLOB publicKey = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey;
+
+ Sequence< sal_Int8 > key( publicKey.cbData ) ;
+ auto keyRange = asNonConstRange(key);
+ for( unsigned int i = 0 ; i < publicKey.cbData ; i++ )
+ {
+ keyRange[i] = *(publicKey.pbData + i) ;
+ }
+
+ return key;
+ }
+ else
+ {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getSignatureAlgorithm()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SignatureAlgorithm;
+ return findOIDDescription( algorithm.pszObjId ) ;
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+uno::Sequence<sal_Int8> X509Certificate_MSCryptImpl::getSHA256Thumbprint()
+{
+ return getThumbprint(m_pCertContext, CERT_SHA256_HASH_PROP_ID);
+}
+
+svl::crypto::SignatureMethodAlgorithm X509Certificate_MSCryptImpl::getSignatureMethodAlgorithm()
+{
+ svl::crypto::SignatureMethodAlgorithm nRet = svl::crypto::SignatureMethodAlgorithm::RSA;
+
+ if (!m_pCertContext || !m_pCertContext->pCertInfo)
+ return nRet;
+
+ CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm;
+ OString aObjId(algorithm.pszObjId);
+ if (aObjId == szOID_ECC_PUBLIC_KEY)
+ nRet = svl::crypto::SignatureMethodAlgorithm::ECDSA;
+
+ return nRet;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSHA1Thumbprint()
+{
+ return getThumbprint(m_pCertContext, CERT_SHA1_HASH_PROP_ID);
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getMD5Thumbprint()
+{
+ return getThumbprint(m_pCertContext, CERT_MD5_HASH_PROP_ID);
+}
+
+CertificateKind SAL_CALL X509Certificate_MSCryptImpl::getCertificateKind()
+{
+ return CertificateKind_X509;
+}
+
+sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage( )
+{
+ sal_Int32 usage =
+ CERT_DATA_ENCIPHERMENT_KEY_USAGE |
+ CERT_DIGITAL_SIGNATURE_KEY_USAGE |
+ CERT_KEY_AGREEMENT_KEY_USAGE |
+ CERT_KEY_CERT_SIGN_KEY_USAGE |
+ CERT_KEY_ENCIPHERMENT_KEY_USAGE |
+ CERT_NON_REPUDIATION_KEY_USAGE |
+ CERT_OFFLINE_CRL_SIGN_KEY_USAGE;
+
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 )
+ {
+ CERT_EXTENSION* pExtn = CertFindExtension(
+ szOID_KEY_USAGE,
+ m_pCertContext->pCertInfo->cExtension,
+ m_pCertContext->pCertInfo->rgExtension);
+
+ if (pExtn != nullptr)
+ {
+ DWORD length = 0;
+ bool rc = CryptDecodeObject(
+ X509_ASN_ENCODING,
+ X509_KEY_USAGE,
+ pExtn->Value.pbData,
+ pExtn->Value.cbData,
+ 0,
+ nullptr,
+ &length);
+
+ if (!rc)
+ SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError()));
+ else
+ {
+ std::vector<char>buffer(length);
+
+ rc = CryptDecodeObject(
+ X509_ASN_ENCODING,
+ X509_KEY_USAGE,
+ pExtn->Value.pbData,
+ pExtn->Value.cbData,
+ 0,
+ buffer.data(),
+ &length);
+
+ CRYPT_BIT_BLOB *blob = reinterpret_cast<CRYPT_BIT_BLOB*>(buffer.data());
+ if (!rc)
+ SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError()));
+ else if (blob->cbData == 1)
+ usage = blob->pbData[0];
+ else
+ SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject(X509_KEY_USAGE) returned unexpected amount of data: " << blob->cbData);
+ }
+ }
+ }
+
+ return usage;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL X509Certificate_MSCryptImpl::getImplementationName()
+{
+ return "com.sun.star.xml.security.gpg.XCertificate_MsCryptImpl";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL X509Certificate_MSCryptImpl::supportsService(const OUString& serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence<OUString> SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceNames()
+{
+ return { OUString() };
+}
+
+namespace xmlsecurity {
+
+// based on some guesswork and:
+// https://datatracker.ietf.org/doc/html/rfc1485
+// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR
+// the main problem appears to be that in values NSS uses \ escapes but CryptoAPI requires " quotes around value
+static OUString CompatDNNSS(OUString const& rDN)
+{
+ OUStringBuffer buf(rDN.getLength());
+ enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT);
+ for (sal_Int32 i = 0; i < rDN.getLength(); ++i)
+ {
+ if (state == DEFAULT)
+ {
+ buf.append(rDN[i]);
+ if (rDN[i] == '=')
+ {
+ if (rDN.getLength() == i+1)
+ {
+ break; // invalid?
+ }
+ else
+ {
+ buf.append('"');
+ state = INVALUE;
+ }
+ }
+ }
+ else if (state == INVALUE)
+ {
+ if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';')
+ {
+ buf.append('"');
+ buf.append(rDN[i]);
+ state = DEFAULT;
+ }
+ else if (rDN[i] == '\\')
+ {
+ if (rDN.getLength() == i+1)
+ {
+ break; // invalid?
+ }
+ if (rDN[i+1] == '"')
+ {
+ buf.append('"');
+ }
+ buf.append(rDN[i+1]);
+ ++i;
+ }
+ else
+ {
+ buf.append(rDN[i]);
+ }
+ if (i+1 == rDN.getLength())
+ {
+ buf.append('"');
+ state = DEFAULT;
+ }
+ }
+ }
+ return buf.makeStringAndClear();
+}
+
+static bool EncodeDistinguishedName(std::u16string_view const rName, CERT_NAME_BLOB & rBlob)
+{
+ LPCWSTR pszError;
+ if (!CertStrToNameW(X509_ASN_ENCODING,
+ reinterpret_cast<LPCWSTR>(rName.data()), CERT_X500_NAME_STR,
+ nullptr, nullptr, &rBlob.cbData, &pszError))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError)));
+ return false;
+ }
+ rBlob.pbData = new BYTE[rBlob.cbData];
+ if (!CertStrToNameW(X509_ASN_ENCODING,
+ reinterpret_cast<LPCWSTR>(rName.data()), CERT_X500_NAME_STR,
+ nullptr, rBlob.pbData, &rBlob.cbData, &pszError))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError)));
+ return false;
+ }
+ return true;
+}
+
+bool EqualDistinguishedNames(
+ std::u16string_view const rName1, std::u16string_view const rName2,
+ EqualMode const eMode)
+{
+ if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2)
+ { // handle case where both need to be converted
+ return true;
+ }
+ CERT_NAME_BLOB blob1;
+ if (!EncodeDistinguishedName(rName1, blob1))
+ {
+ return false;
+ }
+ CERT_NAME_BLOB blob2;
+ bool ret(false);
+ if (EncodeDistinguishedName(rName2, blob2))
+ {
+ ret = CertCompareCertificateName(X509_ASN_ENCODING,
+ &blob1, &blob2) == TRUE;
+ delete[] blob2.pbData;
+ }
+ if (!ret && eMode == COMPAT_2ND)
+ {
+ CERT_NAME_BLOB blob2compat;
+ if (!EncodeDistinguishedName(CompatDNNSS(OUString(rName2)), blob2compat))
+ {
+ delete[] blob1.pbData;
+ return false;
+ }
+ ret = CertCompareCertificateName(X509_ASN_ENCODING,
+ &blob1, &blob2compat) == TRUE;
+ delete[] blob2compat.pbData;
+ }
+ delete[] blob1.pbData;
+ return ret;
+}
+
+} // namespace xmlsecurity
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
new file mode 100644
index 000000000..9bd6a34ce
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
@@ -0,0 +1,96 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <Windows.h>
+#include <WinCrypt.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <certificate.hxx>
+
+class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::security::XCertificate ,
+ css::lang::XUnoTunnel,
+ css::lang::XServiceInfo > , public xmlsecurity::Certificate
+{
+ private:
+ const CERT_CONTEXT* m_pCertContext ;
+
+ public:
+ X509Certificate_MSCryptImpl() ;
+ virtual ~X509Certificate_MSCryptImpl() override;
+
+ //Methods from XCertificate
+ virtual sal_Int16 SAL_CALL getVersion() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override;
+ virtual OUString SAL_CALL getIssuerName() override;
+ virtual OUString SAL_CALL getSubjectName() override;
+ virtual css::util::DateTime SAL_CALL getNotValidBefore() override;
+ virtual css::util::DateTime SAL_CALL getNotValidAfter() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override;
+ virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override;
+ virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override;
+ virtual OUString SAL_CALL getSignatureAlgorithm() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override;
+ virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
+
+
+ virtual sal_Int32 SAL_CALL getCertificateUsage( ) override;
+
+ //Methods from XUnoTunnel
+ UNO3_GETIMPLEMENTATION_DECL(X509Certificate_MSCryptImpl)
+
+ /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
+ virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
+
+ /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+ virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
+
+ //Helper methods
+ void setMswcryCert( const CERT_CONTEXT* cert ) ;
+ const CERT_CONTEXT* getMswcryCert() const ;
+ /// @throws css::uno::RuntimeException
+ void setRawCert( css::uno::Sequence< sal_Int8 > const & rawCert ) ;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx
new file mode 100644
index 000000000..7d71d4863
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx
@@ -0,0 +1,155 @@
+/* -*- 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 <xmlsec-wrapper.h>
+
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include <xmlsec/xmlstreamio.hxx>
+#include "akmngr.hxx"
+
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+using ::com::sun::star::lang::XSingleServiceFactory ;
+
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
+
+namespace {
+
+class XMLSecurityContext_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XXMLSecurityContext ,
+ css::lang::XServiceInfo >
+{
+ private:
+ //xmlSecKeysMngrPtr m_pKeysMngr ;
+ css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment ;
+
+ public:
+ XMLSecurityContext_MSCryptImpl();
+
+ //Methods from XXMLSecurityContext
+ virtual sal_Int32 SAL_CALL addSecurityEnvironment(
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment
+ ) override;
+
+ virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber( ) override;
+
+ virtual css::uno::Reference<
+ css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ getSecurityEnvironmentByIndex( ::sal_Int32 index ) override;
+
+ virtual css::uno::Reference<
+ css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ getSecurityEnvironment( ) override;
+
+ virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex( ) override;
+
+ virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override;
+
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+XMLSecurityContext_MSCryptImpl::XMLSecurityContext_MSCryptImpl()
+{
+}
+
+sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::addSecurityEnvironment(
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment)
+{
+ if( !aSecurityEnvironment.is() )
+ {
+ throw uno::RuntimeException() ;
+ }
+
+ m_xSecurityEnvironment = aSecurityEnvironment;
+
+ return 0;
+}
+
+
+sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentNumber( )
+{
+ return 1;
+}
+
+css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentByIndex( sal_Int32 index )
+{
+ if (index != 0)
+ {
+ throw uno::RuntimeException() ;
+ }
+ return m_xSecurityEnvironment;
+}
+
+css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ XMLSecurityContext_MSCryptImpl::getSecurityEnvironment( )
+{
+ return m_xSecurityEnvironment;
+}
+
+sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getDefaultSecurityEnvironmentIndex( )
+{
+ return 0;
+}
+
+void SAL_CALL XMLSecurityContext_MSCryptImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 /*nDefaultEnvIndex*/ )
+{
+ //dummy
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSecurityContext_MSCryptImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.XMLSecurityContext" ;
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSecurityContext_MSCryptImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+uno::Sequence< OUString > SAL_CALL XMLSecurityContext_MSCryptImpl::getSupportedServiceNames() {
+ return { "com.sun.star.xml.crypto.XMLSecurityContext" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_XMLSecurityContext_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLSecurityContext_MSCryptImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
new file mode 100644
index 000000000..87af0f040
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
@@ -0,0 +1,312 @@
+/* -*- 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 <sal/log.hxx>
+#include <rtl/uuid.h>
+#include <xmlsec-wrapper.h>
+
+#include <xmlsec/mscng/x509.h>
+
+#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
+#include <xmlelementwrapper_xmlsecimpl.hxx>
+#include <xmlsec/xmlstreamio.hxx>
+#include <xmlsec/errorcallback.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+using ::com::sun::star::lang::XSingleServiceFactory ;
+
+using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
+using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ;
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::xml::crypto::XXMLSignature ;
+using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
+using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
+using ::com::sun::star::xml::crypto::XUriBinding ;
+
+namespace {
+
+class XMLSignature_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XXMLSignature ,
+ css::lang::XServiceInfo >
+{
+ public:
+ explicit XMLSignature_MSCryptImpl();
+
+ //Methods from XXMLSignature
+ virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate(
+ const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment
+ ) override;
+
+ virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate(
+ const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
+ const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext
+ ) override;
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+} ;
+
+}
+
+XMLSignature_MSCryptImpl::XMLSignature_MSCryptImpl() {
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_MSCryptImpl::generate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XSecurityEnvironment >& aEnvironment
+)
+{
+ xmlSecKeysMngrPtr pMngr = nullptr ;
+ xmlSecDSigCtxPtr pDsigCtx = nullptr ;
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aEnvironment.is() )
+ throw RuntimeException() ;
+
+ //Get Keys Manager
+ Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
+ SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecTunnel);
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() ) {
+ throw RuntimeException() ;
+ }
+
+ Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+ if( pElement == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ setErrorRecorder( );
+
+ pMngr = pSecEnv->createKeysManager();
+ if( !pMngr ) {
+ throw RuntimeException() ;
+ }
+
+ //Create Signature context
+ pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
+ if( pDsigCtx == nullptr )
+ {
+ //throw XMLSignatureException() ;
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ //Sign the template
+ if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 )
+ {
+ if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+ else
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+ else
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+
+
+ xmlSecDSigCtxDestroy( pDsigCtx ) ;
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+ clearErrorRecorder();
+ return aTemplate ;
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_MSCryptImpl::validate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XXMLSecurityContext >& aSecurityCtx
+) {
+ xmlSecKeysMngrPtr pMngr = nullptr ;
+ xmlSecDSigCtxPtr pDsigCtx = nullptr ;
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aSecurityCtx.is() )
+ throw RuntimeException() ;
+
+ //Get Keys Manager
+ Reference< XSecurityEnvironment > xSecEnv
+ = aSecurityCtx->getSecurityEnvironmentByIndex(
+ aSecurityCtx->getDefaultSecurityEnvironmentIndex());
+ Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY_THROW ) ;
+ SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecTunnel);
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() )
+ throw RuntimeException() ;
+
+ Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+ if( pElement == nullptr )
+ throw RuntimeException() ;
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ setErrorRecorder( );
+
+ pMngr = pSecEnv->createKeysManager();
+ if( !pMngr ) {
+ throw RuntimeException() ;
+ }
+
+ //Create Signature context
+ pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
+ if( pDsigCtx == nullptr )
+ {
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ // We do certificate verification ourselves.
+ pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+
+ // limit possible key data to valid X509 certificates only, no KeyValues
+ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0)
+ throw RuntimeException("failed to limit allowed key data");
+
+ //Verify signature
+ //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0)
+ //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if
+ //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the
+ //error recorder feature to get the ONE error that made the verification fail, because there is no
+ //documentation/specification as to how to interpret the number of recorded errors and what is the initial
+ //error.
+ int rs = xmlSecDSigCtxVerify(pDsigCtx , pNode);
+
+ // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
+ xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
+ // Require that all manifest references are also good.
+ xmlSecSize nReferenceGood = 0;
+ for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
+ {
+ xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
+ if (pReference)
+ {
+ if (pReference->status == xmlSecDSigStatusSucceeded)
+ ++nReferenceGood;
+ }
+ }
+ SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount);
+
+ if (rs == 0 && nReferenceCount == nReferenceGood)
+ {
+ if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+ else
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+ else
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+
+ xmlSecDSigCtxDestroy( pDsigCtx ) ;
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+
+ clearErrorRecorder();
+ return aTemplate;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSignature_MSCryptImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.XMLSignature";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSignature_MSCryptImpl::supportsService( const OUString& serviceName) {
+return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl::getSupportedServiceNames() {
+ return { "com.sun.star.xml.crypto.XMLSignature" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLSignature_MSCryptImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */