Local Open Scope logic.
Instance CompSpecs : compspecs.
Definition ThirtyTwoByte (q:SixteenByte * SixteenByte) (v:val) : mpred :=
match q with (q1, q2) =>
@data_at CompSpecs Tsh (Tarray tuchar 32 noattr) ((SixteenByte2ValList q1) ++ (SixteenByte2ValList q2)) v
end.
Definition QByte (q:QuadByte) (v:val) : mpred :=
data_at Tsh (Tarray tuchar 4 noattr) (QuadByte2ValList q) v.
Definition QuadChunks2ValList (l: list QuadByte) : list val :=
List.fold_right (fun q vals => QuadByte2ValList q ++ vals) nil l.
Definition flatten16 (B:SixteenByte) : list QuadByte :=
match B with (q0, q1, q2, q3) => [q0; q1; q2; q3] end.
destruct B as (((q0, q1), q2), q3). simpl.
rewrite SixteenByte2ValList_char, app_nil_r. trivial.
Qed.
destruct q as (((q0, q1), q2), q3). simpl. reflexivity. Qed.
destruct q as (((q0, q1), q2), q3). simpl. reflexivity. Qed.
destruct C as (((q0, q1), q2), q3). unfold SixteenByte2ValList.
repeat rewrite Zlength_map.  simpl.
repeat rewrite Zlength_app. repeat rewrite <- QuadByteByteList_ZLength.
reflexivity. Qed.
Definition SByte (q:SixteenByte) (v:val) : mpred :=
@data_at CompSpecs Tsh (Tarray tuchar 16 noattr) (SixteenByte2ValList q) v.
Definition QBytes (l:list QuadByte) (v:val) : mpred :=
data_at Tsh (Tarray tuchar (4*Zlength l) noattr) (QuadChunks2ValList l) v.
Definition QuadWordRep (q:QuadWord):list val :=
match q with (q0, q1, q2, q3) => map Vint [q0;q1;q2;q3] end.
Definition SixteenWordRep (w:SixteenWord):list val :=
match w with (q0, q1, q2, q3) => QuadWordRep q0 ++ QuadWordRep q1 ++ QuadWordRep q2 ++ QuadWordRep q3 end.
Definition littleendian_of_SixteenByte (x:SixteenByte): QuadWord :=
match x with (q0, q1, q2, q3) => (littleendian q0, littleendian q1, littleendian q2, littleendian q3) end.
destruct q as [[[? ?] ?] ?]. simpl. reflexivity. Qed.
rewrite Zlength_correct, QuadWR_length. trivial. Qed.
destruct s as [[[? ?] ?] ?]. simpl.
repeat rewrite app_length. repeat rewrite  QuadWR_length. reflexivity. Qed.
rewrite Zlength_correct, SixteenWR_length. trivial. Qed.
intros. destruct q as [[[? ?] ?] ?]. simpl.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity. omega. Qed.
intros. destruct s as [[[? ?] ?] ?]. simpl.
destruct q as [[[? ?] ?] ?]. destruct q0 as [[[? ?] ?] ?].
destruct q1 as [[[? ?] ?] ?]. destruct q2 as [[[? ?] ?] ?]. simpl.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity.
destruct i. eexists; reflexivity. omega.
Qed.
Definition QuadWordRepI (q : QuadWord) :=
match q with (q0, q1, q2, q3) => [q0; q1; q2; q3] end.
Fixpoint upd_upto (x: SixteenByte * SixteenByte * (SixteenByte * SixteenByte)) i (l:list val):list val :=
match i with
O => l
| S n =>
match x with (Nonce, C, (Key1, Key2)) =>
((upd_Znth (11 + (Z.of_nat n))
(upd_Znth(6 + (Z.of_nat n))
(upd_Znth (1 + (Z.of_nat n))
(upd_Znth (5 * (Z.of_nat n)) (upd_upto x n l)
(Vint (littleendian (Select16Q C (Z.of_nat n)))))
(Vint (littleendian (Select16Q Key1 (Z.of_nat n)))))
(Vint (littleendian (Select16Q Nonce (Z.of_nat n)))))
(Vint (littleendian (Select16Q Key2 (Z.of_nat n))))))
end
end.
reflexivity. Qed.

(*cf xsalsa-paper, beginning of Section 2*)
Lemma upd_upto_char data l: Zlength l = 16 ->
upd_upto data 4 l = match data with ((Nonce, C), (Key1, Key2)) =>
match Nonce with (N1, N2, N3, N4) =>
match C with (C1, C2, C3, C4) =>
match Key1 with (K1, K2, K3, K4) =>
match Key2 with (L1, L2, L3, L4) =>
map Vint (map littleendian [C1; K1; K2; K3;
K4; C2; N1; N2;
N3; N4; C3; L1;
L2; L3; L4; C4]) end end end end end.