From c8a641c39f524051900feac7175ca7300f151f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Wed, 1 Feb 2023 00:02:33 +0100 Subject: riscv: aes: Move reusable Perl code into Perl module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move helper functions and instruction encoding functions into a riscv.pm Perl module to avoid pointless code duplication. Signed-off-by: Christoph Müllner Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/20078) --- crypto/aes/asm/aes-riscv64-zkn.pl | 201 +++++++++++--------------------------- crypto/perlasm/riscv.pm | 101 +++++++++++++++++++ 2 files changed, 157 insertions(+), 145 deletions(-) create mode 100644 crypto/perlasm/riscv.pm diff --git a/crypto/aes/asm/aes-riscv64-zkn.pl b/crypto/aes/asm/aes-riscv64-zkn.pl index fe4d26eac5..89114b6223 100644 --- a/crypto/aes/asm/aes-riscv64-zkn.pl +++ b/crypto/aes/asm/aes-riscv64-zkn.pl @@ -6,10 +6,18 @@ # in the file LICENSE in the source distribution or at # https://www.openssl.org/source/license.html +use strict; +use warnings; + +use FindBin qw($Bin); +use lib "$Bin"; +use lib "$Bin/../../perlasm"; +use riscv; + # $output is the last argument if it looks like a file (it has an extension) # $flavour is the first argument if it doesn't look like a file -$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; -$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; +my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $output and open STDOUT,">$output"; @@ -69,103 +77,6 @@ $output and open STDOUT,">$output"; } } -################################################################################ -# util for encoding scalar crypto extension instructions -################################################################################ - -my @regs = map("x$_",(0..31)); -my %reglookup; -@reglookup{@regs} = @regs; - -# Takes a register name, possibly an alias, and converts it to a register index -# from 0 to 31 -sub read_reg { - my $reg = lc shift; - if (!exists($reglookup{$reg})) { - die("Unknown register ".$reg); - } - my $regstr = $reglookup{$reg}; - if (!($regstr =~ /^x([0-9]+)$/)) { - die("Could not process register ".$reg); - } - return $1; -} - -sub rv64_aes64ds { - # Encoding for aes64ds rd, rs1, rs2 instruction on RV64 - # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX - my $template = 0b0011101_00000_00000_000_00000_0110011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - my $rs2 = read_reg shift; - - return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); -} - -sub rv64_aes64dsm { - # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64 - # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX - my $template = 0b0011111_00000_00000_000_00000_0110011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - my $rs2 = read_reg shift; - - return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); -} - -sub rv64_aes64es { - # Encoding for aes64es rd, rs1, rs2 instruction on RV64 - # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX - my $template = 0b0011001_00000_00000_000_00000_0110011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - my $rs2 = read_reg shift; - - return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); -} - -sub rv64_aes64esm { - # Encoding for aes64esm rd, rs1, rs2 instruction on RV64 - # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX - my $template = 0b0011011_00000_00000_000_00000_0110011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - my $rs2 = read_reg shift; - - return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); -} - -sub rv64_aes64im { - # Encoding for aes64im rd, rs1 instruction on RV64 - # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX - my $template = 0b001100000000_00000_001_00000_0010011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - - return ".word ".($template | ($rs1 << 15) | ($rd << 7)); -} - -sub rv64_aes64ks1i { - # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64 - # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX - my $template = 0b00110001_0000_00000_001_00000_0010011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - my $rnum = shift; - - return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7)); -} - -sub rv64_aes64ks2 { - # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64 - # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX - my $template = 0b0111111_00000_00000_000_00000_0110011; - my $rd = read_reg shift; - my $rs1 = read_reg shift; - my $rs2 = read_reg shift; - - return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); -} ################################################################################ # Register assignment for rv64i_zkne_encrypt and rv64i_zknd_decrypt ################################################################################ @@ -219,8 +130,8 @@ $code .= <<___; # Do Nr - 1 rounds (final round is special) 1: - @{[rv64_aes64esm $Q2,$Q0,$Q1]} - @{[rv64_aes64esm $Q3,$Q1,$Q0]} + @{[aes64esm $Q2,$Q0,$Q1]} + @{[aes64esm $Q3,$Q1,$Q0]} # Update key ptr to point to next key in schedule add $KEYP,$KEYP,16 @@ -235,8 +146,8 @@ $code .= <<___; bgtz $loopcntr,1b # final round - @{[rv64_aes64es $Q2,$Q0,$Q1]} - @{[rv64_aes64es $Q3,$Q1,$Q0]} + @{[aes64es $Q2,$Q0,$Q1]} + @{[aes64es $Q3,$Q1,$Q0]} # since not added 16 before ld $T0,16($KEYP) @@ -293,8 +204,8 @@ $code .= <<___; # Do Nr - 1 rounds (final round is special) 1: - @{[rv64_aes64dsm $Q2,$Q0,$Q1]} - @{[rv64_aes64dsm $Q3,$Q1,$Q0]} + @{[aes64dsm $Q2,$Q0,$Q1]} + @{[aes64dsm $Q3,$Q1,$Q0]} # Update key ptr to point to next key in schedule add $KEYP,$KEYP,-16 @@ -309,8 +220,8 @@ $code .= <<___; bgtz $loopcntr,1b # final round - @{[rv64_aes64ds $Q2,$Q0,$Q1]} - @{[rv64_aes64ds $Q3,$Q1,$Q0]} + @{[aes64ds $Q2,$Q0,$Q1]} + @{[aes64ds $Q3,$Q1,$Q0]} add $KEYP,$KEYP,-16 ld $T0,0($KEYP) @@ -356,9 +267,9 @@ $ret .= <<___; ___ while($rnum < 10) { $ret .= <<___; - @{[rv64_aes64ks1i $T2,$T1,$rnum]} - @{[rv64_aes64ks2 $T0,$T2,$T0]} - @{[rv64_aes64ks2 $T1,$T0,$T1]} + @{[aes64ks1i $T2,$T1,$rnum]} + @{[aes64ks2 $T0,$T2,$T0]} + @{[aes64ks2 $T1,$T0,$T1]} add $KEYP,$KEYP,16 sd $T0,0($KEYP) sd $T1,8($KEYP) @@ -381,15 +292,15 @@ $ret .= <<___; ___ while($rnum < 8) { $ret .= <<___; - @{[rv64_aes64ks1i $T3,$T2,$rnum]} - @{[rv64_aes64ks2 $T0,$T3,$T0]} - @{[rv64_aes64ks2 $T1,$T0,$T1]} + @{[aes64ks1i $T3,$T2,$rnum]} + @{[aes64ks2 $T0,$T3,$T0]} + @{[aes64ks2 $T1,$T0,$T1]} ___ if ($rnum != 7) { # note that (8+1)*24 = 216, (12+1)*16 = 208 # thus the last 8 bytes can be dropped $ret .= <<___; - @{[rv64_aes64ks2 $T2,$T1,$T2]} + @{[aes64ks2 $T2,$T1,$T2]} ___ } $ret .= <<___; @@ -422,9 +333,9 @@ $ret .= <<___; ___ while($rnum < 7) { $ret .= <<___; - @{[rv64_aes64ks1i $T4,$T3,$rnum]} - @{[rv64_aes64ks2 $T0,$T4,$T0]} - @{[rv64_aes64ks2 $T1,$T0,$T1]} + @{[aes64ks1i $T4,$T3,$rnum]} + @{[aes64ks2 $T0,$T4,$T0]} + @{[aes64ks2 $T1,$T0,$T1]} add $KEYP,$KEYP,32 sd $T0,0($KEYP) sd $T1,8($KEYP) @@ -433,9 +344,9 @@ ___ # note that (7+1)*32 = 256, (14+1)*16 = 240 # thus the last 16 bytes can be dropped $ret .= <<___; - @{[rv64_aes64ks1i $T4,$T1,0xA]} - @{[rv64_aes64ks2 $T2,$T4,$T2]} - @{[rv64_aes64ks2 $T3,$T2,$T3]} + @{[aes64ks1i $T4,$T1,0xA]} + @{[aes64ks2 $T2,$T4,$T2]} + @{[aes64ks2 $T3,$T2,$T3]} sd $T2,16($KEYP) sd $T3,24($KEYP) ___ @@ -515,9 +426,9 @@ $ret .= <<___; ___ while($rnum < 10) { $ret .= <<___; - @{[rv64_aes64ks1i $T2,$T1,$rnum]} - @{[rv64_aes64ks2 $T0,$T2,$T0]} - @{[rv64_aes64ks2 $T1,$T0,$T1]} + @{[aes64ks1i $T2,$T1,$rnum]} + @{[aes64ks2 $T0,$T2,$T0]} + @{[aes64ks2 $T1,$T0,$T1]} add $KEYP,$KEYP,16 ___ # need to aes64im for [1:N-1] round keys @@ -528,9 +439,9 @@ ___ # transform should then be done on the round key if ($rnum < 9) { $ret .= <<___; - @{[rv64_aes64im $T2,$T0]} + @{[aes64im $T2,$T0]} sd $T2,0($KEYP) - @{[rv64_aes64im $T2,$T1]} + @{[aes64im $T2,$T1]} sd $T2,8($KEYP) ___ } else { @@ -553,25 +464,25 @@ $ret .= <<___; ld $T2,16($UKEY) sd $T0,0($KEYP) sd $T1,8($KEYP) - @{[rv64_aes64im $T3,$T2]} + @{[aes64im $T3,$T2]} sd $T3,16($KEYP) ___ while($rnum < 8) { $ret .= <<___; - @{[rv64_aes64ks1i $T3,$T2,$rnum]} - @{[rv64_aes64ks2 $T0,$T3,$T0]} - @{[rv64_aes64ks2 $T1,$T0,$T1]} + @{[aes64ks1i $T3,$T2,$rnum]} + @{[aes64ks2 $T0,$T3,$T0]} + @{[aes64ks2 $T1,$T0,$T1]} add $KEYP,$KEYP,24 ___ if ($rnum < 7) { $ret .= <<___; - @{[rv64_aes64im $T3,$T0]} + @{[aes64im $T3,$T0]} sd $T3,0($KEYP) - @{[rv64_aes64im $T3,$T1]} + @{[aes64im $T3,$T1]} sd $T3,8($KEYP) # the reason is in ke192enc - @{[rv64_aes64ks2 $T2,$T1,$T2]} - @{[rv64_aes64im $T3,$T2]} + @{[aes64ks2 $T2,$T1,$T2]} + @{[aes64im $T3,$T2]} sd $T3,16($KEYP) ___ } else { # rnum == 7 @@ -595,30 +506,30 @@ $ret .= <<___; ld $T3,24($UKEY) sd $T0,0($KEYP) sd $T1,8($KEYP) - @{[rv64_aes64im $T4,$T2]} + @{[aes64im $T4,$T2]} sd $T4,16($KEYP) - @{[rv64_aes64im $T4,$T3]} + @{[aes64im $T4,$T3]} sd $T4,24($KEYP) ___ while($rnum < 7) { $ret .= <<___; - @{[rv64_aes64ks1i $T4,$T3,$rnum]} - @{[rv64_aes64ks2 $T0,$T4,$T0]} - @{[rv64_aes64ks2 $T1,$T0,$T1]} + @{[aes64ks1i $T4,$T3,$rnum]} + @{[aes64ks2 $T0,$T4,$T0]} + @{[aes64ks2 $T1,$T0,$T1]} add $KEYP,$KEYP,32 ___ if ($rnum < 6) { $ret .= <<___; - @{[rv64_aes64ks1i $T4,$T1,0xA]} - @{[rv64_aes64ks2 $T2,$T4,$T2]} - @{[rv64_aes64ks2 $T3,$T2,$T3]} - @{[rv64_aes64im $T4,$T0]} + @{[aes64ks1i $T4,$T1,0xA]} + @{[aes64ks2 $T2,$T4,$T2]} + @{[aes64ks2 $T3,$T2,$T3]} + @{[aes64im $T4,$T0]} sd $T4,0($KEYP) - @{[rv64_aes64im $T4,$T1]} + @{[aes64im $T4,$T1]} sd $T4,8($KEYP) - @{[rv64_aes64im $T4,$T2]} + @{[aes64im $T4,$T2]} sd $T4,16($KEYP) - @{[rv64_aes64im $T4,$T3]} + @{[aes64im $T4,$T3]} sd $T4,24($KEYP) ___ } else { diff --git a/crypto/perlasm/riscv.pm b/crypto/perlasm/riscv.pm new file mode 100644 index 0000000000..384ac5f385 --- /dev/null +++ b/crypto/perlasm/riscv.pm @@ -0,0 +1,101 @@ +#! /usr/bin/env perl +# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use warnings; + +my @regs = map("x$_",(0..31)); +my %reglookup; +@reglookup{@regs} = @regs; + +# Takes a register name, possibly an alias, and converts it to a register index +# from 0 to 31 +sub read_reg { + my $reg = lc shift; + if (!exists($reglookup{$reg})) { + die("Unknown register ".$reg); + } + my $regstr = $reglookup{$reg}; + if (!($regstr =~ /^x([0-9]+)$/)) { + die("Could not process register ".$reg); + } + return $1; +} + +# Scalar crypto instructions + +sub aes64ds { + # Encoding for aes64ds rd, rs1, rs2 instruction on RV64 + # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX + my $template = 0b0011101_00000_00000_000_00000_0110011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + my $rs2 = read_reg shift; + return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); +} + +sub aes64dsm { + # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64 + # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX + my $template = 0b0011111_00000_00000_000_00000_0110011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + my $rs2 = read_reg shift; + return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); +} + +sub aes64es { + # Encoding for aes64es rd, rs1, rs2 instruction on RV64 + # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX + my $template = 0b0011001_00000_00000_000_00000_0110011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + my $rs2 = read_reg shift; + return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); +} + +sub aes64esm { + # Encoding for aes64esm rd, rs1, rs2 instruction on RV64 + # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX + my $template = 0b0011011_00000_00000_000_00000_0110011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + my $rs2 = read_reg shift; + return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); +} + +sub aes64im { + # Encoding for aes64im rd, rs1 instruction on RV64 + # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX + my $template = 0b001100000000_00000_001_00000_0010011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + return ".word ".($template | ($rs1 << 15) | ($rd << 7)); +} + +sub aes64ks1i { + # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64 + # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX + my $template = 0b00110001_0000_00000_001_00000_0010011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + my $rnum = shift; + return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7)); +} + +sub aes64ks2 { + # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64 + # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX + my $template = 0b0111111_00000_00000_000_00000_0110011; + my $rd = read_reg shift; + my $rs1 = read_reg shift; + my $rs2 = read_reg shift; + return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7)); +} + +1; -- cgit v1.2.3