(* Lennart Beringer, June 2015*)
(*This is a formalization in Gallina of Dan Bernstein's document "Salsa20 specification" (version 2005.04.27), Sections 1 - 9.*)
Definition map4 {A B} (f:A -> B) a :=
match a with (a0, a1, a2, a3) => (f a0, f a1, f a2, f a3) end.
Definition bytelist2Z (l:list byte) : Z :=
match l with
[a; b; c; d] => Byte.unsigned d + Byte.unsigned c * 2^8 + Byte.unsigned b * 2^16 + Byte.unsigned a * 2^24
| _ => 0 end.
Definition hexstring_to_Z s := bytelist2Z (hexstring_to_bytelist s).
Goal Zmod (hexstring_to_Z "c0a8787e"%string +
hexstring_to_Z "9fd1161d"%string) (2^32)  =
hexstring_to_Z "60798e9b"%string.
reflexivity. Qed.
(*Explicit definition of sum following Bernstein's "Salsa20 specification" paper:*)
Definition sum (a b:int): int :=
Int.repr (Zmod (Int.unsigned a + Int.unsigned b) (2^32)).
unfold sum. rewrite Int.unsigned_zero.
rewrite Z.add_0_r. rewrite <- Int.unsigned_repr_eq.
rewrite Int.repr_unsigned.
apply Int.repr_unsigned.
Qed.
unfold sum. rewrite Z.add_comm. trivial. Qed.
rewrite sum_sym. apply sum_zero_r. Qed.
(*We're using sum in the following because it appears to compute more nicely.*)
(*hexstring_to_int*)
Definition x2i s : int := Int.repr (hexstring_to_Z s).
Goal sum (x2i "c0a8787e"%string)
(x2i "9fd1161d"%string) =
x2i "60798e9b"%string.
reflexivity. Qed.
Goal Int.xor (x2i "c0a8787e"%string)
(x2i "9fd1161d"%string) =
x2i "5f796e63"%string.
reflexivity. Qed.
Definition QuadWord:Type := (int * int * int * int)%type.
Definition quarterround (y:QuadWord): QuadWord :=
match y with (y0, y1, y2, y3) =>
let z1 := Int.xor y1 (Int.rol (sum y0 y3) (Int.repr 7)) in
let z2 := Int.xor y2 (Int.rol (sum y0 z1) (Int.repr 9)) in
let z3 := Int.xor y3 (Int.rol (sum z1 z2) (Int.repr 13)) in
let z0 := Int.xor y0 (Int.rol (sum z2 z3) (Int.repr 18))
in (z0, z1, z2, z3)
end.
Definition quarterround_old (y:QuadWord): QuadWord :=
match y with (y0, y1, y2, y3) =>
let z1 := Int.xor y1 (Int.rol (sum y0 y3) (Int.repr 7)) in
let z2 := Int.xor y2 (Int.rol (sum z1 y0) (Int.repr 9)) in
let z3 := Int.xor y3 (Int.rol (sum z2 z1) (Int.repr 13)) in
let z0 := Int.xor y0 (Int.rol (sum z3 z2) (Int.repr 18))
in (z0, z1, z2, z3)
end.

Lemma QR y: quarterround y = quarterround_old y.