https://github.com/project-everest/hacl-star
Tip revision: 37b8a39e2ffd970444f7864cc1b32da48ac8111c authored by Tahina Ramananandro on 14 June 2018, 22:31:20 UTC
Remove all proof annotations about modifies
Remove all proof annotations about modifies
Tip revision: 37b8a39
Hacl.Impl.SHA2_512.fst
module Hacl.Impl.SHA2_512
open FStar.Mul
open FStar.Ghost
open FStar.HyperStack
open FStar.HyperStack.All
open FStar.HyperStack.ST
open FStar.Buffer
open C.Loops
open Hacl.Spec.Endianness
open Hacl.Cast
open Hacl.UInt8
open Hacl.UInt32
open FStar.UInt32
open Hacl.Hash.Lib.Create
open Hacl.Hash.Lib.LoadStore
(* Definition of aliases for modules *)
module U8 = FStar.UInt8
module U32 = FStar.UInt32
module U64 = FStar.UInt64
module H32 = Hacl.UInt32
module H64 = Hacl.UInt64
module H128 = Hacl.UInt128
module ST = FStar.HyperStack.ST
module HS = FStar.HyperStack
module Cast = Hacl.Cast
module Spec = Spec.SHA2_512
module Lemmas = Hacl.Impl.SHA2_512.Lemmas
(* Definition of base types *)
private let uint8_t = FStar.UInt8.t
private let uint32_t = FStar.UInt32.t
private let uint64_t = FStar.UInt64.t
private let uint8_ht = Hacl.UInt8.t
private let uint32_ht = Hacl.UInt32.t
private let uint64_ht = Hacl.UInt64.t
private let uint128_ht = Hacl.UInt128.t
private let uint64_p = Buffer.buffer uint64_ht
private let uint8_p = Buffer.buffer uint8_ht
(* Definitions of aliases for functions *)
inline_for_extraction let u8_to_h8 = Cast.uint8_to_sint8
inline_for_extraction let u32_to_h32 = Cast.uint32_to_sint32
inline_for_extraction let u32_to_u64 = FStar.Int.Cast.uint32_to_uint64
inline_for_extraction let u32_to_h64 = Cast.uint32_to_sint64
inline_for_extraction let h32_to_h8 = Cast.sint32_to_sint8
inline_for_extraction let h32_to_h64 = Cast.sint32_to_sint64
inline_for_extraction let u32_to_h128 = Cast.uint32_to_sint128
inline_for_extraction let u64_to_u32 = FStar.Int.Cast.uint64_to_uint32
inline_for_extraction let u64_to_h64 = Cast.uint64_to_sint64
inline_for_extraction let u64_to_h128 = Cast.uint64_to_sint128
inline_for_extraction let h64_to_h32 = Cast.sint64_to_sint32
inline_for_extraction let h64_to_h128 = Cast.sint64_to_sint128
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 10"
//
// SHA-512
//
(* Define word size *)
inline_for_extraction let size_word = 8ul // Size of the word in bytes
(* Define algorithm parameters *)
inline_for_extraction let size_hash_w = 8ul // 8 words (Final hash output size)
inline_for_extraction let size_block_w = 16ul // 16 words (Working data block size)
inline_for_extraction let size_hash = size_word *^ size_hash_w
inline_for_extraction let size_block = size_word *^ size_block_w
(* Sizes of objects in the state *)
inline_for_extraction let size_k_w = 80ul // 80 words of 64 bits (size_block)
inline_for_extraction let size_ws_w = size_k_w
inline_for_extraction let size_whash_w = size_hash_w
inline_for_extraction let size_count_w = 1ul // 1 word
inline_for_extraction let size_len_8 = 2ul *^ size_word
inline_for_extraction let size_state = size_k_w +^ size_ws_w +^ size_whash_w +^ size_count_w
(* Positions of objects in the state *)
inline_for_extraction let pos_k_w = 0ul
inline_for_extraction let pos_ws_w = size_k_w
inline_for_extraction let pos_whash_w = size_k_w +^ size_ws_w
inline_for_extraction let pos_count_w = size_k_w +^ size_ws_w +^ size_whash_w
[@"substitute"]
let rotate_right64 (a:uint64_ht) (b:uint32_t{0 < v b && v b < 64}) : Tot uint64_ht =
H64.logor (H64.shift_right a b) (H64.shift_left a (U32.sub 64ul b))
[@"substitute"]
private val _Ch: x:uint64_ht -> y:uint64_ht -> z:uint64_ht -> Tot uint64_ht
[@"substitute"]
let _Ch x y z = H64.logxor (H64.logand x y) (H64.logand (H64.lognot x) z)
[@"substitute"]
private val _Maj: x:uint64_ht -> y:uint64_ht -> z:uint64_ht -> Tot uint64_ht
[@"substitute"]
let _Maj x y z = H64.logxor (H64.logand x y) (H64.logxor (H64.logand x z) (H64.logand y z))
[@"substitute"]
private val _Sigma0: x:uint64_ht -> Tot uint64_ht
[@"substitute"]
let _Sigma0 x = H64.logxor (rotate_right64 x 28ul) (H64.logxor (rotate_right64 x 34ul) (rotate_right64 x 39ul))
[@"substitute"]
private val _Sigma1: x:uint64_ht -> Tot uint64_ht
[@"substitute"]
let _Sigma1 x = H64.logxor (rotate_right64 x 14ul) (H64.logxor (rotate_right64 x 18ul) (rotate_right64 x 41ul))
[@"substitute"]
private val _sigma0: x:uint64_ht -> Tot uint64_ht
[@"substitute"]
let _sigma0 x = H64.logxor (rotate_right64 x 1ul) (H64.logxor (rotate_right64 x 8ul) (H64.shift_right x 7ul))
[@"substitute"]
private val _sigma1: x:uint64_ht -> Tot uint64_ht
[@"substitute"]
let _sigma1 x = H64.logxor (rotate_right64 x 19ul) (H64.logxor (rotate_right64 x 61ul) (H64.shift_right x 6ul))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 10"
[@"substitute"]
private val constants_set_k:
k:uint64_p{length k = v size_k_w} ->
Stack unit
(requires (fun h -> live h k))
(ensures (fun h0 _ h1 -> live h1 k /\ modifies_1 k h0 h1
/\ (let seq_k = Hacl.Spec.Endianness.reveal_h64s (as_seq h1 k) in
seq_k == Spec.k)))
[@"substitute"]
let constants_set_k k = hupd64_80 k
(u64_to_h64 0x428a2f98d728ae22uL) (u64_to_h64 0x7137449123ef65cduL)
(u64_to_h64 0xb5c0fbcfec4d3b2fuL) (u64_to_h64 0xe9b5dba58189dbbcuL)
(u64_to_h64 0x3956c25bf348b538uL) (u64_to_h64 0x59f111f1b605d019uL)
(u64_to_h64 0x923f82a4af194f9buL) (u64_to_h64 0xab1c5ed5da6d8118uL)
(u64_to_h64 0xd807aa98a3030242uL) (u64_to_h64 0x12835b0145706fbeuL)
(u64_to_h64 0x243185be4ee4b28cuL) (u64_to_h64 0x550c7dc3d5ffb4e2uL)
(u64_to_h64 0x72be5d74f27b896fuL) (u64_to_h64 0x80deb1fe3b1696b1uL)
(u64_to_h64 0x9bdc06a725c71235uL) (u64_to_h64 0xc19bf174cf692694uL)
(u64_to_h64 0xe49b69c19ef14ad2uL) (u64_to_h64 0xefbe4786384f25e3uL)
(u64_to_h64 0x0fc19dc68b8cd5b5uL) (u64_to_h64 0x240ca1cc77ac9c65uL)
(u64_to_h64 0x2de92c6f592b0275uL) (u64_to_h64 0x4a7484aa6ea6e483uL)
(u64_to_h64 0x5cb0a9dcbd41fbd4uL) (u64_to_h64 0x76f988da831153b5uL)
(u64_to_h64 0x983e5152ee66dfabuL) (u64_to_h64 0xa831c66d2db43210uL)
(u64_to_h64 0xb00327c898fb213fuL) (u64_to_h64 0xbf597fc7beef0ee4uL)
(u64_to_h64 0xc6e00bf33da88fc2uL) (u64_to_h64 0xd5a79147930aa725uL)
(u64_to_h64 0x06ca6351e003826fuL) (u64_to_h64 0x142929670a0e6e70uL)
(u64_to_h64 0x27b70a8546d22ffcuL) (u64_to_h64 0x2e1b21385c26c926uL)
(u64_to_h64 0x4d2c6dfc5ac42aeduL) (u64_to_h64 0x53380d139d95b3dfuL)
(u64_to_h64 0x650a73548baf63deuL) (u64_to_h64 0x766a0abb3c77b2a8uL)
(u64_to_h64 0x81c2c92e47edaee6uL) (u64_to_h64 0x92722c851482353buL)
(u64_to_h64 0xa2bfe8a14cf10364uL) (u64_to_h64 0xa81a664bbc423001uL)
(u64_to_h64 0xc24b8b70d0f89791uL) (u64_to_h64 0xc76c51a30654be30uL)
(u64_to_h64 0xd192e819d6ef5218uL) (u64_to_h64 0xd69906245565a910uL)
(u64_to_h64 0xf40e35855771202auL) (u64_to_h64 0x106aa07032bbd1b8uL)
(u64_to_h64 0x19a4c116b8d2d0c8uL) (u64_to_h64 0x1e376c085141ab53uL)
(u64_to_h64 0x2748774cdf8eeb99uL) (u64_to_h64 0x34b0bcb5e19b48a8uL)
(u64_to_h64 0x391c0cb3c5c95a63uL) (u64_to_h64 0x4ed8aa4ae3418acbuL)
(u64_to_h64 0x5b9cca4f7763e373uL) (u64_to_h64 0x682e6ff3d6b2b8a3uL)
(u64_to_h64 0x748f82ee5defb2fcuL) (u64_to_h64 0x78a5636f43172f60uL)
(u64_to_h64 0x84c87814a1f0ab72uL) (u64_to_h64 0x8cc702081a6439ecuL)
(u64_to_h64 0x90befffa23631e28uL) (u64_to_h64 0xa4506cebde82bde9uL)
(u64_to_h64 0xbef9a3f7b2c67915uL) (u64_to_h64 0xc67178f2e372532buL)
(u64_to_h64 0xca273eceea26619cuL) (u64_to_h64 0xd186b8c721c0c207uL)
(u64_to_h64 0xeada7dd6cde0eb1euL) (u64_to_h64 0xf57d4f7fee6ed178uL)
(u64_to_h64 0x06f067aa72176fbauL) (u64_to_h64 0x0a637dc5a2c898a6uL)
(u64_to_h64 0x113f9804bef90daeuL) (u64_to_h64 0x1b710b35131c471buL)
(u64_to_h64 0x28db77f523047d84uL) (u64_to_h64 0x32caab7b40c72493uL)
(u64_to_h64 0x3c9ebe0a15c9bebcuL) (u64_to_h64 0x431d67c49c100d4cuL)
(u64_to_h64 0x4cc5d4becb3e42b6uL) (u64_to_h64 0x597f299cfc657e2auL)
(u64_to_h64 0x5fcb6fab3ad6faecuL) (u64_to_h64 0x6c44198c4a475817uL)
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 10"
[@"substitute"]
val constants_set_h_0:
hash:uint64_p{length hash = v size_hash_w} ->
Stack unit
(requires (fun h -> live h hash))
(ensures (fun h0 _ h1 -> live h1 hash /\ modifies_1 hash h0 h1
/\ (let seq_h_0 = Hacl.Spec.Endianness.reveal_h64s (as_seq h1 hash) in
seq_h_0 == Spec.h_0)))
[@"substitute"]
let constants_set_h_0 hash = hupd64_8 hash
(u64_to_h64 0x6a09e667f3bcc908uL) (u64_to_h64 0xbb67ae8584caa73buL)
(u64_to_h64 0x3c6ef372fe94f82buL) (u64_to_h64 0xa54ff53a5f1d36f1uL)
(u64_to_h64 0x510e527fade682d1uL) (u64_to_h64 0x9b05688c2b3e6c1fuL)
(u64_to_h64 0x1f83d9abfb41bd6buL) (u64_to_h64 0x5be0cd19137e2179uL)
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 20"
[@ Substitute]
private
val ws_part_1_core:
ws_w :uint64_p {length ws_w = v size_ws_w} ->
block_w :uint64_p {length block_w = v size_block_w /\ disjoint ws_w block_w} ->
i:UInt32.t{UInt32.v i < 16} ->
Stack unit
(requires (fun h -> live h ws_w /\ live h block_w
/\ (let seq_ws = reveal_h64s (as_seq h ws_w) in
let seq_block = reveal_h64s (as_seq h block_w) in
(forall (j:nat). {:pattern (Seq.index seq_ws j)} j < UInt32.v i ==> Seq.index seq_ws j == Spec.ws seq_block j))))
(ensures (fun h0 r h1 -> live h1 ws_w /\ live h0 ws_w
/\ live h1 block_w /\ live h0 block_w /\ modifies_1 ws_w h0 h1 /\
as_seq h1 block_w == as_seq h0 block_w
/\ (let w = reveal_h64s (as_seq h1 ws_w) in
let b = reveal_h64s (as_seq h0 block_w) in
(forall (j:nat). {:pattern (Seq.index w j)} j < UInt32.v i+1 ==> Seq.index w j == Spec.ws b j))))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 100"
[@ Substitute]
let ws_part_1_core ws_w block_w t =
(**) let h0 = ST.get() in
(**) let h = ST.get() in
let b = block_w.(t) in
ws_w.(t) <- b;
(**) let h1 = ST.get() in
(**) let h' = ST.get() in
(**) no_upd_lemma_1 h0 h1 ws_w block_w;
(**) Lemmas.lemma_spec_ws_def (reveal_h64s (as_seq h block_w)) (UInt32.v t);
(**) assert(Seq.index (reveal_h64s (as_seq h1 ws_w)) (UInt32.v t) == Seq.index (reveal_h64s(as_seq h block_w)) (UInt32.v t))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 500"
[@"substitute"]
private val ws_part_1:
ws_w :uint64_p {length ws_w = v size_ws_w} ->
block_w :uint64_p {length block_w = v size_block_w /\ disjoint ws_w block_w} ->
Stack unit
(requires (fun h -> live h ws_w /\ live h block_w))
(ensures (fun h0 r h1 -> live h1 ws_w /\ live h0 ws_w
/\ live h1 block_w /\ live h0 block_w /\ modifies_1 ws_w h0 h1
/\ (let w = reveal_h64s (as_seq h1 ws_w) in
let b = reveal_h64s (as_seq h0 block_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 16 ==> Seq.index w i == Spec.ws b i))))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 200"
[@"substitute"]
let ws_part_1 ws_w block_w =
(**) let h0 = ST.get() in
let inv (h1: HS.mem) (i: nat) : Type0 =
i <= 16 /\ live h1 ws_w /\ live h1 block_w /\ modifies_1 ws_w h0 h1 /\
as_seq h1 block_w == as_seq h0 block_w
/\ (let seq_block = reveal_h64s (as_seq h0 block_w) in
let w = reveal_h64s (as_seq h1 ws_w) in
(forall (j:nat). {:pattern (Seq.index w j)} j < i ==> Seq.index w j == Spec.ws seq_block j))
in
let f' (t:uint32_t {v t < 16}) :
Stack unit
(requires (fun h -> inv h (UInt32.v t)))
(ensures (fun h_1 _ h_2 -> inv h_2 (UInt32.v t + 1)))
=
ws_part_1_core ws_w block_w t
in
(**) Lemmas.lemma_modifies_0_is_modifies_1 h0 ws_w;
for 0ul 16ul inv f';
(**) let h1 = ST.get() in ()
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 20"
[@ Substitute]
private
val ws_part_2_core:
ws_w :uint64_p {length ws_w = v size_ws_w} ->
block_w :uint64_p {length block_w = v size_block_w /\ disjoint ws_w block_w} ->
i:UInt32.t{16 <= UInt32.v i /\ UInt32.v i < 80} ->
Stack unit
(requires (fun h -> live h ws_w /\ live h block_w /\
(let w = reveal_h64s (as_seq h ws_w) in
let b = reveal_h64s (as_seq h block_w) in
(forall (j:nat). {:pattern (Seq.index w j)} j < UInt32.v i ==> Seq.index w j == Spec.ws b j))))
(ensures (fun h0 r h1 -> live h1 ws_w /\ live h0 ws_w
/\ live h1 block_w /\ live h0 block_w /\ modifies_1 ws_w h0 h1 /\
reveal_h64s (as_seq h1 block_w) == reveal_h64s (as_seq h0 block_w)
/\ (let w = reveal_h64s (as_seq h1 ws_w) in
let b = reveal_h64s (as_seq h0 block_w) in
(forall (j:nat). {:pattern (Seq.index w j)} j < UInt32.v i+1 ==> Seq.index w j == Spec.ws b j))))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 100"
[@ Substitute]
let ws_part_2_core ws_w block_w t =
(**) let h0 = ST.get () in
let t16 = ws_w.(t -^ 16ul) in
let t15 = ws_w.(t -^ 15ul) in
let t7 = ws_w.(t -^ 7ul) in
let t2 = ws_w.(t -^ 2ul) in
ws_w.(t) <- H64.((_sigma1 t2) +%^ (t7 +%^ ((_sigma0 t15) +%^ t16)));
(**) let h1 = ST.get () in
(**) no_upd_lemma_1 h0 h1 ws_w block_w;
(**) Lemmas.lemma_spec_ws_def2 (reveal_h64s (as_seq h0 block_w)) (UInt32.v t);
(**) assert(Seq.index (reveal_h64s (as_seq h1 ws_w)) (UInt32.v t) == Spec.ws (reveal_h64s (as_seq h0 block_w)) (UInt32.v t))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
private val ws_part_2:
ws_w :uint64_p {length ws_w = v size_ws_w} ->
block_w :uint64_p {length block_w = v size_block_w /\ disjoint ws_w block_w} ->
Stack unit
(requires (fun h -> live h ws_w /\ live h block_w
/\ (let w = reveal_h64s (as_seq h ws_w) in
let b = reveal_h64s (as_seq h block_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 16 ==> Seq.index w i == Spec.ws b i))))
(ensures (fun h0 r h1 -> live h1 ws_w /\ live h0 ws_w
/\ live h1 block_w /\ live h0 block_w /\ modifies_1 ws_w h0 h1
/\ (let w = reveal_h64s (as_seq h1 ws_w) in
let b = reveal_h64s (as_seq h0 block_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 80 ==> Seq.index w i == Spec.ws b i))))
#reset-options " --z3refresh --max_fuel 0 --z3rlimit 200"
[@"substitute"]
let ws_part_2 ws_w block_w =
(**) let h0 = ST.get() in
let inv (h1: HS.mem) (i: nat) : Type0 =
live h1 ws_w /\ live h1 block_w /\ modifies_1 ws_w h0 h1 /\ 16 <= i /\ i <= 80
/\ reveal_h64s (as_seq h1 block_w) == reveal_h64s (as_seq h0 block_w)
/\ (let seq_block = reveal_h64s (as_seq h0 block_w) in
let w = reveal_h64s (as_seq h1 ws_w) in
(forall (j:nat). {:pattern (Seq.index w j)} j < i ==> Seq.index w j == Spec.ws seq_block j))
in
let f' (t:uint32_t {16 <= v t /\ v t < v size_ws_w}) :
Stack unit
(requires (fun h -> inv h (UInt32.v t)))
(ensures (fun h_1 _ h_2 -> inv h_2 (UInt32.v t + 1)))
=
ws_part_2_core ws_w block_w t
in
(**) Lemmas.lemma_modifies_0_is_modifies_1 h0 ws_w;
for 16ul 80ul inv f';
(**) let h1 = ST.get() in ()
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
private val ws:
ws_w :uint64_p {length ws_w = v size_ws_w} ->
block_w :uint64_p {length block_w = v size_block_w /\ disjoint ws_w block_w} ->
Stack unit
(requires (fun h -> live h ws_w /\ live h block_w))
(ensures (fun h0 r h1 -> live h1 ws_w /\ live h0 ws_w
/\ live h1 block_w /\ live h0 block_w /\ modifies_1 ws_w h0 h1
/\ (let w = reveal_h64s (as_seq h1 ws_w) in
let b = reveal_h64s (as_seq h0 block_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 80 ==> Seq.index w i == Spec.ws b i))))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
[@"substitute"]
let ws ws_w block_w =
ws_part_1 ws_w block_w;
ws_part_2 ws_w block_w
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
private val shuffle_core:
hash_w :uint64_p {length hash_w = v size_hash_w} ->
block_w:uint64_p {length block_w = v size_block_w} ->
ws_w :uint64_p {length ws_w = v size_ws_w} ->
k_w :uint64_p {length k_w = v size_k_w} ->
t :uint32_t {v t < v size_k_w} ->
Stack unit
(requires (fun h -> live h hash_w /\ live h ws_w /\ live h k_w /\ live h block_w /\
reveal_h64s (as_seq h k_w) == Spec.k /\
(let w = reveal_h64s (as_seq h ws_w) in
let b = reveal_h64s (as_seq h block_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 80 ==> Seq.index w i == Spec.ws b i)) ))
(ensures (fun h0 r h1 -> live h0 hash_w /\ live h0 ws_w /\ live h0 k_w /\ live h0 block_w
/\ live h1 hash_w /\ modifies_1 hash_w h0 h1
/\ (let seq_hash_0 = reveal_h64s (as_seq h0 hash_w) in
let seq_hash_1 = reveal_h64s (as_seq h1 hash_w) in
let seq_block = reveal_h64s (as_seq h0 block_w) in
seq_hash_1 == Spec.shuffle_core seq_block seq_hash_0 (U32.v t))))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 100"
[@"substitute"]
let shuffle_core hash block ws k t =
let a = hash.(0ul) in
let b = hash.(1ul) in
let c = hash.(2ul) in
let d = hash.(3ul) in
let e = hash.(4ul) in
let f = hash.(5ul) in
let g = hash.(6ul) in
let h = hash.(7ul) in
(* Perform computations *)
let k_t = k.(t) in
let ws_t = ws.(t) in
let t1 = H64.(h +%^ (_Sigma1 e) +%^ (_Ch e f g) +%^ k_t +%^ ws_t) in
let t2 = H64.((_Sigma0 a) +%^ (_Maj a b c)) in
(* Store the new working hash in the state *)
hupd64_8 hash H64.(t1 +%^ t2) a b c H64.(d +%^ t1) e f g
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
private val shuffle:
hash_w :uint64_p {length hash_w = v size_hash_w} ->
block_w:uint64_p {length block_w = v size_block_w /\ disjoint block_w hash_w} ->
ws_w :uint64_p {length ws_w = v size_ws_w /\ disjoint ws_w hash_w} ->
k_w :uint64_p {length k_w = v size_k_w /\ disjoint k_w hash_w} ->
Stack unit
(requires (fun h -> live h hash_w /\ live h ws_w /\ live h k_w /\ live h block_w /\
reveal_h64s (as_seq h k_w) == Spec.k /\
(let w = reveal_h64s (as_seq h ws_w) in
let b = reveal_h64s (as_seq h block_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 80 ==> Seq.index w i == Spec.ws b i)) ))
(ensures (fun h0 r h1 -> live h1 hash_w /\ modifies_1 hash_w h0 h1 /\ live h0 block_w
/\ live h0 hash_w
/\ (let seq_hash_0 = reveal_h64s (as_seq h0 hash_w) in
let seq_hash_1 = reveal_h64s (as_seq h1 hash_w) in
let seq_block = reveal_h64s (as_seq h0 block_w) in
seq_hash_1 == Spec.shuffle seq_hash_0 seq_block)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 100"
[@"substitute"]
let shuffle hash block ws k =
(**) let h0 = ST.get() in
let inv (h1: HS.mem) (i: nat) : Type0 =
live h1 hash /\ modifies_1 hash h0 h1 /\ i <= v size_ws_w
/\ (let seq_block = reveal_h64s (as_seq h0 block) in
reveal_h64s (as_seq h1 hash) == repeat_range_spec 0 i (Spec.shuffle_core seq_block) (reveal_h64s (as_seq h0 hash)))
in
let f' (t:uint32_t {v t < v size_ws_w}) :
Stack unit
(requires (fun h -> inv h (UInt32.v t)))
(ensures (fun h_1 _ h_2 -> inv h_2 (UInt32.v t + 1)))
=
shuffle_core hash block ws k t;
(**) C.Loops.lemma_repeat_range_spec 0 (UInt32.v t + 1) (Spec.shuffle_core (reveal_h64s (as_seq h0 block))) (reveal_h64s (as_seq h0 hash))
in
(**) C.Loops.lemma_repeat_range_0 0 0 (Spec.shuffle_core (reveal_h64s (as_seq h0 block))) (reveal_h64s (as_seq h0 hash));
for 0ul size_ws_w inv f'
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
private val sum_hash:
hash_0:uint64_p{length hash_0 = v size_hash_w} ->
hash_1:uint64_p{length hash_1 = v size_hash_w /\ disjoint hash_0 hash_1} ->
Stack unit
(requires (fun h -> live h hash_0 /\ live h hash_1))
(ensures (fun h0 _ h1 -> live h0 hash_0 /\ live h1 hash_0 /\ live h0 hash_1 /\ modifies_1 hash_0 h0 h1
/\ (let new_seq_hash_0 = reveal_h64s (as_seq h1 hash_0) in
let seq_hash_0 = reveal_h64s (as_seq h0 hash_0) in
let seq_hash_1 = reveal_h64s (as_seq h0 hash_1) in
let res = Spec.Loops.seq_map2 (fun x y -> FStar.UInt64.(x +%^ y)) seq_hash_0 seq_hash_1 in
new_seq_hash_0 == res)))
[@"substitute"]
let sum_hash hash_0 hash_1 =
(**) let h0 = ST.get() in
C.Loops.in_place_map2 hash_0 hash_1 size_hash_w (fun x y -> H64.(x +%^ y));
(**) let h1 = ST.get() in
(**) Seq.lemma_eq_intro (Spec.Loops.seq_map2 (fun x y -> FStar.UInt64.(x +%^ y)) (reveal_h64s (as_seq h0 hash_0))
(reveal_h64s (as_seq h0 hash_1))) (reveal_h64s (as_seq h1 hash_0))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"c_inline"]
val alloc:
unit ->
StackInline (state:uint64_p{length state = v size_state})
(requires (fun h0 -> True))
(ensures (fun h0 st h1 -> ~(contains h0 st) /\ live h1 st /\ modifies_0 h0 h1 /\ frameOf st == (HS.get_tip h1)
/\ Map.domain (HS.get_hmap h1) == Map.domain (HS.get_hmap h0)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"c_inline"]
let alloc () = Buffer.create (u32_to_h64 0ul) size_state
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
val init:
state:uint64_p{length state = v size_state} ->
Stack unit
(requires (fun h0 -> live h0 state))
(ensures (fun h0 r h1 -> live h1 state /\ modifies_1 state h0 h1
/\ (let slice_k = Seq.slice (as_seq h1 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let slice_h_0 = Seq.slice (as_seq h1 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_counter = Seq.slice (as_seq h1 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter = Seq.index seq_counter 0 in
let seq_k = Hacl.Spec.Endianness.reveal_h64s slice_k in
let seq_h_0 = Hacl.Spec.Endianness.reveal_h64s slice_h_0 in
seq_k == Spec.k /\ seq_h_0 == Spec.h_0 /\ H64.v counter = 0)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 100"
let init state =
let n = Buffer.sub state pos_count_w size_count_w in
let k = Buffer.sub state pos_k_w size_k_w in
let h_0 = Buffer.sub state pos_whash_w size_whash_w in
constants_set_k k;
constants_set_h_0 h_0;
Buffer.upd n 0ul 0uL
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
[@"substitute"]
private val copy_hash:
hash_w_1 :uint64_p {length hash_w_1 = v size_hash_w} ->
hash_w_2 :uint64_p {length hash_w_2 = v size_hash_w /\ disjoint hash_w_1 hash_w_2} ->
Stack unit
(requires (fun h0 -> live h0 hash_w_1 /\ live h0 hash_w_2))
(ensures (fun h0 _ h1 -> live h0 hash_w_1 /\ live h0 hash_w_2 /\ live h1 hash_w_1 /\ modifies_1 hash_w_1 h0 h1
/\ (as_seq h1 hash_w_1 == as_seq h0 hash_w_2)))
[@"substitute"]
let copy_hash hash_w_1 hash_w_2 =
(**) let h0 = ST.get () in
Buffer.blit hash_w_2 0ul hash_w_1 0ul size_hash_w;
(**) let h1 = ST.get () in
(**) assert(Seq.slice (as_seq h1 hash_w_1) 0 (v size_hash_w) == Seq.slice (as_seq h0 hash_w_2) 0 (v size_hash_w));
(**) Lemmas.lemma_blit_slices_eq h0 h1 hash_w_1 hash_w_2 (v size_hash_w)
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
private val update_core:
hash_w :uint64_p {length hash_w = v size_hash_w} ->
data :uint8_p {length data = v size_block /\ disjoint data hash_w} ->
data_w :uint64_p {length data_w = v size_block_w /\ disjoint data_w hash_w} ->
ws_w :uint64_p {length ws_w = v size_ws_w /\ disjoint ws_w hash_w} ->
k_w :uint64_p {length k_w = v size_k_w /\ disjoint k_w hash_w} ->
Stack unit
(requires (fun h0 -> live h0 hash_w /\ live h0 data /\ live h0 data_w /\ live h0 ws_w /\ live h0 k_w
/\ reveal_h64s (as_seq h0 k_w) == Spec.k
/\ (reveal_h64s (as_seq h0 data_w) = Spec.Lib.uint64s_from_be (v size_block_w) (reveal_sbytes (as_seq h0 data)))
/\ (let w = reveal_h64s (as_seq h0 ws_w) in
let b = reveal_h64s (as_seq h0 data_w) in
(forall (i:nat). {:pattern (Seq.index w i)} i < 80 ==> Seq.index w i == Spec.ws b i))))
(ensures (fun h0 r h1 ->
live h0 hash_w /\ live h0 data /\
live h0 data_w /\ live h1 hash_w /\
modifies_1 hash_w h0 h1 /\
(let seq_hash_0 = reveal_h64s (as_seq h0 hash_w) in
let seq_hash_1 = reveal_h64s (as_seq h1 hash_w) in
let seq_block = reveal_sbytes (as_seq h0 data) in
let res = Spec.update seq_hash_0 seq_block in
seq_hash_1 == res)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 400"
[@"substitute"]
let update_core hash_w data data_w ws_w k_w =
(**) assert_norm(pow2 32 = 0x100000000);
(**) assert_norm(pow2 64 = 0x10000000000000000);
(**) assert_norm(pow2 125 = 42535295865117307932921825928971026432);
(**) let h0 = ST.get() in
(* Push a new frame *)
(**) push_frame();
(**) let h1 = ST.get() in
(**) assert(let b = Spec.words_from_be Spec.size_block_w (reveal_sbytes (as_seq h0 data)) in
reveal_h64s (as_seq h0 data_w) == b);
(* Allocate space for converting the data block *)
let hash_0 = Buffer.create (u64_to_h64 0uL) size_hash_w in
(**) let h2 = ST.get() in
assert (modifies_0 h1 h2);
(* Keep track of the the current working hash from the state *)
copy_hash hash_0 hash_w;
(**) let h3 = ST.get() in
assert (modifies_1 hash_0 h2 h3);
(* Step 2 : Initialize the eight working variables *)
(* Step 3 : Perform logical operations on the working variables *)
(* Step 4 : Compute the ith intermediate hash value *)
shuffle hash_0 data_w ws_w k_w;
(**) let h4 = ST.get() in
assert (modifies_1 hash_0 h3 h4);
lemma_modifies_1_trans hash_0 h2 h3 h4;
assert (modifies_1 hash_0 h2 h4);
(**) assert(let b = Spec.words_from_be Spec.size_block_w (reveal_sbytes (as_seq h0 data)) in
let ha = Spec.shuffle (reveal_h64s (as_seq h0 hash_w)) b in
as_seq h4 hash_w == as_seq h0 hash_w /\
reveal_h64s (as_seq h4 hash_0) == ha);
(* Use the previous one to update it inplace *)
sum_hash hash_w hash_0;
(**) let h5 = ST.get() in
assert (modifies_1 hash_w h4 h5);
lemma_modifies_1_1 hash_0 hash_w h2 h4 h5;
assert (modifies_2 hash_0 hash_w h2 h5);
lemma_modifies_0_2' hash_w hash_0 h1 h2 h5;
assert (modifies_2_1 hash_w h1 h5);
(**) assert(let x = reveal_h64s (as_seq h4 hash_w) in
let y = reveal_h64s (as_seq h4 hash_0) in
x == reveal_h64s (as_seq h0 hash_w) /\
y == Spec.shuffle (reveal_h64s (as_seq h0 hash_w)) (Spec.words_from_be Spec.size_block_w (reveal_sbytes (as_seq h0 data))));
(**) assert(let x = reveal_h64s (as_seq h0 hash_w) in
let y = Spec.shuffle (reveal_h64s (as_seq h0 hash_w)) (Spec.words_from_be Spec.size_block_w (reveal_sbytes (as_seq h0 data))) in
let z = reveal_h64s (as_seq h5 hash_w) in
let z' = Spec.Loops.seq_map2 (fun x y -> FStar.UInt64.(x +%^ y)) x y in
z == z');
(* Pop the frame *)
(**) pop_frame();
let h6 = ST.get () in
modifies_popped_1 hash_w h0 h1 h5 h6
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
val counter_increment:
counter_w :uint64_p{length counter_w = v size_count_w} ->
Stack unit
(requires (fun h -> live h counter_w
/\ (let counter = Seq.index (as_seq h counter_w) 0 in
H64.v counter < (pow2 64 - 1))))
(ensures (fun h0 _ h1 -> live h1 counter_w /\ live h0 counter_w /\ modifies_1 counter_w h0 h1
/\ (let counter_0 = Seq.index (as_seq h0 counter_w) 0 in
let counter_1 = Seq.index (as_seq h1 counter_w) 0 in
H64.v counter_1 = H64.v counter_0 + 1 /\ H64.v counter_1 < pow2 64)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
[@"substitute"]
let counter_increment counter_w =
let c0 = counter_w.(0ul) in
let one = u32_to_h64 1ul in
counter_w.(0ul) <- H64.(c0 +%^ one)
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 75"
val update:
state :uint64_p {length state = v size_state} ->
data :uint8_p {length data = v size_block /\ disjoint state data} ->
Stack unit
(requires (fun h0 -> live h0 state /\ live h0 data
/\ (let seq_k = Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_counter = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter = Seq.index seq_counter 0 in
reveal_h64s seq_k == Spec.k /\ H64.v counter < (pow2 64 - 1))))
(ensures (fun h0 r h1 -> live h0 state /\ live h0 data /\ live h1 state /\ modifies_1 state h0 h1
/\ (let seq_hash_0 = Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_hash_1 = Seq.slice (as_seq h1 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_k_0 = Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_k_1 = Seq.slice (as_seq h1 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_block = as_seq h0 data in
let seq_counter_0 = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let seq_counter_1 = Seq.slice (as_seq h1 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter_0 = Seq.index seq_counter_0 0 in
let counter_1 = Seq.index seq_counter_1 0 in
seq_k_0 == seq_k_1
/\ H64.v counter_1 = H64.v counter_0 + 1 /\ H64.v counter_1 < pow2 64
/\ reveal_h64s seq_hash_1 == Spec.update (reveal_h64s seq_hash_0) (reveal_sbytes seq_block))))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 250"
let update state data =
(* Push a new frame *)
(**) let h0 = ST.get () in
(**) push_frame();
(**) let h1 = ST.get () in
(**) Lemmas.lemma_eq_state_k_sub_slice h1 state;
(**) Seq.lemma_eq_intro (Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)))
(**) (Seq.slice (as_seq h1 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)));
(**) Lemmas.lemma_eq_state_counter_sub_slice h1 state;
(**) Seq.lemma_eq_intro (Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)))
(Seq.slice (as_seq h1 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)));
(**) Lemmas.lemma_eq_state_hash_sub_slice h1 state;
(**) Seq.lemma_eq_intro (Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)))
(Seq.slice (as_seq h1 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)));
(* Allocate space for converting the data block *)
let data_w = Buffer.create (u32_to_h64 0ul) size_block_w in
(**) let h2 = ST.get () in
(**) no_upd_lemma_0 h1 h2 data;
(**) no_upd_lemma_0 h1 h2 (Buffer.sub state pos_k_w size_k_w);
(**) no_upd_lemma_0 h1 h2 (Buffer.sub state pos_whash_w size_whash_w);
(**) no_upd_lemma_0 h1 h2 (Buffer.sub state pos_count_w size_count_w);
(* Cast the data bytes into a uint32_t buffer *)
uint64s_from_be_bytes data_w data size_block_w;
(**) let h3 = ST.get () in
(**) lemma_modifies_0_1' data_w h1 h2 h3;
(**) no_upd_lemma_1 h2 h3 data_w (Buffer.sub state pos_k_w size_k_w);
(**) no_upd_lemma_1 h2 h3 data_w (Buffer.sub state pos_whash_w size_whash_w);
(**) no_upd_lemma_1 h2 h3 data_w (Buffer.sub state pos_count_w size_count_w);
(**) no_upd_lemma_1 h2 h3 data_w data;
(**) assert(reveal_h64s (as_seq h3 data_w) == Spec.Lib.uint64s_from_be (U32.v size_block_w) (reveal_sbytes (as_seq h3 data)));
(* Retreive values from the state *)
let hash_w = Buffer.sub state pos_whash_w size_whash_w in
let ws_w = Buffer.sub state pos_ws_w size_ws_w in
let k_w = Buffer.sub state pos_k_w size_k_w in
let counter_w = Buffer.sub state pos_count_w size_count_w in
(* Step 1 : Scheduling function for sixty-four 32 bit words *)
ws ws_w data_w;
(**) let h4 = ST.get () in
(**) modifies_subbuffer_1 h3 h4 ws_w state;
(**) no_upd_lemma_1 h3 h4 ws_w data;
(**) no_upd_lemma_1 h3 h4 ws_w k_w;
(**) no_upd_lemma_1 h3 h4 ws_w hash_w;
(**) no_upd_lemma_1 h3 h4 ws_w counter_w;
(* Step 2 : Initialize the eight working variables *)
(* Step 3 : Perform logical operations on the working variables *)
(* Step 4 : Compute the ith intermediate hash value *)
(**) assert(reveal_h64s (as_seq h4 k_w) == Spec.k);
update_core hash_w data data_w ws_w k_w;
(**) let h5 = ST.get () in
(**) modifies_subbuffer_1 h4 h5 hash_w state;
(**) lemma_modifies_1_trans state h3 h4 h5;
(**) no_upd_lemma_1 h4 h5 hash_w data;
(**) no_upd_lemma_1 h4 h5 hash_w k_w;
(**) no_upd_lemma_1 h4 h5 hash_w counter_w;
(**) Lemmas.lemma_eq_state_k_sub_slice h5 state;
(**) Lemmas.lemma_eq_state_counter_sub_slice h5 state;
(**) Lemmas.lemma_eq_state_hash_sub_slice h5 state;
(**) Seq.lemma_eq_intro (as_seq h1 hash_w) (as_seq h4 hash_w);
(**) Seq.lemma_eq_intro (as_seq h1 data) (as_seq h4 data);
(**) assert(reveal_h64s (as_seq h5 hash_w) == Spec.update (reveal_h64s (as_seq h0 hash_w)) (reveal_sbytes (as_seq h0 data)));
(* Increment the total number of blocks processed *)
counter_increment counter_w;
(**) let h6 = ST.get () in
(**) modifies_subbuffer_1 h5 h6 counter_w state;
(**) lemma_modifies_1_trans state h3 h5 h6;
(**) lemma_modifies_0_1 state h1 h3 h6;
(**) no_upd_lemma_1 h5 h6 counter_w data;
(**) no_upd_lemma_1 h5 h6 counter_w k_w;
(**) no_upd_lemma_1 h5 h6 counter_w hash_w;
(**) Lemmas.lemma_eq_state_k_sub_slice h6 state;
(**) Lemmas.lemma_eq_state_counter_sub_slice h6 state;
(**) Lemmas.lemma_eq_state_hash_sub_slice h6 state;
(**) assert(let seq_k_0 = Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_k_1 = Seq.slice (as_seq h6 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
seq_k_0 == seq_k_1);
(**) assert(let seq_counter_0 = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let seq_counter_1 = Seq.slice (as_seq h6 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter_0 = Seq.index seq_counter_0 0 in
let counter_1 = Seq.index seq_counter_1 0 in
H64.v counter_1 = H64.v counter_0 + 1 /\ H64.v counter_1 < pow2 64);
(**) assert(let seq_hash_0 = Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_hash_1 = Seq.slice (as_seq h6 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_block = as_seq h0 data in
reveal_h64s seq_hash_1 == Spec.update (reveal_h64s seq_hash_0) (reveal_sbytes seq_block));
(* Pop the memory frame *)
(**) pop_frame();
(**) let h7 = ST.get () in
(**) modifies_popped_1 state h0 h1 h6 h7;
(**) Seq.lemma_eq_intro (Seq.slice (as_seq h6 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)))
(Seq.slice (as_seq h7 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)));
(**) Seq.lemma_eq_intro (Seq.slice (as_seq h6 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)))
(Seq.slice (as_seq h7 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)));
(**) Seq.lemma_eq_intro (Seq.slice (as_seq h6 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)))
(Seq.slice (as_seq h7 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)))
#reset-options "--z3rlimit 200 --max_fuel 0 --max_ifuel 0"
val update_multi:
state :uint64_p{length state = v size_state} ->
data :uint8_p {length data % v size_block = 0 /\ disjoint state data} ->
n :uint32_t{v n * v size_block = length data} ->
Stack unit
(requires (fun h0 -> live h0 state /\ live h0 data /\
(let seq_k = Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_counter = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter = Seq.index seq_counter 0 in
reveal_h64s seq_k == Spec.k /\ H64.v counter < (pow2 64 - (v n)))))
(ensures (fun h0 _ h1 -> live h0 state /\ live h0 data /\ live h1 state /\ modifies_1 state h0 h1 /\
(let seq_hash0 = Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_hash1 = Seq.slice (as_seq h1 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_k0 = Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_k1 = Seq.slice (as_seq h1 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_blocks = as_seq h0 data in
let seq_counter0 = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let seq_counter1 = Seq.slice (as_seq h1 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter0 = Seq.index seq_counter0 0 in
let counter1 = Seq.index seq_counter1 0 in
seq_k0 == seq_k1 /\
H64.v counter1 = H64.v counter0 + v n /\
H64.v counter1 < pow2 64 /\
reveal_h64s seq_hash1 ==
Spec.update_multi (reveal_h64s seq_hash0) (reveal_sbytes seq_blocks) )))
let rec update_multi state data n =
let h0 = ST.get () in
let inv (h:HS.mem) (i:nat) : Type0 =
live h state /\ live h data /\ modifies_1 state h0 h /\ 0 <= i /\ i <= v n /\
(let hash0 = // Starting value
Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_counter0 =
Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter0 = Seq.index seq_counter0 0 in
let seq_hash = Seq.slice (as_seq h state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_k = Seq.slice (as_seq h state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_counter = Seq.slice (as_seq h state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter = Seq.index seq_counter 0 in
let blocks = as_seq h (Buffer.sub data 0ul (U32.uint_to_t i *^ size_block)) in
reveal_h64s seq_k == Spec.k /\
H64.v counter < pow2 64 - v n + i /\
H64.v counter = H64.v counter0 + i /\
reveal_h64s seq_hash ==
Spec.update_multi (reveal_h64s hash0) (reveal_sbytes blocks) )
in
let empty = Buffer.sub data 0ul (0ul *^ size_block) in
Spec.lemma_update_multi_empty (reveal_h64s (Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)))) (reveal_sbytes (as_seq h0 empty));
Lemmas.lemma_modifies_0_is_modifies_1 h0 state;
let f (i:uint32_t{0 <= v i /\ v i < v n}) : Stack unit
(requires (fun h -> inv h (v i)))
(ensures (fun h0 _ h1 -> inv h0 (v i) /\ inv h1 (v i + 1)))
=
let h = ST.get() in
let blocks = Buffer.sub data 0ul (i *^ size_block) in
let b = Buffer.sub data (i *^ size_block) size_block in
Spec.update_update_multi_append
(reveal_h64s (Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w))))
(reveal_sbytes (as_seq h blocks))
(reveal_sbytes (as_seq h b));
let blocks1 = Buffer.sub data 0ul ((i +^ 1ul) *^ size_block) in
Seq.lemma_eq_intro (Seq.append (as_seq h blocks) (as_seq h b)) (as_seq h blocks1);
lemma_disjoint_sub data b state;
lemma_disjoint_sub data blocks state;
lemma_disjoint_sub data blocks1 state;
update state b
in
for 0ul n inv f
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
inline_for_extraction
val pad0_length: (len:uint32_t{v len + 1 + v size_len_8 <= 2 * v size_block}) ->
Tot (n:uint32_t{v n = Spec.pad0_length (v len)})
let pad0_length len =
(size_block +^ size_block -^ (len +^ size_len_8 +^ 1ul)) %^ size_block
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
inline_for_extraction
let encode_length (count:uint32_ht) (len:uint32_t{v count * v size_block + v len < Spec.max_input_len_8}) : Tot (l:uint128_ht{H128.v l = (v count * v size_block + v len) * 8}) =
let l0 = H128.mul_wide (u32_to_h64 count) (u32_to_h64 size_block) in
let l1 = u32_to_h128 len in
(**) assert(H128.v l0 + H128.v l1 < pow2 125);
(**) assert_norm(pow2 3 = 8);
(**) Math.Lemmas.modulo_lemma Hacl.UInt128.(v (shift_left (l0 +^ l1) 3ul)) (pow2 128);
H128.(H128.shift_left (l0 +^ l1) 3ul) // Multiplication by 2^3
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
val set_pad_part1:
buf1 :uint8_p {length buf1 = 1} ->
Stack unit
(requires (fun h0 -> live h0 buf1))
(ensures (fun h0 _ h1 -> live h0 buf1 /\ live h1 buf1 /\ modifies_1 buf1 h0 h1
/\ (let seq_buf1 = reveal_sbytes (as_seq h1 buf1) in
seq_buf1 = Seq.create 1 0x80uy)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 100"
[@"substitute"]
let set_pad_part1 buf1 =
Buffer.upd buf1 0ul (u8_to_h8 0x80uy);
(**) let h = ST.get () in
(**) Seq.lemma_eq_intro (reveal_sbytes (as_seq h buf1)) (Seq.create 1 0x80uy)
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
val set_pad_part2:
buf2 :uint8_p{length buf2 = v size_len_8} ->
encodedlen :uint128_ht ->
Stack unit
(requires (fun h0 -> live h0 buf2))
(ensures (fun h0 _ h1 -> live h0 buf2 /\ live h1 buf2 /\ modifies_1 buf2 h0 h1
/\ (let seq_buf2 = reveal_sbytes (as_seq h1 buf2) in
seq_buf2 == Endianness.big_bytes size_len_8 (H128.v encodedlen))))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 30"
[@"substitute"]
let set_pad_part2 buf2 encodedlen =
Hacl.Endianness.hstore128_be buf2 encodedlen;
(**) let h = ST.get () in
(**) Lemmas.lemma_eq_endianness h buf2 encodedlen
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
val lemma_downcast: (len:uint64_t) -> Lemma
(requires (UInt64.v len + 1 + UInt32.v size_len_8 <= 2 * UInt32.v size_block))
(ensures ((UInt64.v len + 1 + UInt32.v size_len_8 <= 2 * UInt32.v size_block) ==> (UInt32.v (Int.Cast.uint64_to_uint32 len) + 1 + UInt32.v size_len_8 <= 2 * UInt32.v size_block) ))
let lemma_downcast len =
(**) assert(UInt64.v len + 1 + UInt32.v size_len_8 <= 2 * UInt32.v size_block);
(**) assert(UInt32.v (Int.Cast.uint64_to_uint32 len) + 1 + UInt32.v size_len_8 <= 2 * UInt32.v size_block)
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
val lemma_padding_bounds:
padding :uint8_p ->
len :uint32_t {U32.v len + 1 + v size_len_8 <= 2 * v size_block
/\ length padding = (1 + v size_len_8 + Spec.pad0_length (U32.v len))}
-> Lemma
(ensures (let p0 = pad0_length len in
1 <= length padding
/\ 1 + UInt32.v p0 <= length padding
/\ 1 + UInt32.v p0 + UInt32.v size_len_8 <= length padding))
let lemma_padding_bounds padding len = ()
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 100"
val lemma_eq_pad0_downcast: len:UInt64.t -> Lemma (ensures (Spec.pad0_length (UInt32.v (u64_to_u32 len)) = Spec.pad0_length (U64.v len)))
let lemma_eq_pad0_downcast len = ()
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
[@"substitute"]
val pad:
padding :uint8_p ->
n :uint32_ht ->
len :uint32_t {v len + 1 + v size_len_8 <= 2 * v size_block
/\ v n * v size_block + v len < Spec.max_input_len_8
/\ length padding = (1 + v size_len_8 + Spec.pad0_length (v len))
/\ (length padding + v len) % v size_block = 0} ->
Stack unit
(requires (fun h0 -> live h0 padding
/\ (let seq_padding = reveal_sbytes (as_seq h0 padding) in
seq_padding == Seq.create (1 + v size_len_8 + Spec.pad0_length (v len)) 0uy)))
(ensures (fun h0 _ h1 -> live h0 padding /\ live h1 padding /\ modifies_1 padding h0 h1
/\ (let seq_padding = reveal_sbytes (as_seq h1 padding) in
seq_padding == Spec.pad (v n * v size_block) (v len))))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 500"
[@"substitute"]
let pad padding n len =
(* Compute and encode the total length *)
let encodedlen = encode_length n len in
assert(H128.v encodedlen = ((v n * v size_block + v len) * 8));
(* Get the memory *)
(**) let h0 = ST.get () in
(* Compute the length of zeros *)
(**) assert(v len + 1 + v size_len_8 <= 2 * v size_block);
// (**) lemma_downcast len;
(**) assert(v len + 1 + v size_len_8 <= 2 * v size_block);
let pad0len = pad0_length len in
(**) assert(UInt32.v pad0len = Spec.pad0_length (v len));
// (**) lemma_eq_pad0_downcast len;
(**) assert(UInt32.v pad0len = Spec.pad0_length (v len));
(* Retreive the different parts of the padding *)
(**) assert(length padding = (1 + v size_len_8 + Spec.pad0_length (v len)));
(**) assert(1 <= length padding);
let buf1 = Buffer.sub padding 0ul 1ul in
(**) let h1 = ST.get () in
(**) assert(length padding = (1 + v size_len_8 + Spec.pad0_length (v len)));
// (**) lemma_eq_pad0_downcast len;
(**) assert(1 + UInt32.v pad0len <= length padding);
let zeros = Buffer.sub padding 1ul pad0len in
(**) let h2 = ST.get () in
(**) Seq.lemma_eq_intro (reveal_sbytes (as_seq h2 zeros)) (Seq.create (v pad0len) 0uy);
(**) assert(reveal_sbytes (as_seq h2 zeros) == Seq.create (v pad0len) 0uy);
(**) assert(v (1ul +^ pad0len) + v size_len_8 <= length padding);
let buf2 = Buffer.sub padding (1ul +^ pad0len) size_len_8 in
(* Set the first byte of the padding *)
set_pad_part1 buf1;
(**) no_upd_lemma_1 h0 h1 buf1 zeros;
(**) no_upd_lemma_1 h0 h1 buf1 buf2;
(* Encode the total length at the end of the padding *)
set_pad_part2 buf2 encodedlen;
(* Proof that this is the concatenation of the three parts *)
(**) let h3 = ST.get () in
(**) Buffer.no_upd_lemma_2 h2 h3 buf1 buf2 zeros;
(**) Seq.lemma_eq_intro (reveal_sbytes (as_seq h3 zeros)) (Seq.create (v pad0len) 0uy);
(**) assert(reveal_sbytes (as_seq h3 zeros) == Seq.create (v pad0len) 0uy);
(**) assert(reveal_sbytes (as_seq h3 buf1) == Seq.create 1 0x80uy);
(**) assert(reveal_sbytes (as_seq h3 buf2) == Endianness.big_bytes size_len_8 (H128.v encodedlen));
(**) Lemmas.lemma_sub_append_3 h3 padding 0ul buf1 1ul zeros (1ul +^ pad0len) buf2 (1ul +^ pad0len +^ size_len_8)
// (**) Lemmas.lemma_pad_aux h3 n len buf1 zeros buf2
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 100"
val update_last:
state :uint64_p {length state = v size_state} ->
data :uint8_p {disjoint state data} ->
len :uint32_t {v len = length data /\ (length data + v size_len_8 + 1) < 2 * v size_block} ->
Stack unit
(requires (fun h0 -> live h0 state /\ live h0 data
/\ (let seq_k = Seq.slice (as_seq h0 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_counter = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter = Seq.index seq_counter 0 in
let nb = U32.div len size_block in
reveal_h64s seq_k == Spec.k /\ H64.v counter < (pow2 64 - 2))))
(ensures (fun h0 r h1 -> live h0 state /\ live h0 data /\ live h1 state /\ modifies_1 state h0 h1
/\ (let seq_hash_0 = Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_hash_1 = Seq.slice (as_seq h1 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_data = reveal_sbytes (as_seq h0 data) in
let count = Seq.slice (as_seq h0 state) (U32.v pos_count_w) (U32.v pos_count_w + 1) in
let prevlen = H64.((H64.v (Seq.index count 0)) * (U32.v size_block)) in
reveal_h64s seq_hash_1 == Spec.update_last (reveal_h64s seq_hash_0) prevlen seq_data)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 750"
let update_last state data len =
(**) assert_norm(pow2 32 = 0x100000000);
(**) let hinit = ST.get() in
(* Push a new memory frame *)
(**) push_frame();
(**) let h00 = ST.get() in
(* Alocate memory set to zeros for the last two blocks of data *)
let blocks = Buffer.create (uint8_to_sint8 0uy) (size_block +^ size_block) in
(**) let h0 = ST.get () in
// (**) assert(reveal_sbytes (as_seq h0 blocks) == Seq.create (2 * v size_block) 0uy);
(* Verification of how many blocks are necessary *)
(* Threat model. The length is public ! *)
let nb = if (len <^ 112ul) then 1ul else 2ul in
let final_blocks =
(**) let h1 = ST.get () in
if (len <^ 112ul) then begin
(**) assert(v size_block <= length blocks);
(**) assert(live h1 blocks);
Buffer.offset blocks size_block end
else begin
(**) assert(live h1 blocks);
blocks end in
(**) assert(blocks `includes` final_blocks);
(**) let h2 = ST.get () in
(**) Seq.lemma_eq_intro (reveal_sbytes (as_seq h2 final_blocks))
(if (len <^ 112ul) then
Seq.create (v size_block) 0uy
else Seq.create (v size_block + v size_block) 0uy);
(**) Seq.lemma_eq_intro (reveal_sbytes (as_seq h2 final_blocks)) (Seq.create (
v (if (len <^ 112ul) then 1ul else 2ul) * v size_block) 0uy);
(**) assert(reveal_sbytes (as_seq h2 final_blocks) == Seq.create (v nb * v size_block) 0uy);
(* Copy the data to the final construct *)
(* Leakage model : allowed because the length is public *)
// (**) assert(length final_blocks)
Buffer.blit data 0ul final_blocks 0ul len;
(**) let h3 = ST.get () in
(**) modifies_subbuffer_1 h2 h3 final_blocks blocks;
(**) lemma_modifies_0_1' blocks h00 h0 h3;
(* (\**\) Seq.lemma_eq_intro (as_seq h3 data) (Seq.slice (as_seq h3 data) 0 len); *)
(* (\**\) Seq.lemma_eq_intro (as_seq h3 data) (Seq.slice (as_seq h3 final_blocks) 0 (U64.v len)); *)
(**) assert(as_seq h3 data == Seq.slice (as_seq h3 final_blocks) 0 (v len));
(* Compute the final length of the data *)
let n = state.(pos_count_w) in
(* Set the padding *)
let padding = Buffer.offset final_blocks len in
(**) assert(v len + v size_len_8 + 1 < 2 * v size_block);
(**) assert(H64.v n * v size_block + v len < Spec.max_input_len_8);
(**) assert(length padding = (1 + (Spec.pad0_length (v len)) + v size_len_8));
(**) assert((length padding + v len) % v size_block = 0);
(**) Seq.lemma_eq_intro (reveal_sbytes (as_seq h3 padding)) (Seq.create (1 + (Spec.pad0_length (v len)) + v size_len_8) 0uy);
(**) assert(reveal_sbytes (as_seq h3 padding) == Seq.create (1 + (Spec.pad0_length (v len)) + v size_len_8) 0uy);
pad padding (h64_to_h32 n) len;
(* Proof that final_blocks = data @| padding *)
(**) let h4 = ST.get () in
(**) assert(blocks `includes` padding);
(**) modifies_subbuffer_1 h3 h4 padding blocks;
(**) lemma_modifies_0_1' blocks h00 h3 h4;
(**) lemma_disjoint_sub blocks padding data;
(**) assert(disjoint padding data);
(**) no_upd_lemma_1 h3 h4 padding data;
(**) Seq.lemma_eq_intro (as_seq h4 (Buffer.sub final_blocks 0ul len)) (Seq.slice (as_seq h4 final_blocks) 0 (v len));
(**) no_upd_lemma_1 h3 h4 padding (Buffer.sub final_blocks 0ul len);
(**) assert(reveal_sbytes (as_seq h4 data) == Seq.slice (reveal_sbytes (as_seq h4 final_blocks)) 0 (v len));
(**) Seq.lemma_eq_intro (as_seq h4 (Buffer.offset final_blocks len)) (Seq.slice (as_seq h4 final_blocks) (v len) (v nb * v size_block));
(**) Seq.lemma_eq_intro (as_seq h4 padding) (Seq.slice (as_seq h4 final_blocks) (v len) (v nb * v size_block));
(**) assert(as_seq h4 padding == Seq.slice (as_seq h4 final_blocks) (v len) (v nb * v size_block));
(**) Lemmas.lemma_sub_append_2 h4 final_blocks 0ul data len padding (nb *^ size_block);
(**) assert(as_seq h4 final_blocks == Seq.append (as_seq h4 data) (as_seq h4 padding));
(* Call the update function on one or two blocks *)
(**) assert(length final_blocks % v size_block = 0 /\ disjoint state data);
(**) assert(v nb * v size_block = length final_blocks);
(**) assert(live h4 state /\ live h4 final_blocks);
(**) assert(let seq_k = Seq.slice (as_seq h4 state) (U32.v pos_k_w) (U32.(v pos_k_w + v size_k_w)) in
let seq_counter = Seq.slice (as_seq h4 state) (U32.v pos_count_w) (U32.(v pos_count_w + v size_count_w)) in
let counter = Seq.index seq_counter 0 in
reveal_h64s seq_k == Spec.k /\ H64.v counter < (pow2 64 - 2));
update_multi state final_blocks nb;
(**) let h5 = ST.get() in
(**) lemma_modifies_0_1 state h00 h4 h5;
(* Pop the memory frame *)
(**) pop_frame();
(**) let hfin = ST.get() in
(**) modifies_popped_1 state hinit h00 h5 hfin
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
[@"substitute"]
val finish_core:
hash_w :uint64_p {length hash_w = v size_hash_w} ->
hash :uint8_p {length hash = v size_hash /\ disjoint hash_w hash} ->
Stack unit
(requires (fun h0 -> live h0 hash_w /\ live h0 hash))
(ensures (fun h0 _ h1 -> live h0 hash_w /\ live h0 hash /\ live h1 hash /\ modifies_1 hash h0 h1
/\ (let seq_hash_w = reveal_h64s (as_seq h0 hash_w) in
let seq_hash = reveal_sbytes (as_seq h1 hash) in
seq_hash = Spec.words_to_be (U32.v size_hash_w) seq_hash_w)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 50"
[@"substitute"]
let finish_core hash_w hash = uint64s_to_be_bytes hash hash_w size_hash_w
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
val finish:
state :uint64_p{length state = v size_state} ->
hash :uint8_p{length hash = v size_hash /\ disjoint state hash} ->
Stack unit
(requires (fun h0 -> live h0 state /\ live h0 hash))
(ensures (fun h0 _ h1 -> live h0 state /\ live h1 hash /\ modifies_1 hash h0 h1
/\ (let seq_hash_w = Seq.slice (as_seq h0 state) (U32.v pos_whash_w) (U32.(v pos_whash_w + v size_whash_w)) in
let seq_hash = reveal_sbytes (as_seq h1 hash) in
seq_hash = Spec.finish (reveal_h64s seq_hash_w))))
let finish state hash =
let hash_w = Buffer.sub state pos_whash_w size_whash_w in
finish_core hash_w hash
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 20"
val hash:
hash :uint8_p {length hash = v size_hash} ->
input:uint8_p {length input < Spec.max_input_len_8 /\ disjoint hash input} ->
len :uint32_t{v len = length input} ->
Stack unit
(requires (fun h0 -> live h0 hash /\ live h0 input))
(ensures (fun h0 _ h1 -> live h0 input /\ live h0 hash /\ live h1 hash /\ modifies_1 hash h0 h1
/\ (let seq_input = reveal_sbytes (as_seq h0 input) in
let seq_hash = reveal_sbytes (as_seq h1 hash) in
seq_hash == Spec.hash seq_input)))
#reset-options "--z3refresh --max_fuel 0 --z3rlimit 200"
let hash hash input len =
(**) let hinit = ST.get() in
(* Push a new memory frame *)
(**) push_frame ();
(**) let h0 = ST.get() in
(* Allocate memory for the hash state *)
let state = Buffer.create (u32_to_h64 0ul) size_state in
(**) let h1 = ST.get() in
(* Compute the number of blocks to process *)
let n = U32.div len size_block in
let r = U32.rem len size_block in
(* Get all full blocks the last block *)
let input_blocks = Buffer.sub input 0ul (n *%^ size_block) in
let input_last = Buffer.sub input (n *%^ size_block) r in
(* Initialize the hash function *)
init state;
(**) let h2 = ST.get() in
(**) lemma_modifies_0_1' state h0 h1 h2;
(* Update the state with input blocks *)
update_multi state input_blocks n;
(**) let h3 = ST.get() in
(**) lemma_modifies_0_1' state h0 h2 h3;
(* Process the last block of input *)
update_last state input_last r;
(**) let h4 = ST.get() in
(**) lemma_modifies_0_1' state h0 h3 h4;
(* Finalize the hash output *)
finish state hash;
(**) let h5 = ST.get() in
(**) lemma_modifies_0_1 hash h0 h4 h5;
(* Pop the memory frame *)
(**) pop_frame ();
(**) let hfin = ST.get() in
(**) modifies_popped_1 hash hinit h0 h5 hfin