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
23 changes: 12 additions & 11 deletions cdoc/CDoc2Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ std::string
libcdoc::CDoc2::getSaltForExpand(const std::string& label)
{
std::ostringstream oss;
oss << libcdoc::CDoc2::KEK.data() << cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) << label;
oss << libcdoc::CDoc2::KEK << cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) << label;
return oss.str();
}

Expand All @@ -59,9 +59,10 @@ std::string
libcdoc::CDoc2::getSaltForExpand(const std::vector<uint8_t>& key_material, const std::vector<uint8_t>& rcpt_key)
{
std::ostringstream oss;
oss << libcdoc::CDoc2::KEK.data() << cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) <<
std::string(rcpt_key.cbegin(), rcpt_key.cend()) <<
std::string(key_material.cbegin(), key_material.cend());
oss << libcdoc::CDoc2::KEK
<< cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR)
<< std::string_view((const char*)rcpt_key.data(), rcpt_key.size())
<< std::string_view((const char*)key_material.data(), key_material.size());
return oss.str();
}

Expand Down Expand Up @@ -128,7 +129,7 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)
std::vector<uint8_t> kek_pm;
crypto->extractHKDF(kek_pm, lock.getBytes(Lock::SALT), lock.getBytes(Lock::PW_SALT), lock.getInt(Lock::KDF_ITER), lock_idx);
LOG_DBG("password2");
kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), 32);
kek = libcdoc::Crypto::expand(kek_pm, info_str, 32);
if (kek.empty()) return libcdoc::CRYPTO_ERROR;
LOG_DBG("password3");
} else if (lock.type == Lock::Type::SYMMETRIC_KEY) {
Expand All @@ -137,10 +138,10 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)
std::string info_str = libcdoc::CDoc2::getSaltForExpand(lock.label);
std::vector<uint8_t> kek_pm;
crypto->extractHKDF(kek_pm, lock.getBytes(Lock::SALT), {}, 0, lock_idx);
kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), 32);
kek = libcdoc::Crypto::expand(kek_pm, info_str, 32);

LOG_DBG("Label: {}", lock.label);
LOG_DBG("info: {}", toHex(std::vector<uint8_t>(info_str.cbegin(), info_str.cend())));
LOG_DBG("info: {}", toHex(info_str));
LOG_TRACE_KEY("salt: {}", lock.getBytes(Lock::SALT));
LOG_TRACE_KEY("kek_pm: {}", kek_pm);
LOG_TRACE_KEY("kek: {}", kek);
Expand Down Expand Up @@ -200,9 +201,9 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)

std::string info_str = libcdoc::CDoc2::getSaltForExpand(key_material, lock.getBytes(Lock::Params::RCPT_KEY));

LOG_DBG("info: {}", toHex(std::vector<uint8_t>(info_str.cbegin(), info_str.cend())));
LOG_DBG("info: {}", toHex(info_str));

kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), libcdoc::CDoc2::KEY_LEN);
kek = libcdoc::Crypto::expand(kek_pm, info_str, libcdoc::CDoc2::KEY_LEN);
}
} else if (lock.type == Lock::Type::SHARE_SERVER) {
/* SALT */
Expand Down Expand Up @@ -322,7 +323,7 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)
LOG_ERROR("{}", last_error);
return libcdoc::CRYPTO_ERROR;
}
std::vector<uint8_t> hhk = libcdoc::Crypto::expand(fmk, std::vector<uint8_t>(libcdoc::CDoc2::HMAC.cbegin(), libcdoc::CDoc2::HMAC.cend()));
std::vector<uint8_t> hhk = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::HMAC);

LOG_TRACE_KEY("xor: {}", lock.encrypted_fmk);
LOG_TRACE_KEY("fmk: {}", fmk);
Expand Down Expand Up @@ -386,7 +387,7 @@ CDoc2Reader::beginDecryption(const std::vector<uint8_t>& fmk)
}
}
priv->_at_nonce = false;
std::vector<uint8_t> cek = libcdoc::Crypto::expand(fmk, std::vector<uint8_t>(libcdoc::CDoc2::CEK.cbegin(), libcdoc::CDoc2::CEK.cend()));
std::vector<uint8_t> cek = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::CEK);
LOG_TRACE_KEY("cek: {}", cek);

