Library EVMOpSem.keccak
Require Import Arith.
Require Import Bool.
Require Import List.
Require Import String.
Require Import Program.Wf.
Require Import Lem.coqharness.
Open Scope nat_scope.
Open Scope string_scope.
Require Import Lem.lem_pervasives.
Require Export Lem.lem_pervasives.
Require Import word8.
Require Export word8.
Require Import word256.
Require Export word256.
Require Import word64.
Require Export word64.
Definition rotl64 (w : word64 ) (n : nat ) : word64 := word64Lor ( word64Lsr w ( Coq.Init.Peano.minus( 64%nat) n)) ( word64Lsl w n).
Definition big : word64 := word64Lsl(word64FromNumeral 1%nat)( 63%nat).
Definition two31 : word64 := word64Lsl(word64FromNumeral 1%nat)( 31%nat).
Definition two15 : word64 := word64Lsl(word64FromNumeral 1%nat)( 15%nat).
Definition keccakf_randc : list (word64 ):= [word64FromNumeral 1%nat; word64Lor(word64FromNumeral 130%nat) two15; word64Lor (word64Lor(word64FromNumeral 138%nat) big) two15; word64Lor (word64Lor (word64Lor(word64FromNumeral 0%nat) big) two31) two15; word64Lor(word64FromNumeral 139%nat) two15; word64Lor(word64FromNumeral 1%nat) two31; word64Lor (word64Lor (word64Lor(word64FromNumeral 129%nat) big) two31) two15; word64Lor (word64Lor(word64FromNumeral 9%nat) big) two15;word64FromNumeral 138%nat;word64FromNumeral 136%nat; word64Lor (word64Lor(word64FromNumeral 9%nat) two31) two15; word64Lor(word64FromNumeral 10%nat) two31; word64Lor (word64Lor(word64FromNumeral 139%nat) two31) two15; word64Lor(word64FromNumeral 139%nat) big; word64Lor (word64Lor(word64FromNumeral 137%nat) big) two15; word64Lor (word64Lor(word64FromNumeral 3%nat) big) two15; word64Lor (word64Lor(word64FromNumeral 2%nat) big) two15; word64Lor(word64FromNumeral 128%nat) big; word64Lor(word64FromNumeral 10%nat) two15; word64Lor (word64Lor(word64FromNumeral 10%nat) big) two31; word64Lor (word64Lor (word64Lor(word64FromNumeral 129%nat) big) two31) two15; word64Lor (word64Lor(word64FromNumeral 128%nat) big) two15; word64Lor(word64FromNumeral 1%nat) two31; word64Lor (word64Lor (word64Lor(word64FromNumeral 8%nat) big) two31) two15]
.
Definition keccakf_rotc : list (nat ):= [ 1%nat; 3%nat; 6%nat; 10%nat; 15%nat; 21%nat; 28%nat; 36%nat; 45%nat; 55%nat; 2%nat; 14%nat; 27%nat; 41%nat; 56%nat; 8%nat; 25%nat; 43%nat; 62%nat; 18%nat; 39%nat; 61%nat; 20%nat; 44%nat]
.
Definition keccakf_piln : list (nat ):= [ 10%nat; 7%nat; 11%nat; 17%nat; 18%nat; 3%nat; 5%nat; 16%nat; 8%nat; 21%nat; 24%nat; 4%nat; 15%nat; 23%nat; 19%nat; 13%nat; 12%nat; 2%nat; 20%nat; 14%nat; 22%nat; 9%nat; 6%nat; 1%nat]
.
Definition get (lst : list (word64 )) (n : nat ) : word64 := match ( index lst n) with
| Some x => x
| None =>word64FromNumeral 0%nat
end.
Definition get_n (lst : list (nat )) (n : nat ) : nat := match ( index lst n) with
| Some x => x
| None => 0%nat
end.
Definition setf (lst : list (word64 )) (n : nat ) (w : word64 ) : list (word64 ):=
if nat_ltb (List.length lst) n then (@ List.app _) ((@ List.app _)lst (genlist (fun ( _ : nat ) =>word64FromNumeral 0%nat) ( Coq.Init.Peano.minus (Coq.Init.Peano.minus(List.length lst) n)( 1%nat)))) [w]
else (@ List.app _) ((@ List.app _)(take n lst) [w]) (drop (Coq.Init.Peano.plus n( 1%nat)) lst).
Definition theta1 (i : nat ) (st : list (word64 )) : word64 := word64Lxor (word64Lxor (word64Lxor (word64Lxor
(get st i)
(get st ( Coq.Init.Peano.plus i( 5%nat))))
(get st ( Coq.Init.Peano.plus i( 10%nat))))
(get st ( Coq.Init.Peano.plus i( 15%nat))))
(get st ( Coq.Init.Peano.plus i( 20%nat))).
Definition theta_t (i : nat ) (bc : list (word64 )) : word64 := word64Lxor
(get bc ( Nat.modulo( Coq.Init.Peano.plus i( 4%nat))( 5%nat))) (rotl64 (get bc ( Nat.modulo( Coq.Init.Peano.plus i( 1%nat))( 5%nat)))( 1%nat)).
Definition theta (st : list (word64 )) : list (word64 ):=
let bc := genlist (fun (i : nat ) => theta1 i st)( 5%nat) in
let t := genlist (fun (i : nat ) => theta_t i bc)( 5%nat) in
genlist (fun (ji : nat ) => word64Lxor (get st ji) (get t ( Nat.modulo ji( 5%nat))))( 25%nat).
Definition rho_pi_inner (t_st : (word64 *list (word64 )) % type) (i : nat ) : (word64 *list (word64 )) % type:=
let j := get_n keccakf_piln i in
let bc := get ((@ snd _ _) t_st) j in
(bc, setf ((@ snd _ _) t_st) j (rotl64 ((@ fst _ _) t_st) (get_n keccakf_rotc i))).
Definition rho_pi_changes (i : nat ) (t_st : (word64 *list (word64 )) % type) : (word64 *list (word64 )) % type:= List.fold_left rho_pi_inner (genlist (fun (x : nat ) => x) i) t_st.
Definition rho_pi (st : list (word64 )) : list (word64 ):= (@ snd _ _) (rho_pi_changes( 24%nat) (get st( 1%nat), st)).
Definition chi_for_j (st_slice : list (word64 )) : list (word64 ):=
genlist (fun (i : nat ) => word64Lxor (get st_slice i) ( word64Land(word64Lnot (get st_slice ( Nat.modulo( Coq.Init.Peano.plus i( 1%nat))( 5%nat)))) (get st_slice ( Nat.modulo( Coq.Init.Peano.plus i( 2%nat))( 5%nat)))))( 5%nat).
Definition filterI {a : Type} (lst : list a) (pred : nat -> bool ) : list a:=
List.map (@ fst _ _) (List.filter (fun (p : (a*nat ) % type) => pred ((@ snd _ _) p)) (zip lst (genlist (fun (i : nat ) => i) (List.length lst)))).
Definition chi (st : list (word64 )) : list (word64 ):=
lem_list.concat (genlist (fun (j : nat ) => chi_for_j (filterI st (fun (i : nat ) => nat_lteb (Coq.Init.Peano.mult j( 5%nat)) i && nat_lteb i (Coq.Init.Peano.plus(Coq.Init.Peano.mult j( 5%nat))( 5%nat)))))( 5%nat)).
Definition iota (r : nat ) (st : list (word64 )) : list (word64 ):= setf st( 0%nat) ( word64Lxor(get st( 0%nat)) (get keccakf_randc r)).
Definition for_inner (st : list (word64 )) (r : nat ) : list (word64 ):= iota r (chi (rho_pi (theta st))).
Definition keccakf_rounds : nat := 24%nat.
Definition byte : Type := word8 .
Definition byte_default: byte := word8_default.
Program Fixpoint word_rsplit_aux (lst : list (bool )) (n : nat ) : list (word8 ):= match ( n) with
| 0%nat => []
|S (n) => word8FromBoollist (take( 8%nat) lst) :: word_rsplit_aux (drop( 8%nat) lst) n
end.
Definition word_rsplit (w : word64 ) : list (byte ):= word_rsplit_aux (boolListFromWord64 w)( 8%nat).
Definition word_rcat_k (lst : list (word8 )) : word64 := word64FromBoollist (lem_list.concat (List.map boolListFromWord8 lst)).
Definition invert_endian (w : word64 ) : word64 := word_rcat_k (List.rev (word_rsplit w)).
Definition keccakf (st : list (word64 )) : list (word64 ):= List.fold_left for_inner (genlist (fun (i : nat ) => i) keccakf_rounds) st.
Definition mdlen : nat := Nat.div( 256%nat)( 8%nat).
Definition rsiz : nat := Coq.Init.Peano.minus( 200%nat) (Coq.Init.Peano.mult mdlen( 2%nat)).
Definition word8_to_word64 (w : word8 ) : word64 := word64FromNat (word8ToNat w).
Definition update_byte (i : word8 ) (p : nat ) (st : list (word64 )) : list (word64 ):= setf st ( Nat.div p( 8%nat)) ( word64Lxor(get st ( Nat.div p( 8%nat))) ( word64Lsl(word8_to_word64 i) ( Coq.Init.Peano.mult( 8%nat) ( Nat.modulo p( 8%nat))))).
Program Fixpoint sha3_update (lst : list (word8 )) (pos : nat ) (st : list (word64 )) : (nat *list (word64 )) % type:= match ( lst) with
| [] => (pos, st)
| c :: rest =>
if ( nat_lteb pos rsiz) then sha3_update rest ( Coq.Init.Peano.plus pos( 1%nat)) (update_byte c pos st)
else sha3_update rest( 0%nat) (keccakf (update_byte c pos st))
end.
Definition keccak_final (p : nat ) (st : list (word64 )) : list (word8 ):=
let st0 := update_byte(word8FromNumeral 1%nat) p st in
let st1 := update_byte(word8FromNumeral 128%nat) ( Coq.Init.Peano.minus rsiz( 1%nat)) st0 in
let st2 := take( 4%nat) (keccakf st1) in
lem_list.concat (List.map (fun (x : word64 ) => List.rev (word_rsplit x)) st2).
Definition initial_st : list word64 := genlist (fun ( _ : nat ) =>word64FromNumeral 0%nat)( 25%nat).
Definition initial_pos : nat := 0%nat.
Definition keccak' (input : list (byte )) : list (byte ):=
let mid := sha3_update input initial_pos initial_st in
keccak_final ((@ fst _ _) mid) ((@ snd _ _) mid).
Definition w256 : Type := (Bvector 256) .
Definition w256_default: w256 := word256_default.
Definition list_fill_right (filled : bool ) (target : nat ) (orig : list (bool )) : list (bool ):=
if nat_gteb (List.length orig) target then orig else
let filling_len := Coq.Init.Peano.minus target (List.length orig) in
(@ List.app _) orig (replicate filling_len filled).
Definition list_fill_left (filled : bool ) (target : nat ) (orig : list (bool )) : list (bool ):=
if nat_gteb (List.length orig) target then orig else
let filling_len := Coq.Init.Peano.minus target (List.length orig) in
(@ List.app _) (replicate filling_len filled) orig.
Definition word_of_bytes (lst : list (word8 )) : (Bvector 256) := word256FromBoollist
(list_fill_left false( 256%nat)
(lem_list.concat (List.map boolListFromWord8 lst))).
Definition keccak (input : list (byte )) : (Bvector 256) := word_of_bytes (keccak' input).