summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMÃ¥rten Nordheim <marten.nordheim@qt.io>2023-03-08 11:10:49 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-03-10 16:10:57 +0000
commitdb9dac951733e1072d6b28735023be7277f70368 (patch)
treea77b8a60dee5c398e2d2be4b4a3cec770e73a77a
parent7aac60beea47130b9e9d435579143794fa2e2edc (diff)
Fix overflow in SHA-3/Keccak
state->rate is always larger than or equal to state->bitsInQueue; when bitsInQueue == rate the queue is consumed and bitsInQueue is set to 0 again. Done-with: Marc Mutz <marc.mutz@qt.io> Change-Id: I56d268a19fb3cd542cc027edc962253f09d97a14 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit fa4b7495b741c3e7943860c5ff15212afceda710) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/3rdparty/sha3/KeccakSponge.c5
-rw-r--r--src/3rdparty/sha3/overflow.patch31
-rw-r--r--src/3rdparty/sha3/qt_attribution.json1
-rw-r--r--tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp29
4 files changed, 64 insertions, 2 deletions
diff --git a/src/3rdparty/sha3/KeccakSponge.c b/src/3rdparty/sha3/KeccakSponge.c
index 6f3da95dbb..337c10ccaf 100644
--- a/src/3rdparty/sha3/KeccakSponge.c
+++ b/src/3rdparty/sha3/KeccakSponge.c
@@ -170,9 +170,10 @@ static int Absorb(spongeState *state, const unsigned char *data, unsigned long l
i += wholeBlocks*state->rate;
}
else {
- partialBlock = (unsigned int)(databitlen - i);
- if (partialBlock+state->bitsInQueue > state->rate)
+ if (databitlen-i > state->rate - state->bitsInQueue)
partialBlock = state->rate-state->bitsInQueue;
+ else
+ partialBlock = (unsigned int)(databitlen - i);
partialByte = partialBlock % 8;
partialBlock -= partialByte;
memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8);
diff --git a/src/3rdparty/sha3/overflow.patch b/src/3rdparty/sha3/overflow.patch
new file mode 100644
index 0000000000..f62a932ac8
--- /dev/null
+++ b/src/3rdparty/sha3/overflow.patch
@@ -0,0 +1,31 @@
+From a60180d3f8ffac268f02d2d4b0b4fbf1bff50f11 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <marten.nordheim@qt.io>
+Date: Wed, 8 Mar 2023 11:10:49 +0100
+Subject: [PATCH] Fix overflow in SHA-3/Keccak
+
+Pick-to: 6.5.0 6.5 6.4.3 6.4 6.2 5.15
+Change-Id: I56d268a19fb3cd542cc027edc962253f09d97a14
+---
+ src/3rdparty/sha3/KeccakSponge.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/3rdparty/sha3/KeccakSponge.c b/src/3rdparty/sha3/KeccakSponge.c
+index 6f3da95dbb..337c10ccaf 100644
+--- a/src/3rdparty/sha3/KeccakSponge.c
++++ b/src/3rdparty/sha3/KeccakSponge.c
+@@ -170,9 +170,10 @@ static int Absorb(spongeState *state, const unsigned char *data, unsigned long l
+ i += wholeBlocks*state->rate;
+ }
+ else {
+- partialBlock = (unsigned int)(databitlen - i);
+- if (partialBlock+state->bitsInQueue > state->rate)
++ if (databitlen-i > state->rate - state->bitsInQueue)
+ partialBlock = state->rate-state->bitsInQueue;
++ else
++ partialBlock = (unsigned int)(databitlen - i);
+ partialByte = partialBlock % 8;
+ partialBlock -= partialByte;
+ memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8);
+--
+2.39.2.vfs.0.0
+
diff --git a/src/3rdparty/sha3/qt_attribution.json b/src/3rdparty/sha3/qt_attribution.json
index 4e53cfae0f..53e9791523 100644
--- a/src/3rdparty/sha3/qt_attribution.json
+++ b/src/3rdparty/sha3/qt_attribution.json
@@ -21,6 +21,7 @@
"QtUsage": "Used in Qt Core (QCryptographicHash).",
"Files": "https://keccak.team/obsolete/KeccakReferenceAndOptimized-3.2.zip - but it's obsolete",
"Files": "KeccakF-1600-32-rvk.macros KeccakF-1600-32.macros KeccakF-1600-64.macros KeccakF-1600-interface.h KeccakF-1600-opt32.c KeccakF-1600-opt64.c KeccakF-1600-unrolling.macros KeccakNISTInterface.c KeccakNISTInterface.h KeccakSponge.c KeccakSponge.h",
+ "Files": "With overflow.patch applied",
"Description": "SHA-3, originally known as Keccak, is a cryptographic hash function.",
"Version": "3.2",
diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
index 5e2e854067..e7a80f92aa 100644
--- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
+++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
@@ -34,6 +34,7 @@ private slots:
// keep last
void moreThan4GiBOfData_data();
void moreThan4GiBOfData();
+ void keccakBufferOverflow();
private:
std::vector<char> large;
};
@@ -478,5 +479,33 @@ void tst_QCryptographicHash::moreThan4GiBOfData()
QCOMPARE(single, chunked);
}
+void tst_QCryptographicHash::keccakBufferOverflow()
+{
+#if QT_POINTER_SIZE == 4
+ QSKIP("This is a 64-bit-only test");
+#else
+
+ if (ensureLargeData(); large.empty())
+ return;
+
+ QElapsedTimer timer;
+ timer.start();
+ const auto sg = qScopeGuard([&] {
+ qDebug() << "test finished in" << timer.restart() << "ms";
+ });
+
+ constexpr qsizetype magic = INT_MAX/4;
+ QCOMPARE_GE(large.size(), size_t(magic + 1));
+
+ QCryptographicHash hash(QCryptographicHash::Algorithm::Keccak_224);
+ const auto first = QByteArrayView{large}.first(1);
+ const auto second = QByteArrayView{large}.sliced(1, magic);
+ hash.addData(first);
+ hash.addData(second);
+ (void)hash.resultView();
+ QVERIFY(true); // didn't crash
+#endif
+}
+
QTEST_MAIN(tst_QCryptographicHash)
#include "tst_qcryptographichash.moc"