priv->dec = std::make_unique<libcdoc::DecryptionSource>(*priv->_src, EVP_chacha20_poly1305(), cek, libcdoc::CDoc2::NONCE_LEN);
Expand Down
128 changes: 51 additions & 77 deletions cdoc/CDoc2Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ CDoc2Writer::writeHeader(const std::vector<libcdoc::Recipient> &recipients)
return rv;
}

auto hhk = libcdoc::Crypto::expand(fmk, {libcdoc::CDoc2::HMAC.cbegin(), libcdoc::CDoc2::HMAC.cend()});
auto cek = libcdoc::Crypto::expand(fmk, {libcdoc::CDoc2::CEK.cbegin(), libcdoc::CDoc2::CEK.cend()});
auto hhk = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::HMAC);
auto cek = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::CEK);
std::fill(fmk.begin(), fmk.end(), 0);
LOG_TRACE_KEY("cek: {}", cek);
LOG_TRACE_KEY("hhk: {}", hhk);
Expand Down Expand Up @@ -202,6 +202,25 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
const libcdoc::Recipient& rcpt = recipients.at(rcpt_idx);
if (rcpt.isPKI()) {
std::vector<uint8_t> key_material, kek;
std::string send_url;
if(rcpt.isKeyServer()) {
if(!conf) {
setLastError("Configuration is missing");
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
if(!network) {
setLastError("Network backend is missing");
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
send_url = conf->getValue(rcpt.server_id, libcdoc::Configuration::KEYSERVER_SEND_URL);
if (send_url.empty()) {
setLastError("Missing keyserver URL for ID " + rcpt.server_id);
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
}
if(rcpt.pk_type == libcdoc::Recipient::PKType::RSA) {
crypto->random(kek, libcdoc::CDoc2::KEY_LEN);
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {
Expand All @@ -218,9 +237,25 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
key_material = libcdoc::Crypto::encrypt(publicKey.get(), RSA_PKCS1_OAEP_PADDING, kek);

LOG_TRACE_KEY("publicKeyDer: {}", rcpt.rcpt_key);
LOG_TRACE_KEY("kek: {}", kek);
LOG_TRACE_KEY("fmk_xor_kek: {}", xor_key);
LOG_TRACE_KEY("enc_kek: {}", key_material);
LOG_TRACE_KEY("kek: {}", kek);
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, "rsa", rcpt.expiry_ts);
if (result < 0) {
setLastError(network->getLastErrorStr(result));
LOG_ERROR("{}", last_error);
return libcdoc::IO_ERROR;
}

LOG_DBG("Keyserver Id: {}", rcpt.server_id);
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);

fb_rcpts.push_back(createRSAServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key));
} else {
fb_rcpts.push_back(createRSACapsule(builder, rcpt, key_material, xor_key));
}
} else {
auto publicKey = libcdoc::Crypto::fromECPublicKeyDer(rcpt.rcpt_key, NID_secp384r1);
if(!publicKey) {
Expand All @@ -232,12 +267,9 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
std::vector<uint8_t> sharedSecret = libcdoc::Crypto::deriveSharedSecret(ephKey.get(), publicKey.get());
key_material = libcdoc::Crypto::toPublicKeyDer(ephKey.get());
std::vector<uint8_t> kekPm = libcdoc::Crypto::extract(sharedSecret, std::vector<uint8_t>(libcdoc::CDoc2::KEKPREMASTER.cbegin(), libcdoc::CDoc2::KEKPREMASTER.cend()));
std::string info_str = std::string() + libcdoc::CDoc2::KEK.data() +
cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) +
std::string(rcpt.rcpt_key.cbegin(), rcpt.rcpt_key.cend()) +
std::string(key_material.cbegin(), key_material.cend());
std::string info_str = libcdoc::CDoc2::getSaltForExpand(key_material, rcpt.rcpt_key);

kek = libcdoc::Crypto::expand(kekPm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), fmk.size());
kek = libcdoc::Crypto::expand(kekPm, info_str, fmk.size());
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {
setLastError("Internal error");
LOG_ERROR("{}", last_error);
Expand All @@ -249,65 +281,11 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
LOG_TRACE_KEY("ephPublicKeyDer: {}", key_material);
LOG_TRACE_KEY("sharedSecret: {}", sharedSecret);
LOG_TRACE_KEY("kekPm: {}", kekPm);
}
LOG_TRACE_KEY("kek: {}", kek);
LOG_TRACE_KEY("xor: {}", xor_key);

if(rcpt.pk_type == libcdoc::Recipient::PKType::RSA) {
if(rcpt.isKeyServer()) {
if(!conf) {
setLastError("Configuration is missing");
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
if(!network) {
setLastError("Network backend is missing");
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
std::string send_url = conf->getValue(rcpt.server_id, libcdoc::Configuration::KEYSERVER_SEND_URL);
if (send_url.empty()) {
setLastError("Missing keyserver URL for ID " + rcpt.server_id);
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
libcdoc::NetworkBackend::CapsuleInfo cinfo;
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "RSA", rcpt.expiry_ts);
if (result < 0) {
setLastError(network->getLastErrorStr(result));
LOG_ERROR("{}", last_error);
return libcdoc::IO_ERROR;
}

LOG_DBG("Keyserver Id: {}", rcpt.server_id);
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);

auto record = createRSAServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key);
fb_rcpts.push_back(std::move(record));
} else {
auto record = createRSACapsule(builder, rcpt, key_material, xor_key);
fb_rcpts.push_back(std::move(record));
}
} else {
LOG_TRACE_KEY("kek: {}", kek);
LOG_TRACE_KEY("xor: {}", xor_key);
if(rcpt.isKeyServer()) {
if(!conf) {
setLastError("Configuration is missing");
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
if(!network) {
setLastError("Network backend is missing");
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
std::string send_url = conf->getValue(rcpt.server_id, libcdoc::Configuration::KEYSERVER_SEND_URL);
if (send_url.empty()) {
setLastError("Missing keyserver URL for ID " + rcpt.server_id);
LOG_ERROR("{}", last_error);
return libcdoc::CONFIGURATION_ERROR;
}
libcdoc::NetworkBackend::CapsuleInfo cinfo;
int 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, "ecc_secp384r1", rcpt.expiry_ts);
if (result < 0) {
setLastError(network->getLastErrorStr(result));
LOG_ERROR("{}", last_error);
Expand All @@ -317,11 +295,9 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
LOG_DBG("Keyserver Id: {}", rcpt.server_id);
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);

auto record = createECCServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key);
fb_rcpts.push_back(std::move(record));
fb_rcpts.push_back(createECCServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key));
} else {
auto record = createECCCapsule(builder, rcpt, key_material, xor_key);
fb_rcpts.push_back(std::move(record));
fb_rcpts.push_back(createECCCapsule(builder, rcpt, key_material, xor_key));
}
}
} else if (rcpt.isSymmetric()) {
Expand All @@ -344,11 +320,11 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
setLastError(crypto->getLastErrorStr(result));
return result;
}
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), libcdoc::CDoc2::KEY_LEN);
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, info_str, libcdoc::CDoc2::KEY_LEN);

