-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Import AES-CTR32 modules from pnmadelaine_aes branch and add NI proofs #919
base: main
Are you sure you want to change the base?
Conversation
[CI] Important!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you show us the C code, too?
This is only when the CPU has NI support, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Various tidbits to be fixed. I would really like some thorough testing to make sure this is producing the correct results, with a variety of test cases, on arm and x64. The fact that the arguments to the (unverified) macro glue were in the wrong order makes me... slightly nervous
I would also like to see the incremental API being tested out in the C file.
code/aes/Hacl.AES_128.CTR32.NI.fst
Outdated
let skey = skey Spec.AES128 | ||
|
||
[@ CInline ] | ||
val create_ctx: unit -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is stackinline, it needs to be marked inline_for_extraction noextract
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and as a corollary, it can only be used by verified clients; you might want to consider adding a malloc function to allocate a context on the heap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I replaced create_ctx
with functions that allocate and free buffer on the heap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you'll still need the variant that allocates on the stack when you write aes-gcm and want to allocate aes state on the caller's stack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restored and marked as inline_for_extraction noextract.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great, FYI, we've been calling the functions alloca
in other modules, so please use that name for consistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(when it allocates state on the stack)
nonce_to_bytes m n == state.block /\ | ||
keyx_to_bytes m a kex == state.key_ex))) | ||
|
||
let aes_init #m #a ctx key nonce = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I take it that a toolchain supports either building both variants, or none at all?
st0.block ctr0 msg | ||
|
||
let aes_ctr32_decrypt_bytes_LE v key nonce ctr0 msg = | ||
aes_ctr32_encrypt_bytes_LE v key nonce ctr0 msg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where is the proof that encrypt (decrypt x) == x?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that proof should be applied for aes_ctr32_decrypt_bytes_LE
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes -- it should be pretty trivial in this case but it's a good "sanity check" to make sure you can prove that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vale has no such lemma, in fact Vale doesn't have decryption function for AES/GCTR spec. See https://github.com/hacl-star/hacl-star/blob/main/vale/specs/crypto/Vale.AES.AES_s.fst
https://github.com/hacl-star/hacl-star/blob/main/vale/specs/crypto/Vale.AES.GCTR_s.fst
GCM uses the forward version of AES cipher for encryption and decryption, so I think it's good to have aes_ctr32_decrypt
unlike Vale but a lemma for encrypt (decrypt x) == x is to verify the spec itself and not the implementation.
The order of arguments were flipped in the implementation side of F* code, but it doesn't meet the argument order in spec. To make the order consistent, I could either change the order for impl and spec or in libintvector.h I went for the later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks good, and I think we're nearly there!
My final requests before we merge this.
- Please refresh the C code.
- Please fix the naming convention -- @pnmadelaine spent a great deal of time making sure we have something consistent, so let's keep it neat and tidy.
- Please write API documentation using
CComment
syntax (see the bignum files for an example of how to do that, and what would be considered a good style) - Please fix any merge conflicts with main so that we can merge this soon.
Congrats on another good PR and looking forward to merging soon.
(BV.logxor_vec (to_vec128 (to_elem x)) (to_vec128 (to_elem y))) | ||
(Seq.append (Seq.append (Seq.append (Seq.append (Seq.append | ||
(Seq.append (Seq.append (Seq.append (Seq.append (Seq.append | ||
(Seq.append (Seq.append (Seq.append (Seq.append (Seq.append |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would any of these benefit from using FStar.BigOps for readability? this is quite extreme
code/aes/Hacl.AES_128.CTR32.NI.fst
Outdated
|
||
|
||
[@ CInline ] | ||
val aes128_ctr_decrypt: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pnmadelaine can you review this naming convention? I thought with your big PR, we were now trying to avoid redundant prefixes, such as aes128_
or state_
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, this should be named ctr_decrypt
|
||
#include "libintvector.h" | ||
|
||
typedef Lib_IntVector_Intrinsics_vec128 *Hacl_AES_128_CTR32_NI_aes_ctx; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see state_malloc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated C files in gcc-compatible/
I also renamed state_malloc/free
to context_malloc/free
|
||
typedef uint8_t *Hacl_AES_256_CTR32_NI_skey; | ||
|
||
void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, where is malloc/free?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise.
@msprotz @karthikbhargavan what's the state here? |
*/ | ||
void | ||
Hacl_AES_128_CTR32_NI_ctr_encrypt( | ||
uint32_t len, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please avoid one-letter argument names here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
*/ | ||
void | ||
Hacl_AES_128_CTR32_NI_ctr_decrypt( | ||
uint32_t len, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to me once the comments, parameter names, and the little tidbit in the test file are fixed.
I want @pnmadelaine to look closely at the refreshed C header files and confirm whether the naming convention is correct or not. Let's merge only after PNM confirms we're good. Thank you.
Initiate AES-128 context buffer with key expansion and nonce | ||
*/ | ||
void | ||
Hacl_AES_128_CTR32_NI_init(Lib_IntVector_Intrinsics_vec128 *ctx, uint8_t *key, uint8_t *nonce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good to have a comment, but it's rephrasing what's already visible from the name of the function and the arguments. The questions that should be answered by the comment are:
- can I call this after encryption?
- does it reset the state to an initial state? should it be called reset? @pnmadelaine
- does it reset the nonce to zero?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AES-CTR32 API doesn't maintain the state of the counter, that state is supposed to be handled by the caller who is supposed to pass the counter though parameters for Encrypt/Decrypt functions (Proper doc is added to describe that) and this is by design. TBH I don't see what's the point since GCM is the only spec that utilizes this algorithm AES-CTR32
, and basically it's implemented after GCM spec.
tests/Makefile
Outdated
ifneq ($(COMPILE_AESNI),) | ||
CFLAGS += -DHACL_CAN_COMPILE_AESNI | ||
else | ||
TARGETS := $(filter-out aes128-ctr32-ni-test.exe, $(TARGETS)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: just put %-ni-test.exe
here so that future tests are filtered out too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
This PR imports AES-CTR32 modules from
pnmadelaine_aes
branch and adds proofs for NI functions.