From 80b8b33f7dd61b4f557c4237a124b104ef1fa425 Mon Sep 17 00:00:00 2001 From: Julian Zhu Date: Mon, 7 Sep 2026 12:33:25 +0800 Subject: RISC-V: handle misaligned input in the SHA-512 core Build each doubleword from two aligned loads when the input is misaligned, as for SHA-256, instead of relying on slow misaligned ld. Signed-off-by: Julian Zhu Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz Merge-date: Fri Oct 2 08:26:49 2026 Merged-from: https://github.com/openssl/openssl/pull/33008 (cherry picked from commit 4f307857f9bde35039517e55468e929560a716ff) --- crypto/sha/asm/sha512-riscv64-zbb.pl | 73 ++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/crypto/sha/asm/sha512-riscv64-zbb.pl b/crypto/sha/asm/sha512-riscv64-zbb.pl index 142c32b3a6e..7edae831d92 100644 --- a/crypto/sha/asm/sha512-riscv64-zbb.pl +++ b/crypto/sha/asm/sha512-riscv64-zbb.pl @@ -62,15 +62,34 @@ my $K512 = "K512"; # Function arguments my ($INP, $LEN, $ADDR) = ("a1", "a2", "sp"); my ($KT, $T1, $T2, $T3, $T4, $T5, $T6) = ("t0", "t1", "t2", "t3", "t4", "t5", "t6"); +# Shift amounts for misaligned input +my ($SHL, $SHR) = ("a3", "a4"); +my ($MISALIGNED_INPUT, $ALIGNED_INPUT) = (0, 1); # Parity-indexed pairs: W = W[i], U = W[i-15], X = a ^ b my ($W0, $W1, $U0, $U1, $X0, $X1) = ("a5", "a6", "a7", "s0", "s1", "s10"); my ($A, $B, $C, $D ,$E ,$F ,$G ,$H) = ("s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9"); +# Misaligned: $dst = (lo >> SHL) | (hi << SHR) from two aligned loads +sub loadDword { + my ($ALIGNED, $dst, $off) = @_; + if ($ALIGNED) { + return "ld $dst, $off($INP)"; + } + my $code=<<___; + ld $T5, $off($INP) + ld $T6, ($off+8)($INP) + srl $dst, $T5, $SHL + sll $T6, $T6, $SHR + or $dst, $dst, $T6 +___ + return $code; +} + sub MSGSCHEDULE0 { - my ($index) = @_; + my ($ALIGNED, $index) = @_; my $Wi = ($index & 1) ? $W1 : $W0; my $code=<<___; - ld $Wi, 8*$index($INP) + @{[loadDword $ALIGNED, $Wi, "8*$index"]} @{[rev8 $Wi, $Wi]} sd $Wi, 8*$index($ADDR) ___ @@ -165,9 +184,9 @@ ___ } sub SHA512ROUND0 { - my ($INDEX, $a, $b, $c, $d, $e, $f, $g, $h) = @_; + my ($ALIGNED, $INDEX, $a, $b, $c, $d, $e, $f, $g, $h) = @_; my $code=<<___; - @{[MSGSCHEDULE0 $INDEX]} + @{[MSGSCHEDULE0 $ALIGNED, $INDEX]} @{[SHA512ROUND $INDEX, $a, $b, $c, $d, $e, $f, $g, $h]} ___ @@ -184,6 +203,7 @@ ___ return $code; } + ################################################################################ # void sha512_block_data_order_zbb(void *c, const void *p, size_t len) $code .= <<___; @@ -221,28 +241,57 @@ sha512_block_data_order_zbb: ld $G, 48(a0) ld $H, 56(a0) + andi $SHL, $INP, 7 + beqz $SHL, L_round_loop + andi $INP, $INP, -8 + slli $SHL, $SHL, 3 + li $T1, 64 + sub $SHR, $T1, $SHL + L_round_loop: # Decrement length by 1 addi $LEN, $LEN, -1 # b ^ c for round 0's Maj; later rounds reuse the previous a ^ b xor $X1, $B, $C + + bnez $SHL, L_load_misaligned +___ + +# Rounds 0..15, once for aligned and once for misaligned input +for (my $i = 0; $i < 16; $i += 8) { + $code .= <<___; + @{[SHA512ROUND0 $ALIGNED_INPUT, $i, $A, $B, $C, $D, $E, $F, $G, $H]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+1, $H, $A, $B, $C, $D, $E, $F, $G]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+2, $G, $H, $A, $B, $C, $D, $E, $F]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+3, $F, $G, $H, $A, $B, $C, $D, $E]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+4, $E, $F, $G, $H, $A, $B, $C, $D]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+5, $D, $E, $F, $G, $H, $A, $B, $C]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+6, $C, $D, $E, $F, $G, $H, $A, $B]} + @{[SHA512ROUND0 $ALIGNED_INPUT, $i+7, $B, $C, $D, $E, $F, $G, $H, $A]} +___ +} + +$code .= <<___; + j L_message_schedule +L_load_misaligned: ___ for (my $i = 0; $i < 16; $i += 8) { $code .= <<___; - @{[SHA512ROUND0 $i, $A, $B, $C, $D, $E, $F, $G, $H]} - @{[SHA512ROUND0 $i+1, $H, $A, $B, $C, $D, $E, $F, $G]} - @{[SHA512ROUND0 $i+2, $G, $H, $A, $B, $C, $D, $E, $F]} - @{[SHA512ROUND0 $i+3, $F, $G, $H, $A, $B, $C, $D, $E]} - @{[SHA512ROUND0 $i+4, $E, $F, $G, $H, $A, $B, $C, $D]} - @{[SHA512ROUND0 $i+5, $D, $E, $F, $G, $H, $A, $B, $C]} - @{[SHA512ROUND0 $i+6, $C, $D, $E, $F, $G, $H, $A, $B]} - @{[SHA512ROUND0 $i+7, $B, $C, $D, $E, $F, $G, $H, $A]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i, $A, $B, $C, $D, $E, $F, $G, $H]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+1, $H, $A, $B, $C, $D, $E, $F, $G]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+2, $G, $H, $A, $B, $C, $D, $E, $F]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+3, $F, $G, $H, $A, $B, $C, $D, $E]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+4, $E, $F, $G, $H, $A, $B, $C, $D]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+5, $D, $E, $F, $G, $H, $A, $B, $C]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+6, $C, $D, $E, $F, $G, $H, $A, $B]} + @{[SHA512ROUND0 $MISALIGNED_INPUT, $i+7, $B, $C, $D, $E, $F, $G, $H, $A]} ___ } $code .= <<___; +L_message_schedule: # Round 16's W[i-16] is W[0]; later rounds reuse the previous W[i-15] ld $U1, 0($ADDR) ___ -- cgit