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/modexp audit #416

Open
wants to merge 3 commits into
base: develop-durian
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions main/modexp/array_lib/array_add_AGTB.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
; code
; --------------------------
; first_iteration <-- Compute a[0] + b[0]
; while(inB_index_check) { <-- While 0 < i < len(b)
; while(inB_index_check) { <-- While 1 <= i < len(b)
; loop2inB <-- Compute a[i] + b[i] + carry
; }
; while (inA_index_check) { <-- While 0 < i < len(a)
; while (inA_index_check) { <-- While len(b) <= i < len(a)
; loop2inA <-- Compute a[i] + carry
; }
; 1] check_carry <-- If there is a carry, append it to the result
Expand All @@ -36,7 +36,7 @@

VAR GLOBAL array_add_AGTB_inA[%ARRAY_MAX_LEN_DOUBLED]
VAR GLOBAL array_add_AGTB_inB[%ARRAY_MAX_LEN]
VAR GLOBAL array_add_AGTB_out[%ARRAY_MAX_LEN_DOUBLED] ; This cannot be bigger because we use it for division checking
VAR GLOBAL array_add_AGTB_out[%ARRAY_MAX_LEN_DOUBLED] ; This cannot be higher because we use it for division checking
VAR GLOBAL array_add_AGTB_len_inA
VAR GLOBAL array_add_AGTB_len_inB
VAR GLOBAL array_add_AGTB_len_out
Expand Down
4 changes: 2 additions & 2 deletions main/modexp/array_lib/array_add_short.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
; code
; --------------------------
; first_iteration <-- Compute a[0] + b
; while(loop_index_check) { <-- While 0 < i < len(a)
; while(loop_index_check) { <-- While 1 <= i < len(a)
; loop2inA <-- Compute a[i] + carry
; }
; 1] check_carry <-- If there is a carry, append it to the result
Expand All @@ -29,7 +29,7 @@

VAR GLOBAL array_add_short_inA[%ARRAY_MAX_LEN]
VAR GLOBAL array_add_short_inB
VAR GLOBAL array_add_short_out[%ARRAY_MAX_LEN] ; This cannot be bigger because we use it for division checking
VAR GLOBAL array_add_short_out[%ARRAY_MAX_LEN] ; This cannot be higher because we use it for division checking
VAR GLOBAL array_add_short_len_inA
VAR GLOBAL array_add_short_len_out

Expand Down
6 changes: 3 additions & 3 deletions main/modexp/array_lib/array_div_long.zkasm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRE: The input arrays have been trimmed, len(inB) >= 2 and therefore inB != 0
;; PRE: The input arrays have been trimmed, len(inB) >= 2 and therefore inB != 0,1.
;; POST: The quotient and remainder are trimmed.
;;
;; array_div_long:
Expand Down Expand Up @@ -58,7 +58,7 @@

VAR GLOBAL array_div_long_inA[%ARRAY_MAX_LEN_DOUBLED]
VAR GLOBAL array_div_long_inB[%ARRAY_MAX_LEN]
VAR GLOBAL array_div_long_quo[%ARRAY_MAX_LEN_DOUBLED_MINUS_ONE]
VAR GLOBAL array_div_long_quo[%ARRAY_MAX_LEN_DOUBLED_MINUS_ONE] ; Note: This cannot be higher because len(inB) >= 2
VAR GLOBAL array_div_long_rem[%ARRAY_MAX_LEN]

VAR GLOBAL array_div_long_len_inA
Expand Down Expand Up @@ -131,6 +131,7 @@ array_div_long_inA_not_zero_two_chunks:
; where i is the first different chunk from 0 to len(inA)

RR :JMPN(array_div_long_check_inALTinB)
; inA > inB

C - RR :JMPN(failAssert) ; if C < RR ERROR

Expand Down Expand Up @@ -231,7 +232,6 @@ array_div_long_inAGTinB:

C :MSTORE(array_div_long_len_quo)
$ => D :MLOAD(array_div_long_len_inB)
C - 1 => RR
D - 1 => E

; save the first non-zero chunk of quo
Expand Down
19 changes: 8 additions & 11 deletions main/modexp/array_lib/array_div_short.zkasm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRE: The input arrays have been trimmed and inB != 0.
;; PRE: The input arrays have been trimmed and inB != 0,1.
;; POST: The quotient is trimmed.
;;
;; array_div_short:
Expand Down Expand Up @@ -55,14 +55,16 @@ array_div_short:
C :MSTORE(array_div_short_len_quo)

; Let's cover the edge cases
; Is C == 1 and inA == 0?
; 1] Is C == 1 and inA == 0?
C - 1 :JMPNZ(array_div_short_inAGTinB) ; If len(inA) > 1, then we already know that inA > inB
$ => A :MLOAD(array_div_short_inA); Here, len(inA) = len(inB) = 1

