logo
pub fn compress512(state: &mut [u64; 8], block: &[u8; 128])
Expand description

Process a block with the SHA-512 algorithm. (See more…)

Internally, this uses functions that resemble the new Intel SHA instruction set extensions, but since no architecture seems to have any designs, these may not be the final designs if and/or when there are instruction set extensions with SHA-512. So to summarize: SHA-1 and SHA-256 are being implemented in hardware soon (at the time of this writing), but it doesn’t look like SHA-512 will be hardware accelerated any time soon.

Implementation

These functions fall into two categories: message schedule calculation, and the message block 64-round digest calculation. The schedule-related functions allow 4 rounds to be calculated as:

use std::simd::u64x2;
use self::crypto::sha2::{
    sha512msg,
    sha512load
};

fn schedule4_data(work: &mut [u64x2], w: &[u64]) {

    // this is to illustrate the data order
    work[0] = u64x2(w[1], w[0]);
    work[1] = u64x2(w[3], w[2]);
    work[2] = u64x2(w[5], w[4]);
    work[3] = u64x2(w[7], w[6]);
    work[4] = u64x2(w[9], w[8]);
    work[5] = u64x2(w[11], w[10]);
    work[6] = u64x2(w[13], w[12]);
    work[7] = u64x2(w[15], w[14]);
}

fn schedule4_work(work: &mut [u64x2], t: usize) {

    // this is the core expression
    work[t] = sha512msg(work[t - 8],
                        work[t - 7],
                        sha512load(work[t - 4], work[t - 3]),
                        work[t - 1]);
}

instead of 4 rounds of:

fn schedule_work(w: &mut [u64], t: usize) {
    w[t] = sigma1!(w[t - 2]) + w[t - 7] + sigma0!(w[t - 15]) + w[t - 16];
}

and the digest-related functions allow 4 rounds to be calculated as:

use std::simd::u64x2;
use self::crypto::sha2::{K64X2, sha512rnd};

fn rounds4(state: &mut [u64; 8], work: &mut [u64x2], t: usize) {
    let [a, b, c, d, e, f, g, h]: [u64; 8] = *state;

    // this is to illustrate the data order
    let mut ae = u64x2(a, e);
    let mut bf = u64x2(b, f);
    let mut cg = u64x2(c, g);
    let mut dh = u64x2(d, h);
    let u64x2(w1, w0) = K64X2[2*t]     + work[2*t];
    let u64x2(w3, w2) = K64X2[2*t + 1] + work[2*t + 1];

    // this is the core expression
    dh = sha512rnd(ae, bf, cg, dh, w0);
    cg = sha512rnd(dh, ae, bf, cg, w1);
    bf = sha512rnd(cg, dh, ae, bf, w2);
    ae = sha512rnd(bf, cg, dh, ae, w3);

    *state = [ae.0, bf.0, cg.0, dh.0,
              ae.1, bf.1, cg.1, dh.1];
}

instead of 4 rounds of:

fn round(state: &mut [u64; 8], w: &mut [u64], t: usize) {
    let [a, b, c, mut d, e, f, g, mut h]: [u64; 8] = *state;

    h += big_sigma1!(e) +   choose!(e, f, g) + K64[t] + w[t]; d += h;
    h += big_sigma0!(a) + majority!(a, b, c);

    *state = [h, a, b, c, d, e, f, g];
}