Skip to content

Commit bd1358d

Browse files
authored
Streaming decryption for CDoc1 (#75)
* Streaming decryption for CDoc1 Signed-off-by: Raul Metsma <[email protected]> * Reuse DecryptionSource with CDoc2 Signed-off-by: Raul Metsma <[email protected]> --------- Signed-off-by: Raul Metsma <[email protected]>
1 parent 3b0d127 commit bd1358d

File tree

11 files changed

+275
-300
lines changed

11 files changed

+275
-300
lines changed

.github/workflows/build.yml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
container: ubuntu:${{ matrix.container }}
1515
strategy:
1616
matrix:
17-
container: ['22.04', '24.04', '25.04']
17+
container: ['22.04', '24.04', '25.10']
1818
arch: ['amd64', 'arm64']
1919
env:
2020
DEBIAN_FRONTEND: noninteractive
@@ -24,7 +24,7 @@ jobs:
2424
- name: Install dependencies
2525
run: apt update -qq && apt install --no-install-recommends -y lsb-release build-essential devscripts debhelper lintian pkg-config ${UBUNTU_DEPS} doxygen swig openjdk-17-jdk-headless libpython3-dev python3-setuptools libboost-test-dev
2626
- name: Checkout
27-
uses: actions/checkout@v4
27+
uses: actions/checkout@v5
2828
- name: Setup changelog
2929
run: |
3030
export VERSION=$(grep project CMakeLists.txt | egrep -o "([0-9]{1,}\.)+[0-9]{1,}")
@@ -37,7 +37,7 @@ jobs:
3737
- name: Lintian
3838
run: lintian *.deb;
3939
- name: Archive artifacts
40-
uses: actions/upload-artifact@v4
40+
uses: actions/upload-artifact@v5
4141
with:
4242
name: ubuntu_${{ matrix.container }}_${{ matrix.arch }}
4343
path: libcdoc*.*
@@ -55,7 +55,7 @@ jobs:
5555
triplet: x64-android
5656
steps:
5757
- name: Checkout
58-
uses: actions/checkout@v4
58+
uses: actions/checkout@v5
5959
- name: Expose Android NDK env
6060
shell: bash
6161
run: |
@@ -65,7 +65,7 @@ jobs:
6565
uses: actions/cache@v4
6666
with:
6767
path: ${{ github.workspace }}/vcpkg_cache
68-
key: vcpkg-${{ matrix.target }}-${{ hashFiles('.github/workflows/*', 'vcpkg.json', 'CMakeLists.txt', '**/CMakeLists.txt', 'CMakePresets.json') }}
68+
key: vcpkg-${{ matrix.target }}-${{ hashFiles('vcpkg.json') }}
6969
- name: Prepare vcpkg
7070
uses: lukka/run-vcpkg@v11
7171
with:
@@ -80,7 +80,7 @@ jobs:
8080
cmake --build --preset ${{ matrix.target }}
8181
cmake --build --preset ${{ matrix.target }} --target install/strip
8282
- name: Archive artifacts
83-
uses: actions/upload-artifact@v4
83+
uses: actions/upload-artifact@v5
8484
with:
8585
name: ${{ matrix.target }}
8686
path: |
@@ -100,7 +100,7 @@ jobs:
100100
DEST: ${{ github.workspace }}/${{ matrix.target }}
101101
steps:
102102
- name: Checkout
103-
uses: actions/checkout@v4
103+
uses: actions/checkout@v5
104104
- name: Install dependencies
105105
run: |
106106
brew update
@@ -110,7 +110,7 @@ jobs:
110110
uses: actions/cache@v4
111111
with:
112112
path: ${{ github.workspace }}/vcpkg_cache
113-
key: vcpkg-${{ matrix.target }}-${{ hashFiles('.github/workflows/*', 'vcpkg.json', 'CMakeLists.txt', '**/CMakeLists.txt', 'CMakePresets.json') }}
113+
key: vcpkg-${{ matrix.target }}-${{ hashFiles('vcpkg.json') }}
114114
- name: Prepare vcpkg
115115
if: matrix.target != 'macos'
116116
uses: lukka/run-vcpkg@v11
@@ -130,7 +130,7 @@ jobs:
130130
- name: Install
131131
run: cmake --build --preset ${{ matrix.target }} --target install/strip
132132
- name: Archive artifacts
133-
uses: actions/upload-artifact@v4
133+
uses: actions/upload-artifact@v5
134134
with:
135135
name: ${{ matrix.target }}
136136
path: ${{ env.DEST }}
@@ -147,12 +147,12 @@ jobs:
147147
VCPKG_DEFAULT_TRIPLET: ${{ matrix.platform }}-windows-static-md
148148
steps:
149149
- name: Checkout
150-
uses: actions/checkout@v4
150+
uses: actions/checkout@v5
151151
- name: Cache vcpkg
152152
uses: actions/cache@v4
153153
with:
154154
path: ${{ github.workspace }}/vcpkg_cache
155-
key: vcpkg-${{ matrix.image }}-${{ matrix.platform }}-${{ hashFiles('.github/workflows/*', 'vcpkg.json', 'CMakeLists.txt', '**/CMakeLists.txt', 'CMakePresets.json') }}
155+
key: vcpkg-${{ matrix.image }}-${{ matrix.platform }}-${{ hashFiles('vcpkg.json') }}
156156
- name: Prepare vcpkg
157157
uses: lukka/run-vcpkg@v11
158158
with:
@@ -181,7 +181,7 @@ jobs:
181181
ctest -V -C RelWithDebInfo --test-dir build
182182
cmake --install build --config RelWithDebInfo --prefix ${{ env.DEST }}
183183
- name: Archive artifacts
184-
uses: actions/upload-artifact@v4
184+
uses: actions/upload-artifact@v5
185185
with:
186186
name: ${{ matrix.image }}_${{ matrix.platform }}
187187
path: ${{ env.DEST }}
@@ -193,7 +193,7 @@ jobs:
193193
contents: write
194194
steps:
195195
- name: Checkout
196-
uses: actions/checkout@v4
196+
uses: actions/checkout@v5
197197
- name: Install dependencies
198198
run: sudo apt update -qq && sudo apt install --no-install-recommends -y doxygen ${UBUNTU_DEPS}
199199
- name: Build docs
@@ -215,7 +215,7 @@ jobs:
215215
PROJECTNAME: ${{ github.repository }}
216216
steps:
217217
- name: Checkout
218-
uses: actions/checkout@v4
218+
uses: actions/checkout@v5
219219
- name: Install dependencies
220220
run: sudo apt update -qq && sudo apt install --no-install-recommends -y curl ca-certificates ${UBUNTU_DEPS}
221221
- name: Download Coverity Build Tool
@@ -250,7 +250,7 @@ jobs:
250250
security-events: write
251251
steps:
252252
- name: Checkout
253-
uses: actions/checkout@v4
253+
uses: actions/checkout@v5
254254
- name: Install dependencies
255255
run: sudo apt update -qq && sudo apt install --no-install-recommends -y ${UBUNTU_DEPS}
256256
- name: Initialize CodeQL

cdoc/CDoc1Reader.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk, std::string&
384384
return result;
385385
}
386386