LOG_DBG("Label: {}", rcpt.label);
LOG_DBG("KDF iter: {}", rcpt.kdf_iter);
LOG_DBG("info: {}", toHex(std::vector<uint8_t>(info_str.cbegin(), info_str.cend())));
LOG_DBG("info: {}", toHex(info_str));
LOG_TRACE_KEY("salt: {}", salt);
LOG_TRACE_KEY("pw_salt: {}", pw_salt);
LOG_TRACE_KEY("kek_pm: {}", kek_pm);
Expand All @@ -361,11 +337,9 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
return libcdoc::CRYPTO_ERROR;
}
if (rcpt.kdf_iter > 0) {
auto offs = createPasswordCapsule(builder, rcpt, salt, pw_salt, xor_key);
fb_rcpts.push_back(std::move(offs));
fb_rcpts.push_back(createPasswordCapsule(builder, rcpt, salt, pw_salt, xor_key));
} else {
auto offs = createSymmetricKeyCapsule(builder, rcpt, salt, xor_key);
fb_rcpts.push_back(std::move(offs));
fb_rcpts.push_back(createSymmetricKeyCapsule(builder, rcpt, salt, xor_key));
}
} else if (rcpt.isKeyShare()) {
std::string url_list = conf->getValue(rcpt.server_id, libcdoc::Configuration::SHARE_SERVER_URLS);
Expand Down Expand Up @@ -405,7 +379,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
// KEK_i = HKDF_Expand(KEK_i_pm, "CDOC2kek" + FMKEncryptionMethod + RecipientInfo_i, L)
std::string info_str = std::string("CDOC2kek") + cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) + RecipientInfo_i;
LOG_DBG("Info: {}", info_str);
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()));
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, info_str);
LOG_TRACE_KEY("kek: {}", kek);
if (kek.empty()) return libcdoc::CRYPTO_ERROR;
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {
Expand Down
6 changes: 3 additions & 3 deletions cdoc/Crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ uint32_t Crypto::keySize(const std::string &algo)
}

