val va_wp_GhashUnroll_n
      (exactly2: bool)
      (in_b: buffer128)
      (index: nat)
      (h_BE y_prev: quad32)
      (data: (seq quad32))
      (va_s0: va_state)
      (va_k: (va_state -> unit -> Type0))
    : Type0
let va_wp_GhashUnroll_n (exactly2:bool) (in_b:buffer128) (index:nat) (h_BE:quad32) (y_prev:quad32)
  (data:(seq quad32)) (va_s0:va_state) (va_k:(va_state -> unit -> Type0)) : Type0 =
  (va_get_ok va_s0 /\ (let (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in
    let (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in (exactly2 ==> n == 2) /\
    (~exactly2 ==> n == 1) /\ in_b_blocks in_b index n (va_get_mem_heaplet 1 va_s0)
    (va_get_mem_layout va_s0) (va_get_reg 7 va_s0) data /\ Vale.Math.Poly2.Bits_s.of_quad32
    (va_get_vec 1 va_s0) == prev /\ Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 5 va_s0) ==
    Vale.Math.Poly2.swap (Vale.AES.GHash_BE.gf128_power h 1) 64 /\ Vale.Math.Poly2.Bits_s.of_quad32
    (va_get_vec 6 va_s0) == Vale.Math.Poly2_s.mul (Vale.Math.Poly2_s.div
    (Vale.AES.GHash_BE.gf128_power h 1) (Vale.Math.Poly2_s.monomial 64))
    (Vale.Math.Poly2_s.monomial 64) /\ Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 7 va_s0) ==
    Vale.Math.Poly2_s.mod (Vale.AES.GHash_BE.gf128_power h 1) (Vale.Math.Poly2_s.monomial 64) /\
    (exactly2 ==> Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 12 va_s0) == Vale.Math.Poly2.swap
    (Vale.AES.GHash_BE.gf128_power h 2) 64) /\ (exactly2 ==> Vale.Math.Poly2.Bits_s.of_quad32
    (va_get_vec 13 va_s0) == Vale.Math.Poly2_s.mul (Vale.Math.Poly2_s.div
    (Vale.AES.GHash_BE.gf128_power h 2) (Vale.Math.Poly2_s.monomial 64))
    (Vale.Math.Poly2_s.monomial 64)) /\ (exactly2 ==> Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec
    14 va_s0) == Vale.Math.Poly2_s.mod (Vale.AES.GHash_BE.gf128_power h 2)
    (Vale.Math.Poly2_s.monomial 64))) /\ (forall (va_x_r10:nat64) (va_x_v0:quad32) (va_x_v1:quad32)
    (va_x_v2:quad32) (va_x_v3:quad32) (va_x_v4:quad32) (va_x_v8:quad32) (va_x_v9:quad32)
    (va_x_v10:quad32) (va_x_v11:quad32) . let va_sM = va_upd_vec 11 va_x_v11 (va_upd_vec 10
    va_x_v10 (va_upd_vec 9 va_x_v9 (va_upd_vec 8 va_x_v8 (va_upd_vec 4 va_x_v4 (va_upd_vec 3
    va_x_v3 (va_upd_vec 2 va_x_v2 (va_upd_vec 1 va_x_v1 (va_upd_vec 0 va_x_v0 (va_upd_reg 10
    va_x_r10 va_s0))))))))) in va_get_ok va_sM /\ (let (h:Vale.Math.Poly2_s.poly) =
    Vale.Math.Poly2.Bits_s.of_quad32 h_BE in let (prev:Vale.Math.Poly2_s.poly) =
    Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128))
    = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128 data in let (n:Prims.nat) = FStar.Seq.Base.length
    #quad32 data in va_get_vec 1 va_sM == Vale.AES.GHash_BE.ghash_incremental h_BE y_prev data) ==>
    va_k va_sM (())))
val va_wp_GhashUnroll_n
      (exactly2: bool)
      (in_b: buffer128)
      (index: nat)
      (h_BE y_prev: quad32)
      (data: (seq quad32))
      (va_s0: va_state)
      (va_k: (va_state -> unit -> Type0))
    : Type0
