RustCrypto / traits

Collection of cryptography-related traits
569 stars 183 forks source link

cipher: Block alignment #159

Open nickray opened 4 years ago

nickray commented 4 years ago

Some hardware implementations (e.g. of AES) need particular alignment of blocks to operate directly over AHB (e.g. NXP LPC55's HASHCRYPT wants 32-bit alignment, I can imagine this is a typical case for ARM microcontrollers). If a large chunk of data needs to be en/de-crypted that's aligned, it would be neat to pass this information through on the type level to avoid stack copies for each block.

The aligned crate (which is sadly missing an A1 type) would be one approach to do it, set

pub type Block<B> = aligned::Aligned<
    <B as BlockCipher>::BlockAlignment, 
    GenericArray<u8, <B as BlockCipher>::BlockSize>
>;

Splitting this out from https://github.com/RustCrypto/traits/issues/43 for possible discussion.

tarcieri commented 4 years ago

My suggestion on #43 was to have an associated Block type which can have a #[repr(align(...))]

nickray commented 4 years ago

Yeah, that might even be easier to parse mentally than having Block generic over "B" :)

tarcieri commented 4 years ago

We use generic-array for other types like keys because there are real-world cases where they are larger than 32-bytes (e.g. AES-SIV), because 32-bytes special case for trait impls in pre-const generics Rust.

Blocks are a legitimate case where in practice they will probably never be larger than 32-bytes.

newpavlov commented 4 years ago

I am not sure if such change will be practical, at least with the current state of the Rust language. Don't forget that we build other APIs on top of BlockCipher. Such change would either require bubbling alignment restrictions to higher-level APIs and thus removing the convenience of using &mut [u8], or we would have to keep two parallel sets of methods with and without those restrictions.

On modern x86 unaligned loads of aligned pointers have the same performance, but unfortunately it's indeed not true for ARM...

UPD: We could potentially check alignment and switch between aligned and unaligned loads at runtime, but it would add a branch at each block/parblock computation, which is certainly not ideal, but could be tolerable.