Skip to content

Commit c91b85f

Browse files
committed
Merge commit 'a87060d0c1315ba5a4b456c25e896b60679f9f45' into lauris
2 parents 535f588 + a87060d commit c91b85f

File tree

10 files changed

+161
-197
lines changed

10 files changed

+161
-197
lines changed

cdoc/CDoc2Reader.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ std::string
5050
libcdoc::CDoc2::getSaltForExpand(const std::string& label)
5151
{
5252
std::ostringstream oss;
53-
oss << libcdoc::CDoc2::KEK.data() << cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) << label;
53+
oss << libcdoc::CDoc2::KEK << cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) << label;
5454
return oss.str();
5555
}
5656

@@ -59,9 +59,10 @@ std::string
5959
libcdoc::CDoc2::getSaltForExpand(const std::vector<uint8_t>& key_material, const std::vector<uint8_t>& rcpt_key)
6060
{
6161
std::ostringstream oss;
62-
oss << libcdoc::CDoc2::KEK.data() << cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) <<
63-
std::string(rcpt_key.cbegin(), rcpt_key.cend()) <<
64-
std::string(key_material.cbegin(), key_material.cend());
62+
oss << libcdoc::CDoc2::KEK
63+
<< cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR)
64+
<< std::string_view((const char*)rcpt_key.data(), rcpt_key.size())
65+
<< std::string_view((const char*)key_material.data(), key_material.size());
6566
return oss.str();
6667
}
6768

@@ -128,7 +129,7 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)
128129
std::vector<uint8_t> kek_pm;
129130
crypto->extractHKDF(kek_pm, lock.getBytes(Lock::SALT), lock.getBytes(Lock::PW_SALT), lock.getInt(Lock::KDF_ITER), lock_idx);
130131
LOG_DBG("password2");
131-
kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), 32);
132+
kek = libcdoc::Crypto::expand(kek_pm, info_str, 32);
132133
if (kek.empty()) return libcdoc::CRYPTO_ERROR;
133134
LOG_DBG("password3");
134135
} else if (lock.type == Lock::Type::SYMMETRIC_KEY) {
@@ -137,10 +138,10 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)
137138
std::string info_str = libcdoc::CDoc2::getSaltForExpand(lock.label);
138139
std::vector<uint8_t> kek_pm;
139140
crypto->extractHKDF(kek_pm, lock.getBytes(Lock::SALT), {}, 0, lock_idx);
140-
kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), 32);
141+
kek = libcdoc::Crypto::expand(kek_pm, info_str, 32);
141142

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

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

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

205-
kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), libcdoc::CDoc2::KEY_LEN);
206+
kek = libcdoc::Crypto::expand(kek_pm, info_str, libcdoc::CDoc2::KEY_LEN);
206207
}
207208
} else if (lock.type == Lock::Type::SHARE_SERVER) {
208209
/* SALT */
@@ -322,7 +323,7 @@ CDoc2Reader::getFMK(std::vector<uint8_t>& fmk, unsigned int lock_idx)
322323
LOG_ERROR("{}", last_error);
323324
return libcdoc::CRYPTO_ERROR;
324325
}
325-
std::vector<uint8_t> hhk = libcdoc::Crypto::expand(fmk, std::vector<uint8_t>(libcdoc::CDoc2::HMAC.cbegin(), libcdoc::CDoc2::HMAC.cend()));
326+
std::vector<uint8_t> hhk = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::HMAC);
326327

327328
LOG_TRACE_KEY("xor: {}", lock.encrypted_fmk);
328329
LOG_TRACE_KEY("fmk: {}", fmk);
@@ -386,7 +387,7 @@ CDoc2Reader::beginDecryption(const std::vector<uint8_t>& fmk)
386387
}
387388
}
388389
priv->_at_nonce = false;
389-
std::vector<uint8_t> cek = libcdoc::Crypto::expand(fmk, std::vector<uint8_t>(libcdoc::CDoc2::CEK.cbegin(), libcdoc::CDoc2::CEK.cend()));
390+
std::vector<uint8_t> cek = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::CEK);
390391
LOG_TRACE_KEY("cek: {}", cek);
391392

392393
priv->dec = std::make_unique<libcdoc::DecryptionSource>(*priv->_src, EVP_chacha20_poly1305(), cek, libcdoc::CDoc2::NONCE_LEN);

cdoc/CDoc2Writer.cpp

Lines changed: 51 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ CDoc2Writer::writeHeader(const std::vector<libcdoc::Recipient> &recipients)
6363
return rv;
6464
}
6565