let va_wp_GhashUnroll_n
      (exactly2: bool)
      (in_b: buffer128)
      (index: nat)
      (h_BE y_prev: quad32)
      (data: (seq quad32))
      (va_s0: va_state)
      (va_k: (va_state -> unit -> Type0))
    : Type0 =
(va_get_ok va_s0 /\
  (let h:Vale.Math.Poly2_s.poly = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in
    let prev:Vale.Math.Poly2_s.poly = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in
    let pdata:(Prims.int -> Vale.AES.GHash_BE.poly128) =
      Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128 data
    in
    let n:Prims.nat = FStar.Seq.Base.length #quad32 data in
    (exactly2 ==> n == 2) /\ (~exactly2 ==> n == 1) /\
    in_b_blocks in_b
      index
      n
      (va_get_mem_heaplet 1 va_s0)
      (va_get_mem_layout va_s0)
      (va_get_reg 7 va_s0)
      data /\ Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 1 va_s0) == prev /\
    Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 5 va_s0) ==
    Vale.Math.Poly2.swap (Vale.AES.GHash_BE.gf128_power h 1) 64 /\
    Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 6 va_s0) ==
    Vale.Math.Poly2_s.mul (Vale.Math.Poly2_s.div (Vale.AES.GHash_BE.gf128_power h 1)
          (Vale.Math.Poly2_s.monomial 64))
      (Vale.Math.Poly2_s.monomial 64) /\
    Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 7 va_s0) ==
    Vale.Math.Poly2_s.mod (Vale.AES.GHash_BE.gf128_power h 1) (Vale.Math.Poly2_s.monomial 64) /\
    (exactly2 ==>
      Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 12 va_s0) ==
      Vale.Math.Poly2.swap (Vale.AES.GHash_BE.gf128_power h 2) 64) /\
    (exactly2 ==>
      Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 13 va_s0) ==
      Vale.Math.Poly2_s.mul (Vale.Math.Poly2_s.div (Vale.AES.GHash_BE.gf128_power h 2)
            (Vale.Math.Poly2_s.monomial 64))
        (Vale.Math.Poly2_s.monomial 64)) /\
    (exactly2 ==>
      Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 14 va_s0) ==
      Vale.Math.Poly2_s.mod (Vale.AES.GHash_BE.gf128_power h 2) (Vale.Math.Poly2_s.monomial 64))) /\
  (forall (va_x_r10: nat64) (va_x_v0: quad32) (va_x_v1: quad32) (va_x_v2: quad32) (va_x_v3: quad32)
      (va_x_v4: quad32) (va_x_v8: quad32) (va_x_v9: quad32) (va_x_v10: quad32) (va_x_v11: quad32).
      let va_sM =
        va_upd_vec 11
          va_x_v11
          (va_upd_vec 10
              va_x_v10
              (va_upd_vec 9
                  va_x_v9
                  (va_upd_vec 8
                      va_x_v8
                      (va_upd_vec 4
                          va_x_v4
                          (va_upd_vec 3
                              va_x_v3
                              (va_upd_vec 2
                                  va_x_v2
                                  (va_upd_vec 1
                                      va_x_v1
                                      (va_upd_vec 0 va_x_v0 (va_upd_reg 10 va_x_r10 va_s0)))))))))
      in
      va_get_ok va_sM /\
      (let h:Vale.Math.Poly2_s.poly = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in
        let prev:Vale.Math.Poly2_s.poly = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in
        let pdata:(Prims.int -> Vale.AES.GHash_BE.poly128) =
          Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128 data
        in
        let n:Prims.nat = FStar.Seq.Base.length #quad32 data in
        va_get_vec 1 va_sM == Vale.AES.GHash_BE.ghash_incremental h_BE y_prev data) ==>
      va_k va_sM (())))
