fix fuzz 5 reloaded: modexp - endianness issue for exponent MSB (#266)

* fix fuzz 5 reloaded: endianness issue for exponent MSB

* refactoring typo in test vs gmp
This commit is contained in:
Mamy Ratsimbazafy 2023-09-06 20:01:35 +02:00 committed by GitHub
parent b645d68e1a
commit 1ad8499ae5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 16 deletions

View File

@ -361,7 +361,7 @@ func scalarMul_vartime*[scalBits; EC](
const L = scalBits.ceilDiv_vartime(M) + 1
let usedBits = scalar.limbs.getBits_vartime()
let usedBits = scalar.limbs.getBits_LE_vartime()
when scalBits == EC.F.C.getCurveOrderBitwidth() and
EC.F.C.hasEndomorphismAcceleration():

View File

@ -55,8 +55,8 @@ func powOddMod_vartime*(
debug:
doAssert bool(M.isOdd())
let aBits = a.getBits_vartime()
let mBits = M.getBits_vartime()
let aBits = a.getBits_LE_vartime()
let mBits = M.getBits_LE_vartime()
let L = wordsRequired(mBits)
let m0ninv = M[0].negInvModWord()
var rMont = allocStackArray(SecretWord, L)
@ -105,17 +105,17 @@ func powMod_vartime*(
# Special cases: early returns
# -------------------------------------------------------------------
let mBits = M.getBits_vartime()
let mBits = M.getBits_LE_vartime()
if mBits < 2: # Check if modulus = 0 or 1
r.setZero()
return
let eBits = exponent.getBits_vartime()
let eBits = exponent.getBits_BE_vartime()
if eBits == 0: # Check if exponent == 0
r.setOne() # a⁰ = 1 and 0⁰ = 1
return
let aBits = a.getBits_vartime()
let aBits = a.getBits_LE_vartime()
if aBits < 2: # Check if a == 0 or a == 1
r[0] = a[0]
for i in 1 ..< r.len:

View File

@ -109,7 +109,7 @@ func powMod2k_vartime*(
for i in 0 ..< r.len:
r[i] = Zero
let msb = getMSB_vartime(exponent)
let msb = getMSB_BE_vartime(exponent)
if msb == -1: # exponent is 0
r[0] = One # x⁰ = 1, even for 0⁰

View File

@ -105,18 +105,40 @@ func ccopyWords*(
# Bit operations
# ------------------------------------------------------------
func getMSB_vartime*[T](a: openArray[T]): int =
func getMSB_BE_vartime*(a: openArray[byte]): int =
## Returns the position of the most significant bit
## of `a`.
## Returns -1 if a == 0
##
## Input MUST be ordered from most to least significant byte
result = -1
for i in countdown(a.len-1, 0):
if bool(a[i] != T(0)):
return int(log2_vartime(uint64 a[i])) + 8*sizeof(T)*i
for i in 0 ..< a.len:
if bool a[i] != 0:
return int(log2_vartime(uint32 a[i])) + 8*sizeof(byte)*(a.len-1-i)
func getBits_vartime*[T](a: openArray[T]): int {.inline.} =
func getBits_BE_vartime*(a: openArray[byte]): int {.inline.} =
## Returns the number of bits used by `a`
## Returns 0 for 0
1 + getMSB_vartime(a)
##
## Input MUST be ordered from least to most significant byte
1 + getMSB_BE_vartime(a)
func getMSB_LE_vartime(a: openArray[SecretWord]): int =
## Returns the position of the most significant bit
## of `a`.
## Returns -1 if a == 0
##
## Input MUST be ordered from least to most significant word
result = -1
for i in countdown(a.len-1, 0):
if bool a[i] != Zero:
return int(log2_vartime(uint64 a[i])) + 8*sizeof(SecretWord)*i
func getBits_LE_vartime*(a: openArray[SecretWord]): int {.inline.} =
## Returns the number of bits used by `a`
## Returns 0 for 0
##
## Input MUST be ordered from least to most significant word
1 + getMSB_LE_vartime(a)
{.pop.} # raises no exceptions

View File

@ -97,9 +97,9 @@ proc test(rng: var RngState) =
mpz_clear(rr)
let
aBits = a.getBits_vartime()
eBits = e.getBits_vartime()
mBits = M.getBits_vartime()
aBits = a.getBits_LE_vartime()
eBits = e.getBits_BE_vartime()
mBits = M.getBits_LE_vartime()
rCtt.powMod_vartime(a, e, M, window = 4)

View File

@ -42,6 +42,37 @@ suite "EVM ModExp precompile (EIP-198)":
doAssert status == cttEVM_Success
doAssert r[0] == 0, ". Result was " & $r[0]
test "Audit #5-2 - Fuzz failure with even modulus strikes back":
let input = [
# Length of base (1)
uint8 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
# Length of exponent (5)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
# Length of modulus (1)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
# Base
0x3a,
# Exponent
0x01, 0x00, 0x00, 0x00, 0x00,
# Modulus
0x08
]
var r = newSeq[byte](1)
let status = r.eth_evm_modexp(input)
doAssert status == cttEVM_Success
doAssert r[0] == 0, ". Result was " & $r[0]
test "Audit #8 - off-by-1 buffer overflow - ptr + length exclusive vs openArray(lo, hi) inclusive":
let input = [
# Length of base (24)