66-
auto hhk = libcdoc::Crypto::expand(fmk, {libcdoc::CDoc2::HMAC.cbegin(), libcdoc::CDoc2::HMAC.cend()});
67-
auto cek = libcdoc::Crypto::expand(fmk, {libcdoc::CDoc2::CEK.cbegin(), libcdoc::CDoc2::CEK.cend()});
66+
auto hhk = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::HMAC);
67+
auto cek = libcdoc::Crypto::expand(fmk, libcdoc::CDoc2::CEK);
6868
std::fill(fmk.begin(), fmk.end(), 0);
6969
LOG_TRACE_KEY("cek: {}", cek);
7070
LOG_TRACE_KEY("hhk: {}", hhk);
@@ -202,6 +202,25 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
202202
const libcdoc::Recipient& rcpt = recipients.at(rcpt_idx);
203203
if (rcpt.isPKI()) {
204204
std::vector<uint8_t> key_material, kek;
205+
std::string send_url;
206+
if(rcpt.isKeyServer()) {
207+
if(!conf) {
208+
setLastError("Configuration is missing");
209+
LOG_ERROR("{}", last_error);
210+
return libcdoc::CONFIGURATION_ERROR;
211+
}
212+
if(!network) {
213+
setLastError("Network backend is missing");
214+
LOG_ERROR("{}", last_error);
215+
return libcdoc::CONFIGURATION_ERROR;
216+
}
217+
send_url = conf->getValue(rcpt.server_id, libcdoc::Configuration::KEYSERVER_SEND_URL);
218+
if (send_url.empty()) {
219+
setLastError("Missing keyserver URL for ID " + rcpt.server_id);
220+
LOG_ERROR("{}", last_error);
221+
return libcdoc::CONFIGURATION_ERROR;
222+
}
223+
}
205224
if(rcpt.pk_type == libcdoc::Recipient::PKType::RSA) {
206225
crypto->random(kek, libcdoc::CDoc2::KEY_LEN);
207226
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {
@@ -218,9 +237,25 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
218237
key_material = libcdoc::Crypto::encrypt(publicKey.get(), RSA_PKCS1_OAEP_PADDING, kek);
219238

220239
LOG_TRACE_KEY("publicKeyDer: {}", rcpt.rcpt_key);
221-
LOG_TRACE_KEY("kek: {}", kek);
222-
LOG_TRACE_KEY("fmk_xor_kek: {}", xor_key);
223240
LOG_TRACE_KEY("enc_kek: {}", key_material);
241+
LOG_TRACE_KEY("kek: {}", kek);
242+
LOG_TRACE_KEY("xor: {}", xor_key);
243+
if(rcpt.isKeyServer()) {
244+
libcdoc::NetworkBackend::CapsuleInfo cinfo;
245+
auto result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "rsa", rcpt.expiry_ts);
246+
if (result < 0) {
247+
setLastError(network->getLastErrorStr(result));
248+
LOG_ERROR("{}", last_error);
249+
return libcdoc::IO_ERROR;
250+
}
251+
252+
LOG_DBG("Keyserver Id: {}", rcpt.server_id);
253+
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);
254+
255+
fb_rcpts.push_back(createRSAServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key));
256+
} else {
257+
fb_rcpts.push_back(createRSACapsule(builder, rcpt, key_material, xor_key));
258+
}
224259
} else {
225260
auto publicKey = libcdoc::Crypto::fromECPublicKeyDer(rcpt.rcpt_key, NID_secp384r1);
226261
if(!publicKey) {
@@ -232,12 +267,9 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
232267
std::vector<uint8_t> sharedSecret = libcdoc::Crypto::deriveSharedSecret(ephKey.get(), publicKey.get());
233268
key_material = libcdoc::Crypto::toPublicKeyDer(ephKey.get());
234269
std::vector<uint8_t> kekPm = libcdoc::Crypto::extract(sharedSecret, std::vector<uint8_t>(libcdoc::CDoc2::KEKPREMASTER.cbegin(), libcdoc::CDoc2::KEKPREMASTER.cend()));
235-
std::string info_str = std::string() + libcdoc::CDoc2::KEK.data() +
236-
cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) +
237-
std::string(rcpt.rcpt_key.cbegin(), rcpt.rcpt_key.cend()) +
238-
std::string(key_material.cbegin(), key_material.cend());
270+
std::string info_str = libcdoc::CDoc2::getSaltForExpand(key_material, rcpt.rcpt_key);
239271

240-
kek = libcdoc::Crypto::expand(kekPm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), fmk.size());
272+
kek = libcdoc::Crypto::expand(kekPm, info_str, fmk.size());
241273
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {
242274
setLastError("Internal error");
243275
LOG_ERROR("{}", last_error);
@@ -249,65 +281,11 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
249281
LOG_TRACE_KEY("ephPublicKeyDer: {}", key_material);
250282
LOG_TRACE_KEY("sharedSecret: {}", sharedSecret);
251283
LOG_TRACE_KEY("kekPm: {}", kekPm);
252-
}
253-
LOG_TRACE_KEY("kek: {}", kek);
254-
LOG_TRACE_KEY("xor: {}", xor_key);
255-
256-
if(rcpt.pk_type == libcdoc::Recipient::PKType::RSA) {
257-
if(rcpt.isKeyServer()) {
258-
if(!conf) {
259-
setLastError("Configuration is missing");
260-
LOG_ERROR("{}", last_error);
261-
return libcdoc::CONFIGURATION_ERROR;
262-
}
263-
if(!network) {
264-
setLastError("Network backend is missing");
265-
LOG_ERROR("{}", last_error);
266-
return libcdoc::CONFIGURATION_ERROR;
267-
}
268-
std::string send_url = conf->getValue(rcpt.server_id, libcdoc::Configuration::KEYSERVER_SEND_URL);
269-
if (send_url.empty()) {
270-
setLastError("Missing keyserver URL for ID " + rcpt.server_id);
271-
LOG_ERROR("{}", last_error);
272-
return libcdoc::CONFIGURATION_ERROR;
273-
}
274-
libcdoc::NetworkBackend::CapsuleInfo cinfo;
275-
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "RSA", rcpt.expiry_ts);
276-
if (result < 0) {
277-
setLastError(network->getLastErrorStr(result));
278-
LOG_ERROR("{}", last_error);
279-
return libcdoc::IO_ERROR;
280-
}
281-
282-
LOG_DBG("Keyserver Id: {}", rcpt.server_id);
283-
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);
284-
285-
auto record = createRSAServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key);
286-
fb_rcpts.push_back(std::move(record));
287-
} else {
288-
auto record = createRSACapsule(builder, rcpt, key_material, xor_key);
289-
fb_rcpts.push_back(std::move(record));
290-
}
291-
} else {
284+
LOG_TRACE_KEY("kek: {}", kek);
285+
LOG_TRACE_KEY("xor: {}", xor_key);
292286
if(rcpt.isKeyServer()) {
293-
if(!conf) {
294-
setLastError("Configuration is missing");
295-
LOG_ERROR("{}", last_error);
296-
return libcdoc::CONFIGURATION_ERROR;
297-
}
298-
if(!network) {
299-
setLastError("Network backend is missing");
300-
LOG_ERROR("{}", last_error);
301-
return libcdoc::CONFIGURATION_ERROR;
302-
}
303-
std::string send_url = conf->getValue(rcpt.server_id, libcdoc::Configuration::KEYSERVER_SEND_URL);
304-
if (send_url.empty()) {
305-
setLastError("Missing keyserver URL for ID " + rcpt.server_id);
306-
LOG_ERROR("{}", last_error);
307-
return libcdoc::CONFIGURATION_ERROR;
308-
}
309287
libcdoc::NetworkBackend::CapsuleInfo cinfo;
310-
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "ecc_secp384r1", rcpt.expiry_ts);
288+
auto result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "ecc_secp384r1", rcpt.expiry_ts);
311289
if (result < 0) {
312290
setLastError(network->getLastErrorStr(result));
313291
LOG_ERROR("{}", last_error);
@@ -317,11 +295,9 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
317295
LOG_DBG("Keyserver Id: {}", rcpt.server_id);
318296
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);
319297

