Skip to content

Commit e8d78f8

Browse files
committed
Reuse DecryptionSource with CDoc2
Signed-off-by: Raul Metsma <[email protected]>
1 parent 2377b26 commit e8d78f8

File tree

5 files changed

+10
-166
lines changed

5 files changed

+10
-166
lines changed

cdoc/CDoc2Reader.cpp

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,9 @@ struct CDoc2Reader::Private {
8383

8484
std::vector<Lock> locks;
8585

86-
std::unique_ptr<libcdoc::Crypto::Cipher> cipher;
87-
std::unique_ptr<TaggedSource> tgs;
86+
std::unique_ptr<libcdoc::DecryptionSource> dec;
8887
std::unique_ptr<libcdoc::ZSource> zsrc;
8988
std::unique_ptr<libcdoc::TarSource> tar;
90-
9189
};
9290

9391
CDoc2Reader::~CDoc2Reader()
@@ -389,29 +387,19 @@ CDoc2Reader::beginDecryption(const std::vector<uint8_t>& fmk)
389387
}
390388
priv->_at_nonce = false;
391389
std::vector<uint8_t> cek = libcdoc::Crypto::expand(fmk, std::vector<uint8_t>(libcdoc::CDoc2::CEK.cbegin(), libcdoc::CDoc2::CEK.cend()));
392-
std::vector<uint8_t> nonce(libcdoc::CDoc2::NONCE_LEN);
393-
if (priv->_src->read(nonce.data(), libcdoc::CDoc2::NONCE_LEN) != libcdoc::CDoc2::NONCE_LEN) {
394-
setLastError("Error reading nonce");
395-
LOG_ERROR("{}", last_error);
396-
return libcdoc::IO_ERROR;
397-
}
398-
399390
LOG_TRACE_KEY("cek: {}", cek);
400-
LOG_TRACE_KEY("nonce: {}", nonce);
401391

402-
priv->cipher = std::make_unique<libcdoc::Crypto::Cipher>(EVP_chacha20_poly1305(), cek, nonce, false);
392+
priv->dec = std::make_unique<libcdoc::DecryptionSource>(*priv->_src, EVP_chacha20_poly1305(), cek, libcdoc::CDoc2::NONCE_LEN);
403393
std::vector<uint8_t> aad(libcdoc::CDoc2::PAYLOAD.cbegin(), libcdoc::CDoc2::PAYLOAD.cend());
404394
aad.insert(aad.end(), priv->header_data.cbegin(), priv->header_data.cend());
405395
aad.insert(aad.end(), priv->headerHMAC.cbegin(), priv->headerHMAC.cend());
406-
if(!priv->cipher->updateAAD(aad)) {
396+
if(priv->dec->updateAAD(aad) != OK) {
407397
setLastError("Wrong decryption key (FMK)");
408398
LOG_ERROR("{}", last_error);
409399
return libcdoc::WRONG_KEY;
410400
}
411401

412-
priv->tgs = std::make_unique<TaggedSource>(priv->_src, false, 16);
413-
libcdoc::CipherSource *csrc = new libcdoc::CipherSource(priv->tgs.get(), false, priv->cipher.get());
414-
priv->zsrc = std::make_unique<libcdoc::ZSource>(csrc, true);
402+
priv->zsrc = std::make_unique<libcdoc::ZSource>(priv->dec.get(), false);
415403
priv->tar = std::make_unique<libcdoc::TarSource>(priv->zsrc.get(), false);
416404

417405
return libcdoc::OK;
@@ -455,21 +443,15 @@ CDoc2Reader::finishDecryption()
455443
LOG_WARN("{}", last_error);
456444
}
457445

