// ********************************************************************** // // Copyright (c) 2003-present 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 #include #include #include #include #include #include #include #include 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 getAuthorityKeyIdentifier() const; virtual vector 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 > getIssuerAlternativeNames() const; virtual DistinguishedName getSubjectDN() const; virtual vector > 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 > certificateAltNames(Windows::Security::Cryptography::Certificates::SubjectAlternativeNameInfo^ subAltNames) { vector > 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(&r); if(!p) { return false; } return CryptographicBuffer::Compare(_cert->GetCertificateBlob(), p->_cert->GetCertificateBlob()); } vector UWPCertificateI::getAuthorityKeyIdentifier() const { throw FeatureNotSupportedException(__FILE__, __LINE__); } vector 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 data(reader->UnconsumedBufferLength); if(!data.empty()) { reader->ReadBytes(Platform::ArrayReference(&data[0], static_cast(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(_cert->SerialNumber[i]); } return IceUtilInternal::toUpper(os.str()); } DistinguishedName UWPCertificateI::getIssuerDN() const { return DistinguishedName("CN=" + wstringToString(_cert->Issuer->Data())); } vector > UWPCertificateI::getIssuerAlternativeNames() const { throw FeatureNotSupportedException(__FILE__, __LINE__); } DistinguishedName UWPCertificateI::getSubjectDN() const { return DistinguishedName("CN=" + wstringToString(_cert->Subject->Data())); } vector > 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& filename) { try { auto uri = ref new Uri(ref new String(stringToWstring(filename).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 :" + filename); } 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 data(IceInternal::Base64::decode(string(&encoding[startpos], size))); auto writer = ref new DataWriter(); writer->WriteBytes(Platform::ArrayReference(&data[0], static_cast(data.size()))); return make_shared(ref new Certificates::Certificate(writer->DetachBuffer())); }