Skip to content

Commit 3b0d127

Browse files
committed
Add expire date to label
Signed-off-by: Raul Metsma <[email protected]>
1 parent b17fddd commit 3b0d127

File tree

8 files changed

+94
-114
lines changed

8 files changed

+94
-114
lines changed

cdoc/CDoc2Writer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ 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.getLabel({})),
108+
builder.CreateString(rcpt.getLabel({{"x-expiry-time", rcpt.expiry_ts == 0 ? std::string() : std::to_string(rcpt.expiry_ts)}})),
109109
builder.CreateVector(xor_key),
110110
cdoc20::header::FMKEncryptionMethod::XOR);
111111
}
@@ -138,7 +138,7 @@ 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.getLabel({})),
141+
builder.CreateString(rcpt.getLabel({{"x-expiry-time", rcpt.expiry_ts == 0 ? std::string() : std::to_string(rcpt.expiry_ts)}})),
142142
builder.CreateVector(xor_key),
143143
cdoc20::header::FMKEncryptionMethod::XOR);
144144
}

cdoc/Certificate.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,21 @@ Certificate::getSerialNumber() const
7474
return getName(cert, NID_serialNumber);
7575
}
7676

77+
time_t
78+
Certificate::getNotAfter() const
79+
{
80+
if(!cert)
81+
return 0;
82+
tm tm{};
83+
if(ASN1_TIME_to_tm(X509_get0_notAfter(cert.get()), &tm) != 1)
84+
return 0;
85+
#ifdef _WIN32
86+
return _mkgmtime(&tm);
87+
#else
88+
return timegm(&tm);
89+
#endif
90+
}
91+
7792

7893

7994
std::vector<std::string>
@@ -85,8 +100,8 @@ Certificate::policies() const
85100
if(!cert)
86101
return list;
87102

88-
auto p = static_cast<CERTIFICATEPOLICIES *>(X509_get_ext_d2i(cert.get(), NID_certificate_policies, nullptr, nullptr));
89-
auto cp = std::unique_ptr<CERTIFICATEPOLICIES,decltype(&CERTIFICATEPOLICIES_free)>(p,CERTIFICATEPOLICIES_free);
103+
auto cp = make_unique_cast<CERTIFICATEPOLICIES_free>(X509_get_ext_d2i(
104+
cert.get(), NID_certificate_policies, nullptr, nullptr));
90105
if(!cp)
91106
return list;
92107

@@ -122,7 +137,7 @@ Certificate::getAlgorithm() const
122137
return (alg == EVP_PKEY_RSA) ? Algorithm::RSA : Algorithm::ECC;
123138
}
124139

125-
std::vector<uint8_t> Certificate::getDigest()
140+
std::vector<uint8_t> Certificate::getDigest() const
126141
{
127142
if(!cert)
128143
return {};

cdoc/Certificate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ class Certificate {
5050

5151
std::vector<uint8_t> getPublicKey() const;
5252
Algorithm getAlgorithm() const;
53+
time_t getNotAfter() const;
5354

54-
std::vector<uint8_t> getDigest();
55+
std::vector<uint8_t> getDigest() const;
5556
};
5657

5758
} // Namespace