std::vector<uint8_t>
Crypto::hkdf(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt, const std::vector<uint8_t> &info, int len, int mode)
Crypto::hkdf(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt, std::string_view info, int len, int mode)
{
auto ctx = make_unique_ptr<EVP_PKEY_CTX_free>(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
if (!ctx)
Expand All @@ -259,15 +259,15 @@ Crypto::hkdf(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt,
SSL_FAILED(EVP_PKEY_CTX_set_hkdf_md(ctx.get(), EVP_sha256()), "EVP_PKEY_CTX_set_hkdf_md") ||
SSL_FAILED(EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), key.data(), int(key.size())), "EVP_PKEY_CTX_set1_hkdf_key") ||
(!salt.empty() && SSL_FAILED(EVP_PKEY_CTX_set1_hkdf_salt(ctx.get(), salt.data(), int(salt.size())), "EVP_PKEY_CTX_set1_hkdf_salt")) ||
(!info.empty() && SSL_FAILED(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data(), int(info.size())), "EVP_PKEY_CTX_add1_hkdf_info")) ||
(!info.empty() && SSL_FAILED(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), (uint8_t*)info.data(), int(info.size())), "EVP_PKEY_CTX_add1_hkdf_info")) ||
SSL_FAILED(EVP_PKEY_derive(ctx.get(), out.data(), &outlen), "EVP_PKEY_derive"))
return {};

return out;
}

std::vector<uint8_t>
Crypto::expand(const std::vector<uint8_t> &key, const std::vector<uint8_t> &info, int len)
Crypto::expand(const std::vector<uint8_t> &key, std::string_view info, int len)
{
return hkdf(key, {}, info, len, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
}
Expand Down
4 changes: 2 additions & 2 deletions cdoc/Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ class Crypto
static Key generateKey(const std::string &method);
static uint32_t keySize(const std::string &algo);

static std::vector<uint8_t> hkdf(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt, const std::vector<uint8_t> &info, int len = 32, int mode = 0);
static std::vector<uint8_t> expand(const std::vector<uint8_t> &key, const std::vector<uint8_t> &info, int len = 32);
static std::vector<uint8_t> hkdf(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt, std::string_view info, int len = 32, int mode = 0);
static std::vector<uint8_t> expand(const std::vector<uint8_t> &key, std::string_view info, int len = 32);
static std::vector<uint8_t> extract(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt, int len = 32);
static std::vector<uint8_t> sign_hmac(const std::vector<uint8_t> &key, const std::vector<uint8_t> &data);

Expand Down
1 change: 1 addition & 0 deletions libcdoc.i
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ static std::vector<unsigned char> SWIG_JavaArrayToVectorUnsignedChar(JNIEnv *jen

%ignore libcdoc::Recipient::rcpt_key;
%ignore libcdoc::Recipient::cert;
%ignore libcdoc::Recipient::getLabel;
%extend libcdoc::Recipient {
std::vector<uint8_t> getRcptKey() {
return $self->rcpt_key;
Expand Down
Loading