Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
env:
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/${{ matrix.target }}/vcpkg_installed
- name: Build
run: |
cmake --preset ${{ matrix.target }} "-GUnix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=libcdoc.${{ matrix.target }}
Expand Down Expand Up @@ -120,6 +121,7 @@ jobs:
env:
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/${{ matrix.target }}/vcpkg_installed
- name: Build
run: |
cmake --preset ${{ matrix.target }} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=${{ env.DEST }}
Expand Down Expand Up @@ -175,7 +177,7 @@ jobs:
"-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" `
"-DSWIG_EXECUTABLE=$swig" `
-DVCPKG_TARGET_TRIPLET=${{ env.VCPKG_DEFAULT_TRIPLET }} `
-DVCPKG_MANIFEST_FEATURES=tests `
${{ matrix.platform == 'x64' && '-DVCPKG_MANIFEST_FEATURES=tests' || '' }} `
-DCMAKE_INSTALL_LIBDIR=bin
cmake --build build --config RelWithDebInfo
ctest -V -C RelWithDebInfo --test-dir build
Expand Down
89 changes: 44 additions & 45 deletions cdoc/CDoc1Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,53 +171,54 @@ CDoc1Reader::decrypt(const std::vector<uint8_t>& fmk, libcdoc::MultiDataConsumer
result = finishDecryption();
return result;
#else
std::string mime;
std::vector<uint8_t> data;
if (auto result = CDoc1Reader::decryptData(fmk, mime, data); result != OK) {
return result;
}
libcdoc::VectorSource vsrc(data);
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
LOG_DBG("Contains DDoc content {}", mime);
auto result = DDOCReader::parse(&vsrc, dst);
if (result != libcdoc::OK) {
setLastError("Failed to parse DDOC file");
LOG_ERROR("{}", last_error);
return CDoc1Reader::decryptData(fmk, [&](DataSource &src, const std::string &mime) -> result_t {
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
LOG_DBG("Contains DDoc content {}", mime);
auto rv = DDOCReader(&src).parse(dst);
if (rv != libcdoc::OK) {
setLastError("Failed to parse DDOC file");
LOG_ERROR("{}", last_error);
}
return rv;
}
return result;
}
dst->open(d->properties["Filename"], data.size());
dst->writeAll(vsrc);
dst->close();
return libcdoc::OK;
if(auto rv = dst->open(d->properties["Filename"], -1/*data.size()*/); rv != OK)
return rv;
if(auto rv = dst->writeAll(src); rv < OK)
return rv;
return dst->close();
});
#endif
}

libcdoc::result_t
CDoc1Reader::beginDecryption(const std::vector<uint8_t>& fmk)
{
std::string mime;
std::vector<uint8_t> data;
if (auto result = CDoc1Reader::decryptData(fmk, mime, data); result != OK) {
return result;
}
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
LOG_DBG("Contains DDoc content {}", mime);
d->files = DDOCReader::files(data);
} else {
setLastError({});
return CDoc1Reader::decryptData(fmk, [&](DataSource &src, const std::string &mime) -> result_t {
if(mime == MIME_DDOC || mime == MIME_DDOC_OLD) {
LOG_DBG("Contains DDoc content {}", mime);
auto rv = DDOCReader(&src).files(d->files);
if (rv != libcdoc::OK) {
setLastError("Failed to parse DDOC file");
LOG_ERROR("{}", last_error);
d->files.clear();
}
return rv;
}
std::vector<uint8_t> data;
VectorConsumer vsrc(data);
if(auto rv = vsrc.writeAll(src); rv < OK) {
setLastError("Cannot parse container");
LOG_ERROR("{}", last_error);
return rv;
}
d->files.push_back({
d->properties["Filename"],
"application/octet-stream",
std::move(data)
});
}
if (d->files.empty()) {
setLastError("Cannot parse container");
LOG_ERROR("{}", last_error);
return libcdoc::IO_ERROR;
}
setLastError({});
return libcdoc::OK;
return OK;
});
}

libcdoc::result_t
Expand Down Expand Up @@ -361,10 +362,10 @@ CDoc1Reader::isCDoc1File(libcdoc::DataSource *src)
/*
* Returns decrypted data
* @param key Transport key to used for decrypt data
* @param mime decrypted mime type
* @param data decrypted data
* @param f callback with DataSource and mime data
*/
result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk, std::string& mime, std::vector<uint8_t>& data)
result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk,
const std::function<libcdoc::result_t(libcdoc::DataSource &src, const std::string &mime)>& f)
{
if (fmk.empty()) {
setLastError("FMK is missing");
Expand Down Expand Up @@ -413,16 +414,14 @@ result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk, std::string&
setLastError("Failed to decrypt data, verify if FMK is correct");
return CRYPTO_ERROR;
}
libcdoc::VectorConsumer out(data);
setLastError({});

if (d->mime == MIME_ZLIB) {
libcdoc::ZSource zsrc(&dec);
out.writeAll(zsrc);
mime = d->properties["OriginalMimeType"];
}
else {
mime = d->mime;
out.writeAll(dec);
if(auto rv = f(zsrc, d->properties["OriginalMimeType"]); rv < OK)
return rv;
}
else if(auto rv = f(dec, d->mime); rv < OK)
return rv;
return dec.close();
}
5 changes: 4 additions & 1 deletion cdoc/CDoc1Reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "CDocReader.h"

#include <functional>

class Token;

class CDoc1Reader : public libcdoc::CDocReader
Expand All @@ -43,7 +45,8 @@ class CDoc1Reader : public libcdoc::CDocReader
private:
CDoc1Reader(const CDoc1Reader &) = delete;
CDoc1Reader &operator=(const CDoc1Reader &) = delete;
libcdoc::result_t decryptData(const std::vector<uint8_t>& fmk, std::string& mime, std::vector<uint8_t>& data);
libcdoc::result_t decryptData(const std::vector<uint8_t>& fmk,
const std::function<libcdoc::result_t(libcdoc::DataSource &src, const std::string &mime)>& f);
class Private;
Private *d;
};
4 changes: 2 additions & 2 deletions cdoc/Crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ EncryptionConsumer::write(const uint8_t *src, size_t size)
return OK;
if(error != OK)
return error;
buf.resize(std::max(buf.size(), size + EVP_CIPHER_CTX_block_size(ctx.get()) - 1));
buf.resize(std::max<size_t>(buf.size(), size + EVP_CIPHER_CTX_block_size(ctx.get()) - 1));
int len = int(buf.size());
if(SSL_FAILED(EVP_CipherUpdate(ctx.get(), buf.data(), &len, src, int(size)), "EVP_CipherUpdate"))
return CRYPTO_ERROR;
Expand All @@ -474,7 +474,7 @@ EncryptionConsumer::writeAAD(const std::vector<uint8_t> &data)
result_t
EncryptionConsumer::close()
{
buf.resize(std::max(buf.size(), size_t(EVP_CIPHER_CTX_block_size(ctx.get()))));
buf.resize(std::max<size_t>(buf.size(), size_t(EVP_CIPHER_CTX_block_size(ctx.get()))));
int len = int(buf.size());
if(SSL_FAILED(EVP_CipherFinal(ctx.get(), buf.data(), &len), "EVP_CipherFinal"))
return CRYPTO_ERROR;
Expand Down
68 changes: 33 additions & 35 deletions cdoc/DDocReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,52 +19,50 @@
#include "DDocReader.h"
#include "CDoc.h"
#include "Io.h"
#include "XmlReader.h"

using namespace libcdoc;

int
DDOCReader::parse(libcdoc::DataSource *src, libcdoc::MultiDataConsumer *dst)
int64_t
DDOCReader::parse(MultiDataConsumer *dst)
{
XMLReader reader(src);
while(reader.read()) {
if(reader.isEndElement()) continue;
// EncryptedData
if(!reader.isElement("DataFile")) continue;
std::string name = reader.attribute("Filename");
std::vector<uint8_t> content = reader.readBase64();
int result = dst->open(name, content.size());
if (result != libcdoc::OK) return result;
int64_t n_written = dst->write(content.data(), content.size());
if (n_written < 0) return (int) n_written;
result = dst->close();
if (result != libcdoc::OK) return result;
while(read()) {
if(isEndElement())
continue;
// EncryptedData
if(!isElement("DataFile"))
continue;
std::string name = attribute("Filename");
std::vector<uint8_t> content = readBase64();
if (auto rv = dst->open(name, content.size()); rv != libcdoc::OK)
return rv;
if (auto rv = dst->write(content.data(), content.size()); rv < 0)
return rv;
if (auto rv = dst->close(); rv != libcdoc::OK)
return rv;
}
return (dst->isError()) ? libcdoc::IO_ERROR : libcdoc::OK;
}

struct DDocFileListConsumer : public libcdoc::MultiDataConsumer {
std::vector<DDOCReader::File> files;
std::vector<DDOCReader::File> &files;

explicit DDocFileListConsumer() = default;
int64_t write(const uint8_t *src, size_t size) override final {
DDOCReader::File& file = files.back();
file.data.insert(file.data.end(), src, src + size);
return size;
}
libcdoc::result_t close() override final { return libcdoc::OK; }
bool isError() override final { return false; }
libcdoc::result_t open(const std::string& name, int64_t size) override final {
files.push_back({name, "application/octet-stream", {}});
return libcdoc::OK;
}
DDocFileListConsumer(std::vector<DDOCReader::File> &_files): files(_files) {}
int64_t write(const uint8_t *src, size_t size) final {
DDOCReader::File& file = files.back();
file.data.insert(file.data.end(), src, src + size);
return size;
}
libcdoc::result_t close() final { return libcdoc::OK; }
bool isError() final { return false; }
libcdoc::result_t open(const std::string& name, int64_t /*size*/) final {
files.push_back({name, "application/octet-stream", {}});
return libcdoc::OK;
}
};

std::vector<DDOCReader::File>
DDOCReader::files(const std::vector<uint8_t> &data)
int64_t
DDOCReader::files(std::vector<DDOCReader::File> &files)
{
libcdoc::VectorSource src(data);
DDocFileListConsumer list;
parse(&src, &list);
return std::move(list.files);
DDocFileListConsumer list{files};
return parse(&list);
}
15 changes: 6 additions & 9 deletions cdoc/DDocReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,23 @@

#pragma once

#include <string>
#include <vector>
#include <cstdint>
#include "XmlReader.h"

namespace libcdoc {

struct DataSource;
struct MultiDataConsumer;

class DDOCReader
struct DDOCReader: public XMLReader
{
public:
using XMLReader::XMLReader;
struct File
{
std::string name, mime;
std::vector<uint8_t> data;
};
static int parse(libcdoc::DataSource *src, libcdoc::MultiDataConsumer *dst);
int64_t parse(MultiDataConsumer *dst);

static std::vector<File> files(const std::vector<uint8_t> &data);
int64_t files(std::vector<DDOCReader::File> &files);
};

} // namespace libcdoc
} // namespace libcdoc
13 changes: 9 additions & 4 deletions cdoc/PKCS11Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,12 +427,17 @@ libcdoc::PKCS11Backend::deriveECDH1(std::vector<uint8_t>& dst, const std::vector
CK_ECDH1_DERIVE_PARAMS ecdh_parms = { CKD_NULL, 0, nullptr, CK_ULONG(public_key.size()), CK_BYTE_PTR(public_key.data()) };
CK_MECHANISM mech = { CKM_ECDH1_DERIVE, &ecdh_parms, sizeof(CK_ECDH1_DERIVE_PARAMS) };
CK_BBOOL _false = CK_FALSE;
CK_BBOOL _true = CK_TRUE;
CK_OBJECT_CLASS newkey_class = CKO_SECRET_KEY;
CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
std::vector<CK_ATTRIBUTE> newkey_template{
{CKA_TOKEN, &_false, sizeof(_false)},
{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)}
CK_ULONG value_len = (public_key.size() - 1) / 2;
std::array newkey_template{
CK_ATTRIBUTE{CKA_TOKEN, &_false, sizeof(_false)},
CK_ATTRIBUTE{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
CK_ATTRIBUTE{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)},
CK_ATTRIBUTE{CKA_SENSITIVE, &_false, sizeof(_false)},
CK_ATTRIBUTE{CKA_EXTRACTABLE, &_true, sizeof(_true)},
CK_ATTRIBUTE{CKA_VALUE_LEN, &value_len, sizeof(value_len)},
};
CK_OBJECT_HANDLE newkey = CK_INVALID_HANDLE;
unsigned long p11result = d->f->C_DeriveKey(d->session, &mech, d->key, newkey_template.data(), CK_ULONG(newkey_template.size()), &newkey);
Expand Down
19 changes: 1 addition & 18 deletions cdoc/XmlReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,7 @@ XMLReader::XMLReader(libcdoc::DataSource *src, bool delete_on_close)
d->reader = xmlReaderForIO(Private::xmlInputReadCallback, nullptr, d, nullptr, nullptr, XML_PARSE_HUGE);
}

XMLReader::XMLReader(std::istream *ifs, bool delete_on_close)
: XMLReader(new libcdoc::IStreamSource(ifs, delete_on_close), true)
{
}

XMLReader::XMLReader(const std::string &file)
: d(new Private)
{
d->reader = xmlReaderForFile(file.c_str(), nullptr, XML_PARSE_HUGE);
}

XMLReader::XMLReader(const std::vector<uint8_t> &data)
: d(new Private)
{
d->reader = xmlReaderForMemory((const char*)data.data(), int(data.size()), nullptr, nullptr, XML_PARSE_HUGE);
}

XMLReader::~XMLReader()
XMLReader::~XMLReader() noexcept
{
xmlFreeTextReader(d->reader);
if(d->_src && d->_delete_src) delete d->_src;
Expand Down
7 changes: 2 additions & 5 deletions cdoc/XmlReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ class XMLReader
{
public:
XMLReader(libcdoc::DataSource *src, bool delete_on_close = false);
XMLReader(std::istream *ifs, bool delete_on_close = false);
XMLReader(const std::string &file);
XMLReader(const std::vector<uint8_t> &data);
~XMLReader();
virtual ~XMLReader() noexcept;

std::string attribute(const char *attr) const;
bool isElement(const char *element) const;
Expand All @@ -48,4 +45,4 @@ class XMLReader
Private *d;
};

} // namespace libcdoc
} // namespace libcdoc
4 changes: 2 additions & 2 deletions cdoc/cdoc-tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ static void print_usage(ostream& ofs)
ofs << " --key-id - PKCS11 key ID" << endl;
ofs << " --key-label - PKCS11 key label" << endl;
ofs << endl;
ofs << "cdoc-tool re-encrypt FILE" << endl;
ofs << "cdoc-tool locks FILE" << endl;
ofs << endl;
ofs << "cdoc-tool locks DECRYPT_ARGUMENTS ENCRYPT_ARGUMENTS FILE --out OUTPUTFILE" << endl;
ofs << "cdoc-tool re-encrypt DECRYPT_ARGUMENTS ENCRYPT_ARGUMENTS FILE --out OUTPUTFILE" << endl;
ofs << " Re-encrypts container for different recipient(s)" << endl;
ofs << endl;
ofs << "Common arguments:" << endl;
Expand Down
Loading
Loading