Vale.AES.PPC64LE.GHash.fsti.checked
Vale.PPC64LE.State.fsti.checked Vale.PPC64LE.QuickCodes.fsti.checked Vale.PPC64LE.QuickCode.fst.checked Vale.PPC64LE.Memory.fsti.checked Vale.PPC64LE.Machine_s.fst.checked Vale.PPC64LE.InsVector.fsti.checked Vale.PPC64LE.InsMem.fsti.checked Vale.PPC64LE.InsBasic.fsti.checked Vale.PPC64LE.Decls.fsti.checked Vale.Poly1305.Math.fsti.checked Vale.Math.Poly2_s.fsti.checked Vale.Math.Poly2.Lemmas.fsti.checked Vale.Math.Poly2.Bits_s.fsti.checked Vale.Math.Poly2.Bits.fsti.checked Vale.Math.Poly2.fsti.checked Vale.Def.Words_s.fsti.checked Vale.Def.Types_s.fst.checked Vale.Def.Prop_s.fst.checked Vale.Def.Opaque_s.fsti.checked Vale.Arch.TypesNative.fsti.checked Vale.Arch.Types.fsti.checked Vale.Arch.HeapImpl.fsti.checked Vale.AES.PPC64LE.PolyOps.fsti.checked Vale.AES.PPC64LE.GF128_Mul.fsti.checked Vale.AES.GHash_BE.fsti.checked Vale.AES.GF128_s.fsti.checked Vale.AES.GF128.fsti.checked Vale.AES.GCTR_BE_s.fst.checked Vale.AES.GCTR_BE.fsti.checked Vale.AES.GCM_helpers_BE.fsti.checked Vale.AES.AES_helpers.fsti.checked Vale.AES.AES_BE_s.fst.checked prims.fst.checked FStar.Seq.Base.fsti.checked FStar.Seq.fst.checked FStar.Pervasives.Native.fst.checked FStar.Pervasives.fsti.checked
Vale.AES.PPC64LE.GHash.fsti
Prims.bool Vale.PPC64LE.Memory.buffer128 Prims.nat Vale.PPC64LE.Memory.quad32 FStar.Seq.Base.seq Vale.PPC64LE.Decls.va_state Prims.unit Prims.l_and Prims.b2t Vale.PPC64LE.Decls.va_get_ok Prims.l_imp Prims.eq2 Prims.int Prims.l_not Vale.AES.PPC64LE.GHash.in_b_blocks Vale.PPC64LE.Decls.va_get_mem_heaplet Vale.PPC64LE.Decls.va_get_mem_layout Vale.PPC64LE.Decls.va_get_reg Vale.Math.Poly2_s.poly Vale.Math.Poly2.Bits_s.of_quad32 Vale.PPC64LE.Decls.va_get_vec Vale.Math.Poly2.swap Vale.AES.GHash_BE.gf128_power Vale.Math.Poly2_s.mul Vale.Math.Poly2_s.div Vale.Math.Poly2_s.monomial Vale.Math.Poly2_s.mod FStar.Seq.Base.length Vale.AES.GHash_BE.poly128 Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128 Prims.l_Forall Vale.PPC64LE.Memory.nat64 Vale.Def.Types_s.quad32 Vale.AES.GHash_BE.ghash_incremental Vale.PPC64LE.Machine_s.state Vale.PPC64LE.Decls.va_upd_vec Vale.PPC64LE.Decls.va_upd_reg
module Vale.AES.PPC64LE.GHash
open Vale.Def.Prop_s
open Vale.Def.Opaque_s
open Vale.Def.Words_s
open Vale.Def.Types_s
open FStar.Seq
open Vale.Arch.Types
open Vale.Arch.HeapImpl
open Vale.AES.AES_BE_s
open Vale.PPC64LE.Machine_s
open Vale.PPC64LE.Memory
open Vale.PPC64LE.State
open Vale.PPC64LE.Decls
open Vale.PPC64LE.InsBasic
open Vale.PPC64LE.InsMem
open Vale.PPC64LE.InsVector
open Vale.PPC64LE.QuickCode
open Vale.PPC64LE.QuickCodes
open Vale.AES.AES_helpers
open Vale.Poly1305.Math    // For lemma_poly_bits64()
open Vale.AES.GCM_helpers_BE
open Vale.AES.GCTR_BE_s
open Vale.AES.GCTR_BE
open Vale.Arch.TypesNative
open Vale.AES.PPC64LE.PolyOps
open Vale.AES.PPC64LE.GF128_Mul
open Vale.Math.Poly2_s
open Vale.Math.Poly2
open Vale.Math.Poly2.Bits_s
open Vale.Math.Poly2.Bits
open Vale.Math.Poly2.Lemmas
open Vale.AES.GF128_s
open Vale.AES.GF128
open Vale.AES.GHash_BE
#reset-options "--z3rlimit 50"

