Skip to content

Commit

Permalink
Update AES-GCM modules
Browse files Browse the repository at this point in the history
  • Loading branch information
mamonet committed Jun 26, 2024
1 parent 1508438 commit 5a07924
Show file tree
Hide file tree
Showing 48 changed files with 8,240 additions and 87 deletions.
22 changes: 20 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,13 @@ INTRINSIC_FLAGS = \
-add-include 'Hacl_Hash_Blake2b_Simd256:"libintvector.h"' \
-add-include 'Hacl_MAC_Poly1305_Simd256:"libintvector.h"' \
\
-add-include 'Hacl_Hash_SHA3_Simd256:"libintvector.h"'
-add-include 'Hacl_Hash_SHA3_Simd256:"libintvector.h"' \
\
-add-include 'Hacl_AES_128_NI:"libintvector.h"' \
-add-include 'Hacl_AES_256_NI:"libintvector.h"' \
-add-include 'Hacl_AES_128_GCM_NI:"libintvector.h"' \
-add-include 'Hacl_AES_256_GCM_NI:"libintvector.h"' \
-add-include 'Hacl_Gf128_NI:"libintvector.h"'

# Disabled for distributions that don't include code based on intrinsics.
INTRINSIC_INT_FLAGS = \
Expand Down Expand Up @@ -763,7 +769,10 @@ BUNDLE_FLAGS =\
$(INTTYPES_128_BUNDLE) \
$(RSAPSS_BUNDLE) \
$(FFDHE_BUNDLE) \
$(LEGACY_BUNDLE)
$(LEGACY_BUNDLE) \
$(AES_BUNDLE) \
$(GF128_BUNDLE) \
$(AES_GCM_BUNDLE)

DEFAULT_FLAGS = \
$(HAND_WRITTEN_LIB_FLAGS) \
Expand All @@ -775,6 +784,10 @@ DEFAULT_FLAGS = \
$(REQUIRED_FLAGS) \
$(TARGET_H_INCLUDE)

IGNORE_AES_BUNDLE = -bundle Hacl.AES_128.*,Hacl.AES_256.*,Hacl.Impl.*
IGNORE_GF128_BUNDLE = -bundle Hacl.Impl.Gf128.*,Hacl.Gf128.*
IGNORE_AES_GCM_BUNDLE = -bundle Hacl.AES_128_GCM.*,Hacl.AES_256_GCM.*

# WASM distribution
# -----------------
#
Expand Down Expand Up @@ -833,6 +846,11 @@ dist/wasm/Makefile.basic: POLY_BUNDLE = \
-bundle 'Hacl.Poly1305_128,Hacl.Poly1305_256,Hacl.Impl.Poly1305.*' \
-bundle 'Hacl.Streaming.Poly1305_128,Hacl.Streaming.Poly1305_256'

# Disabling AES
dist/wasm/Makefile.basic: AES_BUNDLE = $(IGNORE_AES_BUNDLE)
dist/wasm/Makefile.basic: GF128_BUNDLE = $(IGNORE_GF128_BUNDLE)
dist/wasm/Makefile.basic: AES_GCM_BUNDLE = $(IGNORE_AES_GCM_BUNDLE)

