Skip to content

Commit a6701a4

Browse files
authored
Add backwards compatibility with servers without x-expiry-time (#80)
MOPPAND-1717 Signed-off-by: Raul Metsma <[email protected]>
1 parent 19d61d9 commit a6701a4

File tree

5 files changed

+92
-104
lines changed

5 files changed

+92
-104
lines changed

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;

cdoc/NetworkBackend.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons
293293
if (expiry_ts) {
294294
std::string expiry_str = timeToISO(expiry_ts);
295295
LOG_DBG("Expiry time: {}", expiry_str);
296-
hdrs.emplace(std::make_pair("x-expiry-time", expiry_str));
296+
hdrs.emplace("x-expiry-time", expiry_str);
297297
}
298298
httplib::Response rsp;
299299
result = post(cli, full, hdrs, req_str, rsp);
@@ -306,12 +306,18 @@ libcdoc::NetworkBackend::sendKey (CapsuleInfo& dst, const std::string& url, cons
306306
}
307307
error = {};
308308
/* Remove /key-capsules/ */
309-
dst.transaction_id = location.substr(14);
309+
location.erase(0, 14);
310+
dst.transaction_id = std::move(location);
310311

311312
std::string expiry_str = rsp.get_header_value("x-expiry-time");
312313
LOG_DBG("Server expiry: {}", expiry_str);
313-
dst.expiry_time = uint64_t(timeFromISO(expiry_str));
314-
LOG_DBG("Server expiry timestamp: {}", dst.expiry_time);
314+
if (expiry_str.empty()) {
315+
dst.expiry_time = expiry_ts;
316+
LOG_DBG("Given expiry timestamp: {}", dst.expiry_time);
317+
} else {
318+
dst.expiry_time = uint64_t(timeFromISO(expiry_str));
319+
LOG_DBG("Server expiry timestamp: {}", dst.expiry_time);
320+
}
315321

316322
return OK;
317323
}

cdoc/Recipient.cpp

Lines changed: 37 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "ILogger.h"
2525
#include "Utils.h"
2626

27+
#include <algorithm>
28+
#include <chrono>
29+
2730
using namespace std;
2831

2932
namespace libcdoc {
@@ -58,9 +61,10 @@ Recipient::makeSymmetric(std::string label, int32_t kdf_iter)
5861
}
5962

6063
Recipient
61-
Recipient::makePublicKey(std::string label, const std::vector<uint8_t>& public_key, PKType pk_type)
64+
Recipient::makePublicKey(std::string label, std::vector<uint8_t> public_key, PKType pk_type)
6265
{
63-
if (public_key.empty()) return Recipient(Type::NONE);
66+
if (public_key.empty())
67+
return {Type::NONE};
6468
Recipient rcpt(Type::PUBLIC_KEY);
6569
rcpt.label = std::move(label);
6670
rcpt.pk_type = pk_type;
@@ -69,18 +73,20 @@ Recipient::makePublicKey(std::string label, const std::vector<uint8_t>& public_k
6973
auto evp = Crypto::fromECPublicKeyDer(public_key);
7074
rcpt.rcpt_key = Crypto::toPublicKeyDer(evp.get());
7175
} else {
72-
rcpt.rcpt_key = public_key;
76+
rcpt.rcpt_key = std::move(public_key);
7377
}
7478
return rcpt;
7579
}
7680