unfold let va_subscript_FStar__Seq__Base__seq = Seq.index

let hkeys_b_powers (hkeys_b:buffer128) (heap0:vale_heap) (layout:vale_heap_layout) (ptr:int) (h:poly) =
  validSrcAddrs128 heap0 ptr hkeys_b 3 layout Secret /\
  of_quad32 (reverse_bytes_quad32 (buffer128_read hkeys_b 0 heap0)) == gf128_power h 1 /\
  of_quad32 (reverse_bytes_quad32 (buffer128_read hkeys_b 1 heap0)) == gf128_power h 2

let in_b_blocks
    (in_b:buffer128) (in_index count:int) (heap_s:vale_heap) (layout:vale_heap_layout) (ptr:int) (data:seq quad32)
  =
  validSrcAddrsOffset128 heap_s ptr in_b in_index count layout Secret /\
  (forall (i:nat).{:pattern (index data i)}
    i < count /\ i < length data ==>
      reverse_bytes_quad32 (buffer128_read in_b (in_index + i) heap_s) == index data i)
//-- ReduceLast

val va_code_ReduceLast : va_dummy:unit -> Tot va_code

val va_codegen_success_ReduceLast : va_dummy:unit -> Tot va_pbool

val va_lemma_ReduceLast : va_b0:va_code -> va_s0:va_state -> h_BE:quad32 -> y_prev:quad32 ->
  data:(seq quad32)
  -> Ghost (va_state & va_fuel)
  (requires (va_require_total va_b0 (va_code_ReduceLast ()) va_s0 /\ va_get_ok va_s0 /\ (let
    (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in let
    (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in va_get_vec 8 va_s0 ==
    Vale.Def.Words_s.Mkfour #Vale.Def.Types_s.nat32 0 3254779904 0 0 /\ n > 0 /\ add (add
    (Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 2 va_s0)) (Vale.Math.Poly2_s.shift
    (Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 3 va_s0)) 64)) (Vale.Math.Poly2_s.shift
    (Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 4 va_s0)) 128) ==
    Vale.AES.GHash_BE.ghash_unroll_back h prev pdata 0 n (n - 1))))
  (ensures (fun (va_sM, va_fM) -> va_ensure_total va_b0 va_s0 va_sM va_fM /\ va_get_ok va_sM /\
    (let (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in let
    (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in let xi =
    Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 1 va_sM) in Vale.Math.Poly2.Bits_s.to_quad32 xi ==
    Vale.AES.GHash_BE.ghash_incremental h_BE y_prev data /\ xi == Vale.Math.Poly2.Bits_s.of_quad32
    (Vale.Math.Poly2.Bits_s.to_quad32 xi)) /\ va_state_eq va_sM (va_update_vec 10 va_sM
    (va_update_vec 9 va_sM (va_update_vec 8 va_sM (va_update_vec 4 va_sM (va_update_vec 3 va_sM
    (va_update_vec 2 va_sM (va_update_vec 1 va_sM (va_update_vec 0 va_sM (va_update_ok va_sM
    va_s0)))))))))))
[@ va_qattr]
let va_wp_ReduceLast (h_BE:quad32) (y_prev:quad32) (data:(seq quad32)) (va_s0:va_state)
  (va_k:(va_state -> unit -> Type0)) : Type0 =
  (va_get_ok va_s0 /\ (let (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in
    let (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in va_get_vec 8 va_s0 ==
    Vale.Def.Words_s.Mkfour #Vale.Def.Types_s.nat32 0 3254779904 0 0 /\ n > 0 /\ add (add
    (Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 2 va_s0)) (Vale.Math.Poly2_s.shift
    (Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 3 va_s0)) 64)) (Vale.Math.Poly2_s.shift
    (Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 4 va_s0)) 128) ==
    Vale.AES.GHash_BE.ghash_unroll_back h prev pdata 0 n (n - 1)) /\ (forall (va_x_v0:quad32)
    (va_x_v1:quad32) (va_x_v2:quad32) (va_x_v3:quad32) (va_x_v4:quad32) (va_x_v8:quad32)
    (va_x_v9:quad32) (va_x_v10:quad32) . let va_sM = va_upd_vec 10 va_x_v10 (va_upd_vec 9 va_x_v9
    (va_upd_vec 8 va_x_v8 (va_upd_vec 4 va_x_v4 (va_upd_vec 3 va_x_v3 (va_upd_vec 2 va_x_v2
    (va_upd_vec 1 va_x_v1 (va_upd_vec 0 va_x_v0 va_s0))))))) in va_get_ok va_sM /\ (let
    (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in let
    (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in let xi =
    Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 1 va_sM) in Vale.Math.Poly2.Bits_s.to_quad32 xi ==
    Vale.AES.GHash_BE.ghash_incremental h_BE y_prev data /\ xi == Vale.Math.Poly2.Bits_s.of_quad32
    (Vale.Math.Poly2.Bits_s.to_quad32 xi)) ==> va_k va_sM (())))