dist/wasm/Makefile.basic: CTR_BUNDLE =
dist/wasm/Makefile.basic: RSAPSS_BUNDLE = -bundle Hacl.RSAPSS,Hacl.Impl.RSAPSS.*,Hacl.Impl.RSAPSS
dist/wasm/Makefile.basic: FFDHE_BUNDLE = -bundle Hacl.FFDHE,Hacl.Impl.FFDHE.*,Hacl.Impl.FFDHE
Expand Down
3 changes: 3 additions & 0 deletions Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ BIGNUM_BUNDLE= \
-bundle Hacl.Bignum.Base,Hacl.Bignum.Addition,Hacl.Bignum.Convert,Hacl.Bignum.Lib,Hacl.Bignum.Multiplication[rename=Hacl_Bignum_Base] \
-static-header Hacl.Bignum.Base,Hacl.Bignum.Addition,Hacl.Bignum.Convert,Hacl.Bignum.Lib,Hacl.Bignum.Multiplication \
-bundle Hacl.Bignum,Hacl.Bignum.*[rename=Hacl_Bignum]
AES_BUNDLE=-bundle Hacl.AES_128.CTR32.BitSlice=Hacl.Impl.AES.* -bundle Hacl.AES_128.CTR32.NI=Hacl.Impl.AES.* -bundle Hacl.AES_256.CTR32.BitSlice=Hacl.Impl.AES.* -bundle Hacl.AES_256.CTR32.NI=Hacl.Impl.AES.*
GF128_BUNDLE=-bundle Hacl.Gf128.NI=Hacl.Impl.Gf128.FieldNI -bundle Hacl.Gf128.CT64=Hacl.Impl.Gf128.CT64
AES_GCM_BUNDLE=-bundle Hacl.AES_GCM_128.NI -bundle Hacl.AES_GCM_256.NI -bundle Hacl.AES_GCM_128.CT64 -bundle Hacl.AES_GCM_256.CT64

# 3. OCaml

Expand Down
1 change: 1 addition & 0 deletions code/aes-gcm/AUTHORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This code was primarily written by Karthikeyan Bhargavan (INRIA) and Benjamin Beurdouche (INRIA).
230 changes: 230 additions & 0 deletions code/aes-gcm/Hacl.AES_128_GCM.CT64.fst
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
module Hacl.AES_128_GCM.CT64
open FStar.HyperStack
open FStar.HyperStack.All
open Lib.IntTypes
open Lib.Buffer
open Lib.ByteBuffer

open Hacl.AES_128.CTR32.BitSlice
open Hacl.Gf128.CT64

module ST = FStar.HyperStack.ST
module M = LowStar.Modifies

#reset-options "--z3rlimit 1500 --max_fuel 1"

let aes_gcm_ctx_len = 116ul

type aes_gcm_ctx = lbuffer uint64 aes_gcm_ctx_len

inline_for_extraction noextract
val aes128_gcm_compute_iv:
ctx: aes_gcm_ctx
-> iv_len: size_t
-> iv: lbuffer uint8 iv_len ->
Stack uint32
(requires (fun h -> live h ctx /\ live h iv))
(ensures (fun h0 _ h1 -> modifies1 ctx h0 h1))

let aes128_gcm_compute_iv ctx iv_len iv =
push_frame();
if (iv_len =. size 12) then (
let tag_mix = create 16ul (u8 0) in
let aes_ctx = sub ctx (size 0) (size 96) in
aes128_set_nonce aes_ctx iv;
aes128_key_block tag_mix aes_ctx (u32 1);
ctx.(114ul) <- uint_from_bytes_le #U64 (sub tag_mix 0ul 8ul);
ctx.(115ul) <- uint_from_bytes_le #U64 (sub tag_mix 8ul 8ul);
pop_frame();
u32 2)
else (
let gcm_key = create 16ul (u8 0) in
let tag_iv = create 16ul (u8 0) in
let size_iv = create 16ul (u8 0) in
let tag_mix = create 16ul (u8 0) in
let aes_ctx = sub ctx (size 0) (size 96) in
let gcm_ctx = sub ctx (size 96) (size 18) in
uint_to_bytes_be #U64 (sub gcm_key (size 8) (size 8)) gcm_ctx.(size 8);
uint_to_bytes_be #U64 (sub gcm_key (size 0) (size 8)) gcm_ctx.(size 9);
ghash tag_iv iv_len iv gcm_key;
uint_to_bytes_be #U64 (sub size_iv (size 8) (size 8)) (to_u64 (iv_len *. 8ul));
let h0 = ST.get() in
loop_nospec #h0 (size 16) size_iv
(fun i -> size_iv.(i) <- tag_iv.(i) ^. size_iv.(i));
ghash tag_iv (size 16) size_iv gcm_key;
aes128_set_nonce aes_ctx (sub tag_iv (size 0) (size 12));
let ctr = uint_from_bytes_be #U32 (sub tag_iv (size 12) (size 4)) in
aes128_key_block tag_mix aes_ctx ctr;
ctx.(114ul) <- uint_from_bytes_le #U64 (sub tag_mix 0ul 8ul);
ctx.(115ul) <- uint_from_bytes_le #U64 (sub tag_mix 8ul 8ul);
let ctr = ctr +. u32 1 in
pop_frame();
ctr)