458-
LOG_TRACE_KEY("tag: {}", priv->tgs->tag);
459-
460-
priv->cipher->setTag(priv->tgs->tag);
461-
if (!priv->cipher->result()) {
462-
setLastError("Stream tag is invalid");
463-
LOG_ERROR("{}", last_error);
464-
return HASH_MISMATCH;
465-
}
466446
setLastError({});
467-
priv->tgs.reset();
468447
priv->zsrc.reset();
469448
priv->tar.reset();
470-
priv->cipher->clear();
471-
priv->cipher.reset();
472-
return OK;
449+
auto rv = priv->dec->close();
450+
priv->dec.reset();
451+
if (rv != OK) {
452+
setLastError("Crypto payload integrity check failed");
453+
}
454+
return rv;
473455
}
474456

475457
CDoc2Reader::CDoc2Reader(libcdoc::DataSource *src, bool take_ownership)

cdoc/Crypto.cpp

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -54,60 +54,6 @@ constexpr auto d2i(const std::vector<uint8_t> &data, Args&&... args) noexcept
5454
return make_unique_ptr(F(std::forward<Args>(args)..., &p, long(data.size())), Free);
5555
}
5656

57-
58-
Crypto::Cipher::Cipher(const EVP_CIPHER *cipher, const std::vector<uint8_t> &key, const std::vector<uint8_t> &iv, bool encrypt)
59-
: ctx(EVP_CIPHER_CTX_new())
60-
{
61-
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
62-
EVP_CipherInit_ex(ctx, cipher, nullptr, key.data(), iv.empty() ? nullptr : iv.data(), int(encrypt));
63-
}
64-
65-
Crypto::Cipher::~Cipher()
66-
{
67-
EVP_CIPHER_CTX_free(ctx);
68-
}
69-
70-
bool Crypto::Cipher::updateAAD(const std::vector<uint8_t> &data) const
71-
{
72-
int len = 0;
73-
return !SSL_FAILED(EVP_CipherUpdate(ctx, nullptr, &len, data.data(), int(data.size())), "EVP_CipherUpdate");
74-
}
75-
76-
bool
77-
Crypto::Cipher::update(uint8_t *data, int size) const
78-
{
79-
int len = 0;
80-
return !SSL_FAILED(EVP_CipherUpdate(ctx, data, &len, data, size), "EVP_CipherUpdate");
81-
}
82-
83-
bool Crypto::Cipher::result() const
84-
{
85-
std::vector<uint8_t> result(EVP_CIPHER_CTX_block_size(ctx), 0);
86-
int len = int(result.size());
87-
if(SSL_FAILED(EVP_CipherFinal(ctx, result.data(), &len), "EVP_CipherFinal"))
88-
return false;
89-
if(result.size() != len)
90-
result.resize(len);
91-
return true;
92-
}
93-
94-
bool Crypto::Cipher::setTag(const std::vector<uint8_t> &data) const
95-
{
96-
return !SSL_FAILED(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, int(data.size()), (void *) data.data()), "EVP_CIPHER_CTX_ctrl");
97-
}
98-
99-
int
100-
Crypto::Cipher::blockSize() const
101-
{
102-
return EVP_CIPHER_CTX_get_block_size(ctx);
103-
}
104-
105-
void
106-
Crypto::Cipher::clear()
107-
{
108-
EVP_CIPHER_CTX_reset(ctx);
109-
}
110-
11157
std::vector<uint8_t> Crypto::AESWrap(const std::vector<uint8_t> &key, const std::vector<uint8_t> &data, bool encrypt)
11258
{
11359
AES_KEY aes;

cdoc/Crypto.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,6 @@ class Crypto
3939
public:
4040
using EVP_PKEY_ptr = unique_free_t<EVP_PKEY>;
4141

42-
struct Cipher {
43-
EVP_CIPHER_CTX *ctx;
44-
Cipher(const EVP_CIPHER *cipher, const std::vector<uint8_t> &key, const std::vector<uint8_t> &iv, bool encrypt = true);
45-
~Cipher();
46-
bool updateAAD(const std::vector<uint8_t> &data) const;
47-
bool update(uint8_t *data, int size) const;
48-
bool result() const;
49-
static constexpr int tagLen() { return 16; }
50-
bool setTag(const std::vector<uint8_t> &data) const;
51-
int blockSize() const;
52-
void clear();
53-
};
54-
5542
static constexpr std::string_view KWAES128_MTH = "http://www.w3.org/2001/04/xmlenc#kw-aes128";
5643
static constexpr std::string_view KWAES192_MTH = "http://www.w3.org/2001/04/xmlenc#kw-aes192";
5744
static constexpr std::string_view KWAES256_MTH = "http://www.w3.org/2001/04/xmlenc#kw-aes256";

cdoc/Utils.h

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -127,51 +127,4 @@ std::string urlDecode(const std::string &src);
127127

128128
} // namespace libcdoc
129129

