This commit is contained in:
Adrian Stanciu 2025-03-20 23:31:15 +01:00 committed by GitHub
commit b7008619c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 663 additions and 124 deletions

View file

@ -0,0 +1,224 @@
#! /usr/bin/env perl
# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
# Copyright (c) 2025, Intel Corporation. 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
#
# Implements AES-CFB128 encryption and decryption with Intel(R) VAES
$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
or die "can't call $xlate: $!";
*STDOUT=*OUT;
$code=".text\n";
#################################################################
# Signature:
#
# void aes_cfb128_vaes_enc(
# const unsigned char *in,
# unsigned char *out,
# size_t len,
# const AES_KEY *ks,
# const unsigned char ivec[16],
# /*in-out*/ int *num);
#
# Preconditions:
# - all pointers are valid (not NULL...)
# - AES key schedule and rounds in `ks` are precomputed
#
# Invariants:
# - `*num` is between 0 and 15
#################################################################
$code.=<<___;
.globl aes_cfb128_vaes_enc
.type aes_cfb128_vaes_enc,\@function,6
.align 16
aes_cfb128_vaes_enc:
.cfi_startproc
endbranch
___
$inp="%rdi"; # arg0
$out="%rsi"; # arg1
$len="%rdx"; # arg2
$key_original="%rcx"; # arg3
$key_backup="%r10";
$key_crt="%r10";
$ivp="%r8"; # arg4
$nump="%r9"; # arg5
$num="%r11";
$left="%rcx";
$mask="%rax";
$rounds="%r11d";
$rnd0key="%xmm0";
$rndNkey="%xmm1";
$temp="%xmm2";
$plain="%xmm3";
sub vaes_encrypt_block() {
my ($aes_enc_loop_label)=@_;
$code.=<<___;
vmovdqu ($key_crt),$rnd0key # load round 0 key
vmovdqu 16($key_crt),$rndNkey # load round 1 key
lea 32($key_crt),$key_crt # key points to the 2nd round key
vpxor $rnd0key,$temp,$temp # pre-whitening
$aes_enc_loop_label:
vaesenc $rndNkey,$temp,$temp # encrypt with current round key
dec $rounds
vmovdqu ($key_crt),$rndNkey # load next round key
lea 16($key_crt),$key_crt # key points to the next round key
jnz $aes_enc_loop_label # process all encryption rounds but the last
vaesenclast $rndNkey,$temp,$temp # encrypt with the last round key
___
}
$code.=<<___;
movsl ($nump),$num # $num is the current byte index in the first partial block
# $num belongs to 0..15; non-zero means a partial first block
test $len,$len # return early if $len==0, unlikely to occur
jz .Laes_cfb128_vaes_enc
test $num,$num # check if the first block is partial
jz .Laes_cfb128_enc_mid
###########################################################
# first partial block pre-processing
###########################################################
mov $key_original,$key_backup # make room for variable shl with cl
mov \$0x10,$left # first block is partial
sub $num,$left # calculate how many bytes $left to process in the block
cmp $len,$left #
cmova $len,$left # $left = min(16-$num,$len)
mov \$1,$mask # build a mask with the least significant $left bits set
shlq %cl,$mask # $left is left shift counter
dec $mask # $mask is 2^$left-1
kmovq $mask,%k1
mov $num,%rax # keep in-out $num in %al
add $left,%rax # advance $num
and \$0x0F,%al # wrap-around $num in a 16-byte block
leaq ($num,$ivp),%r11 # process $left iv bytes
vmovdqu8 (%r11),%xmm0
vmovdqu8 ($inp),%xmm1 # process $left input bytes
vpxor %xmm0,%xmm1,%xmm2 # CipherFeedBack XOR
vmovdqu8 %xmm2,($out){%k1} # write $left output bytes
vmovdqu8 %xmm2,(%r11){%k1} # write $left chained/streaming input bytes
add $left,$inp # advance pointers
add $left,$out
sub $left,$len
jz .Laes_cfb128_enc_end # return early if no AES encryption required
mov $key_backup,$key_original # restore "key_original" as arg3
.Laes_cfb128_enc_mid:
###########################################################
# inner full blocks processing
###########################################################
vmovdqu ($ivp),$temp # load iv
cmp \$0x10,$len # any full plaintext blocks left ?
jb .Laes_cfb128_enc_post
.Loop_aes_cfb128_enc_main:
sub \$0x10,$len
mov $key_original,$key_crt
mov 240($key_crt),$rounds # load AES rounds
# 240 is the byte-offset of the rounds field in AES_KEY
vmovdqu ($inp),$plain # load plaintext block
lea 16($inp),$inp # inp points to next plaintext
___
&vaes_encrypt_block(".Loop_aes_enc_mid");
$code.=<<___;
vpxor $plain,$temp,$temp # CipherFeedBack XOR
cmp \$0x10,$len
vmovdqu $temp,($out) # write ciphertext
lea 16($out),$out # out points to the next output block
jge .Loop_aes_cfb128_enc_main
xor %eax,%eax # reset num when processing full blocks
vmovdqu $temp,($ivp) # latest ciphertext block is next encryption input
.Laes_cfb128_enc_post:
###########################################################
# last partial block post-processing
###########################################################
test $len,$len
jz .Laes_cfb128_enc_end
mov $key_original,$key_crt
mov 240($key_crt),$rounds # load AES rounds
# 240 is the byte-offset of the rounds field in AES_KEY
___
&vaes_encrypt_block(".Loop_aes_enc_post");
$code.=<<___;
mov $len,%rax # num=$len
mov \$1,%r11 # build a mask with the least significant $len bits set
mov %dl,%cl # $len is left shift counter less than 16
shlq %cl,%r11
dec %r11 # mask is 2^$len-1
kmovq %r11,%k1
vmovdqu8 ($inp),%xmm1{%k1}{z} # read $len input bytes
vpxor $temp,%xmm1,%xmm0 # CipherFeedBack XOR
vmovdqu8 %xmm0,($out){%k1} # write $len output bytes
vmovdqu8 %xmm0,($ivp) # write $len chained/streaming input bytes
.Laes_cfb128_enc_end:
mov %eax,($nump) # num is in/out, update for future/chained calls
vpxor $rnd0key,$rnd0key,$rnd0key # zeroize
vpxor $rndNkey,$rndNkey,$rndNkey # zeroize
vpxor $plain,$plain,$plain # zeroize
vpxor $temp,$temp,$temp # zeroize
.Laes_cfb128_vaes_enc:
ret
.cfi_endproc
.size aes_cfb128_vaes_enc,.-aes_cfb128_vaes_enc
___
print $code;
close STDOUT or die "error closing STDOUT: $!";