; Here, len(inA) = len(inB) = 1
$ => A :MLOAD(array_div_short_inA)
0 => B
$ :EQ, JMPC(array_div_short_inA_is_zero)

array_div_short_equal_len:
; Here, C = 1
; 2] Check if inA = inB, inA < inB or inA > inB

; If the lengths are equal, then we must compare the only chunk
$0{signedComparison(addr.array_div_short_inA,addr.array_div_short_inB)} => RR :JMPZ(array_div_short_check_same_input)
Expand All @@ -76,9 +78,7 @@ array_div_short_equal_len:

RR :JMPN(array_div_short_check_inALTinB)

1 - RR :JMPN(failAssert) ; if 1 < RR ERROR

; Ensure that the chunk is higher
; Ensure inB < inA
$ => A :MLOAD(array_div_short_inB)
$ => B :MLOAD(array_div_short_inA)
1 :LT, JMP(array_div_short_inAGTinB)
Expand All @@ -101,8 +101,7 @@ array_div_short_same_input:
0 :MSTORE(array_div_short_rem), JMP(array_div_short_end)

array_div_short_check_inALTinB:
RR + 1 :JMPN(failAssert) ; if RR < -1 ERROR

; Ensure inA < inB
$ => A :MLOAD(array_div_short_inA)
$ => B :MLOAD(array_div_short_inB)
1 :LT
Expand Down Expand Up @@ -138,7 +137,6 @@ array_div_short_inAGTinB:
; 3] Let's multiply the quotient by inB

C :MSTORE(array_div_short_len_quo)
C - 1 => RR

; save the first non-zero chunk of quo
A :MSTORE(array_div_short_quo + RR)
Expand Down Expand Up @@ -200,7 +198,6 @@ array_div_short_check_result_eq_inA1:
A :MLOAD(array_div_short_inA + RR)
RR - 1 => RR :JMPN(array_div_short_end, array_div_short_check_result_eq_inA1)


; Path with remainder equal to 0
array_div_short_rem_is_zero:
0 :ASSERT, MSTORE(array_div_short_rem)
Expand Down
37 changes: 14 additions & 23 deletions main/modexp/array_lib/array_div_two.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,17 @@ array_div_two:
C :MSTORE(array_div_two_len_quo)

; Let's cover the edge cases
0 => B
; 1] Is C == 1 and in == 0?
C - 1 :JMPNZ(array_div_two_inAGTinB) ; If len(in) > 1, then we already know that in > 2
$ => A :MLOAD(array_div_two_in); Here, len(in) = 1
$ :EQ, JMPC(array_div_two_inALTinB)

; Here, len(in) = 1
$ => A :MLOAD(array_div_two_in)
0 => B
$ :EQ, JMPC(array_div_two_inALTinB)

array_div_two_equal_len:
; 2] Check if in = 2, in < 2 or in > 2

; If the lengths are equal, then we must compare the only chunk
$0{signedComparisonWithConst(addr.array_div_two_in,2)} => RR :JMPZ(array_div_two_check_same_input)

Expand All @@ -71,9 +74,7 @@ array_div_two:

RR :JMPN(array_div_two_check_inALTtwo)

1 - RR :JMPN(failAssert) ; if 1 < RR ERROR

; Ensure that the chunk is higher
; Ensure 2 < inA
2 => A
$ => B :MLOAD(array_div_two_in)
1 :LT, JMP(array_div_two_inAGTinB)
Expand All @@ -88,14 +89,11 @@ array_div_two_same_input:
1 :MSTORE(array_div_two_len_quo), JMP(array_div_two_end)

