blob: 1d1e886f0329d72b62e3251711ea9f1733e2da17 [file] [log] [blame]
#!/usr/bin/env perl
# Copyright 2020-2022 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;
my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
my $xlate;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate ) or
die "can't locate arm-xlate.pl";
open OUT,"| \"$^X\" $xlate $flavour $output";
*STDOUT=*OUT;
my $code = data();
print $code;
close STDOUT or die "error closing STDOUT: $!"; # enforce flush
sub data
{
local $/;
return <DATA>;
}
__END__
// Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
//
// Licensed under the OpenSSL license (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
//
// ====================================================================
// Written by Ben Avison <bavison@riscosopen.org> for the OpenSSL
// project. Rights for redistribution and usage in source and binary
// forms are granted according to the OpenSSL license.
// ====================================================================
//
// This implementation is a translation of bsaes-armv7 for AArch64.
// No attempt has been made to carry across the build switches for
// kernel targets, since the Linux kernel crypto support has moved on
// from when it was based on OpenSSL.
// A lot of hand-scheduling has been performed. Consequently, this code
// doesn't factor out neatly into macros in the same way that the
// AArch32 version did, and there is little to be gained by wrapping it
// up in Perl, and it is presented as pure assembly.
#include "crypto/arm_arch.h"
.text
.extern AES_cbc_encrypt
.extern AES_encrypt
.extern AES_decrypt
.type _bsaes_decrypt8,%function
.align 4
// On entry:
// x9 -> key (previously expanded using _bsaes_key_convert)
// x10 = number of rounds
// v0-v7 input data
// On exit:
// x9-x11 corrupted
// other general-purpose registers preserved
// v0-v7 output data
// v11-v15 preserved
// other SIMD registers corrupted
_bsaes_decrypt8:
ldr q8, [x9], #16
adr x11, .LM0ISR
movi v9.16b, #0x55
ldr q10, [x11], #16
movi v16.16b, #0x33
movi v17.16b, #0x0f
sub x10, x10, #1
eor v0.16b, v0.16b, v8.16b
eor v1.16b, v1.16b, v8.16b
eor v2.16b, v2.16b, v8.16b
eor v4.16b, v4.16b, v8.16b
eor v3.16b, v3.16b, v8.16b
eor v5.16b, v5.16b, v8.16b
tbl v0.16b, {v0.16b}, v10.16b
tbl v1.16b, {v1.16b}, v10.16b
tbl v2.16b, {v2.16b}, v10.16b
tbl v4.16b, {v4.16b}, v10.16b
eor v6.16b, v6.16b, v8.16b
eor v7.16b, v7.16b, v8.16b
tbl v3.16b, {v3.16b}, v10.16b
tbl v5.16b, {v5.16b}, v10.16b
tbl v6.16b, {v6.16b}, v10.16b
ushr v8.2d, v0.2d, #1
tbl v7.16b, {v7.16b}, v10.16b
ushr v10.2d, v4.2d, #1
ushr v18.2d, v2.2d, #1
eor v8.16b, v8.16b, v1.16b
ushr v19.2d, v6.2d, #1
eor v10.16b, v10.16b, v5.16b
eor v18.16b, v18.16b, v3.16b
and v8.16b, v8.16b, v9.16b
eor v19.16b, v19.16b, v7.16b
and v10.16b, v10.16b, v9.16b
and v18.16b, v18.16b, v9.16b
eor v1.16b, v1.16b, v8.16b
shl v8.2d, v8.2d, #1
and v9.16b, v19.16b, v9.16b
eor v5.16b, v5.16b, v10.16b
shl v10.2d, v10.2d, #1
eor v3.16b, v3.16b, v18.16b
shl v18.2d, v18.2d, #1
eor v0.16b, v0.16b, v8.16b
shl v8.2d, v9.2d, #1
eor v7.16b, v7.16b, v9.16b
eor v4.16b, v4.16b, v10.16b
eor v2.16b, v2.16b, v18.16b
ushr v9.2d, v1.2d, #2
eor v6.16b, v6.16b, v8.16b
ushr v8.2d, v0.2d, #2
ushr v10.2d, v5.2d, #2
ushr v18.2d, v4.2d, #2
eor v9.16b, v9.16b, v3.16b
eor v8.16b, v8.16b, v2.16b
eor v10.16b, v10.16b, v7.16b
eor v18.16b, v18.16b, v6.16b
and v9.16b, v9.16b, v16.16b
and v8.16b, v8.16b, v16.16b
and v10.16b, v10.16b, v16.16b
and v16.16b, v18.16b, v16.16b
eor v3.16b, v3.16b, v9.16b
shl v9.2d, v9.2d, #2
eor v2.16b, v2.16b, v8.16b
shl v8.2d, v8.2d, #2
eor v7.16b, v7.16b, v10.16b
shl v10.2d, v10.2d, #2
eor v6.16b, v6.16b, v16.16b
shl v16.2d, v16.2d, #2
eor v1.16b, v1.16b, v9.16b
eor v0.16b, v0.16b, v8.16b
eor v5.16b, v5.16b, v10.16b
eor v4.16b, v4.16b, v16.16b
ushr v8.2d, v3.2d, #4
ushr v9.2d, v2.2d, #4
ushr v10.2d, v1.2d, #4
ushr v16.2d, v0.2d, #4
eor v8.16b, v8.16b, v7.16b
eor v9.16b, v9.16b, v6.16b
eor v10.16b, v10.16b, v5.16b
eor v16.16b, v16.16b, v4.16b
and v8.16b, v8.16b, v17.16b
and v9.16b, v9.16b, v17.16b
and v10.16b, v10.16b, v17.16b
and v16.16b, v16.16b, v17.16b
eor v7.16b, v7.16b, v8.16b
shl v8.2d, v8.2d, #4
eor v6.16b, v6.16b, v9.16b
shl v9.2d, v9.2d, #4
eor v5.16b, v5.16b, v10.16b
shl v10.2d, v10.2d, #4
eor v4.16b, v4.16b, v16.16b
shl v16.2d, v16.2d, #4
eor v3.16b, v3.16b, v8.16b
eor v2.16b, v2.16b, v9.16b
eor v1.16b, v1.16b, v10.16b
eor v0.16b, v0.16b, v16.16b
b .Ldec_sbox
.align 4
.Ldec_loop:
ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x9], #64
ldp q8, q9, [x9], #32
eor v0.16b, v16.16b, v0.16b
ldr q10, [x9], #16
eor v1.16b, v17.16b, v1.16b
ldr q16, [x9], #16
eor v2.16b, v18.16b, v2.16b
eor v3.16b, v19.16b, v3.16b
eor v4.16b, v8.16b, v4.16b
eor v5.16b, v9.16b, v5.16b
eor v6.16b, v10.16b, v6.16b
eor v7.16b, v16.16b, v7.16b
tbl v0.16b, {v0.16b}, v28.16b
tbl v1.16b, {v1.16b}, v28.16b
tbl v2.16b, {v2.16b}, v28.16b
tbl v3.16b, {v3.16b}, v28.16b
tbl v4.16b, {v4.16b}, v28.16b
tbl v5.16b, {v5.16b}, v28.16b
tbl v6.16b, {v6.16b}, v28.16b
tbl v7.16b, {v7.16b}, v28.16b
.Ldec_sbox:
eor v1.16b, v1.16b, v4.16b
eor v3.16b, v3.16b, v4.16b
subs x10, x10, #1
eor v4.16b, v4.16b, v7.16b
eor v2.16b, v2.16b, v7.16b
eor v1.16b, v1.16b, v6.16b
eor v6.16b, v6.16b, v4.16b
eor v2.16b, v2.16b, v5.16b
eor v0.16b, v0.16b, v1.16b
eor v7.16b, v7.16b, v6.16b
eor v8.16b, v6.16b, v2.16b
and v9.16b, v4.16b, v6.16b
eor v10.16b, v2.16b, v6.16b
eor v3.16b, v3.16b, v0.16b
eor v5.16b, v5.16b, v0.16b
eor v16.16b, v7.16b, v4.16b
eor v17.16b, v4.16b, v0.16b
and v18.16b, v0.16b, v2.16b
eor v19.16b, v7.16b, v4.16b
eor v1.16b, v1.16b, v3.16b
eor v20.16b, v3.16b, v0.16b
eor v21.16b, v5.16b, v2.16b
eor v22.16b, v3.16b, v7.16b
and v8.16b, v17.16b, v8.16b
orr v17.16b, v3.16b, v5.16b
eor v23.16b, v1.16b, v6.16b
eor v24.16b, v20.16b, v16.16b
eor v25.16b, v1.16b, v5.16b
orr v26.16b, v20.16b, v21.16b
and v20.16b, v20.16b, v21.16b
and v27.16b, v7.16b, v1.16b
eor v21.16b, v21.16b, v23.16b
orr v28.16b, v16.16b, v23.16b
orr v29.16b, v22.16b, v25.16b
eor v26.16b, v26.16b, v8.16b
and v16.16b, v16.16b, v23.16b
and v22.16b, v22.16b, v25.16b
and v21.16b, v24.16b, v21.16b
eor v8.16b, v28.16b, v8.16b
eor v23.16b, v5.16b, v2.16b
eor v24.16b, v1.16b, v6.16b
eor v16.16b, v16.16b, v22.16b
eor v22.16b, v3.16b, v0.16b
eor v25.16b, v29.16b, v21.16b
eor v21.16b, v26.16b, v21.16b
eor v8.16b, v8.16b, v20.16b
eor v26.16b, v23.16b, v24.16b
eor v16.16b, v16.16b, v20.16b
eor v28.16b, v22.16b, v19.16b
eor v20.16b, v25.16b, v20.16b
eor v9.16b, v21.16b, v9.16b
eor v8.16b, v8.16b, v18.16b
eor v18.16b, v5.16b, v1.16b
eor v21.16b, v16.16b, v17.16b
eor v16.16b, v16.16b, v17.16b
eor v17.16b, v20.16b, v27.16b
eor v20.16b, v3.16b, v7.16b
eor v25.16b, v9.16b, v8.16b
eor v27.16b, v0.16b, v4.16b
and v29.16b, v9.16b, v17.16b
eor v30.16b, v8.16b, v29.16b
eor v31.16b, v21.16b, v29.16b
eor v29.16b, v21.16b, v29.16b
bsl v30.16b, v17.16b, v21.16b
bsl v31.16b, v9.16b, v8.16b
bsl v16.16b, v30.16b, v29.16b
bsl v21.16b, v29.16b, v30.16b
eor v8.16b, v31.16b, v30.16b
and v1.16b, v1.16b, v31.16b
and v9.16b, v16.16b, v31.16b
and v6.16b, v6.16b, v30.16b
eor v16.16b, v17.16b, v21.16b
and v4.16b, v4.16b, v30.16b
eor v17.16b, v8.16b, v30.16b
and v21.16b, v24.16b, v8.16b
eor v9.16b, v9.16b, v25.16b
and v19.16b, v19.16b, v8.16b
eor v24.16b, v30.16b, v16.16b
eor v25.16b, v30.16b, v16.16b
and v7.16b, v7.16b, v17.16b
and v10.16b, v10.16b, v16.16b
eor v29.16b, v9.16b, v16.16b
eor v30.16b, v31.16b, v9.16b
and v0.16b, v24.16b, v0.16b
and v9.16b, v18.16b, v9.16b
and v2.16b, v25.16b, v2.16b
eor v10.16b, v10.16b, v6.16b
eor v18.16b, v29.16b, v16.16b
and v5.16b, v30.16b, v5.16b
eor v24.16b, v8.16b, v29.16b
and v25.16b, v26.16b, v29.16b
and v26.16b, v28.16b, v29.16b
eor v8.16b, v8.16b, v29.16b
eor v17.16b, v17.16b, v18.16b
eor v5.16b, v1.16b, v5.16b
and v23.16b, v24.16b, v23.16b
eor v21.16b, v21.16b, v25.16b
eor v19.16b, v19.16b, v26.16b
eor v0.16b, v4.16b, v0.16b
and v3.16b, v17.16b, v3.16b
eor v1.16b, v9.16b, v1.16b
eor v9.16b, v25.16b, v23.16b
eor v5.16b, v5.16b, v21.16b
eor v2.16b, v6.16b, v2.16b
and v6.16b, v8.16b, v22.16b
eor v3.16b, v7.16b, v3.16b
and v8.16b, v20.16b, v18.16b
eor v10.16b, v10.16b, v9.16b
eor v0.16b, v0.16b, v19.16b
eor v9.16b, v1.16b, v9.16b
eor v1.16b, v2.16b, v21.16b
eor v3.16b, v3.16b, v19.16b
and v16.16b, v27.16b, v16.16b
eor v17.16b, v26.16b, v6.16b
eor v6.16b, v8.16b, v7.16b
eor v7.16b, v1.16b, v9.16b
eor v1.16b, v5.16b, v3.16b
eor v2.16b, v10.16b, v3.16b
eor v4.16b, v16.16b, v4.16b
eor v8.16b, v6.16b, v17.16b
eor v5.16b, v9.16b, v3.16b
eor v9.16b, v0.16b, v1.16b
eor v6.16b, v7.16b, v1.16b
eor v0.16b, v4.16b, v17.16b
eor v4.16b, v8.16b, v7.16b
eor v7.16b, v9.16b, v2.16b
eor v8.16b, v3.16b, v0.16b
eor v7.16b, v7.16b, v5.16b
eor v3.16b, v4.16b, v7.16b
eor v4.16b, v7.16b, v0.16b
eor v7.16b, v8.16b, v3.16b
bcc .Ldec_done
ext v8.16b, v0.16b, v0.16b, #8
ext v9.16b, v1.16b, v1.16b, #8
ldr q28, [x11] // load from .LISR in common case (x10 > 0)
ext v10.16b, v6.16b, v6.16b, #8
ext v16.16b, v3.16b, v3.16b, #8
ext v17.16b, v5.16b, v5.16b, #8
ext v18.16b, v4.16b, v4.16b, #8
eor v8.16b, v8.16b, v0.16b
eor v9.16b, v9.16b, v1.16b
eor v10.16b, v10.16b, v6.16b
eor v16.16b, v16.16b, v3.16b
eor v17.16b, v17.16b, v5.16b
ext v19.16b, v2.16b, v2.16b, #8
ext v20.16b, v7.16b, v7.16b, #8
eor v18.16b, v18.16b, v4.16b
eor v6.16b, v6.16b, v8.16b
eor v8.16b, v2.16b, v10.16b
eor v4.16b, v4.16b, v9.16b
eor v2.16b, v19.16b, v2.16b
eor v9.16b, v20.16b, v7.16b
eor v0.16b, v0.16b, v16.16b
eor v1.16b, v1.16b, v16.16b
eor v6.16b, v6.16b, v17.16b
eor v8.16b, v8.16b, v16.16b
eor v7.16b, v7.16b, v18.16b
eor v4.16b, v4.16b, v16.16b
eor v2.16b, v3.16b, v2.16b
eor v1.16b, v1.16b, v17.16b
eor v3.16b, v5.16b, v9.16b
eor v5.16b, v8.16b, v17.16b
eor v7.16b, v7.16b, v17.16b
ext v8.16b, v0.16b, v0.16b, #12
ext v9.16b, v6.16b, v6.16b, #12
ext v10.16b, v4.16b, v4.16b, #12
ext v16.16b, v1.16b, v1.16b, #12
ext v17.16b, v5.16b, v5.16b, #12
ext v18.16b, v7.16b, v7.16b, #12
eor v0.16b, v0.16b, v8.16b
eor v6.16b, v6.16b, v9.16b
eor v4.16b, v4.16b, v10.16b
ext v19.16b, v2.16b, v2.16b, #12
ext v20.16b, v3.16b, v3.16b, #12
eor v1.16b, v1.16b, v16.16b
eor v5.16b, v5.16b, v17.16b
eor v7.16b, v7.16b, v18.16b
eor v2.16b, v2.16b, v19.16b
eor v16.16b, v16.16b, v0.16b
eor v3.16b, v3.16b, v20.16b
eor v17.16b, v17.16b, v4.16b
eor v10.16b, v10.16b, v6.16b
ext v0.16b, v0.16b, v0.16b, #8
eor v9.16b, v9.16b, v1.16b
ext v1.16b, v1.16b, v1.16b, #8
eor v8.16b, v8.16b, v3.16b
eor v16.16b, v16.16b, v3.16b
eor v18.16b, v18.16b, v5.16b
eor v19.16b, v19.16b, v7.16b
ext v21.16b, v5.16b, v5.16b, #8
ext v5.16b, v7.16b, v7.16b, #8
eor v7.16b, v20.16b, v2.16b
ext v4.16b, v4.16b, v4.16b, #8
ext v20.16b, v3.16b, v3.16b, #8
eor v17.16b, v17.16b, v3.16b
ext v2.16b, v2.16b, v2.16b, #8
eor v3.16b, v10.16b, v3.16b
ext v10.16b, v6.16b, v6.16b, #8
eor v0.16b, v0.16b, v8.16b
eor v1.16b, v1.16b, v16.16b
eor v5.16b, v5.16b, v18.16b
eor v3.16b, v3.16b, v4.16b
eor v7.16b, v20.16b, v7.16b
eor v6.16b, v2.16b, v19.16b
eor v4.16b, v21.16b, v17.16b
eor v2.16b, v10.16b, v9.16b
bne .Ldec_loop
ldr q28, [x11, #16]! // load from .LISRM0 on last round (x10 == 0)
b .Ldec_loop
.align 4
.Ldec_done:
ushr v8.2d, v0.2d, #1
movi v9.16b, #0x55
ldr q10, [x9]
ushr v16.2d, v2.2d, #1
movi v17.16b, #0x33
ushr v18.2d, v6.2d, #1
movi v19.16b, #0x0f
eor v8.16b, v8.16b, v1.16b
ushr v20.2d, v3.2d, #1
eor v16.16b, v16.16b, v7.16b
eor v18.16b, v18.16b, v4.16b
and v8.16b, v8.16b, v9.16b
eor v20.16b, v20.16b, v5.16b
and v16.16b, v16.16b, v9.16b
and v18.16b, v18.16b, v9.16b
shl v21.2d, v8.2d, #1
eor v1.16b, v1.16b, v8.16b
and v8.16b, v20.16b, v9.16b
eor v7.16b, v7.16b, v16.16b
shl v9.2d, v16.2d, #1
eor v4.16b, v4.16b, v18.16b
shl v16.2d, v18.2d, #1
eor v0.16b, v0.16b, v21.16b
shl v18.2d, v8.2d, #1
eor v5.16b, v5.16b, v8.16b
eor v2.16b, v2.16b, v9.16b
eor v6.16b, v6.16b, v16.16b
ushr v8.2d, v1.2d, #2
eor v3.16b, v3.16b, v18.16b
ushr v9.2d, v0.2d, #2
ushr v16.2d, v7.2d, #2
ushr v18.2d, v2.2d, #2
eor v8.16b, v8.16b, v4.16b
eor v9.16b, v9.16b, v6.16b
eor v16.16b, v16.16b, v5.16b
eor v18.16b, v18.16b, v3.16b
and v8.16b, v8.16b, v17.16b
and v9.16b, v9.16b, v17.16b
and v16.16b, v16.16b, v17.16b
and v17.16b, v18.16b, v17.16b
eor v4.16b, v4.16b, v8.16b
shl v8.2d, v8.2d, #2
eor v6.16b, v6.16b, v9.16b
shl v9.2d, v9.2d, #2
eor v5.16b, v5.16b, v16.16b
shl v16.2d, v16.2d, #2
eor v3.16b, v3.16b, v17.16b
shl v17.2d, v17.2d, #2
eor v1.16b, v1.16b, v8.16b
eor v0.16b, v0.16b, v9.16b
eor v7.16b, v7.16b, v16.16b
eor v2.16b, v2.16b, v17.16b
ushr v8.2d, v4.2d, #4
ushr v9.2d, v6.2d, #4
ushr v16.2d, v1.2d, #4
ushr v17.2d, v0.2d, #4
eor v8.16b, v8.16b, v5.16b
eor v9.16b, v9.16b, v3.16b
eor v16.16b, v16.16b, v7.16b
eor v17.16b, v17.16b, v2.16b
and v8.16b, v8.16b, v19.16b
and v9.16b, v9.16b, v19.16b
and v16.16b, v16.16b, v19.16b
and v17.16b, v17.16b, v19.16b
eor v5.16b, v5.16b, v8.16b
shl v8.2d, v8.2d, #4
eor v3.16b, v3.16b, v9.16b
shl v9.2d, v9.2d, #4
eor v7.16b, v7.16b, v16.16b
shl v16.2d, v16.2d, #4
eor v2.16b, v2.16b, v17.16b
shl v17.2d, v17.2d, #4
eor v4.16b, v4.16b, v8.16b
eor v6.16b, v6.16b, v9.16b
eor v7.16b, v7.16b, v10.16b
eor v1.16b, v1.16b, v16.16b
eor v2.16b, v2.16b, v10.16b
eor v0.16b, v0.16b, v17.16b
eor v4.16b, v4.16b, v10.16b
eor v6.16b, v6.16b, v10.16b
eor v3.16b, v3.16b, v10.16b
eor v5.16b, v5.16b, v10.16b
eor v1.16b, v1.16b, v10.16b
eor v0.16b, v0.16b, v10.16b
ret
.size _bsaes_decrypt8,.-_bsaes_decrypt8
.type _bsaes_const,%object
.align 6
_bsaes_const:
// InvShiftRows constants
// Used in _bsaes_decrypt8, which assumes contiguity
// .LM0ISR used with round 0 key
// .LISR used with middle round keys
// .LISRM0 used with final round key
.LM0ISR:
.quad 0x0a0e0206070b0f03, 0x0004080c0d010509
.LISR:
.quad 0x0504070602010003, 0x0f0e0d0c080b0a09
.LISRM0:
.quad 0x01040b0e0205080f, 0x0306090c00070a0d
// ShiftRows constants
// Used in _bsaes_encrypt8, which assumes contiguity
// .LM0SR used with round 0 key
// .LSR used with middle round keys
// .LSRM0 used with final round key
.LM0SR:
.quad 0x0a0e02060f03070b, 0x0004080c05090d01
.LSR:
.quad 0x0504070600030201, 0x0f0e0d0c0a09080b
.LSRM0:
.quad 0x0304090e00050a0f, 0x01060b0c0207080d
.LM0_bigendian:
.quad 0x02060a0e03070b0f, 0x0004080c0105090d
.LM0_littleendian:
.quad 0x0105090d0004080c, 0x03070b0f02060a0e
// Used in ossl_bsaes_ctr32_encrypt_blocks, prior to dropping into
// _bsaes_encrypt8_alt, for round 0 key in place of .LM0SR
.LREVM0SR:
.quad 0x090d01050c000408, 0x03070b0f060a0e02
.align 6
.size _bsaes_const,.-_bsaes_const
.type _bsaes_encrypt8,%function
.align 4
// On entry:
// x9 -> key (previously expanded using _bsaes_key_convert)
// x10 = number of rounds
// v0-v7 input data
// On exit:
// x9-x11 corrupted
// other general-purpose registers preserved
// v0-v7 output data
// v11-v15 preserved
// other SIMD registers corrupted
_bsaes_encrypt8:
ldr q8, [x9], #16
adr x11, .LM0SR
ldr q9, [x11], #16
_bsaes_encrypt8_alt:
eor v0.16b, v0.16b, v8.16b
eor v1.16b, v1.16b, v8.16b
sub x10, x10, #1
eor v2.16b, v2.16b, v8.16b
eor v4.16b, v4.16b, v8.16b
eor v3.16b, v3.16b, v8.16b
eor v5.16b, v5.16b, v8.16b
tbl v0.16b, {v0.16b}, v9.16b
tbl v1.16b, {v1.16b}, v9.16b
tbl v2.16b, {v2.16b}, v9.16b
tbl v4.16b, {v4.16b}, v9.16b
eor v6.16b, v6.16b, v8.16b
eor v7.16b, v7.16b, v8.16b
tbl v3.16b, {v3.16b}, v9.16b
tbl v5.16b, {v5.16b}, v9.16b
tbl v6.16b, {v6.16b}, v9.16b
ushr v8.2d, v0.2d, #1
movi v10.16b, #0x55
tbl v7.16b, {v7.16b}, v9.16b
ushr v9.2d, v4.2d, #1
movi v16.16b, #0x33
ushr v17.2d, v2.2d, #1
eor v8.16b, v8.16b, v1.16b
movi v18.16b, #0x0f
ushr v19.2d, v6.2d, #1
eor v9.16b, v9.16b, v5.16b
eor v17.16b, v17.16b, v3.16b
and v8.16b, v8.16b, v10.16b
eor v19.16b, v19.16b, v7.16b
and v9.16b, v9.16b, v10.16b
and v17.16b, v17.16b, v10.16b
eor v1.16b, v1.16b, v8.16b
shl v8.2d, v8.2d, #1
and v10.16b, v19.16b, v10.16b
eor v5.16b, v5.16b, v9.16b
shl v9.2d, v9.2d, #1
eor v3.16b, v3.16b, v17.16b
shl v17.2d, v17.2d, #1
eor v0.16b, v0.16b, v8.16b
shl v8.2d, v10.2d, #1
eor v7.16b, v7.16b, v10.16b
eor v4.16b, v4.16b, v9.16b
eor v2.16b, v2.16b, v17.16b
ushr v9.2d, v1.2d, #2
eor v6.16b, v6.16b, v8.16b
ushr v8.2d, v0.2d, #2
ushr v10.2d, v5.2d, #2
ushr v17.2d, v4.2d, #2
eor v9.16b, v9.16b, v3.16b
eor v8.16b, v8.16b, v2.16b
eor v10.16b, v10.16b, v7.16b
eor v17.16b, v17.16b, v6.16b
and v9.16b, v9.16b, v16.16b
and v8.16b, v8.16b, v16.16b
and v10.16b, v10.16b, v16.16b
and v16.16b, v17.16b, v16.16b
eor v3.16b, v3.16b, v9.16b
shl v9.2d, v9.2d, #2
eor v2.16b, v2.16b, v8.16b
shl v8.2d, v8.2d, #2
eor v7.16b, v7.16b, v10.16b
shl v10.2d, v10.2d, #2
eor v6.16b, v6.16b, v16.16b
shl v16.2d, v16.2d, #2
eor v1.16b, v1.16b, v9.16b
eor v0.16b, v0.16b, v8.16b
eor v5.16b, v5.16b, v10.16b
eor v4.16b, v4.16b, v16.16b
ushr v8.2d, v3.2d, #4
ushr v9.2d, v2.2d, #4
ushr v10.2d, v1.2d, #4
ushr v16.2d, v0.2d, #4
eor v8.16b, v8.16b, v7.16b
eor v9.16b, v9.16b, v6.16b
eor v10.16b, v10.16b, v5.16b
eor v16.16b, v16.16b, v4.16b
and v8.16b, v8.16b, v18.16b
and v9.16b, v9.16b, v18.16b
and v10.16b, v10.16b, v18.16b
and v16.16b, v16.16b, v18.16b
eor v7.16b, v7.16b, v8.16b
shl v8.2d, v8.2d, #4
eor v6.16b, v6.16b, v9.16b
shl v9.2d, v9.2d, #4
eor v5.16b, v5.16b, v10.16b
shl v10.2d, v10.2d, #4
eor v4.16b, v4.16b, v16.16b
shl v16.2d, v16.2d, #4
eor v3.16b, v3.16b, v8.16b
eor v2.16b, v2.16b, v9.16b
eor v1.16b, v1.16b, v10.16b
eor v0.16b, v0.16b, v16.16b
b .Lenc_sbox
.align 4
.Lenc_loop:
ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x9], #64
ldp q8, q9, [x9], #32
eor v0.16b, v16.16b, v0.16b
ldr q10, [x9], #16
eor v1.16b, v17.16b, v1.16b
ldr q16, [x9], #16
eor v2.16b, v18.16b, v2.16b
eor v3.16b, v19.16b, v3.16b
eor v4.16b, v8.16b, v4.16b
eor v5.16b, v9.16b, v5.16b
eor v6.16b, v10.16b, v6.16b
eor v7.16b, v16.16b, v7.16b
tbl v0.16b, {v0.16b}, v28.16b
tbl v1.16b, {v1.16b}, v28.16b
tbl v2.16b, {v2.16b}, v28.16b
tbl v3.16b, {v3.16b}, v28.16b
tbl v4.16b, {v4.16b}, v28.16b
tbl v5.16b, {v5.16b}, v28.16b
tbl v6.16b, {v6.16b}, v28.16b
tbl v7.16b, {v7.16b}, v28.16b
.Lenc_sbox:
eor v5.16b, v5.16b, v6.16b
eor v3.16b, v3.16b, v0.16b
subs x10, x10, #1
eor v2.16b, v2.16b, v1.16b
eor v5.16b, v5.16b, v0.16b
eor v8.16b, v3.16b, v7.16b
eor v6.16b, v6.16b, v2.16b
eor v7.16b, v7.16b, v5.16b
eor v8.16b, v8.16b, v4.16b
eor v3.16b, v6.16b, v3.16b
eor v4.16b, v4.16b, v5.16b
eor v6.16b, v1.16b, v5.16b
eor v2.16b, v2.16b, v7.16b
eor v1.16b, v8.16b, v1.16b
eor v8.16b, v7.16b, v4.16b
eor v9.16b, v3.16b, v0.16b
eor v10.16b, v7.16b, v6.16b
eor v16.16b, v5.16b, v3.16b
eor v17.16b, v6.16b, v2.16b
eor v18.16b, v5.16b, v1.16b
eor v19.16b, v2.16b, v4.16b
eor v20.16b, v1.16b, v0.16b
orr v21.16b, v8.16b, v9.16b
orr v22.16b, v10.16b, v16.16b
eor v23.16b, v8.16b, v17.16b
eor v24.16b, v9.16b, v18.16b
and v19.16b, v19.16b, v20.16b
orr v20.16b, v17.16b, v18.16b
and v8.16b, v8.16b, v9.16b
and v9.16b, v17.16b, v18.16b
and v17.16b, v23.16b, v24.16b
and v10.16b, v10.16b, v16.16b
eor v16.16b, v21.16b, v19.16b
eor v18.16b, v20.16b, v19.16b
and v19.16b, v2.16b, v1.16b
and v20.16b, v6.16b, v5.16b
eor v21.16b, v22.16b, v17.16b
eor v9.16b, v9.16b, v10.16b
eor v10.16b, v16.16b, v17.16b
eor v16.16b, v18.16b, v8.16b
and v17.16b, v4.16b, v0.16b
orr v18.16b, v7.16b, v3.16b
eor v21.16b, v21.16b, v8.16b
eor v8.16b, v9.16b, v8.16b
eor v9.16b, v10.16b, v19.16b
eor v10.16b, v3.16b, v0.16b
eor v16.16b, v16.16b, v17.16b
eor v17.16b, v5.16b, v1.16b
eor v19.16b, v21.16b, v20.16b
eor v20.16b, v8.16b, v18.16b
eor v8.16b, v8.16b, v18.16b
eor v18.16b, v7.16b, v4.16b
eor v21.16b, v9.16b, v16.16b
eor v22.16b, v6.16b, v2.16b
and v23.16b, v9.16b, v19.16b
eor v24.16b, v10.16b, v17.16b
eor v25.16b, v0.16b, v1.16b
eor v26.16b, v7.16b, v6.16b
eor v27.16b, v18.16b, v22.16b
eor v28.16b, v3.16b, v5.16b
eor v29.16b, v16.16b, v23.16b
eor v30.16b, v20.16b, v23.16b
eor v23.16b, v20.16b, v23.16b
eor v31.16b, v4.16b, v2.16b
bsl v29.16b, v19.16b, v20.16b
bsl v30.16b, v9.16b, v16.16b
bsl v8.16b, v29.16b, v23.16b
bsl v20.16b, v23.16b, v29.16b
eor v9.16b, v30.16b, v29.16b
and v5.16b, v5.16b, v30.16b
and v8.16b, v8.16b, v30.16b
and v1.16b, v1.16b, v29.16b
eor v16.16b, v19.16b, v20.16b
and v2.16b, v2.16b, v29.16b
eor v19.16b, v9.16b, v29.16b
and v17.16b, v17.16b, v9.16b
eor v8.16b, v8.16b, v21.16b
and v20.16b, v22.16b, v9.16b
eor v21.16b, v29.16b, v16.16b
eor v22.16b, v29.16b, v16.16b
and v23.16b, v25.16b, v16.16b
and v6.16b, v6.16b, v19.16b
eor v25.16b, v8.16b, v16.16b
eor v29.16b, v30.16b, v8.16b
and v4.16b, v21.16b, v4.16b
and v8.16b, v28.16b, v8.16b
and v0.16b, v22.16b, v0.16b
eor v21.16b, v23.16b, v1.16b
eor v22.16b, v9.16b, v25.16b
eor v9.16b, v9.16b, v25.16b
eor v23.16b, v25.16b, v16.16b
and v3.16b, v29.16b, v3.16b
and v24.16b, v24.16b, v25.16b
and v25.16b, v27.16b, v25.16b
and v10.16b, v22.16b, v10.16b
and v9.16b, v9.16b, v18.16b
eor v18.16b, v19.16b, v23.16b
and v19.16b, v26.16b, v23.16b
eor v3.16b, v5.16b, v3.16b
eor v17.16b, v17.16b, v24.16b
eor v10.16b, v24.16b, v10.16b
and v16.16b, v31.16b, v16.16b
eor v20.16b, v20.16b, v25.16b
eor v9.16b, v25.16b, v9.16b
eor v4.16b, v2.16b, v4.16b
and v7.16b, v18.16b, v7.16b
eor v18.16b, v19.16b, v6.16b
eor v5.16b, v8.16b, v5.16b
eor v0.16b, v1.16b, v0.16b
eor v1.16b, v21.16b, v10.16b
eor v8.16b, v3.16b, v17.16b
eor v2.16b, v16.16b, v2.16b
eor v3.16b, v6.16b, v7.16b
eor v6.16b, v18.16b, v9.16b
eor v4.16b, v4.16b, v20.16b
eor v10.16b, v5.16b, v10.16b
eor v0.16b, v0.16b, v17.16b
eor v9.16b, v2.16b, v9.16b
eor v3.16b, v3.16b, v20.16b
eor v7.16b, v6.16b, v1.16b
eor v5.16b, v8.16b, v4.16b
eor v6.16b, v10.16b, v1.16b
eor v2.16b, v4.16b, v0.16b
eor v4.16b, v3.16b, v10.16b
eor v9.16b, v9.16b, v7.16b
eor v3.16b, v0.16b, v5.16b
eor v0.16b, v1.16b, v4.16b
eor v1.16b, v4.16b, v8.16b
eor v4.16b, v9.16b, v5.16b
eor v6.16b, v6.16b, v3.16b
bcc .Lenc_done
ext v8.16b, v0.16b, v0.16b, #12
ext v9.16b, v4.16b, v4.16b, #12
ldr q28, [x11]
ext v10.16b, v6.16b, v6.16b, #12
ext v16.16b, v1.16b, v1.16b, #12
ext v17.16b, v3.16b, v3.16b, #12
ext v18.16b, v7.16b, v7.16b, #12
eor v0.16b, v0.16b, v8.16b
eor v4.16b, v4.16b, v9.16b
eor v6.16b, v6.16b, v10.16b
ext v19.16b, v2.16b, v2.16b, #12
ext v20.16b, v5.16b, v5.16b, #12
eor v1.16b, v1.16b, v16.16b
eor v3.16b, v3.16b, v17.16b
eor v7.16b, v7.16b, v18.16b
eor v2.16b, v2.16b, v19.16b
eor v16.16b, v16.16b, v0.16b
eor v5.16b, v5.16b, v20.16b
eor v17.16b, v17.16b, v6.16b
eor v10.16b, v10.16b, v4.16b
ext v0.16b, v0.16b, v0.16b, #8
eor v9.16b, v9.16b, v1.16b
ext v1.16b, v1.16b, v1.16b, #8
eor v8.16b, v8.16b, v5.16b
eor v16.16b, v16.16b, v5.16b
eor v18.16b, v18.16b, v3.16b
eor v19.16b, v19.16b, v7.16b
ext v3.16b, v3.16b, v3.16b, #8
ext v7.16b, v7.16b, v7.16b, #8
eor v20.16b, v20.16b, v2.16b
ext v6.16b, v6.16b, v6.16b, #8
ext v21.16b, v5.16b, v5.16b, #8
eor v17.16b, v17.16b, v5.16b
ext v2.16b, v2.16b, v2.16b, #8
eor v10.16b, v10.16b, v5.16b
ext v22.16b, v4.16b, v4.16b, #8
eor v0.16b, v0.16b, v8.16b
eor v1.16b, v1.16b, v16.16b
eor v5.16b, v7.16b, v18.16b
eor v4.16b, v3.16b, v17.16b
eor v3.16b, v6.16b, v10.16b
eor v7.16b, v21.16b, v20.16b
eor v6.16b, v2.16b, v19.16b
eor v2.16b, v22.16b, v9.16b
bne .Lenc_loop
ldr q28, [x11, #16]! // load from .LSRM0 on last round (x10 == 0)
b .Lenc_loop
.align 4
.Lenc_done:
ushr v8.2d, v0.2d, #1
movi v9.16b, #0x55
ldr q10, [x9]
ushr v16.2d, v3.2d, #1
movi v17.16b, #0x33
ushr v18.2d, v4.2d, #1
movi v19.16b, #0x0f
eor v8.16b, v8.16b, v1.16b
ushr v20.2d, v2.2d, #1
eor v16.16b, v16.16b, v7.16b
eor v18.16b, v18.16b, v6.16b
and v8.16b, v8.16b, v9.16b
eor v20.16b, v20.16b, v5.16b
and v16.16b, v16.16b, v9.16b
and v18.16b, v18.16b, v9.16b
shl v21.2d, v8.2d, #1
eor v1.16b, v1.16b, v8.16b
and v8.16b, v20.16b, v9.16b
eor v7.16b, v7.16b, v16.16b
shl v9.2d, v16.2d, #1
eor v6.16b, v6.16b, v18.16b
shl v16.2d, v18.2d, #1
eor v0.16b, v0.16b, v21.16b
shl v18.2d, v8.2d, #1
eor v5.16b, v5.16b, v8.16b
eor v3.16b, v3.16b, v9.16b
eor v4.16b, v4.16b, v16.16b
ushr v8.2d, v1.2d, #2
eor v2.16b, v2.16b, v18.16b
ushr v9.2d, v0.2d, #2
ushr v16.2d, v7.2d, #2
ushr v18.2d, v3.2d, #2
eor v8.16b, v8.16b, v6.16b
eor v9.16b, v9.16b, v4.16b
eor v16.16b, v16.16b, v5.16b
eor v18.16b, v18.16b, v2.16b
and v8.16b, v8.16b, v17.16b
and v9.16b, v9.16b, v17.16b
and v16.16b, v16.16b, v17.16b
and v17.16b, v18.16b, v17.16b
eor v6.16b, v6.16b, v8.16b
shl v8.2d, v8.2d, #2
eor v4.16b, v4.16b, v9.16b
shl v9.2d, v9.2d, #2
eor v5.16b, v5.16b, v16.16b
shl v16.2d, v16.2d, #2
eor v2.16b, v2.16b, v17.16b
shl v17.2d, v17.2d, #2
eor v1.16b, v1.16b, v8.16b
eor v0.16b, v0.16b, v9.16b
eor v7.16b, v7.16b, v16.16b
eor v3.16b, v3.16b, v17.16b
ushr v8.2d, v6.2d, #4
ushr v9.2d, v4.2d, #4
ushr v16.2d, v1.2d, #4
ushr v17.2d, v0.2d, #4
eor v8.16b, v8.16b, v5.16b
eor v9.16b, v9.16b, v2.16b
eor v16.16b, v16.16b, v7.16b
eor v17.16b, v17.16b, v3.16b
and v8.16b, v8.16b, v19.16b
and v9.16b, v9.16b, v19.16b
and v16.16b, v16.16b, v19.16b
and v17.16b, v17.16b, v19.16b
eor v5.16b, v5.16b, v8.16b
shl v8.2d, v8.2d, #4
eor v2.16b, v2.16b, v9.16b
shl v9.2d, v9.2d, #4
eor v7.16b, v7.16b, v16.16b
shl v16.2d, v16.2d, #4
eor v3.16b, v3.16b, v17.16b
shl v17.2d, v17.2d, #4
eor v6.16b, v6.16b, v8.16b
eor v4.16b, v4.16b, v9.16b
eor v7.16b, v7.16b, v10.16b
eor v1.16b, v1.16b, v16.16b
eor v3.16b, v3.16b, v10.16b
eor v0.16b, v0.16b, v17.16b
eor v6.16b, v6.16b, v10.16b
eor v4.16b, v4.16b, v10.16b
eor v2.16b, v2.16b, v10.16b
eor v5.16b, v5.16b, v10.16b
eor v1.16b, v1.16b, v10.16b
eor v0.16b, v0.16b, v10.16b
ret
.size _bsaes_encrypt8,.-_bsaes_encrypt8
.type _bsaes_key_convert,%function
.align 4
// On entry:
// x9 -> input key (big-endian)
// x10 = number of rounds
// x17 -> output key (native endianness)
// On exit:
// x9, x10 corrupted
// x11 -> .LM0_bigendian
// x17 -> last quadword of output key
// other general-purpose registers preserved
// v2-v6 preserved
// v7.16b[] = 0x63
// v8-v14 preserved
// v15 = last round key (converted to native endianness)
// other SIMD registers corrupted
_bsaes_key_convert:
#ifdef __AARCH64EL__
adr x11, .LM0_littleendian
#else
adr x11, .LM0_bigendian
#endif
ldr q0, [x9], #16 // load round 0 key
ldr q1, [x11] // .LM0
ldr q15, [x9], #16 // load round 1 key
movi v7.16b, #0x63 // compose .L63
movi v16.16b, #0x01 // bit masks
movi v17.16b, #0x02
movi v18.16b, #0x04
movi v19.16b, #0x08
movi v20.16b, #0x10
movi v21.16b, #0x20
movi v22.16b, #0x40
movi v23.16b, #0x80
#ifdef __AARCH64EL__
rev32 v0.16b, v0.16b
#endif
sub x10, x10, #1
str q0, [x17], #16 // save round 0 key
.align 4
.Lkey_loop:
tbl v0.16b, {v15.16b}, v1.16b
ldr q15, [x9], #16 // load next round key
eor v0.16b, v0.16b, v7.16b
cmtst v24.16b, v0.16b, v16.16b
cmtst v25.16b, v0.16b, v17.16b
cmtst v26.16b, v0.16b, v18.16b
cmtst v27.16b, v0.16b, v19.16b
cmtst v28.16b, v0.16b, v20.16b
cmtst v29.16b, v0.16b, v21.16b
cmtst v30.16b, v0.16b, v22.16b
cmtst v31.16b, v0.16b, v23.16b
sub x10, x10, #1
st1 {v24.16b-v27.16b}, [x17], #64 // write bit-sliced round key
st1 {v28.16b-v31.16b}, [x17], #64
cbnz x10, .Lkey_loop
// don't save last round key
#ifdef __AARCH64EL__
rev32 v15.16b, v15.16b
adr x11, .LM0_bigendian
#endif
ret
.size _bsaes_key_convert,.-_bsaes_key_convert
.globl ossl_bsaes_cbc_encrypt
.type ossl_bsaes_cbc_encrypt,%function
.align 4
// On entry:
// x0 -> input ciphertext
// x1 -> output plaintext
// x2 = size of ciphertext and plaintext in bytes (assumed a multiple of 16)
// x3 -> key
// x4 -> 128-bit initialisation vector (or preceding 128-bit block of ciphertext if continuing after an earlier call)
// w5 must be == 0
// On exit:
// Output plaintext filled in
// Initialisation vector overwritten with last quadword of ciphertext
// No output registers, usual AAPCS64 register preservation
ossl_bsaes_cbc_encrypt:
cmp x2, #128
#ifdef __APPLE__
bhs .Lcbc_do_bsaes
b AES_cbc_encrypt
.Lcbc_do_bsaes:
#else
blo AES_cbc_encrypt
#endif
// it is up to the caller to make sure we are called with enc == 0
stp x29, x30, [sp, #-48]!
stp d8, d9, [sp, #16]
stp d10, d15, [sp, #32]
lsr x2, x2, #4 // len in 16 byte blocks
ldr w15, [x3, #240] // get # of rounds
mov x14, sp
// allocate the key schedule on the stack
add x17, sp, #96
sub x17, x17, x15, lsl #7 // 128 bytes per inner round key, less 96 bytes
// populate the key schedule
mov x9, x3 // pass key
mov x10, x15 // pass # of rounds
mov sp, x17 // sp is sp
bl _bsaes_key_convert
ldr q6, [sp]
str q15, [x17] // save last round key
eor v6.16b, v6.16b, v7.16b // fix up round 0 key (by XORing with 0x63)
str q6, [sp]
ldr q15, [x4] // load IV
b .Lcbc_dec_loop
.align 4
.Lcbc_dec_loop:
subs x2, x2, #0x8
bmi .Lcbc_dec_loop_finish
ldr q0, [x0], #16 // load input
mov x9, sp // pass the key
ldr q1, [x0], #16
mov x10, x15
ldr q2, [x0], #16
ldr q3, [x0], #16
ldr q4, [x0], #16
ldr q5, [x0], #16
ldr q6, [x0], #16
ldr q7, [x0], #-7*16
bl _bsaes_decrypt8
ldr q16, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
eor v1.16b, v1.16b, v16.16b
str q0, [x1], #16 // write output
ldr q0, [x0], #16
str q1, [x1], #16
ldr q1, [x0], #16
eor v1.16b, v4.16b, v1.16b
ldr q4, [x0], #16
eor v2.16b, v2.16b, v4.16b
eor v0.16b, v6.16b, v0.16b
ldr q4, [x0], #16
str q0, [x1], #16
str q1, [x1], #16
eor v0.16b, v7.16b, v4.16b
ldr q1, [x0], #16
str q2, [x1], #16
ldr q2, [x0], #16
ldr q15, [x0], #16
str q0, [x1], #16
eor v0.16b, v5.16b, v2.16b
eor v1.16b, v3.16b, v1.16b
str q1, [x1], #16
str q0, [x1], #16
b .Lcbc_dec_loop
.Lcbc_dec_loop_finish:
adds x2, x2, #8
beq .Lcbc_dec_done
ldr q0, [x0], #16 // load input
cmp x2, #2
blo .Lcbc_dec_one
ldr q1, [x0], #16
mov x9, sp // pass the key
mov x10, x15
beq .Lcbc_dec_two
ldr q2, [x0], #16
cmp x2, #4
blo .Lcbc_dec_three
ldr q3, [x0], #16
beq .Lcbc_dec_four
ldr q4, [x0], #16
cmp x2, #6
blo .Lcbc_dec_five
ldr q5, [x0], #16
beq .Lcbc_dec_six
ldr q6, [x0], #-6*16
bl _bsaes_decrypt8
ldr q5, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
ldr q8, [x0], #16
ldr q9, [x0], #16
ldr q10, [x0], #16
str q0, [x1], #16 // write output
ldr q0, [x0], #16
eor v1.16b, v1.16b, v5.16b
ldr q5, [x0], #16
eor v6.16b, v6.16b, v8.16b
ldr q15, [x0]
eor v4.16b, v4.16b, v9.16b
eor v2.16b, v2.16b, v10.16b
str q1, [x1], #16
eor v0.16b, v7.16b, v0.16b
str q6, [x1], #16
eor v1.16b, v3.16b, v5.16b
str q4, [x1], #16
str q2, [x1], #16
str q0, [x1], #16
str q1, [x1]
b .Lcbc_dec_done
.align 4
.Lcbc_dec_six:
sub x0, x0, #0x60
bl _bsaes_decrypt8
ldr q3, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
ldr q5, [x0], #16
ldr q8, [x0], #16
ldr q9, [x0], #16
str q0, [x1], #16 // write output
ldr q0, [x0], #16
eor v1.16b, v1.16b, v3.16b
ldr q15, [x0]
eor v3.16b, v6.16b, v5.16b
eor v4.16b, v4.16b, v8.16b
eor v2.16b, v2.16b, v9.16b
str q1, [x1], #16
eor v0.16b, v7.16b, v0.16b
str q3, [x1], #16
str q4, [x1], #16
str q2, [x1], #16
str q0, [x1]
b .Lcbc_dec_done
.align 4
.Lcbc_dec_five:
sub x0, x0, #0x50
bl _bsaes_decrypt8
ldr q3, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
ldr q5, [x0], #16
ldr q7, [x0], #16
ldr q8, [x0], #16
str q0, [x1], #16 // write output
ldr q15, [x0]
eor v0.16b, v1.16b, v3.16b
eor v1.16b, v6.16b, v5.16b
eor v3.16b, v4.16b, v7.16b
str q0, [x1], #16
eor v0.16b, v2.16b, v8.16b
str q1, [x1], #16
str q3, [x1], #16
str q0, [x1]
b .Lcbc_dec_done
.align 4
.Lcbc_dec_four:
sub x0, x0, #0x40
bl _bsaes_decrypt8
ldr q2, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
ldr q3, [x0], #16
ldr q5, [x0], #16
str q0, [x1], #16 // write output
ldr q15, [x0]
eor v0.16b, v1.16b, v2.16b
eor v1.16b, v6.16b, v3.16b
eor v2.16b, v4.16b, v5.16b
str q0, [x1], #16
str q1, [x1], #16
str q2, [x1]
b .Lcbc_dec_done
.align 4
.Lcbc_dec_three:
sub x0, x0, #0x30
bl _bsaes_decrypt8
ldr q2, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
ldr q3, [x0], #16
ldr q15, [x0]
str q0, [x1], #16 // write output
eor v0.16b, v1.16b, v2.16b
eor v1.16b, v6.16b, v3.16b
str q0, [x1], #16
str q1, [x1]
b .Lcbc_dec_done
.align 4
.Lcbc_dec_two:
sub x0, x0, #0x20
bl _bsaes_decrypt8
ldr q2, [x0], #16 // reload input
eor v0.16b, v0.16b, v15.16b // ^= IV
ldr q15, [x0]
str q0, [x1], #16 // write output
eor v0.16b, v1.16b, v2.16b
str q0, [x1]
b .Lcbc_dec_done
.align 4
.Lcbc_dec_one:
sub x0, x0, #0x10
stp x1, x4, [sp, #-32]!
str x14, [sp, #16]
mov v8.16b, v15.16b
mov v15.16b, v0.16b
mov x2, x3
bl AES_decrypt
ldr x14, [sp, #16]
ldp x1, x4, [sp], #32
ldr q0, [x1] // load result
eor v0.16b, v0.16b, v8.16b // ^= IV
str q0, [x1] // write output
.align 4
.Lcbc_dec_done:
movi v0.16b, #0
movi v1.16b, #0
.Lcbc_dec_bzero:// wipe key schedule [if any]
stp q0, q1, [sp], #32
cmp sp, x14
bne .Lcbc_dec_bzero
str q15, [x4] // return IV
ldp d8, d9, [sp, #16]
ldp d10, d15, [sp, #32]
ldp x29, x30, [sp], #48
ret
.size ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt
.globl ossl_bsaes_ctr32_encrypt_blocks
.type ossl_bsaes_ctr32_encrypt_blocks,%function
.align 4
// On entry:
// x0 -> input text (whole 16-byte blocks)
// x1 -> output text (whole 16-byte blocks)
// x2 = number of 16-byte blocks to encrypt/decrypt (> 0)
// x3 -> key
// x4 -> initial value of 128-bit counter (stored big-endian) which increments, modulo 2^32, for each block
// On exit:
// Output text filled in
// No output registers, usual AAPCS64 register preservation
ossl_bsaes_ctr32_encrypt_blocks:
cmp x2, #8 // use plain AES for
blo .Lctr_enc_short // small sizes
stp x29, x30, [sp, #-80]!
stp d8, d9, [sp, #16]
stp d10, d11, [sp, #32]
stp d12, d13, [sp, #48]
stp d14, d15, [sp, #64]
ldr w15, [x3, #240] // get # of rounds
mov x14, sp
// allocate the key schedule on the stack
add x17, sp, #96
sub x17, x17, x15, lsl #7 // 128 bytes per inner round key, less 96 bytes
// populate the key schedule
mov x9, x3 // pass key
mov x10, x15 // pass # of rounds
mov sp, x17 // sp is sp
bl _bsaes_key_convert
eor v7.16b, v7.16b, v15.16b // fix up last round key
str q7, [x17] // save last round key
ldr q0, [x4] // load counter
add x13, x11, #.LREVM0SR-.LM0_bigendian
ldr q4, [sp] // load round0 key
movi v8.4s, #1 // compose 1<<96
movi v9.16b, #0
rev32 v15.16b, v0.16b
rev32 v0.16b, v0.16b
ext v11.16b, v9.16b, v8.16b, #4
rev32 v4.16b, v4.16b
add v12.4s, v11.4s, v11.4s // compose 2<<96
str q4, [sp] // save adjusted round0 key
add v13.4s, v11.4s, v12.4s // compose 3<<96
add v14.4s, v12.4s, v12.4s // compose 4<<96
b .Lctr_enc_loop
.align 4
.Lctr_enc_loop:
// Intermix prologue from _bsaes_encrypt8 to use the opportunity
// to flip byte order in 32-bit counter
add v1.4s, v15.4s, v11.4s // +1
add x9, sp, #0x10 // pass next round key
add v2.4s, v15.4s, v12.4s // +2
ldr q9, [x13] // .LREVM0SR
ldr q8, [sp] // load round0 key
add v3.4s, v15.4s, v13.4s // +3
mov x10, x15 // pass rounds
sub x11, x13, #.LREVM0SR-.LSR // pass constants
add v6.4s, v2.4s, v14.4s
add v4.4s, v15.4s, v14.4s // +4
add v7.4s, v3.4s, v14.4s
add v15.4s, v4.4s, v14.4s // next counter
add v5.4s, v1.4s, v14.4s
bl _bsaes_encrypt8_alt
subs x2, x2, #8
blo .Lctr_enc_loop_done
ldr q16, [x0], #16
ldr q17, [x0], #16
eor v1.16b, v1.16b, v17.16b
ldr q17, [x0], #16
eor v0.16b, v0.16b, v16.16b
eor v4.16b, v4.16b, v17.16b
str q0, [x1], #16
ldr q16, [x0], #16
str q1, [x1], #16
mov v0.16b, v15.16b
str q4, [x1], #16
ldr q1, [x0], #16
eor v4.16b, v6.16b, v16.16b
eor v1.16b, v3.16b, v1.16b
ldr q3, [x0], #16
eor v3.16b, v7.16b, v3.16b
ldr q6, [x0], #16
eor v2.16b, v2.16b, v6.16b
ldr q6, [x0], #16
eor v5.16b, v5.16b, v6.16b
str q4, [x1], #16
str q1, [x1], #16
str q3, [x1], #16
str q2, [x1], #16
str q5, [x1], #16
bne .Lctr_enc_loop
b .Lctr_enc_done
.align 4
.Lctr_enc_loop_done:
add x2, x2, #8
ldr q16, [x0], #16 // load input
eor v0.16b, v0.16b, v16.16b
str q0, [x1], #16 // write output
cmp x2, #2
blo .Lctr_enc_done
ldr q17, [x0], #16
eor v1.16b, v1.16b, v17.16b
str q1, [x1], #16
beq .Lctr_enc_done
ldr q18, [x0], #16
eor v4.16b, v4.16b, v18.16b
str q4, [x1], #16
cmp x2, #4
blo .Lctr_enc_done
ldr q19, [x0], #16
eor v6.16b, v6.16b, v19.16b
str q6, [x1], #16
beq .Lctr_enc_done
ldr q20, [x0], #16
eor v3.16b, v3.16b, v20.16b
str q3, [x1], #16
cmp x2, #6
blo .Lctr_enc_done
ldr q21, [x0], #16
eor v7.16b, v7.16b, v21.16b
str q7, [x1], #16
beq .Lctr_enc_done
ldr q22, [x0]
eor v2.16b, v2.16b, v22.16b
str q2, [x1], #16
.Lctr_enc_done:
movi v0.16b, #0
movi v1.16b, #0
.Lctr_enc_bzero: // wipe key schedule [if any]
stp q0, q1, [sp], #32
cmp sp, x14
bne .Lctr_enc_bzero
ldp d8, d9, [sp, #16]
ldp d10, d11, [sp, #32]
ldp d12, d13, [sp, #48]
ldp d14, d15, [sp, #64]
ldp x29, x30, [sp], #80
ret
.Lctr_enc_short:
stp x29, x30, [sp, #-96]!
stp x19, x20, [sp, #16]
stp x21, x22, [sp, #32]
str x23, [sp, #48]
mov x19, x0 // copy arguments
mov x20, x1
mov x21, x2
mov x22, x3
ldr w23, [x4, #12] // load counter .LSW
ldr q1, [x4] // load whole counter value
#ifdef __AARCH64EL__
rev w23, w23
#endif
str q1, [sp, #80] // copy counter value
.Lctr_enc_short_loop:
add x0, sp, #80 // input counter value
add x1, sp, #64 // output on the stack
mov x2, x22 // key
bl AES_encrypt
ldr q0, [x19], #16 // load input
ldr q1, [sp, #64] // load encrypted counter
add x23, x23, #1
#ifdef __AARCH64EL__
rev w0, w23
str w0, [sp, #80+12] // next counter value
#else
str w23, [sp, #80+12] // next counter value
#endif
eor v0.16b, v0.16b, v1.16b
str q0, [x20], #16 // store output
subs x21, x21, #1
bne .Lctr_enc_short_loop
movi v0.16b, #0
movi v1.16b, #0
stp q0, q1, [sp, #64]
ldr x23, [sp, #48]
ldp x21, x22, [sp, #32]
ldp x19, x20, [sp, #16]
ldp x29, x30, [sp], #96
ret
.size ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks
.globl ossl_bsaes_xts_encrypt
.type ossl_bsaes_xts_encrypt,%function
.align 4
// On entry:
// x0 -> input plaintext
// x1 -> output ciphertext
// x2 -> length of text in bytes (must be at least 16)
// x3 -> key1 (used to encrypt the XORed plaintext blocks)
// x4 -> key2 (used to encrypt the initial vector to yield the initial tweak)
// x5 -> 16-byte initial vector (typically, sector number)
// On exit:
// Output ciphertext filled in
// No output registers, usual AAPCS64 register preservation
ossl_bsaes_xts_encrypt:
// Stack layout:
// sp ->
// nrounds*128-96 bytes: key schedule
// x19 ->
// 16 bytes: frame record
// 4*16 bytes: tweak storage across _bsaes_encrypt8
// 6*8 bytes: storage for 5 callee-saved general-purpose registers
// 8*8 bytes: storage for 8 callee-saved SIMD registers
stp x29, x30, [sp, #-192]!
stp x19, x20, [sp, #80]
stp x21, x22, [sp, #96]
str x23, [sp, #112]
stp d8, d9, [sp, #128]
stp d10, d11, [sp, #144]
stp d12, d13, [sp, #160]
stp d14, d15, [sp, #176]
mov x19, sp
mov x20, x0
mov x21, x1
mov x22, x2
mov x23, x3
// generate initial tweak
sub sp, sp, #16
mov x0, x5 // iv[]
mov x1, sp
mov x2, x4 // key2
bl AES_encrypt
ldr q11, [sp], #16
ldr w1, [x23, #240] // get # of rounds
// allocate the key schedule on the stack
add x17, sp, #96
sub x17, x17, x1, lsl #7 // 128 bytes per inner round key, less 96 bytes
// populate the key schedule
mov x9, x23 // pass key
mov x10, x1 // pass # of rounds
mov sp, x17
bl _bsaes_key_convert
eor v15.16b, v15.16b, v7.16b // fix up last round key
str q15, [x17] // save last round key
subs x22, x22, #0x80
blo .Lxts_enc_short
b .Lxts_enc_loop
.align 4
.Lxts_enc_loop:
ldr q8, .Lxts_magic
mov x10, x1 // pass rounds
add x2, x19, #16
ldr q0, [x20], #16
sshr v1.2d, v11.2d, #63
mov x9, sp // pass key schedule
ldr q6, .Lxts_magic+16
add v2.2d, v11.2d, v11.2d
cmtst v3.2d, v11.2d, v6.2d
and v1.16b, v1.16b, v8.16b
ext v1.16b, v1.16b, v1.16b, #8
and v3.16b, v3.16b, v8.16b
ldr q4, [x20], #16
eor v12.16b, v2.16b, v1.16b
eor v1.16b, v4.16b, v12.16b
eor v0.16b, v0.16b, v11.16b
cmtst v2.2d, v12.2d, v6.2d
add v4.2d, v12.2d, v12.2d
add x0, x19, #16
ext v3.16b, v3.16b, v3.16b, #8
and v2.16b, v2.16b, v8.16b
eor v13.16b, v4.16b, v3.16b
ldr q3, [x20], #16
ext v4.16b, v2.16b, v2.16b, #8
eor v2.16b, v3.16b, v13.16b
ldr q3, [x20], #16
add v5.2d, v13.2d, v13.2d
cmtst v7.2d, v13.2d, v6.2d
and v7.16b, v7.16b, v8.16b
ldr q9, [x20], #16
ext v7.16b, v7.16b, v7.16b, #8
ldr q10, [x20], #16
eor v14.16b, v5.16b, v4.16b
ldr q16, [x20], #16
add v4.2d, v14.2d, v14.2d
eor v3.16b, v3.16b, v14.16b
eor v15.16b, v4.16b, v7.16b
add v5.2d, v15.2d, v15.2d
ldr q7, [x20], #16
cmtst v4.2d, v14.2d, v6.2d
and v17.16b, v4.16b, v8.16b
cmtst v18.2d, v15.2d, v6.2d
eor v4.16b, v9.16b, v15.16b
ext v9.16b, v17.16b, v17.16b, #8
eor v9.16b, v5.16b, v9.16b
add v17.2d, v9.2d, v9.2d
and v18.16b, v18.16b, v8.16b
eor v5.16b, v10.16b, v9.16b
str q9, [x2], #16
ext v10.16b, v18.16b, v18.16b, #8
cmtst v9.2d, v9.2d, v6.2d
and v9.16b, v9.16b, v8.16b
eor v10.16b, v17.16b, v10.16b
cmtst v17.2d, v10.2d, v6.2d
eor v6.16b, v16.16b, v10.16b
str q10, [x2], #16
ext v9.16b, v9.16b, v9.16b, #8
add v10.2d, v10.2d, v10.2d
eor v9.16b, v10.16b, v9.16b
str q9, [x2], #16
eor v7.16b, v7.16b, v9.16b
add v9.2d, v9.2d, v9.2d
and v8.16b, v17.16b, v8.16b
ext v8.16b, v8.16b, v8.16b, #8
eor v8.16b, v9.16b, v8.16b
str q8, [x2] // next round tweak
bl _bsaes_encrypt8
ldr q8, [x0], #16
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
ldr q9, [x0], #16
eor v4.16b, v4.16b, v13.16b
eor v6.16b, v6.16b, v14.16b
ldr q10, [x0], #16
eor v3.16b, v3.16b, v15.16b
subs x22, x22, #0x80
str q0, [x21], #16
ldr q11, [x0] // next round tweak
str q1, [x21], #16
eor v0.16b, v7.16b, v8.16b
eor v1.16b, v2.16b, v9.16b
str q4, [x21], #16
eor v2.16b, v5.16b, v10.16b
str q6, [x21], #16
str q3, [x21], #16
str q0, [x21], #16
str q1, [x21], #16
str q2, [x21], #16
bpl .Lxts_enc_loop
.Lxts_enc_short:
adds x22, x22, #0x70
bmi .Lxts_enc_done
ldr q8, .Lxts_magic
sshr v1.2d, v11.2d, #63
add v2.2d, v11.2d, v11.2d
ldr q9, .Lxts_magic+16
subs x22, x22, #0x10
ldr q0, [x20], #16
and v1.16b, v1.16b, v8.16b
cmtst v3.2d, v11.2d, v9.2d
ext v1.16b, v1.16b, v1.16b, #8
and v3.16b, v3.16b, v8.16b
eor v12.16b, v2.16b, v1.16b
ext v1.16b, v3.16b, v3.16b, #8
add v2.2d, v12.2d, v12.2d
cmtst v3.2d, v12.2d, v9.2d
eor v13.16b, v2.16b, v1.16b
and v22.16b, v3.16b, v8.16b
bmi .Lxts_enc_1
ext v2.16b, v22.16b, v22.16b, #8
add v3.2d, v13.2d, v13.2d
ldr q1, [x20], #16
cmtst v4.2d, v13.2d, v9.2d
subs x22, x22, #0x10
eor v14.16b, v3.16b, v2.16b
and v23.16b, v4.16b, v8.16b
bmi .Lxts_enc_2
ext v3.16b, v23.16b, v23.16b, #8
add v4.2d, v14.2d, v14.2d
ldr q2, [x20], #16
cmtst v5.2d, v14.2d, v9.2d
eor v0.16b, v0.16b, v11.16b
subs x22, x22, #0x10
eor v15.16b, v4.16b, v3.16b
and v24.16b, v5.16b, v8.16b
bmi .Lxts_enc_3
ext v4.16b, v24.16b, v24.16b, #8
add v5.2d, v15.2d, v15.2d
ldr q3, [x20], #16
cmtst v6.2d, v15.2d, v9.2d
eor v1.16b, v1.16b, v12.16b
subs x22, x22, #0x10
eor v16.16b, v5.16b, v4.16b
and v25.16b, v6.16b, v8.16b
bmi .Lxts_enc_4
ext v5.16b, v25.16b, v25.16b, #8
add v6.2d, v16.2d, v16.2d
add x0, x19, #16
cmtst v7.2d, v16.2d, v9.2d
ldr q4, [x20], #16
eor v2.16b, v2.16b, v13.16b
str q16, [x0], #16
subs x22, x22, #0x10
eor v17.16b, v6.16b, v5.16b
and v26.16b, v7.16b, v8.16b
bmi .Lxts_enc_5
ext v7.16b, v26.16b, v26.16b, #8
add v18.2d, v17.2d, v17.2d
ldr q5, [x20], #16
eor v3.16b, v3.16b, v14.16b
str q17, [x0], #16
subs x22, x22, #0x10
eor v18.16b, v18.16b, v7.16b
bmi .Lxts_enc_6
ldr q6, [x20], #16
eor v4.16b, v4.16b, v15.16b
eor v5.16b, v5.16b, v16.16b
str q18, [x0] // next round tweak
mov x9, sp // pass key schedule
mov x10, x1
add x0, x19, #16
sub x22, x22, #0x10
eor v6.16b, v6.16b, v17.16b
bl _bsaes_encrypt8
ldr q16, [x0], #16
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
ldr q17, [x0], #16
eor v4.16b, v4.16b, v13.16b
eor v6.16b, v6.16b, v14.16b
eor v3.16b, v3.16b, v15.16b
ldr q11, [x0] // next round tweak
str q0, [x21], #16
str q1, [x21], #16
eor v0.16b, v7.16b, v16.16b
eor v1.16b, v2.16b, v17.16b
str q4, [x21], #16
str q6, [x21], #16
str q3, [x21], #16
str q0, [x21], #16
str q1, [x21], #16
b .Lxts_enc_done
.align 4
.Lxts_enc_6:
eor v4.16b, v4.16b, v15.16b
eor v5.16b, v5.16b, v16.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_encrypt8
ldr q16, [x0], #16
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
eor v4.16b, v4.16b, v13.16b
eor v6.16b, v6.16b, v14.16b
ldr q11, [x0] // next round tweak
eor v3.16b, v3.16b, v15.16b
str q0, [x21], #16
str q1, [x21], #16
eor v0.16b, v7.16b, v16.16b
str q4, [x21], #16
str q6, [x21], #16
str q3, [x21], #16
str q0, [x21], #16
b .Lxts_enc_done
.align 4
.Lxts_enc_5:
eor v3.16b, v3.16b, v14.16b
eor v4.16b, v4.16b, v15.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_encrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
ldr q11, [x0] // next round tweak
eor v4.16b, v4.16b, v13.16b
eor v6.16b, v6.16b, v14.16b
eor v3.16b, v3.16b, v15.16b
str q0, [x21], #16
str q1, [x21], #16
str q4, [x21], #16
str q6, [x21], #16
str q3, [x21], #16
b .Lxts_enc_done
.align 4
.Lxts_enc_4:
eor v2.16b, v2.16b, v13.16b
eor v3.16b, v3.16b, v14.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_encrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
eor v4.16b, v4.16b, v13.16b
eor v6.16b, v6.16b, v14.16b
mov v11.16b, v15.16b // next round tweak
str q0, [x21], #16
str q1, [x21], #16
str q4, [x21], #16
str q6, [x21], #16
b .Lxts_enc_done
.align 4
.Lxts_enc_3:
eor v1.16b, v1.16b, v12.16b
eor v2.16b, v2.16b, v13.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_encrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
eor v4.16b, v4.16b, v13.16b
mov v11.16b, v14.16b // next round tweak
str q0, [x21], #16
str q1, [x21], #16
str q4, [x21], #16
b .Lxts_enc_done
.align 4
.Lxts_enc_2:
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_encrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
mov v11.16b, v13.16b // next round tweak
str q0, [x21], #16
str q1, [x21], #16
b .Lxts_enc_done
.align 4
.Lxts_enc_1:
eor v0.16b, v0.16b, v11.16b
sub x0, sp, #16
sub x1, sp, #16
mov x2, x23
mov v13.d[0], v11.d[1] // just in case AES_encrypt corrupts top half of callee-saved SIMD registers
mov v14.d[0], v12.d[1]
str q0, [sp, #-16]!
bl AES_encrypt
ldr q0, [sp], #16
trn1 v13.2d, v11.2d, v13.2d
trn1 v11.2d, v12.2d, v14.2d // next round tweak
eor v0.16b, v0.16b, v13.16b
str q0, [x21], #16
.Lxts_enc_done:
adds x22, x22, #0x10
beq .Lxts_enc_ret
sub x6, x21, #0x10
// Penultimate plaintext block produces final ciphertext part-block
// plus remaining part of final plaintext block. Move ciphertext part
// to final position and re-use penultimate ciphertext block buffer to
// construct final plaintext block
.Lxts_enc_steal:
ldrb w0, [x20], #1
ldrb w1, [x21, #-0x10]
strb w0, [x21, #-0x10]
strb w1, [x21], #1
subs x22, x22, #1
bhi .Lxts_enc_steal
// Finally encrypt the penultimate ciphertext block using the
// last tweak
ldr q0, [x6]
eor v0.16b, v0.16b, v11.16b
str q0, [sp, #-16]!
mov x0, sp
mov x1, sp
mov x2, x23
mov x21, x6
mov v13.d[0], v11.d[1] // just in case AES_encrypt corrupts top half of callee-saved SIMD registers
bl AES_encrypt
trn1 v11.2d, v11.2d, v13.2d
ldr q0, [sp], #16
eor v0.16b, v0.16b, v11.16b
str q0, [x21]
.Lxts_enc_ret:
movi v0.16b, #0
movi v1.16b, #0
.Lxts_enc_bzero: // wipe key schedule
stp q0, q1, [sp], #32
cmp sp, x19
bne .Lxts_enc_bzero
ldp x19, x20, [sp, #80]
ldp x21, x22, [sp, #96]
ldr x23, [sp, #112]
ldp d8, d9, [sp, #128]
ldp d10, d11, [sp, #144]
ldp d12, d13, [sp, #160]
ldp d14, d15, [sp, #176]
ldp x29, x30, [sp], #192
ret
.size ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt
// The assembler doesn't seem capable of de-duplicating these when expressed
// using `ldr qd,=` syntax, so assign a symbolic address
.align 5
.Lxts_magic:
.quad 1, 0x87, 0x4000000000000000, 0x4000000000000000
.globl ossl_bsaes_xts_decrypt
.type ossl_bsaes_xts_decrypt,%function
.align 4
// On entry:
// x0 -> input ciphertext
// x1 -> output plaintext
// x2 -> length of text in bytes (must be at least 16)
// x3 -> key1 (used to decrypt the XORed ciphertext blocks)
// x4 -> key2 (used to encrypt the initial vector to yield the initial tweak)
// x5 -> 16-byte initial vector (typically, sector number)
// On exit:
// Output plaintext filled in
// No output registers, usual AAPCS64 register preservation
ossl_bsaes_xts_decrypt:
// Stack layout:
// sp ->
// nrounds*128-96 bytes: key schedule
// x19 ->
// 16 bytes: frame record
// 4*16 bytes: tweak storage across _bsaes_decrypt8
// 6*8 bytes: storage for 5 callee-saved general-purpose registers
// 8*8 bytes: storage for 8 callee-saved SIMD registers
stp x29, x30, [sp, #-192]!
stp x19, x20, [sp, #80]
stp x21, x22, [sp, #96]
str x23, [sp, #112]
stp d8, d9, [sp, #128]
stp d10, d11, [sp, #144]
stp d12, d13, [sp, #160]
stp d14, d15, [sp, #176]
mov x19, sp
mov x20, x0
mov x21, x1
mov x22, x2
mov x23, x3
// generate initial tweak
sub sp, sp, #16
mov x0, x5 // iv[]
mov x1, sp
mov x2, x4 // key2
bl AES_encrypt
ldr q11, [sp], #16
ldr w1, [x23, #240] // get # of rounds
// allocate the key schedule on the stack
add x17, sp, #96
sub x17, x17, x1, lsl #7 // 128 bytes per inner round key, less 96 bytes
// populate the key schedule
mov x9, x23 // pass key
mov x10, x1 // pass # of rounds
mov sp, x17
bl _bsaes_key_convert
ldr q6, [sp]
str q15, [x17] // save last round key
eor v6.16b, v6.16b, v7.16b // fix up round 0 key (by XORing with 0x63)
str q6, [sp]
sub x30, x22, #0x10
tst x22, #0xf // if not multiple of 16
csel x22, x30, x22, ne // subtract another 16 bytes
subs x22, x22, #0x80
blo .Lxts_dec_short
b .Lxts_dec_loop
.align 4
.Lxts_dec_loop:
ldr q8, .Lxts_magic
mov x10, x1 // pass rounds
add x2, x19, #16
ldr q0, [x20], #16
sshr v1.2d, v11.2d, #63
mov x9, sp // pass key schedule
ldr q6, .Lxts_magic+16
add v2.2d, v11.2d, v11.2d
cmtst v3.2d, v11.2d, v6.2d
and v1.16b, v1.16b, v8.16b
ext v1.16b, v1.16b, v1.16b, #8
and v3.16b, v3.16b, v8.16b
ldr q4, [x20], #16
eor v12.16b, v2.16b, v1.16b
eor v1.16b, v4.16b, v12.16b
eor v0.16b, v0.16b, v11.16b
cmtst v2.2d, v12.2d, v6.2d
add v4.2d, v12.2d, v12.2d
add x0, x19, #16
ext v3.16b, v3.16b, v3.16b, #8
and v2.16b, v2.16b, v8.16b
eor v13.16b, v4.16b, v3.16b
ldr q3, [x20], #16
ext v4.16b, v2.16b, v2.16b, #8
eor v2.16b, v3.16b, v13.16b
ldr q3, [x20], #16
add v5.2d, v13.2d, v13.2d
cmtst v7.2d, v13.2d, v6.2d
and v7.16b, v7.16b, v8.16b
ldr q9, [x20], #16
ext v7.16b, v7.16b, v7.16b, #8
ldr q10, [x20], #16
eor v14.16b, v5.16b, v4.16b
ldr q16, [x20], #16
add v4.2d, v14.2d, v14.2d
eor v3.16b, v3.16b, v14.16b
eor v15.16b, v4.16b, v7.16b
add v5.2d, v15.2d, v15.2d
ldr q7, [x20], #16
cmtst v4.2d, v14.2d, v6.2d
and v17.16b, v4.16b, v8.16b
cmtst v18.2d, v15.2d, v6.2d
eor v4.16b, v9.16b, v15.16b
ext v9.16b, v17.16b, v17.16b, #8
eor v9.16b, v5.16b, v9.16b
add v17.2d, v9.2d, v9.2d
and v18.16b, v18.16b, v8.16b
eor v5.16b, v10.16b, v9.16b
str q9, [x2], #16
ext v10.16b, v18.16b, v18.16b, #8
cmtst v9.2d, v9.2d, v6.2d
and v9.16b, v9.16b, v8.16b
eor v10.16b, v17.16b, v10.16b
cmtst v17.2d, v10.2d, v6.2d
eor v6.16b, v16.16b, v10.16b
str q10, [x2], #16
ext v9.16b, v9.16b, v9.16b, #8
add v10.2d, v10.2d, v10.2d
eor v9.16b, v10.16b, v9.16b
str q9, [x2], #16
eor v7.16b, v7.16b, v9.16b
add v9.2d, v9.2d, v9.2d
and v8.16b, v17.16b, v8.16b
ext v8.16b, v8.16b, v8.16b, #8
eor v8.16b, v9.16b, v8.16b
str q8, [x2] // next round tweak
bl _bsaes_decrypt8
eor v6.16b, v6.16b, v13.16b
eor v0.16b, v0.16b, v11.16b
ldr q8, [x0], #16
eor v7.16b, v7.16b, v8.16b
str q0, [x21], #16
eor v0.16b, v1.16b, v12.16b
ldr q1, [x0], #16
eor v1.16b, v3.16b, v1.16b
subs x22, x22, #0x80
eor v2.16b, v2.16b, v15.16b
eor v3.16b, v4.16b, v14.16b
ldr q4, [x0], #16
str q0, [x21], #16
ldr q11, [x0] // next round tweak
eor v0.16b, v5.16b, v4.16b
str q6, [x21], #16
str q3, [x21], #16
str q2, [x21], #16
str q7, [x21], #16
str q1, [x21], #16
str q0, [x21], #16
bpl .Lxts_dec_loop
.Lxts_dec_short:
adds x22, x22, #0x70
bmi .Lxts_dec_done
ldr q8, .Lxts_magic
sshr v1.2d, v11.2d, #63
add v2.2d, v11.2d, v11.2d
ldr q9, .Lxts_magic+16
subs x22, x22, #0x10
ldr q0, [x20], #16
and v1.16b, v1.16b, v8.16b
cmtst v3.2d, v11.2d, v9.2d
ext v1.16b, v1.16b, v1.16b, #8
and v3.16b, v3.16b, v8.16b
eor v12.16b, v2.16b, v1.16b
ext v1.16b, v3.16b, v3.16b, #8
add v2.2d, v12.2d, v12.2d
cmtst v3.2d, v12.2d, v9.2d
eor v13.16b, v2.16b, v1.16b
and v22.16b, v3.16b, v8.16b
bmi .Lxts_dec_1
ext v2.16b, v22.16b, v22.16b, #8
add v3.2d, v13.2d, v13.2d
ldr q1, [x20], #16
cmtst v4.2d, v13.2d, v9.2d
subs x22, x22, #0x10
eor v14.16b, v3.16b, v2.16b
and v23.16b, v4.16b, v8.16b
bmi .Lxts_dec_2
ext v3.16b, v23.16b, v23.16b, #8
add v4.2d, v14.2d, v14.2d
ldr q2, [x20], #16
cmtst v5.2d, v14.2d, v9.2d
eor v0.16b, v0.16b, v11.16b
subs x22, x22, #0x10
eor v15.16b, v4.16b, v3.16b
and v24.16b, v5.16b, v8.16b
bmi .Lxts_dec_3
ext v4.16b, v24.16b, v24.16b, #8
add v5.2d, v15.2d, v15.2d
ldr q3, [x20], #16
cmtst v6.2d, v15.2d, v9.2d
eor v1.16b, v1.16b, v12.16b
subs x22, x22, #0x10
eor v16.16b, v5.16b, v4.16b
and v25.16b, v6.16b, v8.16b
bmi .Lxts_dec_4
ext v5.16b, v25.16b, v25.16b, #8
add v6.2d, v16.2d, v16.2d
add x0, x19, #16
cmtst v7.2d, v16.2d, v9.2d
ldr q4, [x20], #16
eor v2.16b, v2.16b, v13.16b
str q16, [x0], #16
subs x22, x22, #0x10
eor v17.16b, v6.16b, v5.16b
and v26.16b, v7.16b, v8.16b
bmi .Lxts_dec_5
ext v7.16b, v26.16b, v26.16b, #8
add v18.2d, v17.2d, v17.2d
ldr q5, [x20], #16
eor v3.16b, v3.16b, v14.16b
str q17, [x0], #16
subs x22, x22, #0x10
eor v18.16b, v18.16b, v7.16b
bmi .Lxts_dec_6
ldr q6, [x20], #16
eor v4.16b, v4.16b, v15.16b
eor v5.16b, v5.16b, v16.16b
str q18, [x0] // next round tweak
mov x9, sp // pass key schedule
mov x10, x1
add x0, x19, #16
sub x22, x22, #0x10
eor v6.16b, v6.16b, v17.16b
bl _bsaes_decrypt8
ldr q16, [x0], #16
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
ldr q17, [x0], #16
eor v6.16b, v6.16b, v13.16b
eor v4.16b, v4.16b, v14.16b
eor v2.16b, v2.16b, v15.16b
ldr q11, [x0] // next round tweak
str q0, [x21], #16
str q1, [x21], #16
eor v0.16b, v7.16b, v16.16b
eor v1.16b, v3.16b, v17.16b
str q6, [x21], #16
str q4, [x21], #16
str q2, [x21], #16
str q0, [x21], #16
str q1, [x21], #16
b .Lxts_dec_done
.align 4
.Lxts_dec_6:
eor v4.16b, v4.16b, v15.16b
eor v5.16b, v5.16b, v16.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_decrypt8
ldr q16, [x0], #16
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
eor v6.16b, v6.16b, v13.16b
eor v4.16b, v4.16b, v14.16b
ldr q11, [x0] // next round tweak
eor v2.16b, v2.16b, v15.16b
str q0, [x21], #16
str q1, [x21], #16
eor v0.16b, v7.16b, v16.16b
str q6, [x21], #16
str q4, [x21], #16
str q2, [x21], #16
str q0, [x21], #16
b .Lxts_dec_done
.align 4
.Lxts_dec_5:
eor v3.16b, v3.16b, v14.16b
eor v4.16b, v4.16b, v15.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_decrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
ldr q11, [x0] // next round tweak
eor v6.16b, v6.16b, v13.16b
eor v4.16b, v4.16b, v14.16b
eor v2.16b, v2.16b, v15.16b
str q0, [x21], #16
str q1, [x21], #16
str q6, [x21], #16
str q4, [x21], #16
str q2, [x21], #16
b .Lxts_dec_done
.align 4
.Lxts_dec_4:
eor v2.16b, v2.16b, v13.16b
eor v3.16b, v3.16b, v14.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_decrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
eor v6.16b, v6.16b, v13.16b
eor v4.16b, v4.16b, v14.16b
mov v11.16b, v15.16b // next round tweak
str q0, [x21], #16
str q1, [x21], #16
str q6, [x21], #16
str q4, [x21], #16
b .Lxts_dec_done
.align 4
.Lxts_dec_3:
eor v1.16b, v1.16b, v12.16b
eor v2.16b, v2.16b, v13.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_decrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
eor v6.16b, v6.16b, v13.16b
mov v11.16b, v14.16b // next round tweak
str q0, [x21], #16
str q1, [x21], #16
str q6, [x21], #16
b .Lxts_dec_done
.align 4
.Lxts_dec_2:
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
mov x9, sp // pass key schedule
mov x10, x1 // pass rounds
add x0, x19, #16
bl _bsaes_decrypt8
eor v0.16b, v0.16b, v11.16b
eor v1.16b, v1.16b, v12.16b
mov v11.16b, v13.16b // next round tweak
str q0, [x21], #16
str q1, [x21], #16
b .Lxts_dec_done
.align 4
.Lxts_dec_1:
eor v0.16b, v0.16b, v11.16b
sub x0, sp, #16
sub x1, sp, #16
mov x2, x23
mov v13.d[0], v11.d[1] // just in case AES_decrypt corrupts top half of callee-saved SIMD registers
mov v14.d[0], v12.d[1]
str q0, [sp, #-16]!
bl AES_decrypt
ldr q0, [sp], #16
trn1 v13.2d, v11.2d, v13.2d
trn1 v11.2d, v12.2d, v14.2d // next round tweak
eor v0.16b, v0.16b, v13.16b
str q0, [x21], #16
.Lxts_dec_done:
adds x22, x22, #0x10
beq .Lxts_dec_ret
// calculate one round of extra tweak for the stolen ciphertext
ldr q8, .Lxts_magic
sshr v6.2d, v11.2d, #63
and v6.16b, v6.16b, v8.16b
add v12.2d, v11.2d, v11.2d
ext v6.16b, v6.16b, v6.16b, #8
eor v12.16b, v12.16b, v6.16b
// perform the final decryption with the last tweak value
ldr q0, [x20], #16
eor v0.16b, v0.16b, v12.16b
str q0, [sp, #-16]!
mov x0, sp
mov x1, sp
mov x2, x23
mov v13.d[0], v11.d[1] // just in case AES_decrypt corrupts top half of callee-saved SIMD registers
mov v14.d[0], v12.d[1]
bl AES_decrypt
trn1 v12.2d, v12.2d, v14.2d
trn1 v11.2d, v11.2d, v13.2d
ldr q0, [sp], #16
eor v0.16b, v0.16b, v12.16b
str q0, [x21]
mov x6, x21
// Penultimate ciphertext block produces final plaintext part-block
// plus remaining part of final ciphertext block. Move plaintext part
// to final position and re-use penultimate plaintext block buffer to
// construct final ciphertext block
.Lxts_dec_steal:
ldrb w1, [x21]
ldrb w0, [x20], #1
strb w1, [x21, #0x10]
strb w0, [x21], #1
subs x22, x22, #1
bhi .Lxts_dec_steal
// Finally decrypt the penultimate plaintext block using the
// penultimate tweak
ldr q0, [x6]
eor v0.16b, v0.16b, v11.16b
str q0, [sp, #-16]!
mov x0, sp
mov x1, sp
mov x2, x23
mov x21, x6
bl AES_decrypt
trn1 v11.2d, v11.2d, v13.2d
ldr q0, [sp], #16
eor v0.16b, v0.16b, v11.16b
str q0, [x21]
.Lxts_dec_ret:
movi v0.16b, #0
movi v1.16b, #0
.Lxts_dec_bzero: // wipe key schedule
stp q0, q1, [sp], #32
cmp sp, x19
bne .Lxts_dec_bzero
ldp x19, x20, [sp, #80]
ldp x21, x22, [sp, #96]
ldr x23, [sp, #112]
ldp d8, d9, [sp, #128]
ldp d10, d11, [sp, #144]
ldp d12, d13, [sp, #160]
ldp d14, d15, [sp, #176]
ldp x29, x30, [sp], #192
ret
.size ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt