diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2eb8b38f1..01e7e47e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: container: ${{ matrix.container }} strategy: matrix: - container: ['ubuntu:20.04', 'ubuntu:22.04', 'ubuntu:23.04', 'ubuntu:23.10'] + container: ['ubuntu:20.04', 'ubuntu:22.04', 'ubuntu:23.10'] env: DEBIAN_FRONTEND: noninteractive DEBFULLNAME: github-actions diff --git a/client/CDoc2.cpp b/client/CDoc2.cpp index f0c8bb81e..8d16979ec 100644 --- a/client/CDoc2.cpp +++ b/client/CDoc2.cpp @@ -127,7 +127,7 @@ namespace cdoc20 { qint64 bytesAvailable() const final { - return io->bytesAvailable() + buf.size() + QIODevice::bytesAvailable(); + return (io->bytesAvailable() - Crypto::Cipher::tagLen()) + buf.size() + QIODevice::bytesAvailable(); } qint64 readData(char *data, qint64 maxlen) final @@ -137,7 +137,8 @@ namespace cdoc20 { std::array in{}; for(int res = Z_OK; s.avail_out > 0 && res == Z_OK;) { - if(auto size = io->read(in.data(), in.size()); size > 0) + if(auto insize = io->bytesAvailable() - Crypto::Cipher::tagLen(), + size = io->read(in.data(), qMin(insize, in.size())); size > 0) { if(!cipher->update(in.data(), int(size))) return -1; @@ -532,6 +533,11 @@ bool CDoc2::decryptPayload(const QByteArray &fmk) files = cdoc20::TAR(std::unique_ptr(new cdoc20::stream(this, &dec))).files(warning); if(warning) setLastError(tr("CDoc contains additional payload data that is not part of content")); + QByteArray tag = read(16); +#ifndef NDEBUG + qDebug() << "tag" << tag.toHex(); +#endif + dec.setTag(tag); if(!dec.result()) files.clear(); return !files.empty(); diff --git a/client/Crypto.cpp b/client/Crypto.cpp index ee671b046..1d397b981 100644 --- a/client/Crypto.cpp +++ b/client/Crypto.cpp @@ -85,6 +85,11 @@ QByteArray Crypto::Cipher::tag() const return {}; } +bool Crypto::Cipher::setTag(const QByteArray &data) const +{ + return !isError(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_TAG, int(data.size()), const_cast(data.data()))); +} + QByteArray Crypto::aes_wrap(const QByteArray &key, const QByteArray &data, bool encrypt) { Cipher c(key.size() == 32 ? EVP_aes_256_wrap() : EVP_aes_128_wrap(), key, {}, encrypt); diff --git a/client/Crypto.h b/client/Crypto.h index 3c91235ca..58e8972bd 100644 --- a/client/Crypto.h +++ b/client/Crypto.h @@ -47,6 +47,7 @@ class Crypto bool result() const; QByteArray tag() const; static constexpr int tagLen() { return 16; } + bool setTag(const QByteArray &data) const; }; static QByteArray aes_wrap(const QByteArray &key, const QByteArray &data, bool encrypt);