Skip to content

Commit bc0ff87

Browse files
committed
Make CDoc1Writer::Private subclass of XMLWriter
Signed-off-by: Raul Metsma <[email protected]>
1 parent 594c6eb commit bc0ff87

File tree

5 files changed

+87
-83
lines changed

5 files changed

+87
-83
lines changed

cdoc/CDoc1Writer.cpp

Lines changed: 60 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -45,58 +45,54 @@ struct FileEntry {
4545
* @brief CDoc1Writer is used for encrypt data.
4646
*/
4747

48-
class CDoc1Writer::Private
48+
struct CDoc1Writer::Private: public XMLWriter
4949
{
50-
public:
51-
std::unique_ptr<XMLWriter> _xml;
52-
std::vector<FileEntry> files;
53-
std::vector<libcdoc::Recipient> rcpts;
50+
static const XMLWriter::NS DENC, DS, XENC11, DSIG11;
5451

55-
static const XMLWriter::NS DENC, DS, XENC11, DSIG11;
56-
std::string method, documentFormat = "ENCDOC-XML|1.1", lastError;
52+
using XMLWriter::XMLWriter;
5753

58-
uint64_t writeEncryptionProperties(bool use_ddoc);
59-
uint64_t writeKeyInfo(bool use_ddoc, const libcdoc::Crypto::Key& transportKey);
60-
uint64_t writeRecipient(const std::vector<uint8_t> &recipient, const libcdoc::Crypto::Key& transportKey);
54+
std::string method = "http://www.w3.org/2009/xmlenc11#aes256-gcm";
55+
std::string documentFormat = "ENCDOC-XML|1.1", lastError;
56+
std::vector<FileEntry> files;
57+
std::vector<libcdoc::Recipient> rcpts;
58+
59+
int64_t writeEncryptionProperties(bool use_ddoc);
60+
int64_t writeKeyInfo(bool use_ddoc, const libcdoc::Crypto::Key& transportKey);
61+
int64_t writeRecipient(const std::vector<uint8_t> &recipient, const libcdoc::Crypto::Key& transportKey);
6162
};
6263

6364
const XMLWriter::NS CDoc1Writer::Private::DENC{ "denc", "http://www.w3.org/2001/04/xmlenc#" };
6465
const XMLWriter::NS CDoc1Writer::Private::DS{ "ds", "http://www.w3.org/2000/09/xmldsig#" };
6566
const XMLWriter::NS CDoc1Writer::Private::XENC11{ "xenc11", "http://www.w3.org/2009/xmlenc11#" };
6667
const XMLWriter::NS CDoc1Writer::Private::DSIG11{ "dsig11", "http://www.w3.org/2009/xmldsig11#" };
6768

68-
CDoc1Writer::CDoc1Writer(libcdoc::DataConsumer *dst, bool take_ownership, const std::string &method)
69-
: CDocWriter(1, dst, take_ownership), d(new Private())
70-
{
71-
d->method = method;
72-
}
69+
CDoc1Writer::CDoc1Writer(libcdoc::DataConsumer *dst, bool take_ownership)
70+
: CDocWriter(1, dst, take_ownership)
71+
{}
7372

74-
CDoc1Writer::~CDoc1Writer()
75-
{
76-
delete d;
77-
}
73+
CDoc1Writer::~CDoc1Writer() noexcept = default;
7874

79-
uint64_t CDoc1Writer::Private::writeEncryptionProperties(bool use_ddoc)
75+
int64_t CDoc1Writer::Private::writeEncryptionProperties(bool use_ddoc)
8076
{
81-
RET_ERROR(_xml->writeElement(DENC, "EncryptionProperties", [&]() -> uint64_t {
82-
RET_ERROR(_xml->writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "LibraryVersion"}}, "cdoc|0.0.1"));
83-
RET_ERROR(_xml->writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "DocumentFormat"}}, documentFormat));
84-
RET_ERROR(_xml->writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "Filename"}}, use_ddoc ? "tmp.ddoc" : files.at(0).name));
77+
RET_ERROR(writeElement(DENC, "EncryptionProperties", [&]() -> int64_t {
78+
RET_ERROR(writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "LibraryVersion"}}, "cdoc|0.0.1"));
79+
RET_ERROR(writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "DocumentFormat"}}, documentFormat));
80+
RET_ERROR(writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "Filename"}}, use_ddoc ? "tmp.ddoc" : files.at(0).name));
8581
for(const FileEntry &file: files)
8682
{
87-
RET_ERROR(_xml->writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "orig_file"}},
83+
RET_ERROR(writeTextElement(Private::DENC, "EncryptionProperty", {{"Name", "orig_file"}},
8884
file.name + "|" + std::to_string(file.size) + "|" + "application/octet-stream" + "|D0"));
8985
}
9086
return OK;
9187
}));
92-
return _xml->writeEndElement(Private::DENC); // EncryptedData
88+
return writeEndElement(Private::DENC); // EncryptedData
9389
}
9490

