diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2012-10-04 13:27:11 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2012-10-04 13:27:11 +0000 |
commit | c616200172f922718c7200002470a48d31ec4fb5 (patch) | |
tree | 4e4444efb31b89b58de6c75e38e47584a7869179 | |
parent | 7b899c10cd9ff366ef834615ecaabed8629edc06 (diff) |
Add support for Windows CE and C64+ to FIPS module.
47 files changed, 4749 insertions, 97 deletions
@@ -610,12 +610,14 @@ my %table=( "uClinux-dist","$ENV{'CC'}:\$(CFLAGS)::-D_REENTRANT::\$(LDFLAGS) \$(LDLIBS):BN_LLONG:${no_asm}:$ENV{'LIBSSL_dlfcn'}:linux-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):$ENV{'RANLIB'}::", "uClinux-dist64","$ENV{'CC'}:\$(CFLAGS)::-D_REENTRANT::\$(LDFLAGS) \$(LDLIBS):SIXTY_FOUR_BIT_LONG:${no_asm}:$ENV{'LIBSSL_dlfcn'}:linux-shared:-fPIC:-shared:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):$ENV{'RANLIB'}::", +"c64xplus","cl6x:-mv6400+ -o2 -ox -ms -pden -DNO_SYS_TYPES_H -DGETPID_IS_MEANINGLESS -DMD32_REG_T=int -DOPENSSL_SMALL_FOOTPRINT:<c6x.h>::DSPBIOS::BN_LLONG:c64xpluscpuid.o:bn-c64xplus.o c64xplus-gf2m.o::aes-c64xplus.o aes_cbc.o aes_ctr.o:::sha1-c64xplus.o sha256-c64xplus.o sha512-c64xplus.o:::::::ghash-c64xplus.o::void:", + ); my @MK1MF_Builds=qw(VC-WIN64I VC-WIN64A debug-VC-WIN64I debug-VC-WIN64A VC-NT VC-CE VC-WIN32 debug-VC-WIN32 - BC-32 + BC-32 c64xplus netware-clib netware-clib-bsdsock netware-libc netware-libc-bsdsock); diff --git a/Makefile.fips b/Makefile.fips index 157e901099..74db06574b 100644 --- a/Makefile.fips +++ b/Makefile.fips @@ -186,7 +186,7 @@ SHARED_LDFLAGS= GENERAL= Makefile BASENAME= openssl NAME= $(BASENAME)-$(VERSION) -TARFILE= openssl-fips-2.0-test.tar +TARFILE= openssl-fips-2.0.tar WTARFILE= $(NAME)-win.tar EXHEADER= e_os2.h HEADER= e_os.h diff --git a/c6x/do_fips b/c6x/do_fips new file mode 100644 index 0000000000..c1c29fcf83 --- /dev/null +++ b/c6x/do_fips @@ -0,0 +1,7 @@ +#!/bin/sh + +perl Configure c64xplus fipscanisteronly no-engine +perl util/mkfiles.pl > MINFO +perl util/mk1mf.pl auto > c6x/fips.mak +make -f c6x/fips.mak +make -f c6x/fips_algvs.mak diff --git a/c6x/env b/c6x/env new file mode 100644 index 0000000000..543d33081e --- /dev/null +++ b/c6x/env @@ -0,0 +1,7 @@ +# MSYS-style PATH +export PATH=/c/CCStudio_v3.3/c6000/cgtools/bin:/c/Program\ Files/ActivePerl58/bin:$PATH + +# Windows-style variables +export C6X_C_DIR='C:\CCStudio_v3.3\c6000\cgtools\include;C:\CCStudio_v3.3\c6000\cgtools\lib' + +export PERL5LIB=C:/CCStudio_v3.3/bin/utilities/ccs_scripting diff --git a/c6x/fips_standalone_sha1 b/c6x/fips_standalone_sha1 new file mode 100644 index 0000000000..ea2268cb4e --- /dev/null +++ b/c6x/fips_standalone_sha1 @@ -0,0 +1,32 @@ +#!/usr/bin/env perl +# +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + +unshift(@INC,$dir); +require "hmac_sha1.pl"; + +(!@ARV[0] && -f @ARGV[$#ARGV]) || die "usage: $0 [-verify] file"; + +$verify=shift if (@ARGV[0] eq "-verify"); + +sysopen(FD,@ARGV[0],0) || die "$!"; +binmode(FD); + +my $ctx = HMAC->Init("etaonrishdlcupfm"); + +while (read(FD,$blob,4*1024)) { $ctx->Update($blob); } + +close(FD); + +my $signature = unpack("H*",$ctx->Final()); + +print "HMAC-SHA1(@ARGV[0])= $signature\n"; + +if ($verify) { + open(FD,"<@ARGV[0].sha1") || die "$!"; + $line = <FD>; + close(FD); + exit(0) if ($line =~ /HMAC\-SHA1\([^\)]*\)=\s*([0-9a-f]+)/i && + $1 eq $signature); + die "signature mismatch"; +} diff --git a/c6x/fipscanister.cmd b/c6x/fipscanister.cmd new file mode 100644 index 0000000000..a06ee15cb3 --- /dev/null +++ b/c6x/fipscanister.cmd @@ -0,0 +1,19 @@ +SECTIONS +{ + .text: + { + *(.fips_text:start) + *(.text) + *(.const:aes_asm) + *(.const:sha_asm) + *(.const:des_sptrans) + *(.switch) + *(.fips_text:end) + } + .const: + { + *(.fips_const:start) + *(.const) + *(.fips_const:end) + } +} diff --git a/c6x/hmac_sha1.pl b/c6x/hmac_sha1.pl new file mode 100644 index 0000000000..494f7e8569 --- /dev/null +++ b/c6x/hmac_sha1.pl @@ -0,0 +1,196 @@ +#!/usr/bin/env perl +# +# Copyright (c) 2011 The OpenSSL Project. +# +###################################################################### +# +# SHA1 and HMAC in Perl by <appro@openssl.org>. +# +{ package SHA1; + use integer; + + { + ################################### SHA1 block code generator + my @V = ('$A','$B','$C','$D','$E'); + my $i; + + sub XUpdate { + my $ret; + $ret="(\$T=\$W[($i-16)%16]^\$W[($i-14)%16]^\$W[($i-8)%16]^\$W[($i-3)%16],\n\t"; + if ((1<<31)<<1) { + $ret.=" \$W[$i%16]=((\$T<<1)|(\$T>>31))&0xffffffff)\n\t "; + } else { + $ret.=" \$W[$i%16]=(\$T<<1)|((\$T>>31)&1))\n\t "; + } + } + sub tail { + my ($a,$b,$c,$d,$e)=@V; + my $ret; + if ((1<<31)<<1) { + $ret.="(($a<<5)|($a>>27));\n\t"; + $ret.="$b=($b<<30)|($b>>2); $e&=0xffffffff; #$b&=0xffffffff;\n\t"; + } else { + $ret.="(($a<<5)|($a>>27)&0x1f);\n\t"; + $ret.="$b=($b<<30)|($b>>2)&0x3fffffff;\n\t"; + } + $ret; + } + sub BODY_00_15 { + my ($a,$b,$c,$d,$e)=@V; + "$e+=\$W[$i]+0x5a827999+((($c^$d)&$b)^$d)+".tail(); + } + sub BODY_16_19 { + my ($a,$b,$c,$d,$e)=@V; + "$e+=".XUpdate()."+0x5a827999+((($c^$d)&$b)^$d)+".tail(); + } + sub BODY_20_39 { + my ($a,$b,$c,$d,$e)=@V; + "$e+=".XUpdate()."+0x6ed9eba1+($b^$c^$d)+".tail(); + } + sub BODY_40_59 { + my ($a,$b,$c,$d,$e)=@V; + "$e+=".XUpdate()."+0x8f1bbcdc+(($b&$c)|(($b|$c)&$d))+".tail(); + } + sub BODY_60_79 { + my ($a,$b,$c,$d,$e)=@V; + "$e+=".XUpdate()."+0xca62c1d6+($b^$c^$d)+".tail(); + } + + my $sha1_impl = + 'sub block { + my $self = @_[0]; + my @W = unpack("N16",@_[1]); + my ($A,$B,$C,$D,$E,$T) = @{$self->{H}}; + '; + + $sha1_impl.=' + $A &= 0xffffffff; + $B &= 0xffffffff; + ' if ((1<<31)<<1); + + for($i=0;$i<16;$i++){ $sha1_impl.=BODY_00_15(); unshift(@V,pop(@V)); } + for(;$i<20;$i++) { $sha1_impl.=BODY_16_19(); unshift(@V,pop(@V)); } + for(;$i<40;$i++) { $sha1_impl.=BODY_20_39(); unshift(@V,pop(@V)); } + for(;$i<60;$i++) { $sha1_impl.=BODY_40_59(); unshift(@V,pop(@V)); } + for(;$i<80;$i++) { $sha1_impl.=BODY_60_79(); unshift(@V,pop(@V)); } + + $sha1_impl.=' + $self->{H}[0]+=$A; $self->{H}[1]+=$B; $self->{H}[2]+=$C; + $self->{H}[3]+=$D; $self->{H}[4]+=$E; }'; + + #print $sha1_impl,"\n"; + eval($sha1_impl); # generate code + } + + sub Init { + my $class = shift; # multiple instances... + my $self = {}; + + bless $self,$class; + $self->{H} = [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]; + $self->{N} = 0; + return $self; + } + + sub Update { + my $self = shift; + my $msg; + + foreach $msg (@_) { + my $len = length($msg); + my $num = length($self->{buf}); + my $off = 0; + + $self->{N} += $len; + + if (($num+$len)<64) + { $self->{buf} .= $msg; next; } + elsif ($num) + { $self->{buf} .= substr($msg,0,($off=64-$num)); + $self->block($self->{buf}); + } + + while(($off+64) <= $len) + { $self->block(substr($msg,$off,64)); + $off += 64; + } + + $self->{buf} = substr($msg,$off); + } + return $self; + } + + sub Final { + my $self = shift; + my $num = length($self->{buf}); + + $self->{buf} .= chr(0x80); $num++; + if ($num>56) + { $self->{buf} .= chr(0)x(64-$num); + $self->block($self->{buf}); + $self->{buf}=undef; + $num=0; + } + $self->{buf} .= chr(0)x(56-$num); + $self->{buf} .= pack("N2",($self->{N}>>29)&0x7,$self->{N}<<3); + $self->block($self->{buf}); + + return pack("N*",@{$self->{H}}); + } + + sub Selftest { + my $hash; + + $hash=SHA1->Init()->Update('abc')->Final(); + die "SHA1 test#1" if (unpack("H*",$hash) ne 'a9993e364706816aba3e25717850c26c9cd0d89d'); + + $hash=SHA1->Init()->Update('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')->Final(); + die "SHA1 test#2" if (unpack("H*",$hash) ne '84983e441c3bd26ebaae4aa1f95129e5e54670f1'); + + #$hash=SHA1->Init()->Update('a'x1000000)->Final(); + #die "SHA1 test#3" if (unpack("H*",$hash) ne '34aa973cd4c4daa4f61eeb2bdbad27316534016f'); + } +} + +{ package HMAC; + + sub Init { + my $class = shift; + my $key = shift; + my $self = {}; + + bless $self,$class; + + if (length($key)>64) { + $key = SHA1->Init()->Update($key)->Final(); + } + $key .= chr(0x00)x(64-length($key)); + + my @ikey = map($_^=0x36,unpack("C*",$key)); + ($self->{hash} = SHA1->Init())->Update(pack("C*",@ikey)); + $self->{okey} = pack("C*",map($_^=0x36^0x5c,@ikey)); + + return $self; + } + + sub Update { + my $self = shift; + $self->{hash}->Update(@_); + return $self; + } + + sub Final { + my $self = shift; + my $ihash = $self->{hash}->Final(); + return SHA1->Init()->Update($self->{okey},$ihash)->Final(); + } + + sub Selftest { + my $hmac; + + $hmac = HMAC->Init('0123456789:;<=>?@ABC')->Update('Sample #2')->Final(); + die "HMAC test" if (unpack("H*",$hmac) ne '0922d3405faa3d194f82a45830737d5cc6c75d24'); + } +} + +1; diff --git a/c6x/incore6x b/c6x/incore6x new file mode 100644 index 0000000000..be73aca2d9 --- /dev/null +++ b/c6x/incore6x @@ -0,0 +1,241 @@ +#!/usr/bin/env perl +# +# Copyright (c) 2011 The OpenSSL Project. +# +# The script embeds fingerprint into TI-COFF executable object. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + +unshift(@INC,$dir); +require "hmac_sha1.pl"; + +###################################################################### +# +# COFF symbol table parser by <appro@openssl.org>. The table entries +# are extended with offset within executable file... +# +{ package COFF; + use FileHandle; + + sub dup { my %copy=map {$_} @_; return \%copy; } + + sub Load { + my $class = shift; + my $self = {}; + my $FD = FileHandle->new(); # autoclose + + bless $self,$class; + + sysopen($FD,shift,0) or die "$!"; + binmode($FD); + + ################################################# + # read and parse COFF header... + # + read($FD,my $coff,22) or die "$!"; + + my %coff_header; + @coff_header{version,nsects,date,syms_off,nsyms,opt,flags,magic}= + unpack("v2V3v3",$coff); + + $!=42; # signal fipsld to revert to two-step link + die "not TI-COFF file" if ($coff_header{version} != 0xC2); + + my $big_endian = ($coff_header{flags}>>9)&1; # 0 or 1 + + my $strings; + my $symsize; + + ################################################# + # load strings table + # + seek($FD,$coff_header{syms_off}+18*$coff_header{nsyms},0) or die "$!"; + read($FD,$strings,4) or die "$!"; + $symsize = unpack("V",$strings); + read($FD,$strings,$symsize,4) or die "$!"; + + ################################################# + # read sections + # + my $i; + my @sections; + + # seek to section headers + seek($FD,22+@coff_header{opt},0) or die "$!"; + for ($i=0;$i<$coff_header{nsects};$i++) { + my %coff_shdr; + my $name; + + read($FD,my $section,48) or die "$!"; + + @coff_shdr{sh_name,sh_phaddr,sh_vaddr, + sh_size,sh_offset,sh_relocs,sh_reserved, + sh_relocoff,sh_lines,sh_flags} = + unpack("a8V9",$section); + + $name = $coff_shdr{sh_name}; + # see if sh_name is a an offset in $strings + my ($hi,$lo) = unpack("V2",$name); + if ($hi==0 && $lo<$symsize) { + $name = substr($strings,$lo,64); + } + $coff_shdr{sh_name} = (split(chr(0),$name))[0]; + + push(@sections,dup(%coff_shdr)); + } + + ################################################# + # load symbols table + # + seek($FD,$coff_header{syms_off},0) or die "$!"; + for ($i=0;$i<$coff_header{nsyms};$i++) { + my %coff_sym; + my $name; + + read($FD,my $blob,18) or die "$!"; + + @coff_sym{st_name,st_value,st_shndx,reserved,class,aux} = + unpack("a8Vv2C2",$blob); + + # skip aux entries + if ($coff_sym{aux}) { + seek($FD,18*$coff_sym{aux},1) or die "$!"; + $i+=$coff_sym{aux}; + } + + $name = $coff_sym{st_name}; + # see if st_name is a an offset in $strings + my ($hi,$lo) = unpack("V2",$name); + if ($hi==0 && $lo<$symsize) { + $name = substr($strings,$lo,64); + } + $coff_sym{st_name} = $name = (split(chr(0),$name))[0]; + + my $st_secn = $coff_sym{st_shndx}-1; + if ($st_secn>=0 && $st_secn<=$#sections + && @sections[$st_secn]->{sh_offset} + && $name =~ m/^_[a-z]+/i) { + # synthesize st_offset, ... + $coff_sym{st_offset} = $coff_sym{st_value} + - @sections[$st_secn]->{sh_vaddr} + + @sections[$st_secn]->{sh_offset}; + $coff_sym{st_section} = @sections[$st_secn]->{sh_name}; + # ... and add to lookup table + $self->{symbols}{$name} = dup(%coff_sym); + } + } + + return $self; + } + + sub Lookup { + my $self = shift; + my $name = shift; + return $self->{symbols}{"_$name"}; + } + + sub Traverse { + my $self = shift; + my $code = shift; + + if (ref($code) eq 'CODE') { + for (keys(%{$self->{symbols}})) { &$code($self->{symbols}{$_}); } + } + } +} + +###################################################################### +# +# main() +# +my $legacy_mode; + +if ($#ARGV<0 || ($#ARGV>0 && !($legacy_mode=(@ARGV[0] =~ /^\-(dso|exe)$/)))) { + print STDERR "usage: $0 [-dso|-exe] ti-coff-binary\n"; + exit(1); +} + +$exe = COFF->Load(@ARGV[$#ARGV]); + +$FIPS_text_start = $exe->Lookup("FIPS_text_start") or die; +$FIPS_text_end = $exe->Lookup("FIPS_text_end") or die; +$FIPS_rodata_start = $exe->Lookup("FIPS_rodata_start") or die; +$FIPS_rodata_end = $exe->Lookup("FIPS_rodata_end") or die; +$FIPS_signature = $exe->Lookup("FIPS_signature") or die; + +# new cross-compile support +$FIPS_text_startX = $exe->Lookup("FIPS_text_startX"); +$FIPS_text_endX = $exe->Lookup("FIPS_text_endX"); + +if (!$legacy_mode) { + if (!$FIPS_text_startX || !$FIPS_text_endX) { + print STDERR "@ARGV[$#ARGV] is not cross-compiler aware.\n"; + exit(42); # signal fipsld to revert to two-step link + } + + $FINGERPRINT_ascii_value + = $exe->Lookup("FINGERPRINT_ascii_value"); +} +if ($FIPS_text_startX && $FIPS_text_endX) { + $FIPS_text_start = $FIPS_text_startX; + $FIPS_text_end = $FIPS_text_endX; +} + +sysopen(FD,@ARGV[$#ARGV],$legacy_mode?0:2) or die "$!"; # 2 is read/write +binmode(FD); + +sub HMAC_Update { + my ($hmac,$off,$len) = @_; + my $blob; + + seek(FD,$off,0) or die "$!"; + read(FD,$blob,$len) or die "$!"; + $$hmac->Update($blob); +} + +# fips/fips.c:FIPS_incore_fingerprint's Perl twin +# +sub FIPS_incore_fingerprint { + my $p1 = $FIPS_text_start->{st_offset}; + my $p2 = $FIPS_text_end->{st_offset}; + my $p3 = $FIPS_rodata_start->{st_offset}; + my $p4 = $FIPS_rodata_end->{st_offset}; + my $sig = $FIPS_signature->{st_offset}; + my $ctx = HMAC->Init("etaonrishdlcupfm"); + + # detect overlapping regions + if ($p1<=$p3 && $p2>=$p3) { + $p3 = $p1; $p4 = $p2>$p4?$p2:$p4; $p1 = 0; $p2 = 0; + } elsif ($p3<=$p1 && $p4>=$p1) { + $p3 = $p3; $p4 = $p2>$p4?$p2:$p4; $p1 = 0; $p2 = 0; + } + + if ($p1) { + HMAC_Update (\$ctx,$p1,$p2-$p1); + } + + if ($sig>=$p3 && $sig<$p4) { + # "punch" hole + HMAC_Update(\$ctx,$p3,$sig-$p3); + $p3 = $sig+20; + HMAC_Update(\$ctx,$p3,$p4-$p3); + } else { + HMAC_Update(\$ctx,$p3,$p4-$p3); + } + + return $ctx->Final(); +} + +$fingerprint = FIPS_incore_fingerprint(); + +if ($legacy_mode) { + print unpack("H*",$fingerprint); +} elsif ($FINGERPRINT_ascii_value) { + seek(FD,$FINGERPRINT_ascii_value->{st_offset},0) or die "$!"; + print FD unpack("H*",$fingerprint) or die "$!"; +} else { + seek(FD,$FIPS_signature->{st_offset},0) or die "$!"; + print FD $fingerprint or die "$!"; +} + +close (FD); diff --git a/c6x/run6x b/c6x/run6x new file mode 100644 index 0000000000..aecfabeb04 --- /dev/null +++ b/c6x/run6x @@ -0,0 +1,43 @@ +#!/usr/bin/env perl + +$exe = @ARGV[0]; +$exe .= ".out" if (! -f $exe); +die if (! -f $exe); + +use CCS_SCRIPTING_PERL; + +my $studio=new CCS_SCRIPTING_PERL::CCS_Scripting(); + +$studio->CCSOpenNamed("*","*",1); # connect to board +$studio->TargetReset(); + +print "loading $exe\n"; +$studio->ProgramLoad($exe); + +sub write_string { + my ($studio,$addr,$str) = @_; + my $len = length($str); + my $i; + + for ($i=0; $i<$len; $i++) { + $studio->MemoryWrite($CCS_SCRIPTING_PERL::PAGE_DATA,$addr+$i,8,vec($str,$i,8)); + } + $studio->MemoryWrite($CCS_SCRIPTING_PERL::PAGE_DATA,$addr+$i,8,0); + + return $i+1; +} + +$addr= $studio->SymbolGetAddress("__c_args"); +printf "setting up __c_args at 0x%X\n",$addr;#\n"; + +$studio->MemoryWrite($CCS_SCRIPTING_PERL::PAGE_DATA,$addr,32,$#ARGV+1); + +for ($i=0,$strings=$addr+($#ARGV+3)*4; $i<=$#ARGV; $i++) { + $off = write_string($studio,$strings,@ARGV[$i]); + $studio->MemoryWrite($CCS_SCRIPTING_PERL::PAGE_DATA,$addr+4*($i+1),32,$strings); + $strings += $off; +} +$studio->MemoryWrite($SCC_SCRIPTING_PERL::PAGE_DATA,$addr+4*($i+1),32,0); + +print "running...\n"; +$studio->TargetRun(); diff --git a/crypto/aes/asm/aes-c64xplus.pl b/crypto/aes/asm/aes-c64xplus.pl new file mode 100644 index 0000000000..206d7dce88 --- /dev/null +++ b/crypto/aes/asm/aes-c64xplus.pl @@ -0,0 +1,1329 @@ +#!/usr/bin/env perl +# +# ==================================================================== +# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# [Endian-neutral] AES for C64x+. +# +# Even though SPLOOPs are scheduled for 13 cycles, and thus expected +# performance is ~8.5 cycles per byte processed with 128-bit key, +# measured performance turned to be ~10 cycles per byte. Discrepancy +# must be caused by limitations of L1D memory banking(*), see SPRU871 +# TI publication for further details. If any consolation it's still +# ~20% faster than TI's linear assembly module anyway... Compared to +# aes_core.c compiled with cl6x 6.0 with -mv6400+ -o2 options this +# code is 3.75x faster and almost 3x smaller (tables included). +# +# (*) This means that there might be subtle correlation between data +# and timing and one can wonder if it can be ... attacked:-( +# On the other hand this also means that *if* one chooses to +# implement *4* T-tables variant [instead of 1 T-table as in +# this implementation, or in addition to], then one ought to +# *interleave* them. Even though it complicates addressing, +# references to interleaved tables would be guaranteed not to +# clash. I reckon that it should be possible to break 8 cycles +# per byte "barrier," i.e. improve by ~20%, naturally at the +# cost of 8x increased pressure on L1D. 8x because you'd have +# to interleave both Te and Td tables... + +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +open STDOUT,">$output"; + +($TEA,$TEB)=("A5","B5"); +($KPA,$KPB)=("A3","B1"); +@K=("A6","B6","A7","B7"); +@s=("A8","B8","A9","B9"); +@Te0=@Td0=("A16","B16","A17","B17"); +@Te1=@Td1=("A18","B18","A19","B19"); +@Te2=@Td2=("A20","B20","A21","B21"); +@Te3=@Td3=("A22","B22","A23","B23"); + +$code=<<___; + .text + + .asg B3,RA + .asg A4,INP + .asg B4,OUT + .asg A6,KEY + .asg A4,RET + .asg B15,SP + + .eval 24,EXT0 + .eval 16,EXT1 + .eval 8,EXT2 + .eval 0,EXT3 + .eval 8,TBL1 + .eval 16,TBL2 + .eval 24,TBL3 + + .if .BIG_ENDIAN + .eval 24-EXT0,EXT0 + .eval 24-EXT1,EXT1 + .eval 24-EXT2,EXT2 + .eval 24-EXT3,EXT3 + .eval 32-TBL1,TBL1 + .eval 32-TBL2,TBL2 + .eval 32-TBL3,TBL3 + .endif + + .global _AES_encrypt +_AES_encrypt: + .asmfunc + MVK 1,B2 +__encrypt: + [B2] LDNDW *INP++,A9:A8 ; load input +|| MVKL (AES_Te-_AES_encrypt),$TEA +|| ADDKPC _AES_encrypt,B0 + [B2] LDNDW *INP++,B9:B8 +|| MVKH (AES_Te-_AES_encrypt),$TEA +|| ADD 0,KEY,$KPA +|| ADD 4,KEY,$KPB + LDW *$KPA++[2],$Te0[0] ; zero round key +|| LDW *$KPB++[2],$Te0[1] +|| MVK 60,A0 +|| ADD B0,$TEA,$TEA ; AES_Te + LDW *KEY[A0],B0 ; rounds +|| MVK 1024,A0 ; sizeof(AES_Te) + LDW *$KPA++[2],$Te0[2] +|| LDW *$KPB++[2],$Te0[3] +|| MV $TEA,$TEB + NOP + .if .BIG_ENDIAN + MV A9,$s[0] +|| MV A8,$s[1] +|| MV B9,$s[2] +|| MV B8,$s[3] + .else + MV A8,$s[0] +|| MV A9,$s[1] +|| MV B8,$s[2] +|| MV B9,$s[3] + .endif + XOR $Te0[0],$s[0],$s[0] +|| XOR $Te0[1],$s[1],$s[1] +|| LDW *$KPA++[2],$K[0] ; 1st round key +|| LDW *$KPB++[2],$K[1] + SUB B0,2,B0 + + SPLOOPD 13 +|| MVC B0,ILC +|| LDW *$KPA++[2],$K[2] +|| LDW *$KPB++[2],$K[3] +;;==================================================================== + EXTU $s[1],EXT1,24,$Te1[1] +|| EXTU $s[0],EXT3,24,$Te3[0] + LDW *${TEB}[$Te1[1]],$Te1[1] ; Te1[s1>>8], t0 +|| LDW *${TEA}[$Te3[0]],$Te3[0] ; Te3[s0>>24], t1 +|| XOR $s[2],$Te0[2],$s[2] ; modulo-scheduled +|| XOR $s[3],$Te0[3],$s[3] ; modulo-scheduled +|| EXTU $s[1],EXT3,24,$Te3[1] +|| EXTU $s[0],EXT1,24,$Te1[0] + LDW *${TEB}[$Te3[1]],$Te3[1] ; Te3[s1>>24], t2 |