Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
25ab007
Tar and workflow fixes and tests
Jan 23, 2026
98224e6
Merge branch 'open-eid:master' into master
lauris71 Jan 26, 2026
b4a1736
Create locks even if capsule is not supported
Jan 30, 2026
414452e
Update cdoc/CDoc2Reader.cpp
lauris71 Feb 2, 2026
0854344
Use toUint8Vector helper
Feb 2, 2026
777700c
Removed some extra check from parsing
Feb 2, 2026
8cdc652
Remove INVALID lock type and rename UNSUPPORTED to UNKNOWN
Feb 3, 2026
5ef36d7
Return NULL from frontend if CDoc constructor fails
Feb 4, 2026
f2c9091
Merge branch 'open-eid:master' into master
lauris71 Feb 4, 2026
b76e104
Merge branch 'open-eid:master' into master
lauris71 Feb 11, 2026
625c768
Remove label creation from Java test
Feb 11, 2026
678a318
Merge branch 'open-eid:master' into master
lauris71 Feb 12, 2026
372f7f7
Keep Java references in CDocReader and CDocWriter to prevent prematur…
Feb 12, 2026
e9155eb
Merge branch 'open-eid:master' into master
lauris71 Feb 12, 2026
4dc229f
Cleaned up logging
Feb 13, 2026
209042f
Renamed ILogger -> Logger
Feb 13, 2026
ee33b97
Added Logger.h
Feb 13, 2026
9930c35
Removed ConsoleLogger from public interface
Feb 13, 2026
ce13f36
Fixed WinBackend.cpp
Feb 13, 2026
4453784
Fixed WinBackend.cpp more
Feb 13, 2026
cb10179
One more Winbackend fix
Feb 13, 2026
1db00de
Merge branch 'open-eid:master' into master
lauris71 Feb 13, 2026
252333f
Merge branch 'logging'
Feb 13, 2026
985e226
Merge branch 'open-eid:master' into master
lauris71 Feb 17, 2026
d939504
Implement secp256r1 curve support
Feb 17, 2026
db3a58b
Added CDoc.h
Feb 17, 2026
44669de
Merge branch 'master' into multi_curve
Feb 17, 2026
df088d7
Added cdoc-tool support and testing for secp256 curve
Feb 18, 2026
4a7a230
Allow unknown curve type while decrypting
Feb 18, 2026
4f41425
Minor cleanups
Feb 18, 2026
7f4aa1c
Removed Algorithm enum from Certificate and PKCS11 cleanup
Feb 19, 2026
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
27 changes: 26 additions & 1 deletion cdoc/CDoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#ifndef __CDOC_H__
#define __CDOC_H__

#include "Exports.h"
#include <cdoc/Exports.h>

#include <cstdint>
#include <string>
Expand Down Expand Up @@ -129,6 +129,31 @@ CDOC_EXPORT std::string getErrorStr(int64_t code);

CDOC_EXPORT std::string getVersion();

/**
* @brief The public key algorithm
*/
enum Algorithm : uint8_t {
UNKNOWN_ALGORITHM,
/**
* Elliptic curve
*/
ECC,
/**
* RSA
*/
RSA
};

/**
* @brief The EC curve used
*/
enum Curve : uint8_t {
UNKNOWN_CURVE,
SECP_384_R1,
SECP_256_R1
};


// Logging interface

