Summary
Incorrect logic inside ecpairing will lead to reject valid proof
Vulnerability Details
Whenever verifier verifies proof he will eventually calls ecpairing -> calls g2ScalarMul
as you can see zr1
is not being used when condition case 0x02
triggers, but yp1 used passed twice to g2JacobianDouble
.
function g2ScalarMul(xp0, xp1, yp0, yp1, zp0, zp1, scalar) -> xr0, xr1, yr0, yr1, zr0, zr1 {
let scalarBitIndex := bitLen(scalar)
switch scalar
case 0x02 {
xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianDouble(xp0, xp1, yp0, yp1, zp0, yp1)
}
default {
xr0 := 0
xr1 := 0
yr0 := MONTGOMERY_ONE()
yr1 := 0
zr0 := 0
zr1 := 0
for {} scalarBitIndex {} {
scalarBitIndex := sub(scalarBitIndex, 1)
xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianDouble(xr0, xr1, yr0, yr1, zr0, zr1)
let bitindex := checkBit(scalarBitIndex, scalar)
if bitindex {
xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianAdd(xp0, xp1, yp0, yp1, zp0, zp1, xr0, xr1, yr0, yr1, zr0, zr1)
}
}
}
}
precompiles/EcPairing.yul#L683
Incorrect g2ScalarMul
leads to g2IsInSubGroup being incorrect -> iszero(g2IsInSubGroup(g2_x0,g2_x1, g2_y0, g2_y1, MONTGOMERY_ONE(), 0))
false
-> rejecting valid proof
Impact
Flase proof will be accepted when condition case 0x02
triggers. For now scalar can only be TWISTED_SUBGROUP_ORDER
or X
- 4965661367192848881, but later it might become dynamic, it will reject valid proofs
Tools Used
Recommendations
function g2ScalarMul(xp0, xp1, yp0, yp1, zp0, zp1, scalar) -> xr0, xr1, yr0, yr1, zr0, zr1 {
let scalarBitIndex := bitLen(scalar)
switch scalar
case 0x02 {
- xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianDouble(xp0, xp1, yp0, yp1, zp0, yp1)
+ xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianDouble(xp0, xp1, yp0, yp1, zp0, zp1)
}
default {
xr0 := 0
xr1 := 0
yr0 := MONTGOMERY_ONE()
yr1 := 0
zr0 := 0
zr1 := 0
for {} scalarBitIndex {} {
scalarBitIndex := sub(scalarBitIndex, 1)
xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianDouble(xr0, xr1, yr0, yr1, zr0, zr1)
let bitindex := checkBit(scalarBitIndex, scalar)
if bitindex {
xr0, xr1, yr0, yr1, zr0, zr1 := g2JacobianAdd(xp0, xp1, yp0, yp1, zp0, zp1, xr0, xr1, yr0, yr1, zr0, zr1)
}
}
}
}