95-
uint64_t CDoc1Writer::Private::writeKeyInfo(bool use_ddoc, const libcdoc::Crypto::Key& transportKey)
91+
int64_t CDoc1Writer::Private::writeKeyInfo(bool use_ddoc, const libcdoc::Crypto::Key& transportKey)
9692
{
97-
RET_ERROR(_xml->writeStartElement(Private::DENC, "EncryptedData", {{"MimeType", use_ddoc ? "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" : "application/octet-stream"}}));
98-
RET_ERROR(_xml->writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", method}}));
99-
return _xml->writeElement(Private::DS, "KeyInfo", {}, [&]() -> uint64_t {
93+
RET_ERROR(writeStartElement(Private::DENC, "EncryptedData", {{"MimeType", use_ddoc ? "http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" : "application/octet-stream"}}));
94+
RET_ERROR(writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", method}}));
95+
return writeElement(Private::DS, "KeyInfo", {}, [&]() -> int64_t {
10096
for (const libcdoc::Recipient& key : rcpts) {
10197
if (!key.isCertificate()) {
10298
lastError = "Invalid recipient type";
@@ -113,7 +109,7 @@ uint64_t CDoc1Writer::Private::writeKeyInfo(bool use_ddoc, const libcdoc::Crypto
113109
});
114110
}
115111

116-
uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipient, const libcdoc::Crypto::Key& transportKey)
112+
int64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipient, const libcdoc::Crypto::Key& transportKey)
117113
{
118114
auto peerCert = libcdoc::Crypto::toX509(recipient);
119115
if(!peerCert)
@@ -136,7 +132,7 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
136132
OPENSSL_free(data);
137133
return cn;
138134
}();
139-
return _xml->writeElement(Private::DENC, "EncryptedKey", {{"Recipient", cn}}, [&]() -> uint64_t {
135+
return writeElement(Private::DENC, "EncryptedKey", {{"Recipient", cn}}, [&]() -> int64_t {
140136
std::vector<uint8_t> encryptedData;
141137
auto *peerPKey = X509_get0_pubkey(peerCert.get());
142138
switch(EVP_PKEY_base_id(peerPKey))
@@ -147,10 +143,10 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
147143
encryptedData.resize(size_t(RSA_size(rsa.get())));
148144
RSA_public_encrypt(int(transportKey.key.size()), transportKey.key.data(),
149145
encryptedData.data(), rsa.get(), RSA_PKCS1_PADDING);
150-
RET_ERROR(_xml->writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", libcdoc::Crypto::RSA_MTH}}));
151-
RET_ERROR(_xml->writeElement(Private::DS, "KeyInfo", [&]{
152-
return _xml->writeElement(Private::DS, "X509Data", [&]{
153-
return _xml->writeBase64Element(Private::DS, "X509Certificate", recipient);
146+
RET_ERROR(writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", libcdoc::Crypto::RSA_MTH}}));
147+
RET_ERROR(writeElement(Private::DS, "KeyInfo", [&] {
148+
return writeElement(Private::DS, "X509Data", [&] {
149+
return writeBase64Element(Private::DS, "X509Certificate", recipient);
154150
});
155151
}));
156152
break;
@@ -188,28 +184,28 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
188184
LOG_TRACE_KEY("iv {}", transportKey.iv);
189185
LOG_TRACE_KEY("transport {}", transportKey.key);
190186

191-
RET_ERROR(_xml->writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", encryptionMethod}}));
192-
RET_ERROR(_xml->writeElement(Private::DS, "KeyInfo", [&]{
193-
return _xml->writeElement(Private::DENC, "AgreementMethod", {{"Algorithm", libcdoc::Crypto::AGREEMENT_MTH}}, [&]{
194-
RET_ERROR(_xml->writeElement(Private::XENC11, "KeyDerivationMethod", {{"Algorithm", libcdoc::Crypto::CONCATKDF_MTH}}, [&]{
195-
return _xml->writeElement(Private::XENC11, "ConcatKDFParams", {
187+
RET_ERROR(writeElement(Private::DENC, "EncryptionMethod", {{"Algorithm", encryptionMethod}}));
188+
RET_ERROR(writeElement(Private::DS, "KeyInfo", [&] {
189+
return writeElement(Private::DENC, "AgreementMethod", {{"Algorithm", libcdoc::Crypto::AGREEMENT_MTH}}, [&] {
190+
RET_ERROR(writeElement(Private::XENC11, "KeyDerivationMethod", {{"Algorithm", libcdoc::Crypto::CONCATKDF_MTH}}, [&] {
191+
return writeElement(Private::XENC11, "ConcatKDFParams", {
196192
{"AlgorithmID", "00" + libcdoc::toHex(AlgorithmID)},
197193
{"PartyUInfo", "00" + libcdoc::toHex(SsDer)},
198-
{"PartyVInfo", "00" + libcdoc::toHex(recipient)}}, [&]{
199-
return _xml->writeElement(Private::DS, "DigestMethod", {{"Algorithm", concatDigest}});
194+
{"PartyVInfo", "00" + libcdoc::toHex(recipient)}}, [&] {
195+
return writeElement(Private::DS, "DigestMethod", {{"Algorithm", concatDigest}});
200196
});
201197
}));
202-
RET_ERROR(_xml->writeElement(Private::DENC, "OriginatorKeyInfo", [&]{
203-
return _xml->writeElement(Private::DS, "KeyValue", [&]{
204-
return _xml->writeElement(Private::DSIG11, "ECKeyValue", [&]{
205-
RET_ERROR(_xml->writeElement(Private::DSIG11, "NamedCurve", {{"URI", "urn:oid:" + oid}}));
206-
return _xml->writeBase64Element(Private::DSIG11, "PublicKey", SsDer);
198+
RET_ERROR(writeElement(Private::DENC, "OriginatorKeyInfo", [&] {
199+
return writeElement(Private::DS, "KeyValue", [&] {
200+
return writeElement(Private::DSIG11, "ECKeyValue", [&] {
201+
RET_ERROR(writeElement(Private::DSIG11, "NamedCurve", {{"URI", "urn:oid:" + oid}}));
202+
return writeBase64Element(Private::DSIG11, "PublicKey", SsDer);
207203
});
208204
});
209205
}));
210-
return _xml->writeElement(Private::DENC, "RecipientKeyInfo", [&]{
211-
return _xml->writeElement(Private::DS, "X509Data", [&]{
212-
return _xml->writeBase64Element(Private::DS, "X509Certificate", recipient);
206+
return writeElement(Private::DENC, "RecipientKeyInfo", [&] {
207+
return writeElement(Private::DS, "X509Data", [&] {
208+
return writeBase64Element(Private::DS, "X509Certificate", recipient);
213209
});
214210
});
215211
});
@@ -222,8 +218,8 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
222218

223219
if (encryptedData.empty())
224220
return UNSPECIFIED_ERROR;
225-
return _xml->writeElement(Private::DENC, "CipherData", [&]{
226-
return _xml->writeBase64Element(Private::DENC, "CipherValue", encryptedData);
221+
return writeElement(Private::DENC, "CipherData", [&] {
222+
return writeBase64Element(Private::DENC, "CipherValue", encryptedData);
227223
});
228224
});
229225
}
@@ -234,14 +230,14 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
234230
libcdoc::result_t
235231
CDoc1Writer::encrypt(libcdoc::MultiDataSource& src, const std::vector<libcdoc::Recipient>& keys)
236232
{
233+
d = std::make_unique<Private>(dst);
234+
d->rcpts = keys;
237235
libcdoc::Crypto::Key transportKey = libcdoc::Crypto::generateKey(d->method);
238236
int n_components = src.getNumComponents();
239237
bool use_ddoc = (n_components > 1) || (n_components == libcdoc::NOT_IMPLEMENTED);
240-
d->rcpts = keys;
241238

242-
d->_xml = std::make_unique<XMLWriter>(dst);
243239
RET_ERROR(d->writeKeyInfo(use_ddoc, transportKey));
244-
RET_ERROR(d->_xml->writeElement(Private::DENC, "CipherData", [&]() -> uint64_t {
240+
RET_ERROR(d->writeElement(Private::DENC, "CipherData", [&]() -> int64_t {
245241
std::vector<uint8_t> data;
246242
if(use_ddoc) {
247243
data.reserve(16384);
@@ -268,18 +264,18 @@ CDoc1Writer::encrypt(libcdoc::MultiDataSource& src, const std::vector<libcdoc::R
268264
return IO_ERROR;
269265
d->files.push_back({std::move(name), (size_t) result});
270266
}
271-
return d->_xml->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, data));
267+
return d->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, data));
272268
}));
273269
RET_ERROR(d->writeEncryptionProperties(use_ddoc));
274-
d->_xml.reset();
270+
d.reset();
275271
if (owned) return dst->close();
276272
return OK;
277273
}
278274

279275
libcdoc::result_t
280276
CDoc1Writer::beginEncryption()
281277
{
282-
d->_xml = std::make_unique<XMLWriter>(dst);
278+
d = std::make_unique<Private>(dst);
283279
return libcdoc::OK;
284280
}
285281

@@ -308,25 +304,25 @@ CDoc1Writer::writeData(const uint8_t *src, size_t size)
308304
libcdoc::result_t
309305
CDoc1Writer::finishEncryption()
310306
{
311-
if (!d->_xml) return libcdoc::WORKFLOW_ERROR;
307+
if (!d) return libcdoc::WORKFLOW_ERROR;
312308
if (d->rcpts.empty()) return libcdoc::WORKFLOW_ERROR;
313309
if (d->files.empty()) return libcdoc::WORKFLOW_ERROR;
314310
bool use_ddoc = d->files.size() > 1;
315311
libcdoc::Crypto::Key transportKey = libcdoc::Crypto::generateKey(d->method);
316312

317313
RET_ERROR(d->writeKeyInfo(use_ddoc, transportKey));
318-
RET_ERROR(d->_xml->writeElement(Private::DENC, "CipherData", [&]{
314+
RET_ERROR(d->writeElement(Private::DENC, "CipherData", [&] {
319315
if(!use_ddoc)
320-
return d->_xml->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, d->files.back().data));
316+
return d->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, d->files.back().data));
321317
std::vector<uint8_t> data;
322318
data.reserve(4096);
323319
for (DDOCWriter ddoc(data); const FileEntry& file : d->files) {
324320
ddoc.addFile(file.name, "application/octet-stream", file.data);
325321
}
326-
return d->_xml->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, data));
322+
return d->writeBase64Element(Private::DENC, "CipherValue", libcdoc::Crypto::encrypt(d->method, transportKey, data));
327323
}));
328324
RET_ERROR(d->writeEncryptionProperties(use_ddoc));
329-
d->_xml.reset();
325+
d.reset();
330326
if (owned) return dst->close();
331327
return libcdoc::OK;
332328
}

cdoc/CDoc1Writer.h

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,24 @@
2020

2121
#include "CDocWriter.h"
2222

23-
class CDoc1Writer : public libcdoc::CDocWriter
23+
#include <memory>
24+
25+
class CDoc1Writer final : public libcdoc::CDocWriter
2426
{
2527
public:
26-
CDoc1Writer(libcdoc::DataConsumer *dst, bool take_ownership, const std::string &method = "http://www.w3.org/2009/xmlenc11#aes256-gcm");
27-
~CDoc1Writer();
28+
CDoc1Writer(libcdoc::DataConsumer *dst, bool take_ownership);
29+
~CDoc1Writer() noexcept final;
2830

29-
libcdoc::result_t beginEncryption() override final;
30-
libcdoc::result_t addRecipient(const libcdoc::Recipient& rcpt) override final;
31-
libcdoc::result_t addFile(const std::string& name, size_t size) override final;
32-
libcdoc::result_t writeData(const uint8_t *src, size_t size) override final;
33-
libcdoc::result_t finishEncryption() override final;
31+
libcdoc::result_t beginEncryption() final;
32+
libcdoc::result_t addRecipient(const libcdoc::Recipient& rcpt) final;
33+
libcdoc::result_t addFile(const std::string& name, size_t size) final;
34+
libcdoc::result_t writeData(const uint8_t *src, size_t size) final;
35+
libcdoc::result_t finishEncryption() final;
3436

3537
libcdoc::result_t encrypt(libcdoc::MultiDataSource& src, const std::vector<libcdoc::Recipient>& keys) final;
38+
3639
private:
37-
CDoc1Writer(const CDoc1Writer &) = delete;
38-
CDoc1Writer &operator=(const CDoc1Writer &) = delete;
39-
class Private;
40-
Private *d;
40+
CDOC_DISABLE_COPY(CDoc1Writer)
41+
struct Private;
42+
std::unique_ptr<Private> d;
4143
};

cdoc/Exports.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,11 @@
5858
#define CDOC_DISABLE_MOVE(Class) \
5959
Class(Class&&) noexcept = delete; \
6060
Class& operator=(Class&&) noexcept = delete;
61+
#define CDOC_DISABLE_COPY(Class) \
62+
Class(const Class&) noexcept = delete; \
63+
Class& operator=(const Class&) noexcept = delete;
64+
#define CDOC_DISABLE_MOVE_COPY(Class) \
65+
CDOC_DISABLE_MOVE(Class) \
66+
CDOC_DISABLE_COPY(Class)
6167

6268
#endif // EXPOORTS_H

cdoc/XmlWriter.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,20 +109,20 @@ int64_t XMLWriter::writeEndElement(const NS &ns)
109109
return OK;
110110
}
111111

112-
int64_t XMLWriter::writeElement(const NS &ns, const std::string &name, const std::function<uint64_t()> &f)
112+
int64_t XMLWriter::writeElement(const NS &ns, const std::string &name, const std::function<int64_t()> &f)
113113
{
114114
if(auto rv = writeStartElement(ns, name, {}); rv != OK)
115115
return rv;
116-
if(uint64_t rv = OK; f && (rv = f()) != OK)
116+
if(int64_t rv = OK; f && (rv = f()) != OK)
117117
return rv;
118118
return writeEndElement(ns);
119119
}
120120

121-
int64_t XMLWriter::writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<uint64_t()> &f)
121+
int64_t XMLWriter::writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<int64_t()> &f)
122122
{
123123
if(auto rv = writeStartElement(ns, name, attr); rv != OK)
124124
return rv;
125-
if(uint64_t rv = OK; f && (rv = f()) != OK)
125+
if(int64_t rv = OK; f && (rv = f()) != OK)
126126
return rv;
127127
return writeEndElement(ns);
128128
}

cdoc/XmlWriter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class XMLWriter
4040

4141
int64_t writeStartElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr);
4242
int64_t writeEndElement(const NS &ns);
43-
int64_t writeElement(const NS &ns, const std::string &name, const std::function<uint64_t()> &f = nullptr);
44-
int64_t writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<uint64_t()> &f = nullptr);
43+
int64_t writeElement(const NS &ns, const std::string &name, const std::function<int64_t()> &f = nullptr);
44+
int64_t writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<int64_t()> &f = nullptr);
4545
int64_t writeBase64Element(const NS &ns, const std::string &name, const std::vector<unsigned char> &data, const std::map<std::string, std::string> &attr = {});
4646
int64_t writeTextElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::string &data);
4747

@@ -50,4 +50,4 @@ class XMLWriter
5050
Private *d;
5151
};
5252

53-
} // namespace libcdoc
53+
} // namespace libcdoc

0 commit comments

Comments
 (0)