Skip to content

Commit b17fddd

Browse files
authored
Added x-expiry time support and cleaned up label autogen (#74)
Signed-off-by: Lauris Kaplinski <[email protected]>
1 parent 2ee27ed commit b17fddd

File tree

12 files changed

+258
-278
lines changed

12 files changed

+258
-278
lines changed

cdoc/CDoc2Writer.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ createRSACapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipie
105105
return cdoc20::header::CreateRecipientRecord(builder,
106106
cdoc20::header::Capsule::recipients_RSAPublicKeyCapsule,
107107
capsule.Union(),
108-
builder.CreateString(rcpt.label),
108+
builder.CreateString(rcpt.getLabel({})),
109109
builder.CreateVector(xor_key),
110110
cdoc20::header::FMKEncryptionMethod::XOR);
111111
}
112112

113113
static flatbuffers::Offset<cdoc20::header::RecipientRecord>
114-
createRSAServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::string& transaction_id, const std::vector<uint8_t>& xor_key)
114+
createRSAServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::string& transaction_id, uint64_t expiry_time, const std::vector<uint8_t>& xor_key)
115115
{
116116
auto rsaKeyServer = cdoc20::recipients::CreateRsaKeyDetails(builder,
117117
builder.CreateVector(rcpt.rcpt_key));
@@ -123,7 +123,7 @@ createRSAServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::R
123123
return cdoc20::header::CreateRecipientRecord(builder,
124124
cdoc20::header::Capsule::recipients_KeyServerCapsule,
125125
capsule.Union(),
126-
builder.CreateString(rcpt.label),
126+
builder.CreateString(rcpt.getLabel({{"x-expiry-time", std::to_string(expiry_time)}})),
127127
builder.CreateVector(xor_key),
128128
cdoc20::header::FMKEncryptionMethod::XOR);
129129
}
@@ -138,13 +138,13 @@ createECCCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipie
138138
return cdoc20::header::CreateRecipientRecord(builder,
139139
cdoc20::header::Capsule::recipients_ECCPublicKeyCapsule,
140140
capsule.Union(),
141-
builder.CreateString(rcpt.label),
141+
builder.CreateString(rcpt.getLabel({})),
142142
builder.CreateVector(xor_key),
143143
cdoc20::header::FMKEncryptionMethod::XOR);
144144
}
145145

146146
static flatbuffers::Offset<cdoc20::header::RecipientRecord>
147-
createECCServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::string& transaction_id, const std::vector<uint8_t>& xor_key)
147+
createECCServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Recipient& rcpt, const std::string& transaction_id, uint64_t expiry_time, const std::vector<uint8_t>& xor_key)
148148
{
149149
auto eccKeyServer = cdoc20::recipients::CreateEccKeyDetails(builder,
150150
cdoc20::recipients::EllipticCurve::secp384r1,
@@ -157,7 +157,7 @@ createECCServerCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::R
157157
return cdoc20::header::CreateRecipientRecord(builder,
158158
cdoc20::header::Capsule::recipients_KeyServerCapsule,
159159
capsule.Union(),
160-
builder.CreateString(rcpt.label),
160+
builder.CreateString(rcpt.getLabel({{"x-expiry-time", std::to_string(expiry_time)}})),
161161
builder.CreateVector(xor_key),
162162
cdoc20::header::FMKEncryptionMethod::XOR);
163163
}
@@ -170,7 +170,7 @@ createSymmetricKeyCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc
170170
return cdoc20::header::CreateRecipientRecord(builder,
171171
cdoc20::header::Capsule::recipients_SymmetricKeyCapsule,
172172
capsule.Union(),
173-
builder.CreateString(rcpt.label),
173+
builder.CreateString(rcpt.getLabel({})),
174174
builder.CreateVector(xor_key),
175175
cdoc20::header::FMKEncryptionMethod::XOR);
176176
}
@@ -186,7 +186,7 @@ createPasswordCapsule(flatbuffers::FlatBufferBuilder& builder, const libcdoc::Re
186186
return cdoc20::header::CreateRecipientRecord(builder,
187187
cdoc20::header::Capsule::recipients_PBKDF2Capsule,
188188
capsule.Union(),
189-
builder.CreateString(rcpt.label),
189+
builder.CreateString(rcpt.getLabel({})),
190190
builder.CreateVector(xor_key),
191191
cdoc20::header::FMKEncryptionMethod::XOR);
192192
}
@@ -272,7 +272,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
272272
return libcdoc::CONFIGURATION_ERROR;
273273
}
274274
libcdoc::NetworkBackend::CapsuleInfo cinfo;
275-
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "RSA");
275+
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "RSA", rcpt.expiry_ts);
276276
if (result < 0) {
277277
setLastError(network->getLastErrorStr(result));
278278
LOG_ERROR("{}", last_error);
@@ -282,7 +282,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
282282
LOG_DBG("Keyserver Id: {}", rcpt.server_id);
283283
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);
284284