array_div_two_check_inALTtwo:
RR + 1 :JMPN(failAssert) ; if RR < -1 ERROR

$ => A :MLOAD(array_div_two_in)
2 => B
1 :LT
; Ensure in < 2 <-> in == 1
1 :MLOAD(array_div_two_in)

array_div_two_inALTinB:
; If in < 2, then the result is 0
; If in == 1, then the result is 0
0 :MSTORE(array_div_two_quo)
1 :MSTORE(array_div_two_len_quo), JMP(array_div_two_end)
; End of edge cases
Expand Down Expand Up @@ -123,7 +121,6 @@ array_div_two_inAGTinB:
; 3] Let's multiply the quotient by 2

C :MSTORE(array_div_two_len_quo)
C - 1 => RR

; save the first non-zero chunk of quo
A :MSTORE(array_div_two_quo + RR)
Expand All @@ -146,13 +143,8 @@ array_div_two_mul_quo_inB:

${A == 0} :JMPNZ(array_div_two_rem_is_zero)

; Check that the remainder is not zero
0 => B
0 :EQ

; We must ensure the the remaider is lower than 2
2 => B
1 :LT
; Check that the remainder is 1 < 2
1 :ASSERT

A :MSTORE(array_add_short_inB)

Expand All @@ -178,16 +170,15 @@ array_div_two_check_result_eq_inA1:
A :MLOAD(array_div_two_in + RR)
RR - 1 => RR :JMPN(array_div_two_end, array_div_two_check_result_eq_inA1)


; Path with remainder equal to 0
array_div_two_rem_is_zero:
0 :ASSERT

; The length of q·b must be the same as the input of a
; The length of q·2 must be the same as the input of a
$ => C :MLOAD(array_div_two_len_in)
C :MLOAD(array_mul_two_len_out)

; Check that input == 2·quo + 0
; Check that input == q·2 + 0
C - 1 => RR
array_div_two_check_result_eq_inA2:
$ => A :MLOAD(array_mul_two_out + RR)
Expand Down
2 changes: 1 addition & 1 deletion main/modexp/array_lib/array_mul_long.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

VAR GLOBAL array_mul_long_inA[%ARRAY_MAX_LEN_DOUBLED]
VAR GLOBAL array_mul_long_inB[%ARRAY_MAX_LEN]
VAR GLOBAL array_mul_long_out[%ARRAY_MAX_LEN_DOUBLED] ; This cannot be bigger because we use it for division checking
VAR GLOBAL array_mul_long_out[%ARRAY_MAX_LEN_DOUBLED] ; This cannot be higher because it is used for division checking (in the w.c.)
VAR GLOBAL array_mul_long_len_inA
VAR GLOBAL array_mul_long_len_inB
VAR GLOBAL array_mul_long_len_out
Expand Down
4 changes: 2 additions & 2 deletions main/modexp/array_lib/array_mul_two.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
; code
; --------------------------
; first_iteration <-- a[0] + a[0]
; while(loop_index_check) { <-- While 0 < i < len(a)
; while(loop_index_check) { <-- While 1 <= i < len(a)
; loop2in <-- Compute a[i] + a[i] + carry
; }
; 1] check_carry <-- If there is a carry, append it to the result
Expand All @@ -27,7 +27,7 @@
; --------------------------

VAR GLOBAL array_mul_two_in[%ARRAY_MAX_LEN]
VAR GLOBAL array_mul_two_out[%ARRAY_MAX_LEN] ; This cannot be bigger because we use it for division checking
VAR GLOBAL array_mul_two_out[%ARRAY_MAX_LEN] ; This cannot be higher because we use it for division checking

