diff options
Diffstat (limited to 'cpp/src/IceSSL/UWPCertificateI.cpp')
-rw-r--r-- | cpp/src/IceSSL/UWPCertificateI.cpp | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/cpp/src/IceSSL/UWPCertificateI.cpp b/cpp/src/IceSSL/UWPCertificateI.cpp new file mode 100644 index 00000000000..e0d26fe159b --- /dev/null +++ b/cpp/src/IceSSL/UWPCertificateI.cpp @@ -0,0 +1,271 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +// +// UWP Certificate implementation +// + +#include <IceSSL/UWP.h> +#include <IceSSL/CertificateI.h> +#include <IceSSL/Util.h> + +#include <Ice/LocalException.h> +#include <Ice/StringConverter.h> +#include <Ice/Base64.h> +#include <Ice/StringUtil.h> + +#include <ppltasks.h> +#include <nserror.h> + +using namespace concurrency; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Storage; +using namespace Windows::Storage::Streams; +using namespace Windows::Security::Cryptography; + +using namespace Ice; +using namespace IceSSL; + +using namespace std; + +namespace +{ + +class UWPCertificateI : public UWP::Certificate, + public CertificateI +{ +public: + + UWPCertificateI(Windows::Security::Cryptography::Certificates::Certificate^); + + virtual bool operator==(const IceSSL::Certificate&) const; + + virtual vector<Ice::Byte> getAuthorityKeyIdentifier() const; + virtual vector<Ice::Byte> getSubjectKeyIdentifier() const; + virtual bool verify(const CertificatePtr&) const; + virtual string encode() const; + + virtual chrono::system_clock::time_point getNotAfter() const; + virtual chrono::system_clock::time_point getNotBefore() const; + virtual string getSerialNumber() const; + virtual DistinguishedName getIssuerDN() const; + virtual vector<pair<int, string> > getIssuerAlternativeNames() const; + virtual DistinguishedName getSubjectDN() const; + virtual vector<pair<int, string> > getSubjectAlternativeNames() const; + virtual int getVersion() const; + virtual Windows::Security::Cryptography::Certificates::Certificate^ getCert() const; + +private: + + Windows::Security::Cryptography::Certificates::Certificate^ _cert; +}; + +const Ice::Long TICKS_PER_MSECOND = 10000LL; +const Ice::Long MSECS_TO_EPOCH = 11644473600000LL; + +vector<pair<int, string> > +certificateAltNames(Windows::Security::Cryptography::Certificates::SubjectAlternativeNameInfo^ subAltNames) +{ + vector<pair<int, string> > altNames; + if(subAltNames) + { + for(auto iter = subAltNames->EmailName->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNameEmail, wstringToString(iter->Current->Data()))); + } + for(auto iter = subAltNames->DnsName->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNameDNS, wstringToString(iter->Current->Data()))); + } + for(auto iter = subAltNames->Url->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNameURL, wstringToString(iter->Current->Data()))); + } + for(auto iter = subAltNames->IPAddress->First(); iter->HasCurrent; iter->MoveNext()) + { + altNames.push_back(make_pair(AltNAmeIP, wstringToString(iter->Current->Data()))); + } + } + return altNames; +} + +} // end anonymous namespace + +UWPCertificateI::UWPCertificateI(Windows::Security::Cryptography::Certificates::Certificate^ cert) : _cert(cert) +{ + if(!_cert) + { + throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Invalid certificate reference"); + } +} + +bool +UWPCertificateI::operator==(const IceSSL::Certificate& r) const +{ + const UWPCertificateI* p = dynamic_cast<const UWPCertificateI*>(&r); + if(!p) + { + return false; + } + + return CryptographicBuffer::Compare(_cert->GetCertificateBlob(), p->_cert->GetCertificateBlob()); +} + +vector<Ice::Byte> +UWPCertificateI::getAuthorityKeyIdentifier() const +{ + throw FeatureNotSupportedException(__FILE__, __LINE__); +} + +vector<Ice::Byte> +UWPCertificateI::getSubjectKeyIdentifier() const +{ + throw FeatureNotSupportedException(__FILE__, __LINE__); +} + +bool +UWPCertificateI::verify(const CertificatePtr&) const +{ + throw FeatureNotSupportedException(__FILE__, __LINE__); +} + +string +UWPCertificateI::encode() const +{ + auto reader = Windows::Storage::Streams::DataReader::FromBuffer(_cert->GetCertificateBlob()); + std::vector<unsigned char> data(reader->UnconsumedBufferLength); + if(!data.empty()) + { + reader->ReadBytes(Platform::ArrayReference<unsigned char>(&data[0], static_cast<unsigned int>(data.size()))); + } + ostringstream os; + os << "-----BEGIN CERTIFICATE-----\n"; + os << IceInternal::Base64::encode(data); + os << "-----END CERTIFICATE-----\n"; + return os.str(); +} + +chrono::system_clock::time_point +UWPCertificateI::getNotAfter() const +{ + // Convert 100ns time from January 1, 1601 to ms from January 1, 1970 + return chrono::system_clock::time_point( + chrono::milliseconds(_cert->ValidTo.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH)); +} + +chrono::system_clock::time_point +UWPCertificateI::getNotBefore() const +{ + // Convert 100ns time from January 1, 1601 to ms from January 1, 1970 + return chrono::system_clock::time_point( + chrono::milliseconds(_cert->ValidFrom.UniversalTime / TICKS_PER_MSECOND - MSECS_TO_EPOCH)); +} + +string +UWPCertificateI::getSerialNumber() const +{ + ostringstream os; + os.fill(0); + os.width(2); + for(unsigned int i = 0; i < _cert->SerialNumber->Length; i++) + { + os << hex << static_cast<int>(_cert->SerialNumber[i]); + } + return IceUtilInternal::toUpper(os.str()); +} + +DistinguishedName +UWPCertificateI::getIssuerDN() const +{ + return DistinguishedName("CN=" + wstringToString(_cert->Issuer->Data())); +} + +vector<pair<int, string> > +UWPCertificateI::getIssuerAlternativeNames() const +{ + throw FeatureNotSupportedException(__FILE__, __LINE__); +} + +DistinguishedName +UWPCertificateI::getSubjectDN() const +{ + return DistinguishedName("CN=" + wstringToString(_cert->Subject->Data())); +} + +vector<pair<int, string> > +UWPCertificateI::getSubjectAlternativeNames() const +{ + return certificateAltNames(_cert->SubjectAlternativeName); +} + +int +UWPCertificateI::getVersion() const +{ + throw FeatureNotSupportedException(__FILE__, __LINE__); +} + +Windows::Security::Cryptography::Certificates::Certificate^ +UWPCertificateI::getCert() const +{ + return _cert; +} + +UWP::CertificatePtr +UWP::Certificate::create(Windows::Security::Cryptography::Certificates::Certificate^ cert) +{ + return ICE_MAKE_SHARED(UWPCertificateI, cert); +} + +UWP::CertificatePtr +UWP::Certificate::load(const std::string& file) +{ + try + { + auto uri = ref new Uri(ref new String(stringToWstring(file).c_str())); + auto file = create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).get(); + auto buffer = create_task(FileIO::ReadTextAsync(file)).get(); + return UWP::Certificate::decode(wstringToString(buffer->Data())); + } + catch(Platform::Exception^ ex) + { + if(HRESULT_CODE(ex->HResult) == ERROR_FILE_NOT_FOUND) + { + throw CertificateReadException(__FILE__, __LINE__, "error opening file :" + file); + } + else + { + throw Ice::SyscallException(__FILE__, __LINE__, ex->HResult); + } + } +} + +UWP::CertificatePtr +UWP::Certificate::decode(const std::string& encoding) +{ + string::size_type size, startpos, endpos = 0; + startpos = encoding.find("-----BEGIN CERTIFICATE-----", endpos); + if (startpos != string::npos) + { + startpos += sizeof("-----BEGIN CERTIFICATE-----"); + endpos = encoding.find("-----END CERTIFICATE-----", startpos); + size = endpos - startpos; + } + else + { + startpos = 0; + endpos = string::npos; + size = encoding.size(); + } + + vector<unsigned char> data(IceInternal::Base64::decode(string(&encoding[startpos], size))); + auto writer = ref new DataWriter(); + writer->WriteBytes(Platform::ArrayReference<unsigned char>(&data[0], static_cast<unsigned int>(data.size()))); + return make_shared<UWPCertificateI>(ref new Certificates::Certificate(writer->DetachBuffer())); +} |