diff options
author | Andy Polyakov <appro@openssl.org> | 2014-06-06 21:27:18 +0200 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2014-06-10 22:51:15 +0200 |
commit | 3a97ebb16b0d1eaab83171b9220280dacd99bf04 (patch) | |
tree | 89717093f8561e28fc5e6c40e02c8411d8eb0f48 /crypto/sha | |
parent | 16f4d2e32f1ea6cfa668ae64493998ae51db7e51 (diff) |
ARM assembly pack: get ARMv7 instruction endianness right.
Pointer out and suggested by: Ard Biesheuvel.
(cherry picked from commit 5dcf70a1c57c2019bfad640fe14fd4a73212860a)
Diffstat (limited to 'crypto/sha')
-rw-r--r-- | crypto/sha/asm/sha1-armv4-large.pl | 20 | ||||
-rw-r--r-- | crypto/sha/asm/sha256-armv4.pl | 20 | ||||
-rw-r--r-- | crypto/sha/asm/sha512-armv4.pl | 3 |
3 files changed, 28 insertions, 15 deletions
diff --git a/crypto/sha/asm/sha1-armv4-large.pl b/crypto/sha/asm/sha1-armv4-large.pl index 43a1b9fd7f..50bd07b331 100644 --- a/crypto/sha/asm/sha1-armv4-large.pl +++ b/crypto/sha/asm/sha1-armv4-large.pl @@ -631,7 +631,7 @@ $code.=<<___; vst1.32 {$E\[0]},[$ctx] vldmia sp!,{d8-d15} - bx lr + ret @ bx lr .size sha1_block_data_order_armv8,.-sha1_block_data_order_armv8 #endif ___ @@ -648,13 +648,18 @@ ___ sub unsha1 { my ($mnemonic,$arg)=@_; - $arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o - && - sprintf ".long\t0x%08x\t@ %s %s", - $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) - |(($2&7)<<17)|(($2&8)<<4) - |(($3&7)<<1) |(($3&8)<<2), + if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, $mnemonic,$arg; + } } } @@ -664,6 +669,7 @@ foreach (split($/,$code)) { s/\b(sha1\w+)\s+(q.*)/unsha1($1,$2)/geo; + s/\bret\b/bx lr/o or s/\bbx\s+lr\b/.word\t0xe12fff1e/o; # make it possible to compile with -march=armv4 print $_,$/; diff --git a/crypto/sha/asm/sha256-armv4.pl b/crypto/sha/asm/sha256-armv4.pl index 5e5c54ec18..505ca8f350 100644 --- a/crypto/sha/asm/sha256-armv4.pl +++ b/crypto/sha/asm/sha256-armv4.pl @@ -608,7 +608,7 @@ $code.=<<___; vst1.32 {$ABCD,$EFGH},[$ctx] - bx lr + ret @ bx lr .size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8 #endif ___ @@ -626,13 +626,18 @@ ___ sub unsha256 { my ($mnemonic,$arg)=@_; - $arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o - && - sprintf ".long\t0x%08x\t@ %s %s", - $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) - |(($2&7)<<17)|(($2&8)<<4) - |(($3&7)<<1) |(($3&8)<<2), + if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) { + my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19) + |(($2&7)<<17)|(($2&8)<<4) + |(($3&7)<<1) |(($3&8)<<2); + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( + sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, $mnemonic,$arg; + } } } @@ -642,6 +647,7 @@ foreach (split($/,$code)) { s/\b(sha256\w+)\s+(q.*)/unsha256($1,$2)/geo; + s/\bret\b/bx lr/go or s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4 print $_,"\n"; diff --git a/crypto/sha/asm/sha512-armv4.pl b/crypto/sha/asm/sha512-armv4.pl index d3065794b3..1d5275b917 100644 --- a/crypto/sha/asm/sha512-armv4.pl +++ b/crypto/sha/asm/sha512-armv4.pl @@ -584,7 +584,7 @@ $code.=<<___; bne .Loop_neon vldmia sp!,{d8-d15} @ epilogue - bx lr + ret @ bx lr #endif ___ } @@ -597,5 +597,6 @@ ___ $code =~ s/\`([^\`]*)\`/eval $1/gem; $code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4 +$code =~ s/\bret\b/bx lr/gm; print $code; close STDOUT; # enforce flush |