130-
// A source implementation that always keeps last 16 bytes in tag
131-
132-
struct TaggedSource : public libcdoc::DataSource {
133-
std::vector<uint8_t> tag;
134-
libcdoc::DataSource *_src;
135-
bool _owned;
136-
137-
TaggedSource(libcdoc::DataSource *src, bool take_ownership, size_t tag_size) : tag(tag_size), _src(src), _owned(take_ownership) {
138-
tag.resize(tag.size());
139-
_src->read(tag.data(), tag.size());
140-
}
141-
~TaggedSource() {
142-
if (_owned) delete(_src);
143-
}
144-
145-
libcdoc::result_t seek(size_t pos) override final {
146-
if (!_src->seek(pos)) return libcdoc::INPUT_STREAM_ERROR;
147-
if (_src->read(tag.data(), tag.size()) != tag.size()) return libcdoc::INPUT_STREAM_ERROR;
148-
return libcdoc::OK;
149-
}
150-
151-
libcdoc::result_t read(uint8_t *dst, size_t size) override final {
152-
std::vector<uint8_t> t(tag.size());
153-
uint8_t *tmp = t.data();
154-
size_t nread = _src->read(dst, size);
155-
if (nread >= tag.size()) {
156-
std::copy(dst + nread - tag.size(), dst + nread, tmp);
157-
std::copy_backward(dst, dst + nread - tag.size(), dst + nread);
158-
std::copy(tag.cbegin(), tag.cend(), dst);
159-
std::copy(tmp, tmp + tag.size(), tag.begin());
160-
} else {
161-
std::copy(dst, dst + nread, tmp);
162-
std::copy(tag.cbegin(), tag.cbegin() + nread, dst);
163-
std::copy(tag.cbegin() + nread, tag.cend(), tag.begin());
164-
std::copy(tmp, tmp + nread, tag.end() - nread);
165-
}
166-
return nread;
167-
}
168-
169-
virtual bool isError() override final {
170-
return _src->isError();
171-
}
172-
virtual bool isEof() override final {
173-
return _src->isEof();
174-
}
175-
};
176-
177130
#endif // UTILS_H

cdoc/ZStream.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,6 @@
2828

2929
namespace libcdoc {
3030

31-
struct CipherSource : public ChainedSource {
32-
bool _fail = false;
33-
libcdoc::Crypto::Cipher *_cipher;
34-
uint32_t _block_size;
35-
CipherSource(DataSource *src, bool take_ownership, libcdoc::Crypto::Cipher *cipher)
36-
: ChainedSource(src, take_ownership), _cipher(cipher), _block_size(cipher->blockSize()) {}
37-
38-
libcdoc::result_t read(uint8_t *dst, size_t size) override final {
39-
if (_fail) return INPUT_ERROR;
40-
size_t n_read = _src->read(dst, _block_size * (size / _block_size));
41-
if (n_read) {
42-
if((n_read % _block_size) || !_cipher->update(dst, n_read)) {
43-
_fail = true;
44-
return INPUT_ERROR;
45-
}
46-
}
47-
return n_read;
48-
}
49-
50-
virtual bool isError() override final {
51-
return _fail || ChainedSource::isError();
52-
};
53-
};
54-
5531
struct ZConsumer : public ChainedConsumer {
5632
static constexpr uint64_t CHUNK = 16LL * 1024LL;
5733
z_stream _s {};

0 commit comments

Comments
 (0)