From 4b1f3b84336a26db9649c5175e29984fa1b54950 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Thu, 20 Oct 2022 23:57:35 -0600 Subject: [PATCH] Fix bug #81738 (buffer overflow in hash_update() on long parameter) (cherry picked from commit de4517ad607df8d4cb3735228b39e4a48f95556c) --- NEWS | 6 ++++++ ext/hash/sha3/generic32lc/KeccakSponge.inc | 14 ++++++++------ ext/hash/sha3/generic64lc/KeccakSponge.inc | 14 ++++++++------ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index e31f007ad0..b6e3c4fe6c 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,12 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +Backported from 7.4.33 + +- Hash: + . Fixed bug #81738: buffer overflow in hash_update() on long parameter. + (CVE-2022-37454) (nicky at mouha dot be) + Backported from 7.4.32 - Core: diff --git a/ext/hash/sha3/generic32lc/KeccakSponge.inc b/ext/hash/sha3/generic32lc/KeccakSponge.inc index 42a15aac6d..f8c42ff788 100644 --- a/ext/hash/sha3/generic32lc/KeccakSponge.inc +++ b/ext/hash/sha3/generic32lc/KeccakSponge.inc @@ -160,7 +160,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat i = 0; curData = data; while(i < dataByteLen) { - if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { + if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { #ifdef SnP_FastLoop_Absorb /* processing full blocks first */ if ((rateInBytes % (SnP_width/200)) == 0) { @@ -186,9 +186,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat } else { /* normal lane: using the message queue */ - partialBlock = (unsigned int)(dataByteLen - i); - if (partialBlock+instance->byteIOIndex > rateInBytes) + if (dataByteLen-i > rateInBytes-instance->byteIOIndex) partialBlock = rateInBytes-instance->byteIOIndex; + else + partialBlock = (unsigned int)(dataByteLen - i); #ifdef KeccakReference displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); #endif @@ -263,7 +264,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte i = 0; curData = data; while(i < dataByteLen) { - if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { + if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) { for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { SnP_Permute(instance->state); SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); @@ -280,9 +281,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte SnP_Permute(instance->state); instance->byteIOIndex = 0; } - partialBlock = (unsigned int)(dataByteLen - i); - if (partialBlock+instance->byteIOIndex > rateInBytes) + if (dataByteLen-i > rateInBytes-instance->byteIOIndex) partialBlock = rateInBytes-instance->byteIOIndex; + else + partialBlock = (unsigned int)(dataByteLen - i); i += partialBlock; SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); diff --git a/ext/hash/sha3/generic64lc/KeccakSponge.inc b/ext/hash/sha3/generic64lc/KeccakSponge.inc index 42a15aac6d..f8c42ff788 100644 --- a/ext/hash/sha3/generic64lc/KeccakSponge.inc +++ b/ext/hash/sha3/generic64lc/KeccakSponge.inc @@ -160,7 +160,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat i = 0; curData = data; while(i < dataByteLen) { - if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { + if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { #ifdef SnP_FastLoop_Absorb /* processing full blocks first */ if ((rateInBytes % (SnP_width/200)) == 0) { @@ -186,9 +186,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat } else { /* normal lane: using the message queue */ - partialBlock = (unsigned int)(dataByteLen - i); - if (partialBlock+instance->byteIOIndex > rateInBytes) + if (dataByteLen-i > rateInBytes-instance->byteIOIndex) partialBlock = rateInBytes-instance->byteIOIndex; + else + partialBlock = (unsigned int)(dataByteLen - i); #ifdef KeccakReference displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); #endif @@ -263,7 +264,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte i = 0; curData = data; while(i < dataByteLen) { - if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { + if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) { for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { SnP_Permute(instance->state); SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); @@ -280,9 +281,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte SnP_Permute(instance->state); instance->byteIOIndex = 0; } - partialBlock = (unsigned int)(dataByteLen - i); - if (partialBlock+instance->byteIOIndex > rateInBytes) + if (dataByteLen-i > rateInBytes-instance->byteIOIndex) partialBlock = rateInBytes-instance->byteIOIndex; + else + partialBlock = (unsigned int)(dataByteLen - i); i += partialBlock; SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); -- 2.37.3