VAR GLOBAL array_mul_two_len_in
VAR GLOBAL array_mul_two_len_out
Expand Down
19 changes: 8 additions & 11 deletions main/modexp/modexp.zkasm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRE: B, E, M have been trimmed.
;; PRE: B, E, M have been trimmed, M != 0,1, B != 0,1 and E != 0.
;; POST: out is trimmed
;;
;; modexp:
Expand All @@ -18,24 +18,21 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; function modexp(base: bigint[], exp: bigint[], mod: bigint[]): bigint[] {
;; if (array_is_zero(mod) || array_is_one(mod)) return [0n];
;; if (array_is_zero(base)) return [0n];
;; if (array_is_one(base)) return [1n];
;; if (array_is_zero(e)) return [1n];
;;
;; let out = [1n];
;; let base = array_div(base, mod)[1];
;; while (!array_is_zero(exp)) {
;; if (array_is_zero(base)) return [0n];
;; if (isOdd(exp)) {
;; out = array_div(array_mul(out, base),mod)[1];
;; }
;; exp = array_div_two(exp);
;; exp = array_div_two(exp)[0];
;; base = array_div(array_square(base),mod)[1];
;; }
;; return r;
;; };

;; TODO: Context variables instead of global ones????

VAR GLOBAL modexp_Blen
VAR GLOBAL modexp_Elen
VAR GLOBAL modexp_Mlen
Expand Down Expand Up @@ -237,7 +234,7 @@ modexp_mul_long_out_and_B:
$ => C :MLOAD(array_mul_long_len_out)
$ => D :MLOAD(modexp_Mlen)
C - 1 => RR
D - 1 => E :JMPNZ(modexp_mul_long_out_to_div_long, modexp_mul_long_out_to_div_short)
D - 1 => E :JMPNZ(modexp_mul_long_out_to_div_long, modexp_mul_long_out_to_div_short) ; Note: div_short cannot happen here

; Compute out = (out * B) % M
;--------------------------------
Expand Down Expand Up @@ -265,7 +262,7 @@ modexp_div_short_out_and_M1:

1 :MSTORE(modexp_outlen)
$ => A :MLOAD(array_div_short_rem)
A :MSTORE(modexp_out), JMP(return_modexp_loop_multiply)
A :MSTORE(modexp_out), JMP(__return_modexp_loop_multiply)

; 3] Mul short out to div long
modexp_mul_short_out_to_div_long:
Expand Down Expand Up @@ -297,7 +294,7 @@ modexp_div_long_out_and_M1:
modexp_rem_from_div2:
$ => A :MLOAD(array_div_long_rem + RR)
A :MSTORE(modexp_out + RR)
RR - 1 => RR :JMPN(return_modexp_loop_multiply, modexp_rem_from_div2)
RR - 1 => RR :JMPN(__return_modexp_loop_multiply, modexp_rem_from_div2)
; -------------------
; End of branching

Expand All @@ -324,7 +321,7 @@ modexp_loop:
$ => A :MLOAD(modexp_E)
1 => B
$ :AND, JMPC(modexp_loop_multiply) ; In the worst case, the exponent is odd in each iteration
return_modexp_loop_multiply:
__return_modexp_loop_multiply:

$ => C :MLOAD(modexp_Elen)
C - 1 => RR
Expand Down
6 changes: 3 additions & 3 deletions main/modexp/modexp_utils.zkasm
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ modexp_getBaseMloadX:
E - C => E
E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
$ => A :MLOAD(readXFromCalldataResult)
32 - C => D :CALL(SHRarith)
32 - C => D :CALL(SHRarith) ; in: [A: value, D: #bytes to right shift (A >> D)] out: [A: shifted result]
0 => C

modexp_getBaseMstore:
Expand Down Expand Up @@ -116,7 +116,7 @@ modexp_getExpMloadX:
E - C => E
E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
$ => A :MLOAD(readXFromCalldataResult)
32 - C => D :CALL(SHRarith)
32 - C => D :CALL(SHRarith) ; in: [A: value, D: #bytes to right shift (A >> D)] out: [A: shifted result]
0 => C

modexp_getExpMstore:
Expand Down Expand Up @@ -187,7 +187,7 @@ modexp_getModMloadX:
E - C => E
E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
$ => A :MLOAD(readXFromCalldataResult)
32 - C => D :CALL(SHRarith)
32 - C => D :CALL(SHRarith) ; in: [A: value, D: #bytes to right shift (A >> D)] out: [A: shifted result]
0 => C

modexp_getModMstore:
Expand Down
Loading
Loading