387+
std::vector<unsigned char> b64;
387388
XMLReader reader(d->dsrc, false);
388389
int skipKeyInfo = 0;
389390
while (reader.read()) {
@@ -397,26 +398,31 @@ result_t CDoc1Reader::decryptData(const std::vector<uint8_t>& fmk, std::string&
397398
// EncryptedData/CipherData/CipherValue
398399
else if(reader.isElement("CipherValue"))
399400
{
400-
data = libcdoc::Crypto::decrypt(d->method, fmk, reader.readBase64());
401+
b64 = reader.readBase64();
401402
break;
402403
}
403404
}
404405

405-
if(data.empty()) {
406+
if(b64.empty()) {
407+
setLastError("Failed to decode base64 data");
408+
return libcdoc::IO_ERROR;
409+
}
410+
VectorSource src(b64);
411+
libcdoc::DecryptionSource dec(src, d->method, fmk);
412+
if(dec.isError()) {
406413
setLastError("Failed to decrypt data, verify if FMK is correct");
407-
return libcdoc::CRYPTO_ERROR;
414+
return CRYPTO_ERROR;
408415
}
416+
libcdoc::VectorConsumer out(data);
409417
setLastError({});
410418
if (d->mime == MIME_ZLIB) {
411-
libcdoc::VectorSource vsrc(data);
412-
libcdoc::ZSource zsrc(&vsrc);
413-
std::vector<uint8_t> tmp;
414-
libcdoc::VectorConsumer vcons(tmp);
415-
vcons.writeAll(zsrc);
416-
data = std::move(tmp);
419+
libcdoc::ZSource zsrc(&dec);
420+
out.writeAll(zsrc);
417421
mime = d->properties["OriginalMimeType"];
418422
}
419-
else
423+
else {
420424
mime = d->mime;
421-
return libcdoc::OK;
425+
out.writeAll(dec);
426+
}
427+
return dec.close();
422428
}

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)

0 commit comments

Comments
 (0)