Local Open Scope logic.
Definition i_8_16_inv F x z c b m nonce k zbytes gv: environ -> mpred :=
EX i:_,
(PROP  ()
LOCAL  (temp _u (Vint (fst (ZZ zbytes (Z.to_nat (i-8)))));
lvar _x (Tarray tuchar 64 noattr) x;
lvar _z (Tarray tuchar 16 noattr) z; temp _c c; temp _m m;
temp _b b; temp _n nonce; temp _k k; gvars gv)
SEP  (F; data_at Tsh (Tarray tuchar 16 noattr) (Bl2VL (snd (ZZ zbytes (Z.to_nat (i-8))))) z)).
Definition for_loop_statement:=
Sfor (Sset _i (Econst_int (Int.repr 8) tint))
(Ebinop Olt (Etempvar _i tuint) (Econst_int (Int.repr 16) tint) tint)
(Ssequence
(Ssequence
(Sset _t'5
(Ederef
(Ebinop Oadd (Evar _z (tarray tuchar 16))
(Etempvar _i tuint) (tptr tuchar)) tuchar))
(Sset _u
(Ebinop Oadd (Etempvar _u tuint)
(Ecast (Etempvar _t'5 tuchar) tuint) tuint)))
(Ssequence
(Sassign
(Ederef
(Ebinop Oadd (Evar _z (tarray tuchar 16))
(Etempvar _i tuint) (tptr tuchar)) tuchar)
(Etempvar _u tuint))
(Sset _u
(Ebinop Oshr (Etempvar _u tuint) (Econst_int (Int.repr 8) tint)
tuint))))
(Sset _i
(Ebinop Oadd (Etempvar _i tuint) (Econst_int (Int.repr 1) tint) tuint)).
Definition null_or_offset x q y :=
match x with
Vint i => i=Int.zero /\ y=nullval
| Vptr _ _ => y=offset_val q x
| _ => False
end.
Definition byte_at x i mbytes :=
match x with
Vint _ => Byte.zero
| _ => Znth i mbytes
end.
Definition loop1_statement:=
Sfor (Sset _i (Econst_int (Int.repr 0) tint))
(Ebinop Olt (Etempvar _i tuint) (Econst_int (Int.repr 64) tint) tint)
(Ssequence
(Sifthenelse (Etempvar _m (tptr tuchar))
(Ssequence
(Sset _t'7
(Ederef
(Ebinop Oadd (Etempvar _m (tptr tuchar))
(Etempvar _i tuint) (tptr tuchar)) tuchar))
(Sset _t'1 (Ecast (Etempvar _t'7 tuchar) tint)))
(Sset _t'1 (Ecast (Econst_int (Int.repr 0) tint) tint)))
(Ssequence
(Sset _t'6
(Ederef
(Ebinop Oadd (Evar _x (tarray tuchar 64))
(Etempvar _i tuint) (tptr tuchar)) tuchar))
(Sassign
(Ederef
(Ebinop Oadd (Etempvar _c (tptr tuchar)) (Etempvar _i tuint)
(tptr tuchar)) tuchar)
(Ebinop Oxor (Etempvar _t'1 tint) (Etempvar _t'6 tuchar) tint))))
(Sset _i
(Ebinop Oadd (Etempvar _i tuint) (Econst_int (Int.repr 1) tint) tuint)).
Definition loop2Inv F x z c mInit m b nonce k gv q xbytes mbytes cLen: environ -> mpred:=
EX i:Z,
(PROP  ()
LOCAL  (lvar _x (Tarray tuchar 64 noattr) x;
lvar _z (Tarray tuchar 16 noattr) z; temp _c c; temp _m m;
temp _b b; temp _n nonce;
temp _k k; gvars gv)
SEP (F;
data_at Tsh (tarray tuchar 64)
(map Vint (map Int.repr (map Byte.unsigned xbytes))) x;
message_at mbytes mInit;
EX l:_,!!(bxorlist (bytes_at mInit q i mbytes)
(sublist 0 i xbytes)
= Some l)
&& data_at Tsh (Tarray tuchar cLen noattr)
(Bl2VL l ++ list_repeat (Z.to_nat (cLen - i)) Vundef) c)).
Definition loop2_statement:=
Sfor (Sset _i (Econst_int (Int.repr 0) tint))
(Ebinop Olt (Etempvar _i tuint) (Etempvar _b tulong) tint)
(Ssequence
(Sifthenelse (Etempvar _m (tptr tuchar))
(Ssequence
(Sset _t'4
(Ederef
(Ebinop Oadd (Etempvar _m (tptr tuchar))
(Etempvar _i tuint) (tptr tuchar)) tuchar))
(Sset _t'2 (Ecast (Etempvar _t'4 tuchar) tint)))
(Sset _t'2 (Ecast (Econst_int (Int.repr 0) tint) tint)))
(Ssequence
(Sset _t'3
(Ederef
(Ebinop Oadd (Evar _x (tarray tuchar 64))
(Etempvar _i tuint) (tptr tuchar)) tuchar))
(Sassign
(Ederef
(Ebinop Oadd (Etempvar _c (tptr tuchar)) (Etempvar _i tuint)
(tptr tuchar)) tuchar)
(Ebinop Oxor (Etempvar _t'2 tint) (Etempvar _t'3 tuchar) tint))))
(Sset _i
(Ebinop Oadd (Etempvar _i tuint) (Econst_int (Int.repr 1) tint) tuint)).

Lemma loop2 Espec F x z c mInit m b nonce k xbytes mbytes gv
q (M: null_or_offset mInit q m) (Q: 0 <= q) (QB: q+Int64.unsigned b = Zlength mbytes) (*(CL: 64 > cLen) *) (*should be b <= cLen or so?*)
(B: Int64.unsigned b < 64):
@semax CompSpecs Espec
(func_tycontext f_crypto_stream_salsa20_tweet_xor SalsaVarSpecs SalsaFunSpecs nil)
(PROP  ()
LOCAL  (lvar _x (Tarray tuchar 64 noattr) x;
lvar _z (Tarray tuchar 16 noattr) z; temp _c c; temp _m m;
temp _b (Vlong b); temp _n nonce;
temp _k k; gvars gv)
SEP  (F; data_at Tsh (tarray tuchar 64)
(map Vint (map Int.repr (map Byte.unsigned xbytes))) x;
data_at_ Tsh (Tarray tuchar (Int64.unsigned b) noattr) c;
message_at mbytes mInit))
loop2_statement
(normal_ret_assert
( PROP  ()
LOCAL  ((*temp _i (Vlong b); *) lvar _x (Tarray tuchar 64 noattr) x;
lvar _z (Tarray tuchar 16 noattr) z; temp _c c; temp _m m; temp _b (Vlong b);
temp _n nonce; temp _k k; gvars gv)
SEP  (F;
data_at Tsh (tarray tuchar 64)
(map Vint (map Int.repr (map Byte.unsigned xbytes))) x;
message_at mbytes mInit;
EX  l : list byte,
!!(bxorlist (bytes_at mInit q (Int64.unsigned b) mbytes) (sublist 0 (Int64.unsigned b) xbytes) = Some l) &&
data_at Tsh (Tarray tuchar (Int64.unsigned b) noattr) (Bl2VL l) c))).