cdoc/Io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
namespace libcdoc {
2828

29-
class DataSource;
29+
struct DataSource;
3030

3131
/**
3232
* @brief The DataConsumer class

cdoc/Recipient.cpp

Lines changed: 59 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,20 @@ static constexpr std::string_view eid_strs[] = {
4949
};
5050

5151
Recipient
52-
Recipient::makeSymmetric(const std::string& label, int32_t kdf_iter)
52+
Recipient::makeSymmetric(std::string label, int32_t kdf_iter)
5353
{
5454
Recipient rcpt(Type::SYMMETRIC_KEY);
55-
rcpt.label = label;
55+
rcpt.label = std::move(label);
5656
rcpt.kdf_iter = kdf_iter;
5757
return rcpt;
5858
}
5959

6060
Recipient
61-
Recipient::makePublicKey(const std::string& label, const std::vector<uint8_t>& public_key, PKType pk_type)
61+
Recipient::makePublicKey(std::string label, const std::vector<uint8_t>& public_key, PKType pk_type)
6262
{
6363
if (public_key.empty()) return Recipient(Type::NONE);
6464
Recipient rcpt(Type::PUBLIC_KEY);
65-
rcpt.label = label;
65+
rcpt.label = std::move(label);
6666
rcpt.pk_type = pk_type;
6767
if (pk_type == PKType::ECC && public_key[0] == 0x30) {
6868
// 0x30 identifies SEQUENCE tag in ASN.1 encoding
@@ -77,13 +77,14 @@ Recipient::makePublicKey(const std::string& label, const std::vector<uint8_t>& p
7777
Recipient
7878
Recipient::makeCertificate(std::string label, std::vector<uint8_t> cert)
7979
{
80-
Recipient rcpt(Type::PUBLIC_KEY);
81-
rcpt.label = std::move(label);
80+
Recipient rcpt(Type::PUBLIC_KEY);
81+
rcpt.label = std::move(label);
8282
rcpt.cert = std::move(cert);
83-
Certificate ssl(rcpt.cert);
84-
rcpt.rcpt_key = ssl.getPublicKey();
85-
rcpt.pk_type = (ssl.getAlgorithm() == libcdoc::Certificate::RSA) ? PKType::RSA : PKType::ECC;
86-
return rcpt;
83+
Certificate x509(rcpt.cert);
84+
rcpt.rcpt_key = x509.getPublicKey();
85+
rcpt.pk_type = (x509.getAlgorithm() == libcdoc::Certificate::RSA) ? PKType::RSA : PKType::ECC;
86+
rcpt.expiry_ts = x509.getNotAfter();
87+
return rcpt;
8788
}
8889

8990
Recipient
@@ -138,26 +139,10 @@ Recipient::isTheSameRecipient(const std::vector<uint8_t>& public_key) const
138139
return rcpt_key == public_key;
139140
}
140141

141-
static std::string
142-
buildLabel(std::vector<std::pair<std::string_view, std::string_view>> components)
143-
{
144-
std::ostringstream ofs;
145-
ofs << LABELPREFIX;
146-
bool first = true;
147-
for (auto& [key, value] : components) {
148-
if (!value.empty()) {
149-
if (!first) ofs << '&';
150-
ofs << libcdoc::urlEncode(key) << '=' << libcdoc::urlEncode(value);
151-
first = false;
152-
}
153-
}
154-
return ofs.str();
155-
}
156-
157142
static Recipient::EIDType
158143
getEIDType(const std::vector<std::string>& policies)
159144
{
160-
for (std::vector<std::string>::const_reference policy : policies)
145+
for (const auto& policy : policies)
161146
{
162147
if (policy.starts_with("1.3.6.1.4.1.51361.1.1.3") ||
163148
policy.starts_with("1.3.6.1.4.1.51361.1.2.3")) {
@@ -181,113 +166,103 @@ getEIDType(const std::vector<std::string>& policies)
181166
return Recipient::EIDType::Unknown;
182167
}
183168

184-
static std::string
185-
BuildLabelEID(const std::vector<uint8_t>& cert)
169+
static void
170+
buildLabel(std::ostream& ofs, std::string_view type, const std::initializer_list<std::pair<std::string_view, std::string_view>> &components)
186171
{
187-
Certificate x509(cert);
188-
Recipient::EIDType type = getEIDType(x509.policies());
189-
std::string cn = x509.getCommonName();
190-
std::string sn = x509.getSerialNumber();
191-
std::string gn = x509.getGivenName();
192-
if (!gn.empty()) {
193-
return buildLabel({
194-
{"v", std::to_string(CDoc2::KEYLABELVERSION)},
195-
{"type", eid_strs[type]},
196-
{"cn", cn},
197-
{"serial_number", sn}
198-
});
199-
} else {
200-
return buildLabel({
201-
{"v", std::to_string(CDoc2::KEYLABELVERSION)},
202-
{"type", eid_strs[type]},
203-
{"cn", cn},
204-
{"serial_number", sn},
205-
{"last_name", x509.getSurname()},
206-
{"first_name", gn}
207-
});
172+
ofs << LABELPREFIX;
173+
ofs << "v" << '=' << std::to_string(CDoc2::KEYLABELVERSION) << '&'
174+
<< "type" << '=' << type;
175+
for (auto& [key, value] : components) {
176+
if (value.empty())
177+
continue;
178+
ofs << '&';
179+
ofs << urlEncode(key) << '=' << urlEncode(value);
208180
}
209181
}
210182

211-
static std::string
212-
BuildLabelCertificate(std::string_view file, const std::vector<uint8_t>& cert)
183+
static void
184+
BuildLabelEID(std::ostream& ofs, Recipient::EIDType type, const Certificate& x509)
213185
{
214-
Certificate x509(cert);
215-
return buildLabel({
216-
{"v", std::to_string(CDoc2::KEYLABELVERSION)},
217-
{"type", "cert"},
186+
buildLabel(ofs, eid_strs[type], {
187+
{"cn", x509.getCommonName()},
188+
{"serial_number", x509.getSerialNumber()},
189+
{"last_name", x509.getSurname()},
190+
{"first_name", x509.getGivenName()},
191+
});
192+
}
193+
194+
static void
195+
BuildLabelCertificate(std::ostream &ofs, std::string_view file, const Certificate& x509)
196+
{
197+
buildLabel(ofs, "cert", {
218198
{"file", file},
219199
{"cn", x509.getCommonName()},
220200
{"cert_sha1", toHex(x509.getDigest())}
221201
});
222202
}
223203

224-
static std::string
225-
BuildLabelPublicKey(int version, const std::string file)
204+
static void
205+
BuildLabelPublicKey(std::ostream &ofs, const std::string file)
226206
{
227-
return buildLabel({
228-
{"v", std::to_string(version)},
229-
{"type", "pub_key"},
207+
buildLabel(ofs, "pub_key", {
230208
{"file", file}
231209
});
232210
}
233211

234-
static std::string
235-
BuildLabelSymmetricKey(int version, const std::string& label, const std::string file)
212+
static void
213+
BuildLabelSymmetricKey(std::ostream &ofs, const std::string& label, const std::string file)
236214
{
237-
return buildLabel({
238-
{"v", std::to_string(version)},
239-
{"type", "secret"},
215+
buildLabel(ofs, "secret", {
240216
{"label", label},
241217
{"file", file}
242218
});
243219
}
244220

245-
static std::string
246-
BuildLabelPassword(int version, const std::string& label)
221+
static void
222+
BuildLabelPassword(std::ostream &ofs, const std::string& label)
247223
{
248-
return buildLabel({
249-
{"v", std::to_string(version)},
250-
{"type", "pw"},
224+
buildLabel(ofs, "pw", {
251225
{"label", label}
252226
});
253227
}
254228

255229
std::string
256-
Recipient::getLabel(std::vector<std::pair<std::string_view, std::string_view>> extra) const
230+
Recipient::getLabel(const std::vector<std::pair<std::string_view, std::string_view>> &extra) const
257231
{
258232
LOG_DBG("Generating label");
259233
if (!label.empty()) return label;
260234
std::ostringstream ofs;
261235
switch(type) {
262-
case NONE:
236+
case NONE:
263237
LOG_DBG("The recipient is not initialized");
264238
break;
265239
case SYMMETRIC_KEY:
266240
if (kdf_iter > 0) {
267-
ofs << BuildLabelPassword(CDoc2::KEYLABELVERSION, key_name);
241+
BuildLabelPassword(ofs, key_name);
268242
} else {
269-
ofs << BuildLabelSymmetricKey(CDoc2::KEYLABELVERSION, key_name, file_name);
243+
BuildLabelSymmetricKey(ofs, key_name, file_name);
270244
}
245+
break;
271246
case PUBLIC_KEY:
272247
if (!cert.empty()) {
273248
Certificate x509(cert);
274-
EIDType eid_type = getEIDType(x509.policies());
275-
if (eid_type != EIDType::Unknown) {
276-
ofs << BuildLabelEID(cert);
249+
if (auto type = getEIDType(x509.policies()); type != EIDType::Unknown) {
250+
BuildLabelEID(ofs, type, x509);
277251
} else {
278-
ofs << BuildLabelCertificate(file_name, cert);
252+
BuildLabelCertificate(ofs, file_name, x509);
279253
}
280254
} else {
281-
ofs << BuildLabelPublicKey(CDoc2::KEYLABELVERSION, file_name);
255+
BuildLabelPublicKey(ofs, file_name);
282256
}
257+
break;
283258
case KEYSHARE:
284259
break;
285260
}
286261
for (auto& [key, value] : extra) {
287-
if (!value.empty()) {
288-
ofs << '&';
289-
ofs << libcdoc::urlEncode(key) << '=' << libcdoc::urlEncode(value);
290-
}
262+
if (value.empty())
263+
continue;
264+
ofs << '&';
265+
ofs << urlEncode(key) << '=' << urlEncode(value);
291266
}
292267
LOG_DBG("Generated label: {}", ofs.str());
293268
return ofs.str();

cdoc/Recipient.h

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,6 @@ struct CDOC_EXPORT Recipient {
8080
DigiID_EResident
8181
};
8282

83-
/**
84-
* @brief Extra parameters for automatic label generation
85-
*/
86-
enum Params : unsigned char {
87-
/**
88-
* @brief Name of symmetric key/password ('label')
89-
*/
90-
LABEL,
91-
/**
92-
* @brief Public key or certificate filename ('file')
93-
*/
94-
FILE
95-
};
96-
9783
Recipient() = default;
9884

9985
/**
@@ -199,15 +185,15 @@ struct CDOC_EXPORT Recipient {
199185
* @param kdf_iter the number of PBKDF iterations (0 if full key is provided)
200186
* @return a new Recipient structure
201187
*/
202-
static Recipient makeSymmetric(const std::string& label, int32_t kdf_iter);
188+
static Recipient makeSymmetric(std::string label, int32_t kdf_iter);
203189
/**
204190
* @brief Create a new public key based Recipient
205191
* @param label the label text
206192
* @param public_key the public key value
207193
* @param pk_type the algorithm type (either ECC or RSA)
208194
* @return a new Recipient structure
209195
*/
210-
static Recipient makePublicKey(const std::string& label, const std::vector<uint8_t>& public_key, PKType pk_type);
196+
static Recipient makePublicKey(std::string label, const std::vector<uint8_t>& public_key, PKType pk_type);
211197
/**
212198
* @brief Create a new certificate based Recipient
213199
* @param label the label text
@@ -257,7 +243,7 @@ struct CDOC_EXPORT Recipient {
257243
* @param extra additional parameter values to use
258244
* @return a label value
259245
*/
260-
std::string getLabel(std::vector<std::pair<std::string_view, std::string_view>> extra) const;
246+
std::string getLabel(const std::vector<std::pair<std::string_view, std::string_view>> &extra) const;
261247

262248
/**
263249
* @brief parse machine-readable CDoc2 label

cdoc/Utils.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,13 @@ buildURL(const std::string& host, int port)
118118
return std::string("https://") + host + ":" + std::to_string(port) + "/";
119119
}
120120

121-
std::string
122-
urlEncode(std::string_view src)
121+
std::ostream&
122+
operator<<(std::ostream& escaped, urlEncode src)
123123
{
124-
std::ostringstream escaped;
125124
escaped.fill('0');
126125
escaped << std::hex;
127126

128-
for (auto c : src) {
127+
for (auto c : src.src) {
129128
// Keep alphanumeric and other accepted characters intact
130129
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
131130
escaped << c;
@@ -136,7 +135,7 @@ urlEncode(std::string_view src)
136135
escaped << '%' << std::setw(2) << int((unsigned char) c);
137136
escaped << std::nouppercase;
138137
}
139-
return escaped.str();
138+
return escaped;
140139
}
141140

142141
std::string

0 commit comments

Comments
 (0)