val va_wpProof_ReduceLast : h_BE:quad32 -> y_prev:quad32 -> data:(seq quad32) -> va_s0:va_state ->
  va_k:(va_state -> unit -> Type0)
  -> Ghost (va_state & va_fuel & unit)
  (requires (va_t_require va_s0 /\ va_wp_ReduceLast h_BE y_prev data va_s0 va_k))
  (ensures (fun (va_sM, va_f0, va_g) -> va_t_ensure (va_code_ReduceLast ()) ([va_Mod_vec 10;
    va_Mod_vec 9; va_Mod_vec 8; va_Mod_vec 4; va_Mod_vec 3; va_Mod_vec 2; va_Mod_vec 1; va_Mod_vec
    0]) va_s0 va_k ((va_sM, va_f0, va_g))))
[@ "opaque_to_smt" va_qattr]
let va_quick_ReduceLast (h_BE:quad32) (y_prev:quad32) (data:(seq quad32)) : (va_quickCode unit
  (va_code_ReduceLast ())) =
  (va_QProc (va_code_ReduceLast ()) ([va_Mod_vec 10; va_Mod_vec 9; va_Mod_vec 8; va_Mod_vec 4;
    va_Mod_vec 3; va_Mod_vec 2; va_Mod_vec 1; va_Mod_vec 0]) (va_wp_ReduceLast h_BE y_prev data)
    (va_wpProof_ReduceLast h_BE y_prev data))
//--
//-- GhashUnroll_n

val va_code_GhashUnroll_n : exactly2:bool -> Tot va_code

val va_codegen_success_GhashUnroll_n : exactly2:bool -> Tot va_pbool

