Skip to content

Bug in Sha512 AVX(2) implementation #344

Closed
@elichai

Description

@elichai

I found a bug in Sha512 AVX2 implementation and I'm not sure what's the nicest fix.
to trigger the bug I ran the following code:

use sha2::{Digest, Sha512};
fn main() {
    let mut h = Sha512::new();
    h.update(&[0u8; 300]);
    println!("{:?}", h.finalize());
}

With these flags: RUSTFLAGS='-Clink-arg=-fuse-ld=lld -Clinker-plugin-lto' cargo r
Output:
Segmentation fault (core dumped)

The source of the bug is here: https://github.com/RustCrypto/hashes/blob/c478cbb/sha2/src/sha512/x86.rs#L117
_mm_store_si128 is used with a pointer to a u64 array, which is aligned to 8 and not to 16 as the instruction requires.
(there are a lot of places that assume that MsgSchedule and RoundStates are aligned to 16 bytes while this is in fact false)

We need to make them aligned correctly, there are a few ways I see how this can be done:

  1. Make 2 structs with repr(align(16)) and implement Index/IndexMut with all the Range* variants.
  2. Make 2 structs with repr(align(16)) and transmute their mutable reference to a mutable reference to u64's.
  3. Make a Align16 type and replace these with arrays of that type, and add a function to receive the lower and higher part of that type.

(we can cut boilerplate of 1 in half via const generics)

Would appreciate thoughts before I implement anything as the first one has a lot of boilerplate code in it.

(P.S. You might notice that &mut ms[2 * $i] as *mut u64 as *mut _ is also a bug because it takes a mutable reference to a single u64 and casts it into a pointer with size 2*64, so reading from that violates Stack Borrows, but that's easier to fix via ms[2 * $i.. 2 * $i + 2].as_mut_ptr() as *mut u64 as *mut _ )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions