Skip to content
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

Adding Key Locker intrinsics #1223

Open
ethindp opened this issue Sep 25, 2021 · 5 comments
Open

Adding Key Locker intrinsics #1223

ethindp opened this issue Sep 25, 2021 · 5 comments

Comments

@ethindp
Copy link

ethindp commented Sep 25, 2021

So, Intel recently released the Intel Key Locker specification, defining new functionality within new Intel CPUs for the AES cryptographic domain. These are the AESENCKL, AESENCWIDEKL, AESDECKL, AESDECWIDEKL, ENCODEKEY*, and LOADIWKEY instructions.
These use SIMD vectors and SIMD technology, however I don't know if they fit into a particular target feature domain (e.g. SSE). I would presume, however, that they are at least SSE2. Clang does not (yet) appear to implement them though, and I don't think any processors exist (at least within the consumer market) that implement Intel KL, so we'd need to mock the tests somehow. Is it worth implementing KL intrinsics at this time?

@Amanieu
Copy link
Member

Amanieu commented Sep 25, 2021

We first need these intrinsics to be implemented in Clang because we need LLVM to support these instructions. After that, it should be fairly straightforward to port them to Rust.

@ethindp
Copy link
Author

ethindp commented Sep 26, 2021

As of commit 413577a87904, Clang supports key locker. I'm just unsure how to port them -- they use pointers. Are there any special rules I need to follow to port them to Rust? Or can I just use *mut c_void? According to Clang, the handles are __m128s, or are type-cast to __m128s:

/// Wrap a 128-bit AES key from __key into a key handle and output in
/// ((__m128i*)__h) to ((__m128i*)__h) + 2  and a 32-bit value as return.
/// The explicit source operand __htype specifies handle restrictions.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> ENCODEKEY128 </c> instructions.
///
/// \operation
/// InputKey[127:0] := __key[127:0]
/// KeyMetadata[2:0] := __htype[2:0]
/// KeyMetadata[23:3] := 0 // Reserved for future usage
/// KeyMetadata[27:24] := 0 // KeyType is AES-128 (value of 0)
/// KeyMetadata[127:28] := 0 // Reserved for future usage
/// Handle[383:0] := WrapKey128(InputKey[127:0], KeyMetadata[127:0],
///                  IWKey.Integrity Key[127:0], IWKey.Encryption Key[255:0])
/// dst[0] := IWKey.NoBackup
/// dst[4:1] := IWKey.KeySource[3:0]
/// dst[31:5] := 0
/// MEM[__h+127:__h] := Handle[127:0]   // AAD
/// MEM[__h+255:__h+128] := Handle[255:128] // Integrity Tag
/// MEM[__h+383:__h+256] := Handle[383:256] // CipherText
/// OF := 0
/// SF := 0
/// ZF := 0
/// AF := 0
/// PF := 0
/// CF := 0
/// \endoperation
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_mm_encodekey128_u32(unsigned int __htype, __m128i __key, void *__h) {
  return __builtin_ia32_encodekey128_u32(__htype, (__v2di)__key, __h);
}

@Amanieu
Copy link
Member

Amanieu commented Sep 26, 2021

You can use *mut u8 for void pointers. You can find the definitions of the LLVM intrinsics that you need to link to in llvm/test/CodeGen/X86/keylocker-intrinsics.ll. They take multiple arguments and return a struct of multiple values.

@ethindp
Copy link
Author

ethindp commented Sep 27, 2021

Okay, so I've found the intrinsics to link to (llvm.x86.loadiwkey, llvm.x86.encodekey128, llvm.x86.encodekey256, llvm.x86.aesenc128kl, llvm.x86.aesdec128kl, llvm.x86.aesenc256kl, llvm.x86.aesdec256kl, llvm.x86.aesencwide128kl, llvm.x86.aesdecwide128kl, llvm.x86.aesencwide256kl, and llvm.x86.aesdecwide256kl). Why do I need these and what's next?

@Amanieu
Copy link
Member

Amanieu commented Sep 28, 2021

I'd recommend having a look at crates/core_arch/src/x86/aes.rs as an example of what to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants