Skip to content

Commit 5eacc3f

Browse files
authored
DDoc reading stream (#77)
Signed-off-by: Raul Metsma <[email protected]>
1 parent f014c86 commit 5eacc3f

File tree

11 files changed

+108
-124
lines changed

11 files changed

+108
-124
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ jobs:
7474
env:
7575
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
7676
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
77+
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/${{ matrix.target }}/vcpkg_installed
7778
- name: Build
7879
run: |
7980
cmake --preset ${{ matrix.target }} "-GUnix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=libcdoc.${{ matrix.target }}
@@ -120,6 +121,7 @@ jobs:
120121
env:
121122
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
122123
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
124+
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/${{ matrix.target }}/vcpkg_installed
123125
- name: Build
124126
run: |
125127
cmake --preset ${{ matrix.target }} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=${{ env.DEST }}
@@ -175,7 +177,7 @@ jobs:
175177
"-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" `
176178
"-DSWIG_EXECUTABLE=$swig" `
177179
-DVCPKG_TARGET_TRIPLET=${{ env.VCPKG_DEFAULT_TRIPLET }} `
178-
-DVCPKG_MANIFEST_FEATURES=tests `
180+
${{ matrix.platform == 'x64' && '-DVCPKG_MANIFEST_FEATURES=tests' || '' }} `
179181
-DCMAKE_INSTALL_LIBDIR=bin
180182
cmake --build build --config RelWithDebInfo
181183
ctest -V -C RelWithDebInfo --test-dir build

cdoc/CDoc1Reader.cpp

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -171,53 +171,54 @@ CDoc1Reader::decrypt(const std::vector<uint8_t>& fmk, libcdoc::MultiDataConsumer
171171
result = finishDecryption();
172172
return result;
173173
#else
174-
std::string mime;
175-
std::vector<uint8_t> data;
176-
if (auto result = CDoc1Reader::decryptData(fmk, mime, data); result != OK) {
177-
return result;
178-
}
179-
libcdoc::VectorSource vsrc(data);
180-
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
181-
LOG_DBG("Contains DDoc content {}", mime);
182-
auto result = DDOCReader::parse(&vsrc, dst);
183-
if (result != libcdoc::OK) {
184-
setLastError("Failed to parse DDOC file");
185-
LOG_ERROR("{}", last_error);
174+
return CDoc1Reader::decryptData(fmk, [&](DataSource &src, const std::string &mime) -> result_t {
175+
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
176+
LOG_DBG("Contains DDoc content {}", mime);
177+
auto rv = DDOCReader(&src).parse(dst);
178+
if (rv != libcdoc::OK) {
179+
setLastError("Failed to parse DDOC file");
180+
LOG_ERROR("{}", last_error);
181+
}
182+
return rv;
186183
}
187-
return result;
188-
}
189-
dst->open(d->properties["Filename"], data.size());
190-
dst->writeAll(vsrc);
191-
dst->close();
192-
return libcdoc::OK;
184+
if(auto rv = dst->open(d->properties["Filename"], -1/*data.size()*/); rv != OK)
185+
return rv;
186+
if(auto rv = dst->writeAll(src); rv < OK)
187+
return rv;
188+
return dst->close();
189+
});
193190
#endif
194191
}
195192

196193
libcdoc::result_t
197194
CDoc1Reader::beginDecryption(const std::vector<uint8_t>& fmk)
198195
{
199-
std::string mime;
200-
std::vector<uint8_t> data;
201-
if (auto result = CDoc1Reader::decryptData(fmk, mime, data); result != OK) {
202-
return result;
203-
}
204-
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
205-
LOG_DBG("Contains DDoc content {}", mime);
206-
d->files = DDOCReader::files(data);
207-
} else {
196+
setLastError({});
197+
return CDoc1Reader::decryptData(fmk, [&](DataSource &src, const std::string &mime) -> result_t {
198+
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
199+
LOG_DBG("Contains DDoc content {}", mime);
200+
auto rv = DDOCReader(&src).files(d->files);
201+
if (rv != libcdoc::OK) {
202+
setLastError("Failed to parse DDOC file");
203+
LOG_ERROR("{}", last_error);
204+
d->files.clear();
205+
}
206+
return rv;
207+
}
208+
std::vector<uint8_t> data;
209+
VectorConsumer vsrc(data);
210+
if(auto rv = vsrc.writeAll(src); rv < OK) {
211+
setLastError("Cannot parse container");
212+
LOG_ERROR("{}", last_error);
213+
return rv;
214+
}
208215
d->files.push_back({
209216
d->properties["Filename"],
210217
"application/octet-stream",
211218
std::move(data)
212219
});
213-
}
214-
if (d->files.empty()) {
215-
setLastError("Cannot parse container");
216-
LOG_ERROR("{}", last_error);
217-
return libcdoc::IO_ERROR;
218-
}
219-
setLastError({});
220-
return libcdoc::OK;
220+
return OK;
221+
});
221222
}
222223

223224
libcdoc::result_t
@@ -361,10 +362,10 @@ CDoc1Reader::isCDoc1File(libcdoc::DataSource *src)
361362
/*
362363
* Returns decrypted data
363364
* @param key Transport key to used for decrypt data
364-
* @param mime decrypted mime type
365-
* @param data decrypted data
365+
* @param f callback with DataSource and mime data
366366
*/
367-
result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk, std::string& mime, std::vector<uint8_t>& data)
367+
result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk,
368+
const std::function<libcdoc::result_t(libcdoc::DataSource &src, const std::string &mime)>& f)
368369
{
369370
if (fmk.empty()) {
370371
setLastError("FMK is missing");
@@ -413,16 +414,14 @@ result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk, std::string&
413414
setLastError("Failed to decrypt data, verify if FMK is correct");
414415
return CRYPTO_ERROR;
415416
}
416-
libcdoc::VectorConsumer out(data);
417417
setLastError({});
418+
418419
if (d->mime == MIME_ZLIB) {
419420
libcdoc::ZSource zsrc(&dec);
420-
out.writeAll(zsrc);
421-
mime = d->properties["OriginalMimeType"];
422-
}
423-
else {
424-
mime = d->mime;
425-
out.writeAll(dec);
421+
if(auto rv = f(zsrc, d->properties["OriginalMimeType"]); rv < OK)
422+
return rv;
426423
}
424+
else if(auto rv = f(dec, d->mime); rv < OK)
425+
return rv;
427426
return dec.close();
428427
}

cdoc/CDoc1Reader.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "CDocReader.h"
2222

23+
#include <functional>
24+
2325
class Token;
2426

2527
class CDoc1Reader : public libcdoc::CDocReader
@@ -43,7 +45,8 @@ class CDoc1Reader : public libcdoc::CDocReader
4345
private:
4446
CDoc1Reader(const CDoc1Reader &) = delete;
4547
CDoc1Reader &operator=(const CDoc1Reader &) = delete;
46-
libcdoc::result_t decryptData(const std::vector<uint8_t>& fmk, std::string& mime, std::vector<uint8_t>& data);
48+
libcdoc::result_t decryptData(const std::vector<uint8_t>& fmk,
49+
const std::function<libcdoc::result_t(libcdoc::DataSource &src, const std::string &mime)>& f);
4750
class Private;
4851
Private *d;
4952
};

cdoc/Crypto.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ EncryptionConsumer::write(const uint8_t *src, size_t size)
455455
return OK;
456456
if(error != OK)
457457
return error;
458-
buf.resize(std::max(buf.size(), size + EVP_CIPHER_CTX_block_size(ctx.get()) - 1));
458+
buf.resize(std::max<size_t>(buf.size(), size + EVP_CIPHER_CTX_block_size(ctx.get()) - 1));
459459
int len = int(buf.size());
460460
if(SSL_FAILED(EVP_CipherUpdate(ctx.get(), buf.data(), &len, src, int(size)), "EVP_CipherUpdate"))
461461
return CRYPTO_ERROR;
@@ -474,7 +474,7 @@ EncryptionConsumer::writeAAD(const std::vector<uint8_t> &data)
474474
result_t
475475
EncryptionConsumer::close()
476476
{
477-
buf.resize(std::max(buf.size(), size_t(EVP_CIPHER_CTX_block_size(ctx.get()))));
477+
buf.resize(std::max<size_t>(buf.size(), size_t(EVP_CIPHER_CTX_block_size(ctx.get()))));
478478
int len = int(buf.size());
479479
if(SSL_FAILED(EVP_CipherFinal(ctx.get(), buf.data(), &len), "EVP_CipherFinal"))
480480
return CRYPTO_ERROR;

cdoc/DDocReader.cpp

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,52 +19,50 @@
1919
#include "DDocReader.h"
2020
#include "CDoc.h"
2121
#include "Io.h"
22-
#include "XmlReader.h"
2322

2423
using namespace libcdoc;
2524

26-
int
27-
DDOCReader::parse(libcdoc::DataSource *src, libcdoc::MultiDataConsumer *dst)
25+
int64_t
26+
DDOCReader::parse(MultiDataConsumer *dst)
2827
{
29-
XMLReader reader(src);
30-
while(reader.read()) {
31-
if(reader.isEndElement()) continue;
32-
// EncryptedData
33-
if(!reader.isElement("DataFile")) continue;
34-
std::string name = reader.attribute("Filename");
35-
std::vector<uint8_t> content = reader.readBase64();
36-
int result = dst->open(name, content.size());
37-
if (result != libcdoc::OK) return result;
38-
int64_t n_written = dst->write(content.data(), content.size());
39-
if (n_written < 0) return (int) n_written;
40-
result = dst->close();
41-
if (result != libcdoc::OK) return result;
28+
while(read()) {
29+
if(isEndElement())
30+
continue;
31+
// EncryptedData
32+
if(!isElement("DataFile"))
33+
continue;
34+
std::string name = attribute("Filename");
35+
std::vector<uint8_t> content = readBase64();
36+
if (auto rv = dst->open(name, content.size()); rv != libcdoc::OK)
37+
return rv;
38+
if (auto rv = dst->write(content.data(), content.size()); rv < 0)
39+
return rv;
40+
if (auto rv = dst->close(); rv != libcdoc::OK)
41+
return rv;
4242
}
4343
return (dst->isError()) ? libcdoc::IO_ERROR : libcdoc::OK;
4444
}
4545

4646
struct DDocFileListConsumer : public libcdoc::MultiDataConsumer {
47-
std::vector<DDOCReader::File> files;
47+
std::vector<DDOCReader::File> &files;
4848

49-
explicit DDocFileListConsumer() = default;
50-
int64_t write(const uint8_t *src, size_t size) override final {
51-
DDOCReader::File& file = files.back();
52-
file.data.insert(file.data.end(), src, src + size);
53-
return size;
54-
}
55-
libcdoc::result_t close() override final { return libcdoc::OK; }
56-
bool isError() override final { return false; }
57-
libcdoc::result_t open(const std::string& name, int64_t size) override final {
58-
files.push_back({name, "application/octet-stream", {}});
59-
return libcdoc::OK;
60-
}
49+
DDocFileListConsumer(std::vector<DDOCReader::File> &_files): files(_files) {}
50+
int64_t write(const uint8_t *src, size_t size) final {
51+
DDOCReader::File& file = files.back();
52+
file.data.insert(file.data.end(), src, src + size);
53+
return size;
54+
}
55+
libcdoc::result_t close() final { return libcdoc::OK; }
56+
bool isError() final { return false; }
57+
libcdoc::result_t open(const std::string& name, int64_t /*size*/) final {
58+
files.push_back({name, "application/octet-stream", {}});
59+
return libcdoc::OK;
60+
}
6161
};
6262

63-
std::vector<DDOCReader::File>
64-
DDOCReader::files(const std::vector<uint8_t> &data)
63+
int64_t
64+
DDOCReader::files(std::vector<DDOCReader::File> &files)
6565
{
66-
libcdoc::VectorSource src(data);
67-
DDocFileListConsumer list;
68-
parse(&src, &list);
69-
return std::move(list.files);
66+
DDocFileListConsumer list{files};
67+
return parse(&list);
7068
}

cdoc/DDocReader.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,23 @@
1818

1919
#pragma once
2020

21-
#include <string>
22-
#include <vector>
23-
#include <cstdint>
21+
#include "XmlReader.h"
2422

2523
namespace libcdoc {
2624

27-
struct DataSource;
2825
struct MultiDataConsumer;
2926

30-
class DDOCReader
27+
struct DDOCReader: public XMLReader
3128
{
32-
public:
29+
using XMLReader::XMLReader;
3330
struct File
3431
{
3532
std::string name, mime;
3633
std::vector<uint8_t> data;
3734
};
38-
static int parse(libcdoc::DataSource *src, libcdoc::MultiDataConsumer *dst);
35+
int64_t parse(MultiDataConsumer *dst);
3936

40-
static std::vector<File> files(const std::vector<uint8_t> &data);
37+
int64_t files(std::vector<DDOCReader::File> &files);
4138
};
4239

43-
} // namespace libcdoc
40+
} // namespace libcdoc

cdoc/PKCS11Backend.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,12 +427,17 @@ libcdoc::PKCS11Backend::deriveECDH1(std::vector<uint8_t>& dst, const std::vector
427427
CK_ECDH1_DERIVE_PARAMS ecdh_parms = { CKD_NULL, 0, nullptr, CK_ULONG(public_key.size()), CK_BYTE_PTR(public_key.data()) };
428428
CK_MECHANISM mech = { CKM_ECDH1_DERIVE, &ecdh_parms, sizeof(CK_ECDH1_DERIVE_PARAMS) };
429429
CK_BBOOL _false = CK_FALSE;
430+
CK_BBOOL _true = CK_TRUE;
430431
CK_OBJECT_CLASS newkey_class = CKO_SECRET_KEY;
431432
CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
432-
std::vector<CK_ATTRIBUTE> newkey_template{
433-
{CKA_TOKEN, &_false, sizeof(_false)},
434-
{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
435-
{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)}
433+
CK_ULONG value_len = (public_key.size() - 1) / 2;
434+
std::array newkey_template{
435+
CK_ATTRIBUTE{CKA_TOKEN, &_false, sizeof(_false)},
436+
CK_ATTRIBUTE{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
437+
CK_ATTRIBUTE{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)},
438+
CK_ATTRIBUTE{CKA_SENSITIVE, &_false, sizeof(_false)},
439+
CK_ATTRIBUTE{CKA_EXTRACTABLE, &_true, sizeof(_true)},
440+
CK_ATTRIBUTE{CKA_VALUE_LEN, &value_len, sizeof(value_len)},
436441
};
437442
CK_OBJECT_HANDLE newkey = CK_INVALID_HANDLE;
438443
unsigned long p11result = d->f->C_DeriveKey(d->session, &mech, d->key, newkey_template.data(), CK_ULONG(newkey_template.size()), &newkey);

cdoc/XmlReader.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,7 @@ XMLReader::XMLReader(libcdoc::DataSource *src, bool delete_on_close)
6262
d->reader = xmlReaderForIO(Private::xmlInputReadCallback, nullptr, d, nullptr, nullptr, XML_PARSE_HUGE);
6363
}
6464

65-
XMLReader::XMLReader(std::istream *ifs, bool delete_on_close)
66-
: XMLReader(new libcdoc::IStreamSource(ifs, delete_on_close), true)
67-
{
68-
}
69-
70-
XMLReader::XMLReader(const std::string &file)
71-
: d(new Private)
72-
{
73-
d->reader = xmlReaderForFile(file.c_str(), nullptr, XML_PARSE_HUGE);
74-
}
75-
76-
XMLReader::XMLReader(const std::vector<uint8_t> &data)
77-
: d(new Private)
78-
{
79-
d->reader = xmlReaderForMemory((const char*)data.data(), int(data.size()), nullptr, nullptr, XML_PARSE_HUGE);
80-
}
81-
82-
XMLReader::~XMLReader()
65+
XMLReader::~XMLReader() noexcept
8366
{
8467
xmlFreeTextReader(d->reader);
8568
if(d->_src && d->_delete_src) delete d->_src;

cdoc/XmlReader.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ class XMLReader
3131
{
3232
public:
3333
XMLReader(libcdoc::DataSource *src, bool delete_on_close = false);
34-
XMLReader(std::istream *ifs, bool delete_on_close = false);
35-
XMLReader(const std::string &file);
36-
XMLReader(const std::vector<uint8_t> &data);
37-
~XMLReader();
34+
virtual ~XMLReader() noexcept;
3835

3936
std::string attribute(const char *attr) const;
4037
bool isElement(const char *element) const;
@@ -48,4 +45,4 @@ class XMLReader
4845
Private *d;
4946
};
5047

51-
} // namespace libcdoc
48+
} // namespace libcdoc

cdoc/cdoc-tool.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ static void print_usage(ostream& ofs)
6363
ofs << " --key-id - PKCS11 key ID" << endl;
6464
ofs << " --key-label - PKCS11 key label" << endl;
6565
ofs << endl;
66-
ofs << "cdoc-tool re-encrypt FILE" << endl;
66+
ofs << "cdoc-tool locks FILE" << endl;
6767
ofs << endl;
68-
ofs << "cdoc-tool locks DECRYPT_ARGUMENTS ENCRYPT_ARGUMENTS FILE --out OUTPUTFILE" << endl;
68+
ofs << "cdoc-tool re-encrypt DECRYPT_ARGUMENTS ENCRYPT_ARGUMENTS FILE --out OUTPUTFILE" << endl;
6969
ofs << " Re-encrypts container for different recipient(s)" << endl;
7070
ofs << endl;
7171
ofs << "Common arguments:" << endl;

0 commit comments

Comments
 (0)