320-
auto record = createECCServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key);
321-
fb_rcpts.push_back(std::move(record));
298+
fb_rcpts.push_back(createECCServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key));
322299
} else {
323-
auto record = createECCCapsule(builder, rcpt, key_material, xor_key);
324-
fb_rcpts.push_back(std::move(record));
300+
fb_rcpts.push_back(createECCCapsule(builder, rcpt, key_material, xor_key));
325301
}
326302
}
327303
} else if (rcpt.isSymmetric()) {
@@ -344,11 +320,11 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
344320
setLastError(crypto->getLastErrorStr(result));
345321
return result;
346322
}
347-
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()), libcdoc::CDoc2::KEY_LEN);
323+
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, info_str, libcdoc::CDoc2::KEY_LEN);
348324

349325
LOG_DBG("Label: {}", rcpt.label);
350326
LOG_DBG("KDF iter: {}", rcpt.kdf_iter);
351-
LOG_DBG("info: {}", toHex(std::vector<uint8_t>(info_str.cbegin(), info_str.cend())));
327+
LOG_DBG("info: {}", toHex(info_str));
352328
LOG_TRACE_KEY("salt: {}", salt);
353329
LOG_TRACE_KEY("pw_salt: {}", pw_salt);
354330
LOG_TRACE_KEY("kek_pm: {}", kek_pm);
@@ -361,11 +337,9 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
361337
return libcdoc::CRYPTO_ERROR;
362338
}
363339
if (rcpt.kdf_iter > 0) {
364-
auto offs = createPasswordCapsule(builder, rcpt, salt, pw_salt, xor_key);
365-
fb_rcpts.push_back(std::move(offs));
340+
fb_rcpts.push_back(createPasswordCapsule(builder, rcpt, salt, pw_salt, xor_key));
366341
} else {
367-
auto offs = createSymmetricKeyCapsule(builder, rcpt, salt, xor_key);
368-
fb_rcpts.push_back(std::move(offs));
342+
fb_rcpts.push_back(createSymmetricKeyCapsule(builder, rcpt, salt, xor_key));
369343
}
370344
} else if (rcpt.isKeyShare()) {
371345
std::string url_list = conf->getValue(rcpt.server_id, libcdoc::Configuration::SHARE_SERVER_URLS);
@@ -405,7 +379,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
405379
// KEK_i = HKDF_Expand(KEK_i_pm, "CDOC2kek" + FMKEncryptionMethod + RecipientInfo_i, L)
406380
std::string info_str = std::string("CDOC2kek") + cdoc20::header::EnumNameFMKEncryptionMethod(cdoc20::header::FMKEncryptionMethod::XOR) + RecipientInfo_i;
407381
LOG_DBG("Info: {}", info_str);
408-
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, std::vector<uint8_t>(info_str.cbegin(), info_str.cend()));
382+
std::vector<uint8_t> kek = libcdoc::Crypto::expand(kek_pm, info_str);
409383
LOG_TRACE_KEY("kek: {}", kek);
410384
if (kek.empty()) return libcdoc::CRYPTO_ERROR;
411385
if (libcdoc::Crypto::xor_data(xor_key, fmk, kek) != libcdoc::OK) {

cdoc/Certificate.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,32 +89,51 @@ Certificate::getNotAfter() const
8989
#endif
9090
}
9191