val aes128_gcm_init:
ctx: aes_gcm_ctx
-> key: lbuffer uint8 16ul ->
Stack unit
(requires (fun h -> live h ctx /\ live h key))
(ensures (fun h0 _ h1 -> modifies1 ctx h0 h1))

let aes128_gcm_init ctx key =
push_frame();
let gcm_key = create 16ul (u8 0) in
let nonce0 = create 12ul (u8 0) in
let aes_ctx = sub ctx (size 0) (size 96) in
let gcm_ctx = sub ctx (size 96) (size 18) in
admit();
aes128_init aes_ctx key nonce0;
aes128_key_block gcm_key aes_ctx (u32 0);
gcm_init gcm_ctx gcm_key;
pop_frame()


val aes128_gcm_encrypt:
ctx: aes_gcm_ctx
-> len: size_t{v len + 16 <= max_size_t}
-> out: lbuffer uint8 (len +. 16ul)
-> text: lbuffer uint8 len
-> aad_len: size_t
-> aad: lbuffer uint8 aad_len
-> iv_len: size_t
-> iv: lbuffer uint8 iv_len ->
Stack unit
(requires (fun h -> live h out /\ live h text /\ live h aad /\ live h iv /\ live h ctx
/\ disjoint out ctx
/\ disjoint ctx text
/\ disjoint ctx aad
/\ disjoint out text
/\ disjoint out aad
/\ disjoint iv out
/\ disjoint iv text
/\ disjoint iv aad
/\ disjoint iv ctx))
(ensures (fun h0 _ h1 -> modifies2 out ctx h0 h1))

let aes128_gcm_encrypt ctx len out text aad_len aad iv_len iv =
push_frame();
let tmp = create 16ul (u8 0) in
let cip = sub out (size 0) len in
let aes_ctx = sub ctx (size 0) (size 96) in
let gcm_ctx = sub ctx (size 96) (size 18) in
let tag_mix = sub ctx (size 114) (size 2) in
admit();
let ctr = aes128_gcm_compute_iv ctx iv_len iv in
aes128_ctr len cip text aes_ctx ctr;
gcm_ctx.(0ul) <- u64 0;
gcm_ctx.(1ul) <- u64 0;
gcm_update_blocks_padded gcm_ctx aad_len aad;
gcm_update_blocks_padded gcm_ctx len cip;
uint_to_bytes_be #U64 (sub tmp (size 0) (size 8)) (to_u64 (aad_len *. 8ul));
uint_to_bytes_be #U64 (sub tmp (size 8) (size 8)) (to_u64 (len *. 8ul));
gcm_update_blocks gcm_ctx (size 16) tmp;
gcm_emit tmp gcm_ctx;
let tmp0 = uint_from_bytes_le #U64 (sub tmp 0ul 8ul) in
let tmp1 = uint_from_bytes_le #U64 (sub tmp 8ul 8ul) in
let tmp0 = tmp0 ^. tag_mix.(0ul) in
let tmp1 = tmp1 ^. tag_mix.(1ul) in
uint_to_bytes_le #U64 (sub out len 8ul) tmp0;
uint_to_bytes_le #U64 (sub out (len +. 8ul) 8ul) tmp1;
pop_frame()


#reset-options "--z3rlimit 1500 --max_fuel 1"

