Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 32 additions & 13 deletions cdoc/Certificate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,32 +89,51 @@ Certificate::getNotAfter() const
#endif
}



std::vector<std::string>
Certificate::policies() const
Certificate::EIDType
Certificate::getEIDType() const
{
constexpr int PolicyBufferLen = 50;
std::vector<std::string> list;

if(!cert)
return list;
return Unknown;

auto cp = make_unique_cast<CERTIFICATEPOLICIES_free>(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<uint8_t>
Expand Down
11 changes: 9 additions & 2 deletions cdoc/Certificate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<X509> cert;

explicit Certificate(const std::vector<uint8_t>& cert);
Expand All @@ -46,7 +53,7 @@ class Certificate {
std::string getSurname() const;
std::string getSerialNumber() const;

std::vector<std::string> policies() const;
EIDType getEIDType() const;

std::vector<uint8_t> getPublicKey() const;
Algorithm getAlgorithm() const;
Expand Down
14 changes: 10 additions & 4 deletions cdoc/NetworkBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
108 changes: 37 additions & 71 deletions cdoc/Recipient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include "ILogger.h"
#include "Utils.h"

#include <algorithm>
#include <chrono>

using namespace std;

namespace libcdoc {
Expand Down Expand Up @@ -58,9 +61,10 @@ Recipient::makeSymmetric(std::string label, int32_t kdf_iter)
}

Recipient
Recipient::makePublicKey(std::string label, const std::vector<uint8_t>& public_key, PKType pk_type)
Recipient::makePublicKey(std::string label, std::vector<uint8_t> 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;
Expand All @@ -69,18 +73,20 @@ Recipient::makePublicKey(std::string label, const std::vector<uint8_t>& 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;
}

Recipient
Recipient::makeCertificate(std::string label, std::vector<uint8_t> 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();
Expand All @@ -90,36 +96,32 @@ Recipient::makeCertificate(std::string label, std::vector<uint8_t> cert)
Recipient
Recipient::makeServer(std::string label, std::vector<uint8_t> 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<uint8_t> 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;
}

Expand All @@ -139,54 +141,20 @@ Recipient::isTheSameRecipient(const std::vector<uint8_t>& public_key) const
return rcpt_key == public_key;
}

static Recipient::EIDType
getEIDType(const std::vector<std::string>& 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<std::pair<std::string_view, std::string_view>> &components)
buildLabel(std::ostream& ofs, std::string_view type, std::initializer_list<std::pair<std::string_view, std::string_view>> 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()},
Expand All @@ -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},
Expand All @@ -207,15 +175,15 @@ 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}
});
}

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},
Expand Down Expand Up @@ -251,8 +219,8 @@ Recipient::getLabel(const std::vector<std::pair<std::string_view, std::string_vi
case PUBLIC_KEY:
if (!cert.empty()) {
Certificate x509(cert);
if (auto type = getEIDType(x509.policies()); type != EIDType::Unknown) {
BuildLabelEID(ofs, type, x509);
if (auto eid = x509.getEIDType(); eid != Certificate::Unknown) {
BuildLabelEID(ofs, eid, x509);
} else {
BuildLabelCertificate(ofs, file_name, x509);
}
Expand All @@ -263,11 +231,9 @@ Recipient::getLabel(const std::vector<std::pair<std::string_view, std::string_vi
case KEYSHARE:
break;
}
for (auto& [key, value] : extra) {
if (value.empty())
continue;
ofs << '&';
ofs << urlEncode(key) << '=' << urlEncode(value);
for (const auto& [key, value] : extra) {
if (!value.empty())
ofs << '&' << urlEncode(key) << '=' << urlEncode(value);
}
LOG_DBG("Generated label: {}", ofs.str());
return ofs.str();
Expand Down
18 changes: 4 additions & 14 deletions cdoc/Recipient.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct CDOC_EXPORT Recipient {
/**
* @brief The recipient type
*/
enum Type : unsigned char {
enum Type : uint8_t {
/**
* Uninitialized recipient
*/
Expand All @@ -59,7 +59,7 @@ struct CDOC_EXPORT Recipient {
/**
* @brief The public key type
*/
enum PKType : unsigned char {
enum PKType : uint8_t {
/**
* Elliptic curve
*/
Expand All @@ -70,16 +70,6 @@ struct CDOC_EXPORT Recipient {
RSA
};

/**
* @brief The EID type
*/
enum EIDType : unsigned char {
Unknown,
IDCard,
DigiID,
DigiID_EResident
};

Recipient() = default;

/**
Expand Down Expand Up @@ -193,7 +183,7 @@ struct CDOC_EXPORT Recipient {
* @param pk_type the algorithm type (either ECC or RSA)
* @return a new Recipient structure
*/
static Recipient makePublicKey(std::string label, const std::vector<uint8_t>& public_key, PKType pk_type);
static Recipient makePublicKey(std::string label, std::vector<uint8_t> public_key, PKType pk_type);
/**
* @brief Create a new certificate based Recipient
* @param label the label text
Expand Down Expand Up @@ -233,7 +223,7 @@ struct CDOC_EXPORT Recipient {
* @param recipient_id the recipient id (PNOEE-01234567890)
* @return Recipient a new Recipient structure
*/
static Recipient makeShare(const std::string& label, const std::string& server_id, const std::string& recipient_id);
static Recipient makeShare(std::string label, std::string server_id, std::string recipient_id);

/**
* @brief Get the label for this recipient
Expand Down