Definition crypto_core_salsa20_spec :=
DECLARE _crypto_core_salsa20_tweet
WITH c : val, k:val,
nonce:val, out:val,
data : SixteenByte * SixteenByte * (SixteenByte * SixteenByte)
PRE [ _out OF tptr tuchar,
_in OF tptr tuchar,
_k OF tptr tuchar,
_c OF tptr tuchar ]
PROP ()
LOCAL (temp _in nonce; temp _out out;
temp _c c; temp _k k)
SEP ( CoreInSEP data (nonce, c, k);
data_at_ Tsh (tarray tuchar 64) out)
POST [ tint ]
EX res:_,
PROP (Snuffle20 (prepare_data data) = Some res)
LOCAL (temp ret_temp (Vint (Int.repr 0)))
SEP (CoreInSEP data (nonce, c, k);
data_at Tsh (tarray tuchar 64) (QuadChunks2ValList (map littleendian_invert res)) out).
Definition hSalsaOut x :=
QuadByte2ValList (littleendian_invert (Znth 0  x)) ++
QuadByte2ValList (littleendian_invert (Znth 5  x)) ++
QuadByte2ValList (littleendian_invert (Znth 10 x)) ++
QuadByte2ValList (littleendian_invert (Znth 15 x)) ++
QuadByte2ValList (littleendian_invert (Znth 6  x)) ++
QuadByte2ValList (littleendian_invert (Znth 7  x)) ++
QuadByte2ValList (littleendian_invert (Znth 8  x)) ++
QuadByte2ValList (littleendian_invert (Znth 9  x)).
Definition crypto_core_hsalsa20_spec :=
DECLARE _crypto_core_hsalsa20_tweet
WITH c : val, k:val,
nonce:val, out:val, OUT: list val,
data : SixteenByte * SixteenByte * (SixteenByte * SixteenByte)
PRE [ _out OF tptr tuchar,
_in OF tptr tuchar,
_k OF tptr tuchar,
_c OF tptr tuchar ]
PROP ()
LOCAL (temp _in nonce; temp _out out;
temp _c c; temp _k k)
SEP (CoreInSEP data (nonce, c, k);
data_at Tsh (tarray tuchar 32) OUT out)
POST [ tint ]
EX res:list int,
PROP (Snuffle 20 (prepare_data data) = Some res)
LOCAL (temp ret_temp (Vint (Int.repr 0)))
SEP (CoreInSEP data (nonce, c, k); data_at Tsh (tarray tuchar 32) (hSalsaOut res) out).
Parameter SIGMA: SixteenByte.
Definition Sigma_vector : val -> mpred :=
data_at Tsh (tarray tuchar 16) (SixteenByte2ValList SIGMA).
Fixpoint ZZ (zbytes: list byte) (n: nat): int * list byte :=
match n with
O => (Int.one, zbytes)
| S k => match ZZ zbytes k with (u,zb) =>
let v := (Int.unsigned u + (Byte.unsigned (Znth (Z.of_nat k+8) zb)))
in (Int.shru (Int.repr v) (Int.repr 8),
upd_Znth (Z.of_nat k+8) zb (Byte.repr (Z.modulo v 256))) end
end.
Fixpoint ZCont (r: nat) (zcont: list byte): list byte :=
match r with
O => zcont
| S n => let zb := ZCont n zcont in
let zz := ZZ zb (8:nat) in snd zz
end.

(* Specifications: *)
Lemma ZCont0 bytes: ZCont O bytes = bytes. reflexivity. Qed.
Lemma ZContS bytes n: ZCont (S n) bytes = snd (ZZ (ZCont n bytes) 8). reflexivity. Qed.
Definition bytes_at x q i mbytes :=
match x with
Vint _ => list_repeat (Z.to_nat i) (Byte.zero)
| _ => sublist q (q+i) mbytes
end.
Lemma Zlength_bytes_at x q i mbytes : 0<=q -> 0 <= i ->
q + i <= Zlength mbytes -> Zlength (bytes_at x q i mbytes) = i.