val va_lemma_GhashUnroll_n : va_b0:va_code -> va_s0:va_state -> exactly2:bool -> in_b:buffer128 ->
  index:nat -> h_BE:quad32 -> y_prev:quad32 -> data:(seq quad32)
  -> Ghost (va_state & va_fuel)
  (requires (va_require_total va_b0 (va_code_GhashUnroll_n exactly2) va_s0 /\ va_get_ok va_s0 /\
    (let (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in let
    (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in (exactly2 ==> n == 2) /\
    (~exactly2 ==> n == 1) /\ in_b_blocks in_b index n (va_get_mem_heaplet 1 va_s0)
    (va_get_mem_layout va_s0) (va_get_reg 7 va_s0) data /\ Vale.Math.Poly2.Bits_s.of_quad32
    (va_get_vec 1 va_s0) == prev /\ Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 5 va_s0) ==
    Vale.Math.Poly2.swap (Vale.AES.GHash_BE.gf128_power h 1) 64 /\ Vale.Math.Poly2.Bits_s.of_quad32
    (va_get_vec 6 va_s0) == Vale.Math.Poly2_s.mul (Vale.Math.Poly2_s.div
    (Vale.AES.GHash_BE.gf128_power h 1) (Vale.Math.Poly2_s.monomial 64))
    (Vale.Math.Poly2_s.monomial 64) /\ Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 7 va_s0) ==
    Vale.Math.Poly2_s.mod (Vale.AES.GHash_BE.gf128_power h 1) (Vale.Math.Poly2_s.monomial 64) /\
    (exactly2 ==> Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec 12 va_s0) == Vale.Math.Poly2.swap
    (Vale.AES.GHash_BE.gf128_power h 2) 64) /\ (exactly2 ==> Vale.Math.Poly2.Bits_s.of_quad32
    (va_get_vec 13 va_s0) == Vale.Math.Poly2_s.mul (Vale.Math.Poly2_s.div
    (Vale.AES.GHash_BE.gf128_power h 2) (Vale.Math.Poly2_s.monomial 64))
    (Vale.Math.Poly2_s.monomial 64)) /\ (exactly2 ==> Vale.Math.Poly2.Bits_s.of_quad32 (va_get_vec
    14 va_s0) == Vale.Math.Poly2_s.mod (Vale.AES.GHash_BE.gf128_power h 2)
    (Vale.Math.Poly2_s.monomial 64)))))
  (ensures (fun (va_sM, va_fM) -> va_ensure_total va_b0 va_s0 va_sM va_fM /\ va_get_ok va_sM /\
    (let (h:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 h_BE in let
    (prev:Vale.Math.Poly2_s.poly) = Vale.Math.Poly2.Bits_s.of_quad32 y_prev in let
    (pdata:(Prims.int -> Vale.AES.GHash_BE.poly128)) = Vale.AES.GHash_BE.fun_seq_quad32_BE_poly128
    data in let (n:Prims.nat) = FStar.Seq.Base.length #quad32 data in va_get_vec 1 va_sM ==
    Vale.AES.GHash_BE.ghash_incremental h_BE y_prev data) /\ va_state_eq va_sM (va_update_vec 11
    va_sM (va_update_vec 10 va_sM (va_update_vec 9 va_sM (va_update_vec 8 va_sM (va_update_vec 4
    va_sM (va_update_vec 3 va_sM (va_update_vec 2 va_sM (va_update_vec 1 va_sM (va_update_vec 0
    va_sM (va_update_reg 10 va_sM (va_update_ok va_sM va_s0)))))))))))))
[@ va_qattr]
let va_wp_GhashUnroll_n (exactly2:bool) (in_b:buffer128) (index:nat) (h_BE:quad32) (y_prev:quad32)
val va_wp_GhashUnroll_n
      (exactly2: bool)
      (in_b: buffer128)
      (index: nat)
      (h_BE y_prev: quad32)
      (data: (seq quad32))
      (va_s0: va_state)
      (va_k: (va_state -> unit -> Type0))
    : Type0

    exactly2: Prims.bool ->
    in_b: Vale.PPC64LE.Memory.buffer128 ->
    index: Prims.nat ->
    h_BE: Vale.PPC64LE.Memory.quad32 ->
    y_prev: Vale.PPC64LE.Memory.quad32 ->
    data: FStar.Seq.Base.seq Vale.PPC64LE.Memory.quad32 ->
    va_s0: Vale.PPC64LE.Decls.va_state ->
    va_k: (_: Vale.PPC64LE.Decls.va_state -> _: Prims.unit -> Type0)
  -> Type0