92-
93-
94-
std::vector<std::string>
95-
Certificate::policies() const
92+
Certificate::EIDType
93+
Certificate::getEIDType() const
9694
{
97-
constexpr int PolicyBufferLen = 50;
98-
std::vector<std::string> list;
99-
10095
if(!cert)
101-
return list;
96+
return Unknown;
10297

10398
auto cp = make_unique_cast<CERTIFICATEPOLICIES_free>(X509_get_ext_d2i(
10499
cert.get(), NID_certificate_policies, nullptr, nullptr));
105100
if(!cp)
106-
return list;
101+
return Unknown;
107102

103+
constexpr int PolicyBufferLen = 50;
104+
char buf[PolicyBufferLen + 1]{};
108105
for(int i = 0; i < sk_POLICYINFO_num(cp.get()); i++) {
109106
POLICYINFO *pi = sk_POLICYINFO_value(cp.get(), i);
110-
char buf[PolicyBufferLen + 1]{};
111107
int len = OBJ_obj2txt(buf, PolicyBufferLen, pi->policyid, 1);
112-
if(len != NID_undef) {
113-
list.push_back(std::string(buf));
108+
if(len == NID_undef) {
109+
continue;
110+
}
111+
112+
std::string_view policy(buf, size_t(len));
113+
if (policy.starts_with("2.999.")) { // Zetes TEST OID prefix
114+
policy = policy.substr(6);
115+
}
116+
117+
if (policy.starts_with("1.3.6.1.4.1.51361.1.1.3") ||
118+
policy.starts_with("1.3.6.1.4.1.51361.1.2.3")) {
119+
return DigiID;
120+
}
121+
122+
if (policy.starts_with("1.3.6.1.4.1.51361.1.1.4") ||
123+
policy.starts_with("1.3.6.1.4.1.51361.1.2.4")) {
124+
return DigiID_EResident;
125+
}
126+
127+
if (policy.starts_with("1.3.6.1.4.1.51361.1.1") ||
128+
policy.starts_with("1.3.6.1.4.1.51455.1.1") ||
129+
policy.starts_with("1.3.6.1.4.1.51361.1.2") ||
130+
policy.starts_with("1.3.6.1.4.1.51455.1.2")) {
131+
return IDCard;
114132
}
115133
}
116134

117-
return list;
135+
// If the execution reaches so far then EID type determination failed.
136+
return Unknown;
118137
}
119138

120139
std::vector<uint8_t>

cdoc/Certificate.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,18 @@ namespace libcdoc {
3232

3333
class Certificate {
3434
public:
35-
enum Algorithm {
35+
enum Algorithm : unsigned char {
3636
RSA,
3737
ECC
3838
};
3939

40+
enum EIDType : unsigned char {
41+
Unknown,
42+
IDCard,
43+
DigiID,
44+
DigiID_EResident
45+
};
46+
4047
unique_free_t<X509> cert;
4148

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

49-
std::vector<std::string> policies() const;
56+
EIDType getEIDType() const;
5057

5158
std::vector<uint8_t> getPublicKey() const;
5259
Algorithm getAlgorithm() const;

0 commit comments

Comments
 (0)