val aes128_gcm_decrypt:
ctx: aes_gcm_ctx
-> len: size_t{v len + 16 <= max_size_t}
-> out: lbuffer uint8 len
-> cipher: lbuffer uint8 (len +. 16ul)
-> aad_len: size_t
-> aad: lbuffer uint8 aad_len
-> iv_len: size_t
-> iv: lbuffer uint8 iv_len ->
Stack bool
(requires (fun h -> live h out /\ live h cipher /\ live h aad /\ live h iv /\ live h ctx
/\ disjoint out ctx
/\ disjoint ctx cipher
/\ disjoint ctx aad
/\ disjoint out cipher
/\ disjoint out aad
/\ disjoint iv out
/\ disjoint iv cipher
/\ disjoint iv aad
/\ disjoint iv ctx))
(ensures (fun h0 r h1 -> modifies2 out ctx h0 h1))

let aes128_gcm_decrypt ctx len out cipher aad_len aad iv_len iv =
admit();
push_frame();
let scratch = create 18ul (u8 0) in
let text = sub scratch 0ul 16ul in
let zero = sub scratch 16ul 1ul in
let result = sub scratch 17ul 1ul in
let ciphertext = sub cipher 0ul len in
let tag = sub cipher len (size 16) in
let ctr = aes128_gcm_compute_iv ctx iv_len iv in
let aes_ctx = sub ctx (size 0) (size 96) in
let gcm_ctx = sub ctx (size 96) (size 18) in
let tag_mix = sub ctx (size 114) (size 2) in
let h1 = ST.get () in
gcm_ctx.(0ul) <- u64 0;
gcm_ctx.(1ul) <- u64 0;
gcm_update_blocks_padded gcm_ctx aad_len aad;
gcm_update_blocks_padded gcm_ctx len ciphertext;
uint_to_bytes_be #U64 (sub text (size 0) (size 8)) (to_u64 (aad_len *. size 8));
uint_to_bytes_be #U64 (sub text (size 8) (size 8)) (to_u64 (len *. size 8));
gcm_update_blocks gcm_ctx (size 16) text;
gcm_emit text gcm_ctx;
let text0 = uint_from_bytes_le #U64 (sub text 0ul 8ul) in
let text1 = uint_from_bytes_le #U64 (sub text 8ul 8ul) in
let text0 = text0 ^. tag_mix.(0ul) in
let text1 = text1 ^. tag_mix.(1ul) in
uint_to_bytes_le #U64 (sub text 0ul 8ul) text0;
uint_to_bytes_le #U64 (sub text 8ul 8ul) text1;
let h7 = ST.get () in
loop_nospec #h7 (size 16) result
(fun i -> result.(0ul) <- result.(0ul) |. (text.(i) ^. tag.(i)));
let h8 = ST.get () in
assert(modifies2 ctx scratch h1 h8);
let res8 = result.(0ul) in
let r =
if Lib.RawIntTypes.u8_to_UInt8 res8 = 0uy then (
aes128_ctr len out ciphertext aes_ctx ctr;
true)
else (
let h9 = ST.get () in
//modifies2_is_modifies3 ctx scratch out h1 h9;
assume(modifies3 out ctx scratch h1 h9);
false)
in
pop_frame();
r

open LowStar.Buffer

val aes128_gcm_malloc:
r:rid
-> ST.ST (s:buffer uint64 { length s = UInt32.v aes_gcm_ctx_len })
(requires (fun _ ->
ST.is_eternal_region r))
(ensures (fun h0 s h1 ->
live h1 s /\
M.(modifies loc_none h0 h1) /\
fresh_loc (loc_addr_of_buffer s) h0 h1 /\
(M.loc_includes (M.loc_region_only true r) (loc_addr_of_buffer s)) /\
freeable s))

let aes128_gcm_malloc r =
malloc r (u64 0) aes_gcm_ctx_len

val aes128_gcm_free:
s:buffer uint64 { length s = UInt32.v aes_gcm_ctx_len }
-> ST.ST unit
(requires fun h0 ->
freeable s /\ live h0 s)
(ensures fun h0 _ h1 ->
M.modifies (loc_addr_of_buffer s) h0 h1)

let aes128_gcm_free s =
free s
Loading

0 comments on commit 5a07924

Please sign in to comment.