7781
Recipient
7882
Recipient::makeCertificate(std::string label, std::vector<uint8_t> cert)
7983
{
84+
Certificate x509(cert);
85+
if (!x509.cert)
86+
return {Type::NONE};
8087
Recipient rcpt(Type::PUBLIC_KEY);
8188
rcpt.label = std::move(label);
8289
rcpt.cert = std::move(cert);
83-
Certificate x509(rcpt.cert);
8490
rcpt.rcpt_key = x509.getPublicKey();
8591
rcpt.pk_type = (x509.getAlgorithm() == libcdoc::Certificate::RSA) ? PKType::RSA : PKType::ECC;
8692
rcpt.expiry_ts = x509.getNotAfter();
@@ -90,36 +96,32 @@ Recipient::makeCertificate(std::string label, std::vector<uint8_t> cert)
9096
Recipient
9197
Recipient::makeServer(std::string label, std::vector<uint8_t> public_key, PKType pk_type, std::string server_id)
9298
{
93-
Recipient rcpt(Type::PUBLIC_KEY);
94-
rcpt.label = std::move(label);
95-
rcpt.pk_type = pk_type;
96-
if (pk_type == PKType::ECC && public_key[0] == 0x30) {
97-
// 0x30 identifies SEQUENCE tag in ASN.1 encoding
98-
auto evp = Crypto::fromECPublicKeyDer(public_key);
99-
rcpt.rcpt_key = Crypto::toPublicKeyDer(evp.get());
100-
} else {
101-
rcpt.rcpt_key = std::move(public_key);
102-
}
99+
Recipient rcpt = makePublicKey(std::move(label), std::move(public_key), pk_type);
103100
rcpt.server_id = std::move(server_id);
101+
const auto six_months_from_now = std::chrono::system_clock::now() + std::chrono::months(6);
102+
const auto expiry_ts = std::chrono::system_clock::to_time_t(six_months_from_now);
103+
rcpt.expiry_ts = uint64_t(expiry_ts);
104104
return rcpt;
105105
}
106106

107107
Recipient
108108
Recipient::makeServer(std::string label, std::vector<uint8_t> cert, std::string server_id)
109109
{
110-
Certificate x509(cert);
111-
Recipient rcpt = makeServer(std::move(label), x509.getPublicKey(), x509.getAlgorithm() == Certificate::Algorithm::RSA ? RSA : ECC, std::move(server_id));
112-
rcpt.cert = cert;
113-
return std::move(rcpt);
110+
Recipient rcpt = makeCertificate(std::move(label), std::move(cert));
111+
rcpt.server_id = std::move(server_id);
112+
const auto six_months_from_now = std::chrono::system_clock::now() + std::chrono::months(6);
113+
const auto expiry_ts = std::chrono::system_clock::to_time_t(six_months_from_now);
114+
rcpt.expiry_ts = std::min(rcpt.expiry_ts, uint64_t(expiry_ts));
115+
return rcpt;
114116
}
115117

116118
Recipient
117-
Recipient::makeShare(const std::string& label, const std::string& server_id, const std::string& recipient_id)
119+
Recipient::makeShare(std::string label, std::string server_id, std::string recipient_id)
118120
{
119121
Recipient rcpt(Type::KEYSHARE);
120-
rcpt.label = label;
121-
rcpt.server_id = server_id;
122-
rcpt.id = recipient_id;
122+
rcpt.label = std::move(label);
123+
rcpt.server_id = std::move(server_id);
124+
rcpt.id = std::move(recipient_id);
123125
return rcpt;
124126
}
125127

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

142-
static Recipient::EIDType
143-
getEIDType(const std::vector<std::string>& policies)
144-
{
145-
for (const auto& pol : policies)
146-
{
147-
std::string_view policy = pol;
148-
if (policy.starts_with("2.999.")) { // Zetes TEST OID prefix
149-
policy = policy.substr(6);
150-
}
151-
152-
if (policy.starts_with("1.3.6.1.4.1.51361.1.1.3") ||
153-
policy.starts_with("1.3.6.1.4.1.51361.1.2.3")) {
154-
return Recipient::EIDType::DigiID;
155-
}
156-
157-
if (policy.starts_with("1.3.6.1.4.1.51361.1.1.4") ||
158-
policy.starts_with("1.3.6.1.4.1.51361.1.2.4")) {
159-
return Recipient::EIDType::DigiID_EResident;
160-
}
161-
162-
if (policy.starts_with("1.3.6.1.4.1.51361.1.1") ||
163-
policy.starts_with("1.3.6.1.4.1.51455.1.1") ||
164-
policy.starts_with("1.3.6.1.4.1.51361.1.2") ||
165-
policy.starts_with("1.3.6.1.4.1.51455.1.2")) {
166-
return Recipient::EIDType::IDCard;
167-
}
168-
}
169-
170-
// If the execution reaches so far then EID type determination failed.
171-
return Recipient::EIDType::Unknown;
172-
}
173-
174144
static void
175-
buildLabel(std::ostream& ofs, std::string_view type, const std::initializer_list<std::pair<std::string_view, std::string_view>> &components)
145+
buildLabel(std::ostream& ofs, std::string_view type, std::initializer_list<std::pair<std::string_view, std::string_view>> components)
176146
{
177147
ofs << LABELPREFIX;
178148
ofs << "v" << '=' << std::to_string(CDoc2::KEYLABELVERSION) << '&'
179149
<< "type" << '=' << type;
180-
for (auto& [key, value] : components) {
181-
if (value.empty())
182-
continue;
183-
ofs << '&';
184-
ofs << urlEncode(key) << '=' << urlEncode(value);
150+
for (const auto& [key, value] : components) {
151+
if (!value.empty())
152+
ofs << '&' << urlEncode(key) << '=' << urlEncode(value);
185153
}
186154
}
187155

188156
static void
189-
BuildLabelEID(std::ostream& ofs, Recipient::EIDType type, const Certificate& x509)
157+
BuildLabelEID(std::ostream& ofs, Certificate::EIDType type, const Certificate& x509)
190158
{
191159
buildLabel(ofs, eid_strs[type], {
192160
{"cn", x509.getCommonName()},
@@ -197,7 +165,7 @@ BuildLabelEID(std::ostream& ofs, Recipient::EIDType type, const Certificate& x50
197165
}
198166

199167
static void
200-
BuildLabelCertificate(std::ostream &ofs, std::string_view file, const Certificate& x509)
168+
BuildLabelCertificate(std::ostream &ofs, const std::string& file, const Certificate& x509)
201169
{
202170
buildLabel(ofs, "cert", {
203171
{"file", file},
@@ -207,15 +175,15 @@ BuildLabelCertificate(std::ostream &ofs, std::string_view file, const Certificat
207175
}
208176

209177
static void
210-
BuildLabelPublicKey(std::ostream &ofs, const std::string file)
178+
BuildLabelPublicKey(std::ostream &ofs, const std::string& file)
211179
{
212180
buildLabel(ofs, "pub_key", {
213181
{"file", file}
214182
});
215183
}
216184

217185
static void
218-
BuildLabelSymmetricKey(std::ostream &ofs, const std::string& label, const std::string file)
186+
BuildLabelSymmetricKey(std::ostream &ofs, const std::string& label, const std::string& file)
219187
{
220188
buildLabel(ofs, "secret", {
221189
{"label", label},
@@ -251,8 +219,8 @@ Recipient::getLabel(const std::vector<std::pair<std::string_view, std::string_vi
251219
case PUBLIC_KEY:
252220
if (!cert.empty()) {
253221
Certificate x509(cert);
254-
if (auto type = getEIDType(x509.policies()); type != EIDType::Unknown) {
255-
BuildLabelEID(ofs, type, x509);
222+
if (auto eid = x509.getEIDType(); eid != Certificate::Unknown) {
223+
BuildLabelEID(ofs, eid, x509);
256224
} else {
257225
BuildLabelCertificate(ofs, file_name, x509);
258226
}
@@ -263,11 +231,9 @@ Recipient::getLabel(const std::vector<std::pair<std::string_view, std::string_vi
263231
case KEYSHARE:
264232
break;
265233
}
266-
for (auto& [key, value] : extra) {
267-
if (value.empty())
268-
continue;
269-
ofs << '&';
270-
ofs << urlEncode(key) << '=' << urlEncode(value);
234+
for (const auto& [key, value] : extra) {
235+
if (!value.empty())
236+
ofs << '&' << urlEncode(key) << '=' << urlEncode(value);
271237
}
272238
LOG_DBG("Generated label: {}", ofs.str());
273239
return ofs.str();

cdoc/Recipient.h

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct CDOC_EXPORT Recipient {
3737
/**
3838
* @brief The recipient type
3939
*/
40-
enum Type : unsigned char {
40+
enum Type : uint8_t {
4141
/**
4242
* Uninitialized recipient
4343
*/
@@ -59,7 +59,7 @@ struct CDOC_EXPORT Recipient {
5959
/**
6060
* @brief The public key type
6161
*/
62-
enum PKType : unsigned char {
62+
enum PKType : uint8_t {
6363
/**
6464
* Elliptic curve
6565
*/
@@ -70,16 +70,6 @@ struct CDOC_EXPORT Recipient {
7070
RSA
7171
};
7272

73-
/**
74-
* @brief The EID type
75-
*/
76-
enum EIDType : unsigned char {
77-
Unknown,
78-
IDCard,
79-
DigiID,
80-
DigiID_EResident
81-
};
82-
8373
Recipient() = default;
8474

8575
/**
@@ -193,7 +183,7 @@ struct CDOC_EXPORT Recipient {
193183
* @param pk_type the algorithm type (either ECC or RSA)
194184
* @return a new Recipient structure
195185
*/
196-
static Recipient makePublicKey(std::string label, const std::vector<uint8_t>& public_key, PKType pk_type);
186+
static Recipient makePublicKey(std::string label, std::vector<uint8_t> public_key, PKType pk_type);
197187
/**
198188
* @brief Create a new certificate based Recipient
199189
* @param label the label text
@@ -233,7 +223,7 @@ struct CDOC_EXPORT Recipient {
233223
* @param recipient_id the recipient id (PNOEE-01234567890)
234224
* @return Recipient a new Recipient structure
235225
*/
236-
static Recipient makeShare(const std::string& label, const std::string& server_id, const std::string& recipient_id);
226+
static Recipient makeShare(std::string label, std::string server_id, std::string recipient_id);
237227

238228
/**
239229
* @brief Get the label for this recipient

0 commit comments

Comments
 (0)