diff --git a/DesktopEditor/xmlsec/src/include/XmlCertificate.h b/DesktopEditor/xmlsec/src/include/XmlCertificate.h index 24bcb0a323..9554d7a186 100644 --- a/DesktopEditor/xmlsec/src/include/XmlCertificate.h +++ b/DesktopEditor/xmlsec/src/include/XmlCertificate.h @@ -8,6 +8,11 @@ #define OOXML_HASH_ALG_SHA1 0 #define OOXML_HASH_ALG_INVALID 1 +#define OPEN_SSL_WARNING_OK 0 +#define OPEN_SSL_WARNING_ERR 1 +#define OPEN_SSL_WARNING_ALL_OK 2 +#define OPEN_SSL_WARNING_PASS 4 + class ICertificate; class Q_DECL_EXPORT ICertificateSelectDialogOpenSsl { @@ -32,7 +37,7 @@ public: class Q_DECL_EXPORT CCertificateInfo { -public: +private: std::wstring m_name; std::string m_date; std::string m_id; @@ -44,6 +49,33 @@ public: ~CCertificateInfo() { } + + std::wstring GetName() + { + return m_name; + } + void SetName(const std::wstring& name) + { + m_name = name; + } + + std::string GetDate() + { + return m_date; + } + void SetDate(const std::string& date) + { + m_date = date; + } + + std::string GetId() + { + return m_id; + } + void SetId(const std::string& id) + { + m_id = id; + } }; class Q_DECL_EXPORT ICertificate @@ -88,9 +120,9 @@ public: virtual CCertificateInfo GetInfo() { CCertificateInfo info; - info.m_name = GetSignerName(); - info.m_date = GetDate(); - info.m_id = GetId(); + info.SetName(GetSignerName()); + info.SetDate(GetDate()); + info.SetId(GetId()); return info; } diff --git a/DesktopEditor/xmlsec/src/ooxmlsignature.pro b/DesktopEditor/xmlsec/src/ooxmlsignature.pro index aa573de915..9814cc0123 100644 --- a/DesktopEditor/xmlsec/src/ooxmlsignature.pro +++ b/DesktopEditor/xmlsec/src/ooxmlsignature.pro @@ -21,6 +21,13 @@ include($$CORE_ROOT_DIR/DesktopEditor/xml/build/qt/libxml2.pri) DEFINES -= UNICODE +core_linux { + CONFIG += signature_openssl +} +core_mac { + CONFIG += signature_openssl +} + HEADERS += \ include/XmlCertificate.h \ include/OOXMLSigner.h \ @@ -29,9 +36,7 @@ HEADERS += \ HEADERS += \ src/XmlCanonicalizator.h \ src/XmlRels.h \ - src/XmlTransform.h \ - src/XmlSigner_mscrypto.h \ - src/XmlSigner_openssl.h + src/XmlTransform.h SOURCES += \ src/XmlTransform.cpp \ @@ -41,13 +46,26 @@ SOURCES += \ core_windows { +HEADERS += \ + src/XmlSigner_mscrypto.h + LIBS += -lcrypt32 LIBS += -lcryptui LIBS += -lAdvapi32 } -core_linux { +signature_openssl { + +HEADERS += \ + src/XmlSigner_openssl.h + +SOURCES += \ + src/XmlSigner_openssl.cpp + +} + +signature_openssl { DEFINES += XMLSEC_OPENSSL_110 INCLUDEPATH += $$CORE_ROOT_DIR/Common/3dParty/openssl/openssl/include diff --git a/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.cpp b/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.cpp new file mode 100644 index 0000000000..fe8d2fe44e --- /dev/null +++ b/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.cpp @@ -0,0 +1,663 @@ +#include "./XmlSigner_openssl.h" + +#include "../../../common/File.h" +#include "../../../common/String.h" +#include "../../../common/BigInteger.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +class CCertificate_openssl_private +{ +protected: + ICertificateSelectDialogOpenSsl* m_pDialog; + + X509* m_cert; + EVP_PKEY* m_key; + +public: + ICertificate* m_pBase; + +public: + CCertificate_openssl_private() + { + m_pDialog = NULL; + + m_cert = NULL; + m_key = NULL; + + m_pBase = NULL; + } + virtual ~CCertificate_openssl_private() + { + if (NULL != m_cert) + X509_free(m_cert); + if (NULL != m_key) + EVP_PKEY_free(m_key); + } + +public: + std::string GetNumber() + { + if (NULL == m_cert) + return ""; + + ASN1_INTEGER* asn1_serial = X509_get_serialNumber(m_cert); + if (asn1_serial == NULL) + return ""; + + BIGNUM* bn = ASN1_INTEGER_to_BN(asn1_serial, NULL); + if (!bn) + { + ASN1_INTEGER_free(asn1_serial); + return ""; + } + + char *tmp = BN_bn2dec(bn); + std::string sReturn(tmp); + + BN_free(bn); + ASN1_INTEGER_free(asn1_serial); + + return sReturn; + } + + std::wstring GetSignerName() + { + if (NULL == m_cert) + return L""; + + X509_NAME* name = X509_get_issuer_name(m_cert); + char* utf_8_name = X509_NAME_oneline(name, NULL, 0); + + std::string sName(utf_8_name); + std::wstring sNameW = UTF8_TO_U(sName); + + OPENSSL_free(utf_8_name); + + return sNameW; + } + + std::string GetCertificateBase64() + { + if (NULL == m_cert) + return ""; + + BIO* bio = BIO_new(BIO_s_mem()); + PEM_write_bio_X509_AUX(bio, m_cert); + + unsigned char *data; + unsigned int len = 0; + len = BIO_get_mem_data(bio, &data); + + std::string sReturn((char*)data, (size_t)len); + + BIO_free(bio); + return sReturn; + } + + std::string GetCertificateHash() + { + std::string sBase64 = GetCertificateBase64(); + BYTE* pData = NULL; + int nLen = 0; + if (NSFile::CBase64Converter::Decode(sBase64.c_str(), (int)sBase64.length(), pData, nLen)) + { + std::string sHash = GetHash(pData, (unsigned int)nLen, OOXML_HASH_ALG_SHA1); + RELEASEARRAYOBJECTS(pData); + return sHash; + } + + return ""; + } + + std::string GetDate() + { + if (NULL == m_cert) + return ""; + + ASN1_TIME* _time1 = X509_get_notBefore(m_cert); + struct tm t1 = this->ASN1_GetTimeT(_time1); + ASN1_TIME_free(_time1); + + ASN1_TIME* _time2 = X509_get_notAfter(m_cert); + struct tm t2 = this->ASN1_GetTimeT(_time2); + ASN1_TIME_free(_time2); + + std::string sRet = std::to_string(t1.tm_mday) + + "/" + + std::to_string(t1.tm_mon + 1) + + "/" + + std::to_string(t1.tm_year + 1900) + + " - " + + std::to_string(t1.tm_mday) + + "/" + + std::to_string(t2.tm_mon + 1) + + "/" + + std::to_string(t2.tm_year + 1900); + return sRet; + } + + std::string GetId() + { + // TODO: + public key? + return GetNumber(); + } + +public: + std::string Sign(const std::string& sXml) + { + EVP_MD_CTX* pCtx = EVP_MD_CTX_create(); + const EVP_MD* pDigest = EVP_sha1(); + + int n1 = EVP_SignInit(pCtx, pDigest); + n1 = n1; + + int n2 = EVP_SignUpdate(pCtx, sXml.c_str(), sXml.length()); + n2 = n2; + + BYTE pSignature[4096]; + unsigned int nSignatureLen = 0; + + int n3 = EVP_SignFinal(pCtx, pSignature, &nSignatureLen, m_key); + n3 = n3; + + EVP_MD_CTX_destroy(pCtx); + + return std::string((char*)pSignature, (size_t)nSignatureLen); + } + + std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg) + { + if (nAlg == OOXML_HASH_ALG_SHA1) + { + unsigned char obuf[20]; + SHA1(pData, (size_t)nSize, obuf); + + char* pBase64_hash = NULL; + int nBase64Len_hash = 0; + NSFile::CBase64Converter::Encode(obuf, 20, pBase64_hash, nBase64Len_hash, NSBase64::B64_BASE64_FLAG_NOCRLF); + + std::string sReturn(pBase64_hash, nBase64Len_hash); + delete [] pBase64_hash; + + return sReturn; + } + return ""; + } + + std::string GetHash(const std::string& sXml, int nAlg) + { + return GetHash((BYTE*)sXml.c_str(), (DWORD)sXml.length(), nAlg); + } + + std::string GetHash(const std::wstring& sXmlFile, int nAlg) + { + BYTE* pFileData = NULL; + DWORD dwFileDataLen = 0; + NSFile::CFileBinary::ReadAllBytes(sXmlFile, &pFileData, dwFileDataLen); + + if (0 == dwFileDataLen) + return ""; + + std::string sReturn = GetHash(pFileData, dwFileDataLen, nAlg); + + RELEASEARRAYOBJECTS(pFileData); + return sReturn; + } + + bool Verify(const std::string& sXml, std::string& sXmlSignature, int nAlg) + { + EVP_MD_CTX* pCtx = EVP_MD_CTX_create(); + const EVP_MD* pDigest = EVP_sha1(); + + int n1 = EVP_VerifyInit(pCtx, pDigest); + n1 = n1; + + BYTE* pDigestValue = NULL; + int nDigestLen = 0; + NSFile::CBase64Converter::Decode(sXmlSignature.c_str(), (int)sXmlSignature.length(), pDigestValue, nDigestLen); + + int n2 = EVP_VerifyUpdate(pCtx, pDigestValue, (size_t)nDigestLen); + n2 = n2; + + EVP_PKEY* pubkey = X509_get_pubkey(m_cert); + + int n3 = EVP_VerifyFinal(pCtx, (BYTE*)sXml.c_str(), (unsigned int)sXml.length(), pubkey); + n3 = n3; + + EVP_MD_CTX_destroy(pCtx); + EVP_PKEY_free(pubkey); + + RELEASEARRAYOBJECTS(pDigestValue); + + return (1 == n3) ? true : false; + } + + bool LoadFromBase64Data(const std::string& data) + { + BYTE* pData = NULL; + int nLen = 0; + if (NSFile::CBase64Converter::Decode(data.c_str(), (int)data.length(), pData, nLen)) + { + X509* pCert = NULL; + int nErr = LoadCert(pData, (DWORD)nLen, "", &pCert); + + if (nErr == OPEN_SSL_WARNING_OK || nErr == OPEN_SSL_WARNING_ALL_OK) + { + m_cert = pCert; + } + else + { + X509_free(pCert); + m_cert = NULL; + } + + RELEASEARRAYOBJECTS(pData); + return (NULL == m_cert) ? false : true; + } + return false; + } + +public: + bool ShowSelectDialog() + { + if (!m_pDialog) + return false; + + bool bResult = m_pDialog->ShowSelectDialog(); + + std::wstring sKeyPath = m_pDialog->GetKeyPath(); + std::wstring sKeyPasswordW = m_pDialog->GetKeyPassword(); + std::string sKeyPassword = U_TO_UTF8(sKeyPasswordW); + + std::wstring sCertPath = m_pDialog->GetCertificatePath(); + std::wstring sCertPasswordW = m_pDialog->GetCertificatePassword(); + std::string sCertPassword = U_TO_UTF8(sCertPasswordW); + + if (sCertPath.empty()) + { + sCertPath = sKeyPath; + sCertPassword = sKeyPassword; + } + + int nErr = LoadKey(sKeyPath, sKeyPassword, &m_key); + + if (nErr != OPEN_SSL_WARNING_OK && nErr != OPEN_SSL_WARNING_ALL_OK) + return false; + + nErr = LoadCert(sCertPath, sCertPassword, &m_cert); + + if (nErr != OPEN_SSL_WARNING_OK && nErr != OPEN_SSL_WARNING_ALL_OK) + return false; + + return true; + } + int ShowCertificate() + { + if (m_pDialog) + return m_pDialog->ShowCertificate(m_pBase); + return 1; + } + + void SetOpenSslDialog(ICertificateSelectDialogOpenSsl* pDialog) + { + m_pDialog = pDialog; + } + +protected: + tm ASN1_GetTimeT(ASN1_TIME* time) + { + struct tm t; + const char* str = (const char*) time->data; + size_t i = 0; + + memset(&t, 0, sizeof(t)); + + if (time->type == V_ASN1_UTCTIME) + { + /* two digit year */ + t.tm_year = (str[i++] - '0') * 10; + t.tm_year += (str[i++] - '0'); + if (t.tm_year < 70) + t.tm_year += 100; + } + else if (time->type == V_ASN1_GENERALIZEDTIME) + { + /* four digit year */ + t.tm_year = (str[i++] - '0') * 1000; + t.tm_year+= (str[i++] - '0') * 100; + t.tm_year+= (str[i++] - '0') * 10; + t.tm_year+= (str[i++] - '0'); + t.tm_year -= 1900; + } + t.tm_mon = (str[i++] - '0') * 10; + t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1. + t.tm_mday = (str[i++] - '0') * 10; + t.tm_mday+= (str[i++] - '0'); + t.tm_hour = (str[i++] - '0') * 10; + t.tm_hour+= (str[i++] - '0'); + t.tm_min = (str[i++] - '0') * 10; + t.tm_min += (str[i++] - '0'); + t.tm_sec = (str[i++] - '0') * 10; + t.tm_sec += (str[i++] - '0'); + + /* Note: we did not adjust the time based on time zone information */ + return t; + } + +public: + static std::string GetOpenSslErrors() + { + BIO* bio = BIO_new(BIO_s_mem()); + ERR_print_errors(bio); + char *buf = NULL; + size_t len = BIO_get_mem_data(bio, &buf); + std::string sRet((char*)buf, len); + NSStringExt::ToLower(sRet); + BIO_free (bio); + return sRet; + } + static bool IsOpenSslPasswordError(const std::string& str) + { + if (std::string::npos != str.find("mac verify error")) + return true; + if (std::string::npos != str.find("mac verify failure")) + return true; + if (std::string::npos != str.find("password")) + return true; + return false; + } + + static int LoadKey(BYTE* pData, DWORD dwDataLen, std::string password, EVP_PKEY** ppKey) + { + int nErr = OPEN_SSL_WARNING_ERR; + std::string sError = ""; + + PKCS12* p12 = NULL; + EVP_PKEY* pKey = NULL; + char* pPassword = (password.empty()) ? NULL : (char*)password.c_str(); + + BIO* bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + if (PEM_read_bio_PrivateKey(bio, &pKey, NULL, (void*)pPassword)) + { + nErr = OPEN_SSL_WARNING_OK; + goto end; + } + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + + BIO_free(bio); + bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + if (d2i_PrivateKey_bio(bio, &pKey)) + { + nErr = OPEN_SSL_WARNING_OK; + goto end; + } + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + + BIO_free(bio); + bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + if (d2i_PKCS8PrivateKey_bio(bio, &pKey, NULL, (void*)pPassword)) + { + nErr = OPEN_SSL_WARNING_OK; + goto end; + } + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + + BIO_free(bio); + bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + + p12 = d2i_PKCS12_bio(bio, NULL); + if (p12) + { + X509* pCert = NULL; + STACK_OF(X509)* pCa = NULL; + + if (PKCS12_parse(p12, pPassword, &pKey, &pCert, &pCa)) + { + sk_X509_pop_free(pCa, X509_free); + X509_free(pCert); + PKCS12_free(p12); + nErr = OPEN_SSL_WARNING_ALL_OK; + goto end; + } + PKCS12_free(p12); + + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + } + +end: + if (NULL == ppKey) + EVP_PKEY_free(pKey); + else + *ppKey = pKey; + + BIO_free(bio); + return nErr; + } + + static int LoadKey(std::wstring file, std::string password, EVP_PKEY** ppKey) + { + BYTE* pData = NULL; + DWORD dwDataLen; + if (!NSFile::CFileBinary::ReadAllBytes(file, &pData, dwDataLen)) + return OPEN_SSL_WARNING_ERR; + + int nErr = LoadKey(pData, dwDataLen, password, ppKey); + RELEASEARRAYOBJECTS(pData); + return nErr; + } + + static int LoadCert(BYTE* pData, DWORD dwDataLen, std::string password, X509** ppCert) + { + int nErr = OPEN_SSL_WARNING_ERR; + std::string sError = ""; + + PKCS12* p12 = NULL; + X509* pCert = NULL; + char* pPassword = (password.empty()) ? NULL : (char*)password.c_str(); + + BIO* bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + if (PEM_read_bio_X509(bio, &pCert, NULL, (void*)pPassword)) + { + nErr = OPEN_SSL_WARNING_OK; + goto end; + } + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + + BIO_free(bio); + bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + if (d2i_X509_bio(bio, &pCert)) + { + nErr = OPEN_SSL_WARNING_OK; + goto end; + } + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + + BIO_free(bio); + bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); + + p12 = d2i_PKCS12_bio(bio, NULL); + if (p12) + { + EVP_PKEY* pKey = NULL; + STACK_OF(X509)* pCa = NULL; + + if (PKCS12_parse(p12, pPassword, &pKey, &pCert, &pCa)) + { + sk_X509_pop_free(pCa, X509_free); + EVP_PKEY_free(pKey); + PKCS12_free(p12); + BIO_free(bio); + nErr = OPEN_SSL_WARNING_ALL_OK; + goto end; + } + + PKCS12_free(p12); + sError = GetOpenSslErrors(); + if (IsOpenSslPasswordError(sError)) + { + nErr = OPEN_SSL_WARNING_PASS; + goto end; + } + } + +end: + if (NULL == ppCert) + X509_free(pCert); + else + *ppCert = pCert; + + BIO_free(bio); + return nErr; + } + + static int LoadCert(std::wstring file, std::string password, X509** ppCert) + { + BYTE* pData = NULL; + DWORD dwDataLen; + if (!NSFile::CFileBinary::ReadAllBytes(file, &pData, dwDataLen)) + return OPEN_SSL_WARNING_ERR; + + int nErr = LoadCert(pData, dwDataLen, password, ppCert); + RELEASEARRAYOBJECTS(pData); + return nErr; + } +}; + +// REALIZE +CCertificate_openssl::CCertificate_openssl() : ICertificate() +{ + m_internal = new CCertificate_openssl_private(); + m_internal->m_pBase = this; +} + +CCertificate_openssl::~CCertificate_openssl() +{ + RELEASEOBJECT(m_internal); +} + +std::string CCertificate_openssl::GetNumber() +{ + return m_internal->GetNumber(); +} + +std::wstring CCertificate_openssl::GetSignerName() +{ + return m_internal->GetSignerName(); +} + +std::string CCertificate_openssl::GetCertificateBase64() +{ + return m_internal->GetCertificateBase64(); +} + +std::string CCertificate_openssl::GetCertificateHash() +{ + return m_internal->GetCertificateHash(); +} + +std::string CCertificate_openssl::GetDate() +{ + return m_internal->GetDate(); +} + +std::string CCertificate_openssl::GetId() +{ + return m_internal->GetId(); +} + +std::string CCertificate_openssl::Sign(const std::string& sXml) +{ + return m_internal->Sign(sXml); +} + +std::string CCertificate_openssl::GetHash(unsigned char* pData, unsigned int nSize, int nAlg) +{ + return m_internal->GetHash(pData, nSize, nAlg); +} + +std::string CCertificate_openssl::GetHash(const std::string& sXml, int nAlg) +{ + return m_internal->GetHash(sXml, nAlg); +} + +std::string CCertificate_openssl::GetHash(const std::wstring& sXmlFile, int nAlg) +{ + return m_internal->GetHash(sXmlFile, nAlg); +} + +bool CCertificate_openssl::Verify(const std::string& sXml, std::string& sXmlSignature, int nAlg) +{ + return m_internal->Verify(sXml, sXmlSignature, nAlg); +} + +bool CCertificate_openssl::LoadFromBase64Data(const std::string& data) +{ + return m_internal->LoadFromBase64Data(data); +} + +bool CCertificate_openssl::ShowSelectDialog() +{ + return m_internal->ShowSelectDialog(); +} + +int CCertificate_openssl::ShowCertificate() +{ + return m_internal->ShowCertificate(); +} + +void CCertificate_openssl::SetOpenSslDialog(ICertificateSelectDialogOpenSsl* pDialog) +{ + return m_internal->SetOpenSslDialog(pDialog); +} + +int LoadKey(std::wstring file, std::string password) +{ + return CCertificate_openssl_private::LoadKey(file, password, NULL); +} + +int LoadCert(std::wstring file, std::string password) +{ + return CCertificate_openssl_private::LoadCert(file, password, NULL); +} diff --git a/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.h b/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.h index ce8d8503cb..f7e2f7a374 100644 --- a/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.h +++ b/DesktopEditor/xmlsec/src/src/XmlSigner_openssl.h @@ -1,577 +1,53 @@ #ifndef _XMLSIGNER_OPENSSL_H_ #define _XMLSIGNER_OPENSSL_H_ -#include "./include/XmlCertificate.h" - -#include "../../../common/File.h" -#include "../../../common/String.h" -#include "../../../common/BigInteger.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define OPEN_SSL_WARNING_OK 0 -#define OPEN_SSL_WARNING_ERR 1 -#define OPEN_SSL_WARNING_ALL_OK 2 -#define OPEN_SSL_WARNING_PASS 4 +#include "./../include/XmlCertificate.h" +class CCertificate_openssl_private; class CCertificate_openssl : public ICertificate { protected: - ICertificateSelectDialogOpenSsl* m_pDialog; - - BYTE* m_rawData; - int m_rawDataLen; - - X509* m_cert; - EVP_PKEY* m_key; + CCertificate_openssl_private* m_internal; public: - CCertificate_openssl() : ICertificate() - { - m_pDialog = NULL; - - m_rawData = NULL; - m_rawDataLen = 0; - - m_cert = NULL; - m_key = NULL; - } - virtual ~CCertificate_openssl() - { - if (NULL != m_cert) - X509_free(m_cert); - if (NULL != m_key) - EVP_PKEY_free(m_key); - } + CCertificate_openssl(); + virtual ~CCertificate_openssl(); public: - virtual std::string GetNumber() - { - if (NULL == m_cert) - return ""; + virtual std::string GetNumber(); - ASN1_INTEGER* asn1_serial = X509_get_serialNumber(m_cert); - if (asn1_serial == NULL) - return ""; + virtual std::wstring GetSignerName(); - BIGNUM* bn = ASN1_INTEGER_to_BN(asn1_serial, NULL); - if (!bn) - { - ASN1_INTEGER_free(asn1_serial); - return ""; - } + virtual std::string GetCertificateBase64(); - char *tmp = BN_bn2dec(bn); - std::string sReturn(tmp); + virtual std::string GetCertificateHash(); - BN_free(bn); - ASN1_INTEGER_free(asn1_serial); + virtual std::string GetDate(); - return sReturn; - } - - virtual std::wstring GetSignerName() - { - if (NULL == m_cert) - return L""; - - X509_NAME* name = X509_get_issuer_name(m_cert); - char* utf_8_name = X509_NAME_oneline(name, NULL, 0); - - std::string sName(utf_8_name); - std::wstring sNameW = UTF8_TO_U(sName); - - OPENSSL_free(utf_8_name); - - return sNameW; - } - - virtual std::string GetCertificateBase64() - { - if (NULL == m_cert) - return ""; - - BIO* bio = BIO_new(BIO_s_mem()); - PEM_write_bio_X509_AUX(bio, m_cert); - - unsigned char *data; - unsigned int len = 0; - len = BIO_get_mem_data(bio, &data); - - std::string sReturn((char*)data, (size_t)len); - - BIO_free(bio); - return sReturn; - } - - virtual std::string GetCertificateHash() - { - std::string sBase64 = GetCertificateBase64(); - BYTE* pData = NULL; - int nLen = 0; - if (NSFile::CBase64Converter::Decode(sBase64.c_str(), (int)sBase64.length(), pData, nLen)) - { - std::string sHash = GetHash(pData, (unsigned int)nLen, OOXML_HASH_ALG_SHA1); - RELEASEARRAYOBJECTS(pData); - return sHash; - } - - return ""; - } - - virtual std::string GetDate() - { - if (NULL == m_cert) - return ""; - - ASN1_TIME* _time1 = X509_get_notBefore(m_cert); - struct tm t1 = this->ASN1_GetTimeT(_time1); - ASN1_TIME_free(_time1); - - ASN1_TIME* _time2 = X509_get_notAfter(m_cert); - struct tm t2 = this->ASN1_GetTimeT(_time2); - ASN1_TIME_free(_time2); - - std::string sRet = std::to_string(t1.tm_mday) + - "/" + - std::to_string(t1.tm_mon + 1) + - "/" + - std::to_string(t1.tm_year + 1900) + - " - " + - std::to_string(t1.tm_mday) + - "/" + - std::to_string(t2.tm_mon + 1) + - "/" + - std::to_string(t2.tm_year + 1900); - return sRet; - } - - virtual std::string GetId() - { - // TODO: + public key? - return GetNumber(); - } + virtual std::string GetId(); public: - virtual std::string Sign(const std::string& sXml) - { - EVP_MD_CTX* pCtx = EVP_MD_CTX_create(); - const EVP_MD* pDigest = EVP_sha1(); + virtual std::string Sign(const std::string& sXml); - int n1 = EVP_SignInit(pCtx, pDigest); - n1 = n1; + virtual std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg); - int n2 = EVP_SignUpdate(pCtx, sXml.c_str(), sXml.length()); - n2 = n2; + virtual std::string GetHash(const std::string& sXml, int nAlg); - BYTE pSignature[4096]; - unsigned int nSignatureLen = 0; + virtual std::string GetHash(const std::wstring& sXmlFile, int nAlg); - int n3 = EVP_SignFinal(pCtx, pSignature, &nSignatureLen, m_key); - n3 = n3; + virtual bool Verify(const std::string& sXml, std::string& sXmlSignature, int nAlg); - EVP_MD_CTX_destroy(pCtx); - - return std::string((char*)pSignature, (size_t)nSignatureLen); - } - - virtual std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg) - { - if (nAlg == OOXML_HASH_ALG_SHA1) - { - unsigned char obuf[20]; - SHA1(pData, (size_t)nSize, obuf); - - char* pBase64_hash = NULL; - int nBase64Len_hash = 0; - NSFile::CBase64Converter::Encode(obuf, 20, pBase64_hash, nBase64Len_hash, NSBase64::B64_BASE64_FLAG_NOCRLF); - - std::string sReturn(pBase64_hash, nBase64Len_hash); - delete [] pBase64_hash; - - return sReturn; - } - return ""; - } - - virtual std::string GetHash(const std::string& sXml, int nAlg) - { - return GetHash((BYTE*)sXml.c_str(), (DWORD)sXml.length(), nAlg); - } - - virtual std::string GetHash(const std::wstring& sXmlFile, int nAlg) - { - BYTE* pFileData = NULL; - DWORD dwFileDataLen = 0; - NSFile::CFileBinary::ReadAllBytes(sXmlFile, &pFileData, dwFileDataLen); - - if (0 == dwFileDataLen) - return ""; - - std::string sReturn = GetHash(pFileData, dwFileDataLen, nAlg); - - RELEASEARRAYOBJECTS(pFileData); - return sReturn; - } - - virtual bool Verify(const std::string& sXml, std::string& sXmlSignature, int nAlg) - { - EVP_MD_CTX* pCtx = EVP_MD_CTX_create(); - const EVP_MD* pDigest = EVP_sha1(); - - int n1 = EVP_VerifyInit(pCtx, pDigest); - n1 = n1; - - BYTE* pDigestValue = NULL; - int nDigestLen = 0; - NSFile::CBase64Converter::Decode(sXmlSignature.c_str(), (int)sXmlSignature.length(), pDigestValue, nDigestLen); - - int n2 = EVP_VerifyUpdate(pCtx, pDigestValue, (size_t)nDigestLen); - n2 = n2; - - EVP_PKEY* pubkey = X509_get_pubkey(m_cert); - - int n3 = EVP_VerifyFinal(pCtx, (BYTE*)sXml.c_str(), (unsigned int)sXml.length(), pubkey); - n3 = n3; - - EVP_MD_CTX_destroy(pCtx); - EVP_PKEY_free(pubkey); - - RELEASEARRAYOBJECTS(pDigestValue); - - return (1 == n3) ? true : false; - } - - virtual bool LoadFromBase64Data(const std::string& data) - { - BYTE* pData = NULL; - int nLen = 0; - if (NSFile::CBase64Converter::Decode(data.c_str(), (int)data.length(), pData, nLen)) - { - X509* pCert = NULL; - int nErr = LoadCert(pData, (DWORD)nLen, "", &pCert); - - if (nErr == OPEN_SSL_WARNING_OK || nErr == OPEN_SSL_WARNING_ALL_OK) - { - m_cert = pCert; - } - else - { - X509_free(pCert); - m_cert = NULL; - } - - RELEASEARRAYOBJECTS(pData); - return (NULL == m_cert) ? false : true; - } - return false; - } + virtual bool LoadFromBase64Data(const std::string& data); public: - virtual bool ShowSelectDialog() - { - if (!m_pDialog) - return false; + virtual bool ShowSelectDialog(); + virtual int ShowCertificate(); - bool bResult = m_pDialog->ShowSelectDialog(); - - std::wstring sKeyPath = m_pDialog->GetKeyPath(); - std::wstring sKeyPasswordW = m_pDialog->GetKeyPassword(); - std::string sKeyPassword = U_TO_UTF8(sKeyPasswordW); - - std::wstring sCertPath = m_pDialog->GetCertificatePath(); - std::wstring sCertPasswordW = m_pDialog->GetCertificatePassword(); - std::string sCertPassword = U_TO_UTF8(sCertPasswordW); - - if (sCertPath.empty()) - { - sCertPath = sKeyPath; - sCertPassword = sKeyPassword; - } - - int nErr = LoadKey(sKeyPath, sKeyPassword, &m_key); - - if (nErr != OPEN_SSL_WARNING_OK && nErr != OPEN_SSL_WARNING_ALL_OK) - return false; - - nErr = LoadCert(sCertPath, sCertPassword, &m_cert); - - if (nErr != OPEN_SSL_WARNING_OK && nErr != OPEN_SSL_WARNING_ALL_OK) - return false; - - return true; - } - virtual int ShowCertificate() - { - if (m_pDialog) - return m_pDialog->ShowCertificate(this); - return 1; - } - - virtual void SetOpenSslDialog(ICertificateSelectDialogOpenSsl* pDialog) - { - m_pDialog = pDialog; - } - -protected: - tm ASN1_GetTimeT(ASN1_TIME* time) - { - struct tm t; - const char* str = (const char*) time->data; - size_t i = 0; - - memset(&t, 0, sizeof(t)); - - if (time->type == V_ASN1_UTCTIME) - { - /* two digit year */ - t.tm_year = (str[i++] - '0') * 10; - t.tm_year += (str[i++] - '0'); - if (t.tm_year < 70) - t.tm_year += 100; - } - else if (time->type == V_ASN1_GENERALIZEDTIME) - { - /* four digit year */ - t.tm_year = (str[i++] - '0') * 1000; - t.tm_year+= (str[i++] - '0') * 100; - t.tm_year+= (str[i++] - '0') * 10; - t.tm_year+= (str[i++] - '0'); - t.tm_year -= 1900; - } - t.tm_mon = (str[i++] - '0') * 10; - t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1. - t.tm_mday = (str[i++] - '0') * 10; - t.tm_mday+= (str[i++] - '0'); - t.tm_hour = (str[i++] - '0') * 10; - t.tm_hour+= (str[i++] - '0'); - t.tm_min = (str[i++] - '0') * 10; - t.tm_min += (str[i++] - '0'); - t.tm_sec = (str[i++] - '0') * 10; - t.tm_sec += (str[i++] - '0'); - - /* Note: we did not adjust the time based on time zone information */ - return t; - } + virtual void SetOpenSslDialog(ICertificateSelectDialogOpenSsl* pDialog); public: - static std::string GetOpenSslErrors() - { - BIO* bio = BIO_new(BIO_s_mem()); - ERR_print_errors(bio); - char *buf = NULL; - size_t len = BIO_get_mem_data(bio, &buf); - std::string sRet((char*)buf, len); - NSStringExt::ToLower(sRet); - BIO_free (bio); - return sRet; - } - static bool IsOpenSslPasswordError(const std::string& str) - { - if (std::string::npos != str.find("mac verify error")) - return true; - if (std::string::npos != str.find("mac verify failure")) - return true; - if (std::string::npos != str.find("password")) - return true; - return false; - } - - static int LoadKey(BYTE* pData, DWORD dwDataLen, std::string password, EVP_PKEY** ppKey) - { - int nErr = OPEN_SSL_WARNING_ERR; - std::string sError = ""; - - PKCS12* p12 = NULL; - EVP_PKEY* pKey = NULL; - char* pPassword = (password.empty()) ? NULL : (char*)password.c_str(); - - BIO* bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - if (PEM_read_bio_PrivateKey(bio, &pKey, NULL, (void*)pPassword)) - { - nErr = OPEN_SSL_WARNING_OK; - goto end; - } - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - - BIO_free(bio); - bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - if (d2i_PrivateKey_bio(bio, &pKey)) - { - nErr = OPEN_SSL_WARNING_OK; - goto end; - } - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - - BIO_free(bio); - bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - if (d2i_PKCS8PrivateKey_bio(bio, &pKey, NULL, (void*)pPassword)) - { - nErr = OPEN_SSL_WARNING_OK; - goto end; - } - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - - BIO_free(bio); - bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - - p12 = d2i_PKCS12_bio(bio, NULL); - if (p12) - { - X509* pCert = NULL; - STACK_OF(X509)* pCa = NULL; - - if (PKCS12_parse(p12, pPassword, &pKey, &pCert, &pCa)) - { - sk_X509_pop_free(pCa, X509_free); - X509_free(pCert); - PKCS12_free(p12); - nErr = OPEN_SSL_WARNING_ALL_OK; - goto end; - } - PKCS12_free(p12); - - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - } - -end: - if (NULL == ppKey) - EVP_PKEY_free(pKey); - else - *ppKey = pKey; - - BIO_free(bio); - return nErr; - } - - static int LoadKey(std::wstring file, std::string password, EVP_PKEY** ppKey) - { - BYTE* pData = NULL; - DWORD dwDataLen; - if (!NSFile::CFileBinary::ReadAllBytes(file, &pData, dwDataLen)) - return OPEN_SSL_WARNING_ERR; - - int nErr = LoadKey(pData, dwDataLen, password, ppKey); - RELEASEARRAYOBJECTS(pData); - return nErr; - } - - static int LoadCert(BYTE* pData, DWORD dwDataLen, std::string password, X509** ppCert) - { - int nErr = OPEN_SSL_WARNING_ERR; - std::string sError = ""; - - PKCS12* p12 = NULL; - X509* pCert = NULL; - char* pPassword = (password.empty()) ? NULL : (char*)password.c_str(); - - BIO* bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - if (PEM_read_bio_X509(bio, &pCert, NULL, (void*)pPassword)) - { - nErr = OPEN_SSL_WARNING_OK; - goto end; - } - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - - BIO_free(bio); - bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - if (d2i_X509_bio(bio, &pCert)) - { - nErr = OPEN_SSL_WARNING_OK; - goto end; - } - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - - BIO_free(bio); - bio = BIO_new_mem_buf((void*)pData, (int)dwDataLen); - - p12 = d2i_PKCS12_bio(bio, NULL); - if (p12) - { - EVP_PKEY* pKey = NULL; - STACK_OF(X509)* pCa = NULL; - - if (PKCS12_parse(p12, pPassword, &pKey, &pCert, &pCa)) - { - sk_X509_pop_free(pCa, X509_free); - EVP_PKEY_free(pKey); - PKCS12_free(p12); - BIO_free(bio); - nErr = OPEN_SSL_WARNING_ALL_OK; - goto end; - } - - PKCS12_free(p12); - sError = GetOpenSslErrors(); - if (IsOpenSslPasswordError(sError)) - { - nErr = OPEN_SSL_WARNING_PASS; - goto end; - } - } - -end: - if (NULL == ppCert) - X509_free(pCert); - else - *ppCert = pCert; - - BIO_free(bio); - return nErr; - } - - static int LoadCert(std::wstring file, std::string password, X509** ppCert) - { - BYTE* pData = NULL; - DWORD dwDataLen; - if (!NSFile::CFileBinary::ReadAllBytes(file, &pData, dwDataLen)) - return OPEN_SSL_WARNING_ERR; - - int nErr = LoadCert(pData, dwDataLen, password, ppCert); - RELEASEARRAYOBJECTS(pData); - return nErr; - } + static int LoadKey(std::wstring file, std::string password); + static int LoadCert(std::wstring file, std::string password); }; #endif // _XMLSIGNER_OPENSSL_H_