View file

@ -10,7 +10,7 @@ IF[{- !$disabled{asm} -}]
$AESASM_x86_64=\
aes-x86_64.s vpaes-x86_64.s bsaes-x86_64.s aesni-x86_64.s \
aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s \
aesni-xts-avx512.s
aesni-xts-avx512.s aes-cfb-avx512.s
$AESDEF_x86_64=AES_ASM VPAES_ASM BSAES_ASM
$AESASM_ia64=aes_core.c aes_cbc.c aes-ia64.s
@ -105,6 +105,7 @@ GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl
GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl
GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl
GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl
GENERATE[aes-cfb-avx512.s]=asm/aes-cfb-avx512.pl
GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl
GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl
GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl

View file

@ -11,6 +11,8 @@
#include <openssl/crypto.h>
#include "crypto/modes.h"
#include <assert.h>
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
typedef size_t size_t_aX __attribute((__aligned__(1)));
#else
@ -52,6 +54,7 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
break;
# endif
while (len >= 16) {
assert(n == 0);
(*block) (ivec, ivec, key);
for (; n < 16; n += sizeof(size_t)) {
*(size_t_aX *)(out + n) =
@ -64,6 +67,7 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
n = 0;
}
if (len) {
assert(n == 0);
(*block) (ivec, ivec, key);
while (len--) {
out[n] = ivec[n] ^= in[n];
@ -102,6 +106,7 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
break;
# endif
while (len >= 16) {
assert(n == 0);
(*block) (ivec, ivec, key);
for (; n < 16; n += sizeof(size_t)) {
size_t t = *(size_t_aX *)(in + n);
@ -115,6 +120,7 @@ void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
n = 0;
}
if (len) {
assert(n == 0);
(*block) (ivec, ivec, key);
while (len--) {
unsigned char c;

View file

@ -199,6 +199,13 @@ int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
void aes_cfb128_vaes_enc(const unsigned char* in, unsigned char* out,
size_t len, const AES_KEY *ks,
const unsigned char ivec[16], int* num);
void aes_cfb128_vaes_dec(const unsigned char* in, unsigned char* out,
size_t len, const AES_KEY *ks,
const unsigned char ivec[16], int* num);
void aesni_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aesni_decrypt(const unsigned char *in, unsigned char *out,

View file

@ -100,6 +100,7 @@ SOURCE[$NULL_GOAL]=\
SOURCE[$AES_GOAL]=\
cipher_aes.c cipher_aes_hw.c \
cipher_aes_xts.c cipher_aes_xts_hw.c \
cipher_aes_cfb.c cipher_aes_cfb_hw.c \
cipher_aes_gcm.c cipher_aes_gcm_hw.c \
cipher_aes_ccm.c cipher_aes_ccm_hw.c \
cipher_aes_wrp.c \

View file

@ -14,7 +14,7 @@
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES cipher modes ecb, cbc, ofb, cfb, ctr */
/* Dispatch functions for AES cipher modes ecb, cbc, ofb, ctr */
#include "cipher_aes.h"
#include "prov/implementations.h"
@ -28,7 +28,7 @@ static void aes_freectx(void *vctx)
PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *aes_dupctx(void *ctx)
@ -53,36 +53,21 @@ IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 256, 128, 0, block)
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 192, 128, 0, block)
/* ossl_aes128ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 128, 128, 0, block)
/* ossl_aes256cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 256, 128, 128, block)
/* ossl_aes192cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 192, 128, 128, block)
/* ossl_aes128cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 128, 128, 128, block)
/* ossl_aes256ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 256, 8, 128, stream)
/* ossl_aes192ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 192, 8, 128, stream)
/* ossl_aes128ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 256, 8, 128, stream)
/* ossl_aes192ctr_functions */

View file

@ -51,11 +51,7 @@ typedef struct prov_aes_ctx_st {
} PROV_AES_CTX;
#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128
#define ossl_prov_cipher_hw_aes_cfb ossl_prov_cipher_hw_aes_cfb128
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ofb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ctr(size_t keybits);

View file

@ -0,0 +1,71 @@
/*
* Copyright 2025 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
*/
/*
* AES low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES cipher mode cfb */
#include "cipher_aes.h"
#include <openssl/proverr.h>
#include "cipher_aes_cfb.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn aes_freectx;
static OSSL_FUNC_cipher_dupctx_fn aes_dupctx;
static void aes_freectx(void *vctx)
{
PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *aes_dupctx(void *ctx)
{
PROV_AES_CTX *in = (PROV_AES_CTX *)ctx;
PROV_AES_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
/* ossl_aes256cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream)

View file

@ -0,0 +1,16 @@
/*
* Copyright 2025 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
*/
#include "prov/ciphercommon.h"
#define ossl_prov_cipher_hw_aes_cfb ossl_prov_cipher_hw_aes_cfb128
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits);

View file

@ -0,0 +1,92 @@
/*
* Copyright 2025 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
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes.h"
#include "cipher_aes_cfb.h"
static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret;
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
AES_KEY *ks = &adat->ks.ks;
dat->ks = ks;
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)HWAES_encrypt;
dat->stream.cbc = NULL;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)vpaes_encrypt;
dat->stream.cbc = NULL;
} else
#endif
{
ret = AES_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)AES_encrypt;
dat->stream.cbc = NULL;
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aes_copyctx, PROV_AES_CTX)
#define PROV_CIPHER_HW_aes_mode(mode) \
static const PROV_CIPHER_HW aes_##mode = { \
cipher_hw_aes_initkey, \
ossl_cipher_hw_generic_##mode, \
cipher_hw_aes_copyctx \
}; \
PROV_CIPHER_HW_declare(mode) \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_##mode(size_t keybits) \
{ \
PROV_CIPHER_HW_select(mode) \
return &aes_##mode; \
}
#if defined(AESNI_CAPABLE)
# include "cipher_aes_cfb_hw_aesni.inc"
#elif defined(SPARC_AES_CAPABLE)
# include "cipher_aes_hw_t4.inc"
#elif defined(S390X_aes_128_CAPABLE)
# include "cipher_aes_cfb_hw_s390x.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
# include "cipher_aes_hw_rv64i.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
# include "cipher_aes_hw_rv32i.inc"
#elif defined(ARMv8_HWAES_CAPABLE)
# include "cipher_aes_hw_armv8.inc"
#else
/* The generic case */
# define PROV_CIPHER_HW_declare(mode)
# define PROV_CIPHER_HW_select(mode)
#endif
PROV_CIPHER_HW_aes_mode(cfb128)
PROV_CIPHER_HW_aes_mode(cfb1)
PROV_CIPHER_HW_aes_mode(cfb8)

View file

@ -0,0 +1,115 @@
/*
* Copyright 2001-2021 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
*/
/*-
* AES-NI and VAES support for AES CFB mode.
* This file is included by cipher_aes_cfb_hw.c
*/
#include <assert.h>
#define cipher_hw_vaes_cfb128 aes_cfb128_vaes_encdec_wrapper
#define cipher_hw_vaes_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_vaes_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_aesni_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_aesni_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_aesni_cfb1 ossl_cipher_hw_generic_cfb1
// active when AES-NI, AVX512F, and VAES are detected
static int aes_cfb128_vaes_encdec_wrapper(
PROV_CIPHER_CTX* dat,
unsigned char *out,
const unsigned char *in,
size_t len)
{
assert(dat != NULL);
assert(out != NULL);
assert(in != NULL);
assert(dat->mode == EVP_CIPH_CFB_MODE);
assert(dat->keylen == 16 || dat->keylen == 24 || dat->keylen == 32);
assert(dat->ks != NULL);
assert(dat->ivlen == 16);
assert(dat->iv != NULL);
assert(dat->enc == 0 || dat->enc == 1);
int num = dat->num;
assert(num < 16);
if (num < 0) {
// from CRYPTO_cfb128_encrypt
dat->num = -1;
return 1;
}
if (dat->enc) {
aes_cfb128_vaes_enc(in, out, len, dat->ks, dat->iv, &num);
} else {
CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
dat->block);
}
assert(num < 16);
dat->num = num;
return 1;
}
// generates AES round keys for AES-NI and VAES implementations
static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret;
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
AES_KEY *ks = &adat->ks.ks;
dat->ks = ks;
ret = aesni_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) aesni_encrypt;
dat->stream.cbc = NULL;
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
#define VAES_BIT (1<<(41-32))
#define AVX512F_BIT (1<<16)
#define AVX512F_VAES_CAPABLE ( \
(OPENSSL_ia32cap_P[3] & VAES_BIT) \
&& \
(OPENSSL_ia32cap_P[2] & AVX512F_BIT) \
)
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW aesni_##mode = { \
cipher_hw_aesni_initkey, \
cipher_hw_aesni_##mode, \
cipher_hw_aes_copyctx \
}; \
static const PROV_CIPHER_HW vaes_##mode = { \
cipher_hw_aesni_initkey, \
cipher_hw_vaes_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (AESNI_CAPABLE) { \
if (AVX512F_VAES_CAPABLE) \
return &vaes_##mode; \
return &aesni_##mode; \
}

View file

@ -0,0 +1,122 @@
/*
* Copyright 2001-2024 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
*/
/*
* IBM S390X support for AES mode cfb.
* This file is included by cipher_aes_cfb_hw.c
*/
#include "s390x_arch.h"
#include <stdio.h>
#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey
#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1
#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
int n = dat->num;
int rem;
unsigned char tmp;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
while (n && len) {
tmp = *in;
*out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
out += len;
in += len;
}
if (rem) {
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
adat->plat.s390x.param.kmo_kmf.cv,
S390X_AES_FC(dat->keylen),
adat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
tmp = in[n];
out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
++n;
}
}
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
dat->num = n;
return 1;
}
static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW s390x_aes_##mode = { \
s390x_aes_##mode##_initkey, \
s390x_aes_##mode##_cipher_hw, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
|| (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \
|| (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \
return &s390x_aes_##mode;

View file

@ -146,7 +146,7 @@ const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_##mode(size_t keybits) \
# include "cipher_aes_hw_rv64i.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
# include "cipher_aes_hw_rv32i.inc"
#elif defined (ARMv8_HWAES_CAPABLE)
#elif defined(ARMv8_HWAES_CAPABLE)
# include "cipher_aes_hw_armv8.inc"
#else
/* The generic case */
@ -157,7 +157,4 @@ const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_##mode(size_t keybits) \
PROV_CIPHER_HW_aes_mode(cbc)
PROV_CIPHER_HW_aes_mode(ecb)
PROV_CIPHER_HW_aes_mode(ofb128)
PROV_CIPHER_HW_aes_mode(cfb128)
PROV_CIPHER_HW_aes_mode(cfb1)
PROV_CIPHER_HW_aes_mode(cfb8)
PROV_CIPHER_HW_aes_mode(ctr)

View file

@ -8,14 +8,11 @@
*/
/*-
* AES-NI support for AES modes ecb, cbc, ofb, cfb, ctr.
* AES-NI support for AES modes ecb, cbc, ofb, ctr.
* This file is included by cipher_aes_hw.c
*/
#define cipher_hw_aesni_ofb128 ossl_cipher_hw_generic_ofb128
#define cipher_hw_aesni_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_aesni_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_aesni_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_aesni_ctr ossl_cipher_hw_generic_ctr
static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat,

View file

@ -17,18 +17,13 @@
#include <stdio.h>
#define s390x_aes_cbc_initkey cipher_hw_aes_initkey
#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey
#define s390x_aes_ctr_initkey cipher_hw_aes_initkey
#define s390x_aes_cbc_cipher_hw ossl_cipher_hw_generic_cbc
#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1
#define s390x_aes_ctr_cipher_hw ossl_cipher_hw_generic_ctr
#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE
#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE
#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE
#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
@ -105,91 +100,6 @@ static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
return 1;
}
static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
int n = dat->num;
int rem;
unsigned char tmp;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
while (n && len) {
tmp = *in;
*out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
out += len;
in += len;
}
if (rem) {
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
adat->plat.s390x.param.kmo_kmf.cv,
S390X_AES_FC(dat->keylen),
adat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
tmp = in[n];
out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
++n;
}
}
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
dat->num = n;
return 1;
}
static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW s390x_aes_##mode = { \
s390x_aes_##mode##_initkey, \
@ -201,4 +111,3 @@ if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
|| (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \
|| (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \
return &s390x_aes_##mode;