Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion constantine/math/elliptic/ec_scalar_mul_vartime.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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⁰
Expand Down
32 changes: 27 additions & 5 deletions constantine/math_arbitrary_precision/arithmetic/limbs_views.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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 0 ..< a.len:
if bool a[i] != 0:
return int(log2_vartime(uint32 a[i])) + 8*sizeof(byte)*(a.len-1-i)

func getBits_BE_vartime*(a: openArray[byte]): int {.inline.} =
## Returns the number of bits used by `a`
## Returns 0 for 0
##
## 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] != T(0)):
return int(log2_vartime(uint64 a[i])) + 8*sizeof(T)*i
if bool a[i] != Zero:
return int(log2_vartime(uint64 a[i])) + 8*sizeof(SecretWord)*i

func getBits_vartime*[T](a: openArray[T]): int {.inline.} =
func getBits_LE_vartime*(a: openArray[SecretWord]): 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 word
1 + getMSB_LE_vartime(a)

{.pop.} # raises no exceptions
6 changes: 3 additions & 3 deletions tests/math_arbitrary_precision/t_bigints_powmod_vs_gmp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
31 changes: 31 additions & 0 deletions tests/t_ethereum_evm_modexp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading