Skip to content

Commit 5e9b95f

Browse files
monneratleenooks
authored andcommitted
Avoid 32-bit signed integer overflow in Blowfish computations.
PHP 8.1 deprecates float to int truncation.
1 parent aeebf3f commit 5e9b95f

File tree

1 file changed

+64
-34
lines changed

1 file changed

+64
-34
lines changed

lib/blowfish.php

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ function setKey($key)
315315
$keyLen = count($key);
316316
for ($i = 0; $i < $iMax; $i++) {
317317
for ($t = 0; $t < 4; $t++) {
318-
$keyXor = ($keyXor << 8) | (($key[$keyPos]) & 0x0ff);
318+
$keyXor = (($keyXor << 8) | (($key[$keyPos]) & 0x0ff)) & 0xFFFFFFFF;
319319
if (++$keyPos == $keyLen) {
320320
$keyPos = 0;
321321
}
@@ -389,6 +389,37 @@ function encryptBlock($block, $key = null)
389389
return pack("NN", $parts['L'], $parts['R']);
390390
}
391391

392+
/**
393+
* Perform an encryption/decryption step.
394+
*
395+
* @param Int $x The bits source for the S tables indexing.
396+
*
397+
* @return Int The 32-bit step result.
398+
*/
399+
function _cryptStep($x)
400+
{
401+
if (PHP_INT_SIZE > 4)
402+
return ((($this->s1[($x >> 24) & 0xFF] + $this->s2[($x >> 16) & 0xFF]) ^ $this->s3[($x >> 8) & 0xFF]) + $this->s4[$x & 0xFF]) & 0xFFFF;
403+
404+
/* For 32-bit machines, split values into 16-bit high and low parts
405+
to avoid negative values and 32-bit overflows. */
406+
$a = $this->s1[($x >> 24) & 0xFF];
407+
$b = $this->s2[($x >> 16) & 0xFF];
408+
$h = (($a >> 16) & 0xFFFF) + (($b >> 16) & 0xFFFF);
409+
$l = ($a & 0xFFFF) + ($b & 0xFFFF);
410+
if ($l & ~0xFFFF)
411+
$h++;
412+
$a = $this->s3[($x >> 8) & 0xFF];
413+
$h ^= $a >> 16;
414+
$l ^= $a;
415+
$a = $this->s4[$x & 0xFF];
416+
$h = ($h & 0xFFFF) + (($a >> 16) & 0xFFFF);
417+
$l = ($l & 0xFFFF) + ($a & 0xFFFF);
418+
if ($l & ~0xFFFF)
419+
$h++;
420+
return (($h & 0xFFFF) << 16) | ($l & 0xFFFF);
421+
}
422+
392423
/**
393424
* Encrypt a block on data.
394425
*
@@ -400,22 +431,22 @@ function encryptBlock($block, $key = null)
400431
function _encryptBlock($L, $R)
401432
{
402433
$L ^= $this->p[0];
403-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[1];
404-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[2];
405-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[3];
406-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[4];
407-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[5];
408-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[6];
409-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[7];
410-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[8];
411-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[9];
412-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[10];
413-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[11];
414-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[12];
415-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[13];
416-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[14];
417-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[15];
418-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[16];
434+
$R ^= $this->_cryptStep($L) ^ $this->p[1];
435+
$L ^= $this->_cryptStep($R) ^ $this->p[2];
436+
$R ^= $this->_cryptStep($L) ^ $this->p[3];
437+
$L ^= $this->_cryptStep($R) ^ $this->p[4];
438+
$R ^= $this->_cryptStep($L) ^ $this->p[5];
439+
$L ^= $this->_cryptStep($R) ^ $this->p[6];
440+
$R ^= $this->_cryptStep($L) ^ $this->p[7];
441+
$L ^= $this->_cryptStep($R) ^ $this->p[8];
442+
$R ^= $this->_cryptStep($L) ^ $this->p[9];
443+
$L ^= $this->_cryptStep($R) ^ $this->p[10];
444+
$R ^= $this->_cryptStep($L) ^ $this->p[11];
445+
$L ^= $this->_cryptStep($R) ^ $this->p[12];
446+
$R ^= $this->_cryptStep($L) ^ $this->p[13];
447+
$L ^= $this->_cryptStep($R) ^ $this->p[14];
448+
$R ^= $this->_cryptStep($L) ^ $this->p[15];
449+
$L ^= $this->_cryptStep($R) ^ $this->p[16];
419450
$R ^= $this->p[17];
420451

421452
return array('L' => $R, 'R' => $L);
@@ -445,23 +476,22 @@ function decryptBlock($block, $key = null)
445476
list($L, $R) = array_values($unpack);
446477

447478
$L ^= $this->p[17];
448-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[16];
449-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[15];
450-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[14];
451-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[13];
452-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[12];
453-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[11];
454-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[10];
455-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[9];
456-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[8];
457-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[7];
458-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[6];
459-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[5];
460-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[4];
461-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[3];
462-
$R ^= ((($this->s1[($L >> 24) & 0xFF] + $this->s2[($L >> 16) & 0x0ff]) ^ $this->s3[($L >> 8) & 0x0ff]) + $this->s4[$L & 0x0ff]) ^ $this->p[2];
463-
$L ^= ((($this->s1[($R >> 24) & 0xFF] + $this->s2[($R >> 16) & 0x0ff]) ^ $this->s3[($R >> 8) & 0x0ff]) + $this->s4[$R & 0x0ff]) ^ $this->p[1];
464-
479+
$R ^= $this->_cryptStep($L) ^ $this->p[16];
480+
$L ^= $this->_cryptStep($R) ^ $this->p[15];
481+
$R ^= $this->_cryptStep($L) ^ $this->p[14];
482+
$L ^= $this->_cryptStep($R) ^ $this->p[13];
483+
$R ^= $this->_cryptStep($L) ^ $this->p[12];
484+
$L ^= $this->_cryptStep($R) ^ $this->p[11];
485+
$R ^= $this->_cryptStep($L) ^ $this->p[10];
486+
$L ^= $this->_cryptStep($R) ^ $this->p[9];
487+
$R ^= $this->_cryptStep($L) ^ $this->p[8];
488+
$L ^= $this->_cryptStep($R) ^ $this->p[7];
489+
$R ^= $this->_cryptStep($L) ^ $this->p[6];
490+
$L ^= $this->_cryptStep($R) ^ $this->p[5];
491+
$R ^= $this->_cryptStep($L) ^ $this->p[4];
492+
$L ^= $this->_cryptStep($R) ^ $this->p[3];
493+
$R ^= $this->_cryptStep($L) ^ $this->p[2];
494+
$L ^= $this->_cryptStep($R) ^ $this->p[1];
465495
$decrypted = pack("NN", $R ^ $this->p[0], $L);
466496
return $decrypted;
467497
}

0 commit comments

Comments
 (0)