diff --git a/cdoc/Certificate.cpp b/cdoc/Certificate.cpp index 03e6636..60769c4 100644 --- a/cdoc/Certificate.cpp +++ b/cdoc/Certificate.cpp @@ -89,32 +89,51 @@ Certificate::getNotAfter() const #endif } - - -std::vector -Certificate::policies() const +Certificate::EIDType +Certificate::getEIDType() const { - constexpr int PolicyBufferLen = 50; - std::vector list; - if(!cert) - return list; + return Unknown; auto cp = make_unique_cast(X509_get_ext_d2i( cert.get(), NID_certificate_policies, nullptr, nullptr)); if(!cp) - return list; + return Unknown; + constexpr int PolicyBufferLen = 50; + char buf[PolicyBufferLen + 1]{}; for(int i = 0; i < sk_POLICYINFO_num(cp.get()); i++) { POLICYINFO *pi = sk_POLICYINFO_value(cp.get(), i); - char buf[PolicyBufferLen + 1]{}; int len = OBJ_obj2txt(buf, PolicyBufferLen, pi->policyid, 1); - if(len != NID_undef) { - list.push_back(std::string(buf)); + if(len == NID_undef) { + continue; + } + + std::string_view policy(buf, size_t(len)); + if (policy.starts_with("2.999.")) { // Zetes TEST OID prefix + policy = policy.substr(6); + } + + if (policy.starts_with("1.3.6.1.4.1.51361.1.1.3") || + policy.starts_with("1.3.6.1.4.1.51361.1.2.3")) { + return DigiID; + } + + if (policy.starts_with("1.3.6.1.4.1.51361.1.1.4") || + policy.starts_with("1.3.6.1.4.1.51361.1.2.4")) { + return DigiID_EResident; + } + + if (policy.starts_with("1.3.6.1.4.1.51361.1.1") || + policy.starts_with("1.3.6.1.4.1.51455.1.1") || + policy.starts_with("1.3.6.1.4.1.51361.1.2") || + policy.starts_with("1.3.6.1.4.1.51455.1.2")) { + return IDCard; } } - return list; + // If the execution reaches so far then EID type determination failed. + return Unknown; } std::vector diff --git a/cdoc/Certificate.h b/cdoc/Certificate.h index 830f7e2..4fd7a54 100644 --- a/cdoc/Certificate.h +++ b/cdoc/Certificate.h @@ -32,11 +32,18 @@ namespace libcdoc { class Certificate { public: - enum Algorithm { + enum Algorithm : unsigned char { RSA, ECC }; + enum EIDType : unsigned char { + Unknown, + IDCard, + DigiID, + DigiID_EResident + }; + unique_free_t cert; explicit Certificate(const std::vector& cert); @@ -46,7 +53,7 @@ class Certificate { std::string getSurname() const; std::string getSerialNumber() const; - std::vector policies() const; + EIDType getEIDType() const; std::vector getPublicKey() const; Algorithm getAlgorithm() const; diff --git a/cdoc/NetworkBackend.cpp b/cdoc/NetworkBackend.cpp index c572313..40163de 100644 --- a/cdoc/NetworkBackend.cpp +++ b/cdoc/NetworkBackend.cpp @@ -293,7 +293,7 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons if (expiry_ts) { std::string expiry_str = timeToISO(expiry_ts); LOG_DBG("Expiry time: {}", expiry_str); - hdrs.emplace(std::make_pair("x-expiry-time", expiry_str)); + hdrs.emplace("x-expiry-time", expiry_str); } httplib::Response rsp; result = post(cli, full, hdrs, req_str, rsp); @@ -306,12 +306,18 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons } error = {}; /* Remove /key-capsules/ */ - dst.transaction_id = location.substr(14); + location.erase(0, 14); + dst.transaction_id = std::move(location); std::string expiry_str = rsp.get_header_value("x-expiry-time"); LOG_DBG("Server expiry: {}", expiry_str); - dst.expiry_time = uint64_t(timeFromISO(expiry_str)); - LOG_DBG("Server expiry timestamp: {}", dst.expiry_time); + if (expiry_str.empty()) { + dst.expiry_time = expiry_ts; + LOG_DBG("Given expiry timestamp: {}", dst.expiry_time); + } else { + dst.expiry_time = uint64_t(timeFromISO(expiry_str)); + LOG_DBG("Server expiry timestamp: {}", dst.expiry_time); + } return OK; } diff --git a/cdoc/Recipient.cpp b/cdoc/Recipient.cpp index 5d9b4d0..16ad32c 100644 --- a/cdoc/Recipient.cpp +++ b/cdoc/Recipient.cpp @@ -24,6 +24,9 @@ #include "ILogger.h" #include "Utils.h" +#include +#include + using namespace std; namespace libcdoc { @@ -58,9 +61,10 @@ Recipient::makeSymmetric(std::string label, int32_t kdf_iter) } Recipient -Recipient::makePublicKey(std::string label, const std::vector& public_key, PKType pk_type) +Recipient::makePublicKey(std::string label, std::vector public_key, PKType pk_type) { - if (public_key.empty()) return Recipient(Type::NONE); + if (public_key.empty()) + return {Type::NONE}; Recipient rcpt(Type::PUBLIC_KEY); rcpt.label = std::move(label); rcpt.pk_type = pk_type; @@ -69,7 +73,7 @@ Recipient::makePublicKey(std::string label, const std::vector& public_k auto evp = Crypto::fromECPublicKeyDer(public_key); rcpt.rcpt_key = Crypto::toPublicKeyDer(evp.get()); } else { - rcpt.rcpt_key = public_key; + rcpt.rcpt_key = std::move(public_key); } return rcpt; } @@ -77,10 +81,12 @@ Recipient::makePublicKey(std::string label, const std::vector& public_k Recipient Recipient::makeCertificate(std::string label, std::vector cert) { + Certificate x509(cert); + if (!x509.cert) + return {Type::NONE}; Recipient rcpt(Type::PUBLIC_KEY); rcpt.label = std::move(label); rcpt.cert = std::move(cert); - Certificate x509(rcpt.cert); rcpt.rcpt_key = x509.getPublicKey(); rcpt.pk_type = (x509.getAlgorithm() == libcdoc::Certificate::RSA) ? PKType::RSA : PKType::ECC; rcpt.expiry_ts = x509.getNotAfter(); @@ -90,36 +96,32 @@ Recipient::makeCertificate(std::string label, std::vector cert) Recipient Recipient::makeServer(std::string label, std::vector public_key, PKType pk_type, std::string server_id) { - Recipient rcpt(Type::PUBLIC_KEY); - rcpt.label = std::move(label); - rcpt.pk_type = pk_type; - if (pk_type == PKType::ECC && public_key[0] == 0x30) { - // 0x30 identifies SEQUENCE tag in ASN.1 encoding - auto evp = Crypto::fromECPublicKeyDer(public_key); - rcpt.rcpt_key = Crypto::toPublicKeyDer(evp.get()); - } else { - rcpt.rcpt_key = std::move(public_key); - } + Recipient rcpt = makePublicKey(std::move(label), std::move(public_key), pk_type); rcpt.server_id = std::move(server_id); + const auto six_months_from_now = std::chrono::system_clock::now() + std::chrono::months(6); + const auto expiry_ts = std::chrono::system_clock::to_time_t(six_months_from_now); + rcpt.expiry_ts = uint64_t(expiry_ts); return rcpt; } Recipient Recipient::makeServer(std::string label, std::vector cert, std::string server_id) { - Certificate x509(cert); - Recipient rcpt = makeServer(std::move(label), x509.getPublicKey(), x509.getAlgorithm() == Certificate::Algorithm::RSA ? RSA : ECC, std::move(server_id)); - rcpt.cert = cert; - return std::move(rcpt); + Recipient rcpt = makeCertificate(std::move(label), std::move(cert)); + rcpt.server_id = std::move(server_id); + const auto six_months_from_now = std::chrono::system_clock::now() + std::chrono::months(6); + const auto expiry_ts = std::chrono::system_clock::to_time_t(six_months_from_now); + rcpt.expiry_ts = std::min(rcpt.expiry_ts, uint64_t(expiry_ts)); + return rcpt; } Recipient -Recipient::makeShare(const std::string& label, const std::string& server_id, const std::string& recipient_id) +Recipient::makeShare(std::string label, std::string server_id, std::string recipient_id) { Recipient rcpt(Type::KEYSHARE); - rcpt.label = label; - rcpt.server_id = server_id; - rcpt.id = recipient_id; + rcpt.label = std::move(label); + rcpt.server_id = std::move(server_id); + rcpt.id = std::move(recipient_id); return rcpt; } @@ -139,54 +141,20 @@ Recipient::isTheSameRecipient(const std::vector& public_key) const return rcpt_key == public_key; } -static Recipient::EIDType -getEIDType(const std::vector& policies) -{ - for (const auto& pol : policies) - { - std::string_view policy = pol; - if (policy.starts_with("2.999.")) { // Zetes TEST OID prefix - policy = policy.substr(6); - } - - if (policy.starts_with("1.3.6.1.4.1.51361.1.1.3") || - policy.starts_with("1.3.6.1.4.1.51361.1.2.3")) { - return Recipient::EIDType::DigiID; - } - - if (policy.starts_with("1.3.6.1.4.1.51361.1.1.4") || - policy.starts_with("1.3.6.1.4.1.51361.1.2.4")) { - return Recipient::EIDType::DigiID_EResident; - } - - if (policy.starts_with("1.3.6.1.4.1.51361.1.1") || - policy.starts_with("1.3.6.1.4.1.51455.1.1") || - policy.starts_with("1.3.6.1.4.1.51361.1.2") || - policy.starts_with("1.3.6.1.4.1.51455.1.2")) { - return Recipient::EIDType::IDCard; - } - } - - // If the execution reaches so far then EID type determination failed. - return Recipient::EIDType::Unknown; -} - static void -buildLabel(std::ostream& ofs, std::string_view type, const std::initializer_list> &components) +buildLabel(std::ostream& ofs, std::string_view type, std::initializer_list> components) { ofs << LABELPREFIX; ofs << "v" << '=' << std::to_string(CDoc2::KEYLABELVERSION) << '&' << "type" << '=' << type; - for (auto& [key, value] : components) { - if (value.empty()) - continue; - ofs << '&'; - ofs << urlEncode(key) << '=' << urlEncode(value); + for (const auto& [key, value] : components) { + if (!value.empty()) + ofs << '&' << urlEncode(key) << '=' << urlEncode(value); } } static void -BuildLabelEID(std::ostream& ofs, Recipient::EIDType type, const Certificate& x509) +BuildLabelEID(std::ostream& ofs, Certificate::EIDType type, const Certificate& x509) { buildLabel(ofs, eid_strs[type], { {"cn", x509.getCommonName()}, @@ -197,7 +165,7 @@ BuildLabelEID(std::ostream& ofs, Recipient::EIDType type, const Certificate& x50 } static void -BuildLabelCertificate(std::ostream &ofs, std::string_view file, const Certificate& x509) +BuildLabelCertificate(std::ostream &ofs, const std::string& file, const Certificate& x509) { buildLabel(ofs, "cert", { {"file", file}, @@ -207,7 +175,7 @@ BuildLabelCertificate(std::ostream &ofs, std::string_view file, const Certificat } static void -BuildLabelPublicKey(std::ostream &ofs, const std::string file) +BuildLabelPublicKey(std::ostream &ofs, const std::string& file) { buildLabel(ofs, "pub_key", { {"file", file} @@ -215,7 +183,7 @@ BuildLabelPublicKey(std::ostream &ofs, const std::string file) } static void -BuildLabelSymmetricKey(std::ostream &ofs, const std::string& label, const std::string file) +BuildLabelSymmetricKey(std::ostream &ofs, const std::string& label, const std::string& file) { buildLabel(ofs, "secret", { {"label", label}, @@ -251,8 +219,8 @@ Recipient::getLabel(const std::vector