/**
Expand Down
6 changes: 3 additions & 3 deletions cdoc/CDoc1Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ CDoc1Reader::getLockForCert(const std::vector<uint8_t>& cert)
ll.encrypted_fmk.empty())
continue;
switch(cc.getAlgorithm()) {
case libcdoc::Certificate::RSA:
case libcdoc::RSA:
if (ll.getString(Lock::Params::METHOD) == libcdoc::Crypto::RSA_MTH) {
return i;
}
break;
case libcdoc::Certificate::ECC:
case libcdoc::ECC:
if(!ll.getBytes(Lock::Params::KEY_MATERIAL).empty() &&
std::find(SUPPORTED_KWAES.cbegin(), SUPPORTED_KWAES.cend(), ll.getString(Lock::Params::METHOD)) != SUPPORTED_KWAES.cend()) {
return i;
Expand Down Expand Up @@ -331,7 +331,7 @@ CDoc1Reader::CDoc1Reader(libcdoc::DataSource *src, bool delete_on_close)
Certificate ssl(cert);
key.setBytes(Lock::CERT, std::move(cert));
key.setBytes(Lock::RCPT_KEY, ssl.getPublicKey());
key.pk_type = (ssl.getAlgorithm() == libcdoc::Certificate::RSA) ? Lock::RSA : Lock::ECC;
key.pk_type = ssl.getAlgorithm();
}
// EncryptedData/KeyInfo/EncryptedKey/KeyInfo/CipherData/CipherValue
else if(reader.isElement("CipherValue"))
Expand Down
50 changes: 29 additions & 21 deletions cdoc/CDoc2Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,44 +508,52 @@ CDoc2Reader::Private::buildLock(Lock& lock, const cdoc20::header::RecipientRecor
switch(recipient.capsule_type())
{
case Capsule::recipients_ECCPublicKeyCapsule:
if(const auto *key = recipient.capsule_as_recipients_ECCPublicKeyCapsule()) {
if(key->curve() == EllipticCurve::secp384r1) {
lock.type = Lock::Type::PUBLIC_KEY;
lock.pk_type = Lock::PKType::ECC;
lock.setBytes(Lock::Params::RCPT_KEY, toUint8Vector(key->recipient_public_key()));
lock.setBytes(Lock::Params::KEY_MATERIAL, toUint8Vector(key->sender_public_key()));
LOG_DBG("Load PK: {}", toHex(lock.getBytes(Lock::Params::RCPT_KEY)));
if(const auto *capsule = recipient.capsule_as_recipients_ECCPublicKeyCapsule()) {
lock.type = Lock::Type::PUBLIC_KEY;
lock.pk_type = Algorithm::ECC;
if(capsule->curve() == EllipticCurve::secp384r1) {
lock.ec_type = Curve::SECP_384_R1;
} else if (capsule->curve() == EllipticCurve::secp256r1) {
lock.ec_type = Curve::SECP_256_R1;
} else {
LOG_ERROR("Unsupported ECC curve: skipping");
LOG_WARN("Unknown ECC curve: {}", (int) capsule->curve());
lock.ec_type = Curve::UNKNOWN_CURVE;
}
lock.setBytes(Lock::Params::RCPT_KEY, toUint8Vector(capsule->recipient_public_key()));
lock.setBytes(Lock::Params::KEY_MATERIAL, toUint8Vector(capsule->sender_public_key()));
LOG_DBG("Load PK: {}", toHex(lock.getBytes(Lock::Params::RCPT_KEY)));
}
return;
case Capsule::recipients_RSAPublicKeyCapsule:
if(const auto *key = recipient.capsule_as_recipients_RSAPublicKeyCapsule())
{
lock.type = Lock::Type::PUBLIC_KEY;
lock.pk_type = Lock::PKType::RSA;
lock.pk_type = Algorithm::RSA;
lock.setBytes(Lock::Params::RCPT_KEY, toUint8Vector(key->recipient_public_key()));
lock.setBytes(Lock::Params::KEY_MATERIAL, toUint8Vector(key->encrypted_kek()));
}
return;
case Capsule::recipients_KeyServerCapsule:
if (const KeyServerCapsule *server = recipient.capsule_as_recipients_KeyServerCapsule()) {
KeyDetailsUnion details = server->recipient_key_details_type();
if (const KeyServerCapsule *capsule = recipient.capsule_as_recipients_KeyServerCapsule()) {
KeyDetailsUnion details = capsule->recipient_key_details_type();
switch (details) {
case KeyDetailsUnion::EccKeyDetails:
if(const EccKeyDetails *eccDetails = server->recipient_key_details_as_EccKeyDetails()) {
if(eccDetails->curve() != EllipticCurve::secp384r1) {
LOG_ERROR("Unsupported elliptic curve key type");
return;
}
lock.pk_type = Lock::PKType::ECC;
if(const EccKeyDetails *eccDetails = capsule->recipient_key_details_as_EccKeyDetails()) {
lock.pk_type = Algorithm::ECC;
lock.setBytes(Lock::Params::RCPT_KEY, toUint8Vector(eccDetails->recipient_public_key()));
if(eccDetails->curve() == EllipticCurve::secp384r1) {
lock.ec_type = Curve::SECP_384_R1;
} else if (eccDetails->curve() == EllipticCurve::secp256r1) {
lock.ec_type = Curve::SECP_256_R1;
} else {
LOG_WARN("Unknown ECC curve: {}", (int) eccDetails->curve());
lock.ec_type = Curve::UNKNOWN_CURVE;
}
}
break;
case KeyDetailsUnion::RsaKeyDetails:
if(const RsaKeyDetails *rsaDetails = server->recipient_key_details_as_RsaKeyDetails()) {
lock.pk_type = Lock::PKType::RSA;
if(const RsaKeyDetails *rsaDetails = capsule->recipient_key_details_as_RsaKeyDetails()) {
lock.pk_type = Algorithm::RSA;
lock.setBytes(Lock::Params::RCPT_KEY, toUint8Vector(rsaDetails->recipient_public_key()));
}
break;
Expand All @@ -554,8 +562,8 @@ CDoc2Reader::Private::buildLock(Lock& lock, const cdoc20::header::RecipientRecor
return;
}
lock.type = Lock::Type::SERVER;
lock.setString(Lock::Params::KEYSERVER_ID, server->keyserver_id()->str());
lock.setString(Lock::Params::TRANSACTION_ID, server->transaction_id()->str());
lock.setString(Lock::Params::KEYSERVER_ID, capsule->keyserver_id()->str());
lock.setString(Lock::Params::TRANSACTION_ID, capsule->transaction_id()->str());
}
return;
case Capsule::recipients_SymmetricKeyCapsule:
Expand Down
26 changes: 21 additions & 5 deletions cdoc/CDoc2Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ CDoc2Writer::writeHeader(const std::vector<libcdoc::Recipient> &recipients)
return OK;
}

struct ECData {
int ossl_nid;
cdoc20::recipients::EllipticCurve fb_type;
const char *api_id;
};

static std::map<Curve,ECData> ecdata = {
{Curve::SECP_384_R1, {NID_secp384r1, cdoc20::recipients::EllipticCurve::secp384r1, "ecc_secp384r1"}},
{Curve::SECP_256_R1, {NID_X9_62_prime256v1, cdoc20::recipients::EllipticCurve::secp256r1, "ecc_secp256r1"}}
};

static flatbuffers::Offset<cdoc20::header::RecipientRecord>
createRSACapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::vector<uint8_t>& encrypted_kek, const std::vector<uint8_t>& xor_key)
{
Expand Down Expand Up @@ -131,7 +142,7 @@ static flatbuffers::Offset<cdoc20::header::RecipientRecord>
createECCCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::vector<uint8_t>& eph_public_key, const std::vector<uint8_t>& xor_key)
{
auto capsule = cdoc20::recipients::CreateECCPublicKeyCapsule(builder,
cdoc20::recipients::EllipticCurve::secp384r1,
ecdata[rcpt.ec_type].fb_type,
builder.CreateVector(rcpt.rcpt_key),
builder.CreateVector(eph_public_key));
return cdoc20::header::CreateRecipientRecord(builder,
Expand All @@ -146,7 +157,7 @@ static flatbuffers::Offset<cdoc20::header::RecipientRecord>
createECCServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::string& transaction_id, uint64_t expiry_time, const std::vector<uint8_t>& xor_key)
{
auto eccKeyServer = cdoc20::recipients::CreateEccKeyDetails(builder,
cdoc20::recipients::EllipticCurve::secp384r1,
ecdata[rcpt.ec_type].fb_type,
builder.CreateVector(rcpt.rcpt_key));
auto capsule = cdoc20::recipients::CreateKeyServerCapsule(builder,
cdoc20::recipients::KeyDetailsUnion::EccKeyDetails,
Expand Down Expand Up @@ -220,7 +231,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
return libcdoc::CONFIGURATION_ERROR;
}
}
if(rcpt.pk_type == libcdoc::Recipient::PKType::RSA) {
if(rcpt.pk_type == libcdoc::Algorithm::RSA) {
crypto->random(kek, libcdoc::CDoc2::KEY_LEN);
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {
setLastError("Internal error");
Expand Down Expand Up @@ -256,7 +267,12 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
fb_rcpts.push_back(createRSACapsule(builder, rcpt, key_material, xor_key));
}
} else {
auto publicKey = libcdoc::Crypto::fromECPublicKeyDer(rcpt.rcpt_key, NID_secp384r1);
if (!ecdata.contains(rcpt.ec_type)) {
setLastError("Invalid EC curve");
LOG_ERROR("{}", last_error);
return libcdoc::CRYPTO_ERROR;
}
auto publicKey = libcdoc::Crypto::fromECPublicKeyDer(rcpt.rcpt_key, ecdata[rcpt.ec_type].ossl_nid);
if(!publicKey) {
setLastError("Invalid ECC key");
LOG_ERROR("{}", last_error);
Expand Down Expand Up @@ -284,7 +300,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
LOG_TRACE_KEY("xor: {}", xor_key);
if(rcpt.isKeyServer()) {
libcdoc::NetworkBackend::CapsuleInfo cinfo;
auto result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "ecc_secp384r1", rcpt.expiry_ts);
auto result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, ecdata[rcpt.ec_type].api_id, rcpt.expiry_ts);
if (result < 0) {
setLastError(network->getLastErrorStr(result));
LOG_ERROR("{}", last_error);
Expand Down
Loading