285-
auto record = createRSAServerCapsule(builder, rcpt, cinfo.transaction_id, xor_key);
285+
auto record = createRSAServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key);
286286
fb_rcpts.push_back(std::move(record));
287287
} else {
288288
auto record = createRSACapsule(builder, rcpt, key_material, xor_key);
@@ -307,7 +307,7 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
307307
return libcdoc::CONFIGURATION_ERROR;
308308
}
309309
libcdoc::NetworkBackend::CapsuleInfo cinfo;
310-
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "ecc_secp384r1");
310+
int result = network->sendKey(cinfo, send_url, rcpt.rcpt_key, key_material, "ecc_secp384r1", rcpt.expiry_ts);
311311
if (result < 0) {
312312
setLastError(network->getLastErrorStr(result));
313313
LOG_ERROR("{}", last_error);
@@ -317,15 +317,15 @@ CDoc2Writer::buildHeader(std::vector<uint8_t>& header, const std::vector<libcdoc
317317
LOG_DBG("Keyserver Id: {}", rcpt.server_id);
318318
LOG_DBG("Transaction Id: {}", cinfo.transaction_id);
319319

320-
auto record = createECCServerCapsule(builder, rcpt, cinfo.transaction_id, xor_key);
320+
auto record = createECCServerCapsule(builder, rcpt, cinfo.transaction_id, cinfo.expiry_time, xor_key);
321321
fb_rcpts.push_back(std::move(record));
322322
} else {
323323
auto record = createECCCapsule(builder, rcpt, key_material, xor_key);
324324
fb_rcpts.push_back(std::move(record));
325325
}
326326
}
327327
} else if (rcpt.isSymmetric()) {
328-
std::string info_str = libcdoc::CDoc2::getSaltForExpand(rcpt.label);
328+
std::string info_str = libcdoc::CDoc2::getSaltForExpand(rcpt.getLabel({}));
329329
std::vector<uint8_t> kek_pm(libcdoc::CDoc2::KEY_LEN);
330330
std::vector<uint8_t> salt;
331331
int64_t result = crypto->random(salt, libcdoc::CDoc2::KEY_LEN);

cdoc/CDocCipher.cpp

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -268,64 +268,17 @@ fill_recipients_from_rcpt_info(ToolConf& conf, ToolCrypto& crypto, std::vector<l
268268
for (const auto& rcpt : recipients) {
269269
// Generate the labels if needed
270270
string label;
271-
if (conf.gen_label) {
272-
switch (rcpt.type) {
273-
case RcptInfo::Type::PASSWORD:
274-
label = Recipient::BuildLabelPassword(CDoc2::KEYLABELVERSION, rcpt.label.empty() ? GenerateRandomSequence() : rcpt.label);
275-
break;
276-
277-
case RcptInfo::Type::SKEY:
278-
label = Recipient::BuildLabelSymmetricKey(CDoc2::KEYLABELVERSION, rcpt.label.empty() ? GenerateRandomSequence() : rcpt.label, rcpt.key_file_name);
279-
break;
280-
281-
case RcptInfo::Type::PKEY:
282-
label = Recipient::BuildLabelPublicKey(CDoc2::KEYLABELVERSION, rcpt.key_file_name);
283-
break;
284-
285-
case RcptInfo::Type::P11_PKI: {
286-
bool isRsa;
287-
vector<uint8_t> cert_bytes;
288-
ToolPKCS11* p11 = dynamic_cast<ToolPKCS11*>(crypto.p11.get());
289-
int result = p11->getCertificate(cert_bytes, isRsa, rcpt.slot, rcpt.secret, rcpt.key_id, rcpt.key_label);
290-
if (result != libcdoc::OK)
291-
{
292-
LOG_ERROR("Certificate reading from SC card failed. Key label: {}", rcpt.key_label);
293-
return 1;
294-
}
295-
LOG_DBG("Got certificate from P11 module");
296-
label = Recipient::BuildLabelEID(cert_bytes);
297-
break;
298-
}
299-
300-
case RcptInfo::Type::CERT:
301-
{
302-
label = Recipient::BuildLabelCertificate(rcpt.key_file_name, rcpt.cert);
303-
break;
304-
} case RcptInfo::Type::P11_SYMMETRIC:
305-
// TODO: what label should be generated in this case?
306-
break;
307-
308-
default:
309-
LOG_ERROR("Unhandled recipient type {} for generating the lock's label", static_cast<int>(rcpt.type));
310-
break;
311-
}
312-
#ifndef NDEBUG
313-
LOG_DBG("Generated label: {}", label);
314-
#endif
315-
} else {
316-
label = rcpt.label;
317-
}
318-
319-
if (label.empty()) {
320-
LOG_ERROR("No lock label");
321-
return 1;
322-
}
271+
if (!conf.gen_label) label = rcpt.label;
323272

324273
crypto_rcpts[idx++] = rcpt;
325274

326275
Recipient key;
327276
if (rcpt.type == RcptInfo::Type::CERT) {
328-
key = libcdoc::Recipient::makeCertificate(label, rcpt.cert);
277+
if (!conf.servers.empty()) {
278+
key = libcdoc::Recipient::makeServer(label, rcpt.cert, conf.servers[0].ID);
279+
} else {
280+
key = libcdoc::Recipient::makeCertificate(label, rcpt.cert);
281+
}
329282
} else if (rcpt.type == RcptInfo::Type::SKEY) {
330283
key = libcdoc::Recipient::makeSymmetric(label, 0);
331284
LOG_DBG("Creating symmetric key:");
@@ -766,7 +719,7 @@ void CDocCipher::Locks(const char* file) const
766719
}
767720

768721
// Output the fields with their values
769-
cout << lock_id << ":" << endl;
722+
cout << lock_id << ":" << lock.label << endl;
770723
for (map<string, string>::const_reference pair : parsed_label) {
771724
cout << " " << setw(maxFieldLength + 1) << left << pair.first << ": " << pair.second << endl;
772725
}

cdoc/ILogger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ class CDOC_EXPORT ILogger
134134
*/
135135
static ILogger* getLogger();
136136

137+
static void setLogger(ILogger *logger);
138+
137139
protected:
138140
/**
139141
* @brief Minimum level of log messages to log.

cdoc/LogEngine.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ struct LogEngine final : public ILogger
5757
return tmp;
5858
}
5959

60+
void setLogger(ILogger *logger) {
61+
lock_guard<mutex> guard(loggers_protector);
62+
while (!loggers.empty()) {
63+
delete loggers.begin()->second;
64+
loggers.erase(loggers.begin()->first);
65+
}
66+
loggers[0] = logger;
67+
}
68+
6069
private:
6170
// Current Cookie value
6271
int currentLoggerCookie = 0;
@@ -91,4 +100,11 @@ ILogger::getLogger()
91100
return &defaultLogEngine;
92101
}
93102

103+
void
104+
ILogger::setLogger(ILogger *logger)
105+
{
106+
defaultLogEngine.setLogger(logger);
107+
}
108+
109+
94110
}

cdoc/NetworkBackend.cpp

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,11 @@ setProxy(httplib::SSLClient& cli, libcdoc::NetworkBackend *network)
224224
// Post request and fetch response
225225
//
226226
static libcdoc::result_t
227-
post(httplib::SSLClient& cli, const std::string& path, const std::string& req, httplib::Response& rsp)
227+
post(httplib::SSLClient& cli, const std::string& path, httplib::Headers& hdrs, const std::string& req, httplib::Response& rsp)
228228
{
229229
// Capture TLS and HTTP errors
230230
libcdoc::LOG_DBG("POST: {} {}", path, req);
231-
httplib::Result res = cli.Post(path, req, "application/json");
231+
httplib::Result res = cli.Post(path, hdrs, req, "application/json");
232232
if (!res) {
233233
error = FORMAT("Cannot connect to https://{}:{}{}", cli.host(), cli.port(), path);
234234
return libcdoc::NetworkBackend::NETWORK_ERROR;
@@ -267,8 +267,9 @@ get(httplib::SSLClient& cli, httplib::Headers& hdrs, const std::string& path, pi
267267
}
268268

269269
libcdoc::result_t
270-
libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, const std::vector<uint8_t>& rcpt_key, const std::vector<uint8_t> &key_material, const std::string& type)
270+
libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, const std::vector<uint8_t>& rcpt_key, const std::vector<uint8_t> &key_material, const std::string& type, uint64_t expiry_ts)
271271
{
272+
LOG_DBG("Sendkey");
272273
picojson::object obj = {
273274
{"recipient_id", picojson::value(libcdoc::toBase64(rcpt_key))},
274275
{"ephemeral_key_material", picojson::value(libcdoc::toBase64(key_material))},
@@ -288,8 +289,14 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons
288289
if (result = setProxy(cli, this); result != OK) return result;
289290

290291
std::string full = path + "/key-capsules";
292+
httplib::Headers hdrs;
293+
if (expiry_ts) {
294+
std::string expiry_str = timeToISO(expiry_ts);
295+
LOG_DBG("Expiry time: {}", expiry_str);
296+
hdrs.emplace(std::make_pair("x-expiry-time", expiry_str));
297+
}
291298
httplib::Response rsp;
292-
result = post(cli, full, req_str, rsp);
299+
result = post(cli, full, hdrs, req_str, rsp);
293300
if (result != libcdoc::OK) return result;
294301

295302
std::string location = rsp.get_header_value("Location");
@@ -298,28 +305,13 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons
298305
return NETWORK_ERROR;
299306
}
300307
error = {};
301-
302308
/* Remove /key-capsules/ */
303309
dst.transaction_id = location.substr(14);
304310

305-
// Calculate expiry time
306-
auto now = std::chrono::system_clock::now();
307-
// Get a days-precision chrono::time_point
308-
auto sd = floor<std::chrono::days>(now);
309-
// Record the time of day
310-
auto time_of_day = now - sd;
311-
// Convert to a y/m/d calendar data structure
312-
std::chrono::year_month_day ymd = sd;
313-
// Add the months
314-
ymd += std::chrono::months{6};
315-
// Add some policy for overflowing the day-of-month if desired
316-
if (!ymd.ok())
317-
ymd = ymd.year()/ymd.month()/std::chrono::last;
318-
// Convert back to system_clock::time_point
319-
std::chrono::system_clock::time_point later = std::chrono::sys_days{ymd} + time_of_day;
320-
auto ttt = std::chrono::system_clock::to_time_t(later);
321-
322-
dst.expiry_time = ttt;
311+
std::string expiry_str = rsp.get_header_value("x-expiry-time");
312+
LOG_DBG("Server expiry: {}", expiry_str);
313+
dst.expiry_time = uint64_t(timeFromISO(expiry_str));
314+
LOG_DBG("Server expiry timestamp: {}", dst.expiry_time);
323315

324316
return OK;
325317
}
@@ -348,8 +340,9 @@ libcdoc::NetworkBackend::sendShare(std::vector<uint8_t>& dst, const std::string&
348340
if (result = setProxy(cli, this); result != OK) return result;
349341

350342
std::string full = path + "/key-shares";
343+
httplib::Headers hdrs;
351344
httplib::Response rsp;
352-
result = post(cli, full, req_str, rsp);
345+
result = post(cli, full, hdrs, req_str, rsp);
353346
if (result != libcdoc::OK) return result;
354347

355348
std::string location = rsp.get_header_value("Location");
@@ -421,8 +414,9 @@ libcdoc::NetworkBackend::fetchNonce(std::vector<uint8_t>& dst, const std::string
421414
if (result = setProxy(cli, this); result != OK) return result;
422415

423416
std::string full = path + "/key-shares/" + share_id + "/nonce";
417+
httplib::Headers hdrs;
424418
httplib::Response rsp;
425-
result = post(cli, full, "", rsp);
419+
result = post(cli, full, hdrs, "", rsp);
426420
if (result != libcdoc::OK) return result;
427421

428422
LOG_DBG("Response: {}", rsp.body);
@@ -710,8 +704,9 @@ libcdoc::NetworkBackend::signSID(std::vector<uint8_t>& dst, std::vector<uint8_t>
710704
//
711705
std::string full = path + "/certificatechoice/" + rcpt_id;
712706
LOG_DBG("SmartID path: {}", full);
707+
httplib::Headers hdrs;
713708
httplib::Response rsp;
714-
result = post(cli, full, query.serialize(), rsp);
709+
result = post(cli, full, hdrs, query.serialize(), rsp);
715710
if (result != libcdoc::OK) return result;
716711

717712

@@ -773,7 +768,7 @@ libcdoc::NetworkBackend::signSID(std::vector<uint8_t>& dst, std::vector<uint8_t>
773768
//
774769
full = path + "/authentication/" + rcpt_id;
775770
LOG_DBG("SmartID path: {}", full);
776-
result = post(cli, full, query.serialize(), rsp);
771+
result = post(cli, full, hdrs, query.serialize(), rsp);
777772
if (result != libcdoc::OK) return result;
778773
LOG_DBG("Response: {}", rsp.body);
779774
picojson::parse(v, rsp.body);
@@ -857,8 +852,9 @@ libcdoc::NetworkBackend::signMID(std::vector<uint8_t>& dst, std::vector<uint8_t>
857852
//
858853
std::string full = path + "/authentication";
859854
LOG_DBG("Mobile ID path: {}", full);
855+
httplib::Headers hdrs;
860856
httplib::Response rsp;
861-
result = post(cli, full, query.serialize(), rsp);
857+
result = post(cli, full, hdrs, query.serialize(), rsp);
862858
if (result != libcdoc::OK) return result;
863859
LOG_DBG("Response: {}", rsp.body);
864860

cdoc/NetworkBackend.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,10 @@ struct CDOC_EXPORT NetworkBackend {
142142
* @param rcpt_key recipient's public key
143143
* @param key_material encrypted KEK or ECDH public Key used to derive shared secret
144144
* @param type algorithm type, currently either "rsa" or "ecc_secp384r1"
145+
* @param expiry_ts the requested capsule expiry timestamp, 0 - use server default
145146
* @return error code or OK
146147
*/
147-
virtual result_t sendKey (CapsuleInfo& dst, const std::string& url, const std::vector<uint8_t>& rcpt_key, const std::vector<uint8_t> &key_material, const std::string& type);
148+
virtual result_t sendKey (CapsuleInfo& dst, const std::string& url, const std::vector<uint8_t>& rcpt_key, const std::vector<uint8_t> &key_material, const std::string& type, uint64_t expiry_ts);
148149
/**
149150
* @brief send key share to server
150151
*

0 commit comments

Comments
 (0)