mirror of
https://github.com/openssl/openssl.git
synced 2024-12-03 05:41:46 +08:00
riscv: aes: Move reusable Perl code into Perl module
Move helper functions and instruction encoding functions into a riscv.pm Perl module to avoid pointless code duplication. Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu> Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20078)
This commit is contained in:
parent
86c69fe841
commit
c8a641c39f
@ -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 {
|
||||
|
101
crypto/perlasm/riscv.pm
Normal file
101
crypto/perlasm/riscv.pm
Normal file
@ -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;
|
Loading…
Reference in New Issue
Block a user