Commit 62663738b0 for openssl.org

commit 62663738b0a73ff453f9d0bb058f69328f0893eb
Author: Simo Sorce <simo@redhat.com>
Date:   Tue Jun 9 18:46:10 2026 -0400

    Refactor AES hardware cipher implementations

    Replace architecture-specific `.inc` files with standalone `.c` files for AES
    ciphers and consolidate CFB mode logic into these new modules.

    This eliminates the direct inclusion of source files and compiles each
    hardware implementation as a separate translation unit.

    This refactoring simplifies code organization and remove macro
    complexity that makes it hard to understand what is implemented and
    where enhancing maintainability.

    Signed-off-by: Simo Sorce <simo@redhat.com>

    Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
    Reviewed-by: Norbert Pocs <norbertp@openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
    MergeDate: Sat Jun 27 09:05:40 2026
    (Merged from https://github.com/openssl/openssl/pull/31472)

diff --git a/.clang-format b/.clang-format
index df41044fe1..b01602a2b9 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1375,6 +1375,7 @@ StatementMacros:
   - "static_ASN1_SEQUENCE_END_cb"
   - "static_ASN1_SEQUENCE_END_name"
   - "static_ASN1_SEQUENCE_END_ref"
+  - "PROV_CIPHER_HW_aes_mode"
   - "PROV_CIPHER_HW_aria_mode"
   - "PROV_CIPHER_HW_camellia_mode"
   - "PROV_CIPHER_HW_des_mode"
diff --git a/include/crypto/aes_platform.h b/include/crypto/aes_platform.h
index 13a31c5708..36ba2665ee 100644
--- a/include/crypto/aes_platform.h
+++ b/include/crypto/aes_platform.h
@@ -13,6 +13,12 @@

 #include <openssl/aes.h>

+typedef int (*aes_set_encrypt_key_fn)(const unsigned char *key,
+    int bits, AES_KEY *ks);
+
+typedef void (*aes_block128_f)(const unsigned char in[16],
+    unsigned char out[16], const AES_KEY *key);
+
 #ifdef VPAES_ASM
 int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
     AES_KEY *key);
diff --git a/providers/fips.module.sources b/providers/fips.module.sources
index c584493244..6a9058e66b 100644
--- a/providers/fips.module.sources
+++ b/providers/fips.module.sources
@@ -661,9 +661,6 @@ providers/implementations/ciphers/cipher_aes_ccm.c
 providers/implementations/ciphers/cipher_aes_ccm.h
 providers/implementations/ciphers/cipher_aes_ccm_hw.c
 providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
-providers/implementations/ciphers/cipher_aes_cfb.h
-providers/implementations/ciphers/cipher_aes_cfb_hw.c
-providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc
 providers/implementations/ciphers/cipher_aes_cts.inc
 providers/implementations/ciphers/cipher_aes_gcm.c
 providers/implementations/ciphers/cipher_aes_gcm.h
@@ -675,8 +672,13 @@ providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.c
 providers/implementations/ciphers/cipher_aes_gcm_hw_rv32i.c
 providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.c
 providers/implementations/ciphers/cipher_aes_gcm_hw_t4.c
+providers/implementations/ciphers/cipher_aes_hw_aesni.c
+providers/implementations/ciphers/cipher_aes_hw_armv8.c
+providers/implementations/ciphers/cipher_aes_hw_rv32i.c
+providers/implementations/ciphers/cipher_aes_hw_rv64i.c
+providers/implementations/ciphers/cipher_aes_hw_s390x.c
+providers/implementations/ciphers/cipher_aes_hw_t4.c
 providers/implementations/ciphers/cipher_aes_hw.c
-providers/implementations/ciphers/cipher_aes_hw_aesni.inc
 providers/implementations/ciphers/cipher_aes_ocb.c
 providers/implementations/ciphers/cipher_aes_ocb.h
 providers/implementations/ciphers/cipher_aes_ocb.inc.in
diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info
index b724c0baa9..6f12c208c3 100644
--- a/providers/implementations/ciphers/build.info
+++ b/providers/implementations/ciphers/build.info
@@ -103,9 +103,10 @@ SOURCE[$NULL_GOAL]=\
         cipher_null.c

 SOURCE[$AES_GOAL]=\
-        cipher_aes.c cipher_aes_hw.c \
+        cipher_aes.c cipher_aes_hw.c cipher_aes_hw_aesni.c \
+        cipher_aes_hw_armv8.c cipher_aes_hw_rv32i.c cipher_aes_hw_rv64i.c \
+        cipher_aes_hw_s390x.c cipher_aes_hw_t4.c \
         cipher_aes_xts.c cipher_aes_xts_hw.c \
-        cipher_aes_cfb_hw.c \
         cipher_aes_gcm.c cipher_aes_gcm_hw.c cipher_aes_gcm_hw_aesni.c \
         cipher_aes_gcm_hw_armv8.c cipher_aes_gcm_hw_ppc.c \
         cipher_aes_gcm_hw_rv32i.c cipher_aes_gcm_hw_rv64i.c \
diff --git a/providers/implementations/ciphers/cipher_aes.c b/providers/implementations/ciphers/cipher_aes.c
index 3444888082..3638919aeb 100644
--- a/providers/implementations/ciphers/cipher_aes.c
+++ b/providers/implementations/ciphers/cipher_aes.c
@@ -19,7 +19,6 @@
 #include "cipher_aes.h"
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
-#include "cipher_aes_cfb.h"

 static OSSL_FUNC_cipher_freectx_fn aes_freectx;
 static OSSL_FUNC_cipher_dupctx_fn aes_dupctx;
diff --git a/providers/implementations/ciphers/cipher_aes.h b/providers/implementations/ciphers/cipher_aes.h
index 48235f32d8..c5dfbc59e2 100644
--- a/providers/implementations/ciphers/cipher_aes.h
+++ b/providers/implementations/ciphers/cipher_aes.h
@@ -53,10 +53,56 @@ typedef struct prov_aes_ctx_st {

 } PROV_AES_CTX;

-#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128
+/* Note that XTS, CCM and GCM modes are handled with separate abstractions
+ * so they are not listed here */
+enum aes_modes {
+    AES_MODE_ECB = 1,
+    AES_MODE_CBC,
+    AES_MODE_CFB128,
+    AES_MODE_CFB8,
+    AES_MODE_CFB1,
+    AES_MODE_OFB128,
+    AES_MODE_CTR,
+};
+
 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);
+#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_cfb8(size_t keybits);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits);
+#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128
 const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ofb128(size_t keybits);
 const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ctr(size_t keybits);

+int ossl_cipher_set_aes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen,
+    aes_set_encrypt_key_fn fn_set_key, aes_block128_f fn_block,
+    ecb128_f fn_ecb, cbc128_f fn_cbc, ctr128_f fn_ctr);
+
+int ossl_cipher_hw_aes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen);
+
+void ossl_cipher_aes_copyctx(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src);
+
+#if defined(AESNI_CAPABLE)
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aesni(enum aes_modes mode,
+    size_t keybits);
+#elif defined(ARMv8_HWAES_CAPABLE)
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_arm(enum aes_modes mode,
+    size_t keybits);
+#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv32i(enum aes_modes mode,
+    size_t keybits);
+#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode,
+    size_t keybits);
+#elif defined(S390X_aes_128_CAPABLE)
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_s390x(enum aes_modes mode,
+    size_t keybits);
+#elif defined(SPARC_AES_CAPABLE)
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_t4(enum aes_modes mode,
+    size_t keybits);
+#endif
+
 #endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_H) */
diff --git a/providers/implementations/ciphers/cipher_aes_cfb.h b/providers/implementations/ciphers/cipher_aes_cfb.h
deleted file mode 100644
index 416ba585fc..0000000000
--- a/providers/implementations/ciphers/cipher_aes_cfb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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
- */
-
-#if !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CFB_H)
-#define OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CFB_H
-
-#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);
-
-#endif /* !defined(OSSL_PROVIDERS_IMPLEMENTATIONS_CIPHERS_CIPHER_AES_CFB_H) */
diff --git a/providers/implementations/ciphers/cipher_aes_cfb_hw.c b/providers/implementations/ciphers/cipher_aes_cfb_hw.c
deleted file mode 100644
index a0399bcdc2..0000000000
--- a/providers/implementations/ciphers/cipher_aes_cfb_hw.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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, (int)(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, (int)(keylen * 8), ks);
-            dat->block = (block128_f)vpaes_encrypt;
-            dat->stream.cbc = NULL;
-        } else {
-#endif
-            {
-                ret = AES_set_encrypt_key(key, (int)(keylen * 8), ks);
-                dat->block = (block128_f)AES_encrypt;
-                dat->stream.cbc = NULL;
-            }
-#ifdef VPAES_CAPABLE
-        }
-#endif
-#ifdef HWAES_CAPABLE
-    }
-#endif
-
-    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)
diff --git a/providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc
deleted file mode 100644
index eb8e0164ac..0000000000
--- a/providers/implementations/ciphers/cipher_aes_cfb_hw_aesni.inc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2001-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-NI and VAES support for AES CFB mode.
- * This file is included by cipher_aes_cfb_hw.c
- */
-
-#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64))
-    #define cipher_hw_vaes_cfb128 aes_cfb128_vaes_encdec_wrapper
-#else
-    #define cipher_hw_vaes_cfb128 ossl_cipher_hw_generic_cfb128
-    int ossl_aes_cfb128_vaes_eligible() {
-        return 0;
-    }
-#endif
-#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
-
-static int ossl_aes_cfb8_vaes_eligible(void) { return 0; }
-static int ossl_aes_cfb1_vaes_eligible(void) { return 0; }
-
-#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64))
-/* active in 64-bit builds 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)
-{
-    ossl_ssize_t num;
-
-    num = (ossl_ssize_t)dat->num;
-
-    if (num < 0) {
-        /* behavior from CRYPTO_cfb128_encrypt */
-        dat->num = -1;
-        return 1;
-    }
-
-    if (dat->enc)
-        ossl_aes_cfb128_vaes_enc(in, out, len, dat->ks, dat->iv, &num);
-    else
-        ossl_aes_cfb128_vaes_dec(in, out, len, dat->ks, dat->iv, &num);
-
-    dat->num = (int)num;
-
-    return 1;
-}
-#endif
-
-/* 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, (int)(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 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 (ossl_aes_##mode##_vaes_eligible())                                     \
-        return &vaes_##mode;                                                   \
-    return &aesni_##mode;                                                      \
-}
diff --git a/providers/implementations/ciphers/cipher_aes_cfb_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_cfb_hw_s390x.inc
deleted file mode 100644
index 113c1de6a9..0000000000
--- a/providers/implementations/ciphers/cipher_aes_cfb_hw_s390x.inc
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2001-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
- */
-
-/*
- * IBM S390X support for AES mode cfb.
- * This file is included by cipher_aes_cfb_hw.c
- */
-
-#include "arch/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;
-
diff --git a/providers/implementations/ciphers/cipher_aes_gcm.h b/providers/implementations/ciphers/cipher_aes_gcm.h
index ef4170c255..d8ce0b4563 100644
--- a/providers/implementations/ciphers/cipher_aes_gcm.h
+++ b/providers/implementations/ciphers/cipher_aes_gcm.h
@@ -45,12 +45,6 @@ typedef struct prov_aes_gcm_ctx_st {
     } plat;
 } PROV_AES_GCM_CTX;

-typedef void (*aes_block128_f)(const unsigned char in[16],
-    unsigned char out[16], const AES_KEY *key);
-
-typedef int (*aes_set_encrypt_key_fn)(const unsigned char *key,
-    int bits, AES_KEY *ks);
-
 int aes_gcm_hw_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
     size_t keylen, aes_set_encrypt_key_fn fn_set_key,
     aes_block128_f fn_block, ctr128_f fn_ctr);
diff --git a/providers/implementations/ciphers/cipher_aes_hw.c b/providers/implementations/ciphers/cipher_aes_hw.c
index da9a6729d0..5ad1d81e94 100644
--- a/providers/implementations/ciphers/cipher_aes_hw.c
+++ b/providers/implementations/ciphers/cipher_aes_hw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2026 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
@@ -16,149 +16,252 @@
 #include <openssl/proverr.h>
 #include "cipher_aes.h"

-static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
-    const unsigned char *key, size_t keylen)
+int ossl_cipher_set_aes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen,
+    aes_set_encrypt_key_fn fn_set_key, aes_block128_f fn_block,
+    ecb128_f fn_ecb, cbc128_f fn_cbc, ctr128_f fn_ctr)
 {
-    int ret;
-    PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
-    AES_KEY *ks = &adat->ks.ks;
+    PROV_AES_CTX *actx = (PROV_AES_CTX *)ctx;
+    AES_KEY *ks = &actx->ks.ks;
+
+    int ret = fn_set_key(key, (int)(keylen * 8), ks);
+    if (ret < 0) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+        return 0;
+    }
+    ctx->ks = ks;

-    dat->ks = ks;
+    ctx->block = (block128_f)fn_block;
+
+    switch (ctx->mode) {
+    case EVP_CIPH_ECB_MODE:
+        ctx->stream.ecb = fn_ecb;
+        break;
+    case EVP_CIPH_CBC_MODE:
+        ctx->stream.cbc = fn_cbc;
+        break;
+    case EVP_CIPH_CTR_MODE:
+        ctx->stream.ctr = fn_ctr;
+        break;
+    default:
+        memset(&ctx->stream, 0, sizeof(ctx->stream));
+        break;
+    }
+
+    return 1;
+}

-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
-        && !dat->enc) {
 #ifdef HWAES_CAPABLE
-        if (HWAES_CAPABLE) {
-            ret = HWAES_set_decrypt_key(key, keylen * 8, ks);
-            dat->block = (block128_f)HWAES_decrypt;
-            dat->stream.cbc = NULL;
-#ifdef HWAES_cbc_encrypt
-            if (dat->mode == EVP_CIPH_CBC_MODE)
-                dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
-#endif
+static int hwaes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if (HWAES_CAPABLE) {
+        ecb128_f fn_ecb = NULL;
+        cbc128_f fn_cbc = NULL;
+        ctr128_f fn_ctr = NULL;
 #ifdef HWAES_ecb_encrypt
-            if (dat->mode == EVP_CIPH_ECB_MODE)
-                dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt;
+        fn_ecb = (ecb128_f)HWAES_ecb_encrypt;
 #endif
-        } else
+#ifdef HWAES_cbc_encrypt
+        fn_cbc = (cbc128_f)HWAES_cbc_encrypt;
 #endif
-#ifdef BSAES_CAPABLE
-            if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
-            ret = AES_set_decrypt_key(key, (int)(keylen * 8), ks);
-            dat->block = (block128_f)AES_decrypt;
-            dat->stream.cbc = (cbc128_f)ossl_bsaes_cbc_encrypt;
-        } else
+#ifdef HWAES_ctr32_encrypt_blocks
+        fn_ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
 #endif
+        if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+            && !ctx->enc)
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                HWAES_set_decrypt_key, HWAES_decrypt, fn_ecb, fn_cbc, fn_ctr);
+        else
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                HWAES_set_encrypt_key, HWAES_encrypt, fn_ecb, fn_cbc, fn_ctr);
+    }
+    return -1;
+}
+#endif /* HWAES_CAPABLE */
+
+#ifdef BSAES_CAPABLE
+static int bsaes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if (BSAES_CAPABLE) {
+        if (ctx->mode == EVP_CIPH_CBC_MODE && !ctx->enc)
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                AES_set_decrypt_key, AES_decrypt, NULL,
+                (cbc128_f)ossl_bsaes_cbc_encrypt, NULL);
+        else if (ctx->mode == EVP_CIPH_CTR_MODE)
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                AES_set_encrypt_key, AES_encrypt, NULL, NULL,
+                (ctr128_f)ossl_bsaes_ctr32_encrypt_blocks);
+    }
+    return -1;
+}
+#endif /* BSAES_CAPABLE */
+
 #ifdef VPAES_CAPABLE
-            if (VPAES_CAPABLE) {
-            ret = vpaes_set_decrypt_key(key, (int)(keylen * 8), ks);
-            dat->block = (block128_f)vpaes_decrypt;
-            dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
-                ? (cbc128_f)vpaes_cbc_encrypt
-                : NULL;
-        } else
-#endif
-        {
-            ret = AES_set_decrypt_key(key, (int)(keylen * 8), ks);
-            dat->block = (block128_f)AES_decrypt;
-            dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
-                ? (cbc128_f)AES_cbc_encrypt
-                : NULL;
+static int vpaes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if (VPAES_CAPABLE) {
+        if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+            && !ctx->enc) {
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                vpaes_set_decrypt_key, vpaes_decrypt, NULL,
+                (cbc128_f)vpaes_cbc_encrypt, NULL);
+        } else {
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                vpaes_set_encrypt_key, vpaes_encrypt, NULL,
+                (cbc128_f)vpaes_cbc_encrypt, NULL);
         }
-    } else
+    }
+    return -1;
+}
+#endif /* VPAES_CAPABLE */
+
+int ossl_cipher_hw_aes_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    int ret = 0;
+
 #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;
-#ifdef HWAES_cbc_encrypt
-        if (dat->mode == EVP_CIPH_CBC_MODE)
-            dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
-        else
-#endif
-#ifdef HWAES_ecb_encrypt
-            if (dat->mode == EVP_CIPH_ECB_MODE)
-            dat->stream.ecb = (ecb128_f)HWAES_ecb_encrypt;
-        else
-#endif
-#ifdef HWAES_ctr32_encrypt_blocks
-            if (dat->mode == EVP_CIPH_CTR_MODE)
-            dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
-        else
-#endif
-            (void)0; /* terminate potentially open 'else' */
-    } else
+    ret = hwaes_initkey(ctx, key, keylen);
+    if (ret >= 0)
+        return ret;
 #endif
+
 #ifdef BSAES_CAPABLE
-        if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
-        ret = AES_set_encrypt_key(key, (int)(keylen * 8), ks);
-        dat->block = (block128_f)AES_encrypt;
-        dat->stream.ctr = (ctr128_f)ossl_bsaes_ctr32_encrypt_blocks;
-    } else
+    ret = bsaes_initkey(ctx, key, keylen);
+    if (ret >= 0)
+        return ret;
 #endif
+
 #ifdef VPAES_CAPABLE
-        if (VPAES_CAPABLE) {
-        ret = vpaes_set_encrypt_key(key, (int)(keylen * 8), ks);
-        dat->block = (block128_f)vpaes_encrypt;
-        dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
-            ? (cbc128_f)vpaes_cbc_encrypt
-            : NULL;
-    } else
+    ret = vpaes_initkey(ctx, key, keylen);
+    if (ret >= 0)
+        return ret;
 #endif
-    {
-        ret = AES_set_encrypt_key(key, (int)(keylen * 8), ks);
-        dat->block = (block128_f)AES_encrypt;
-        dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
-            ? (cbc128_f)AES_cbc_encrypt
-            : NULL;
+
+    if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+        && !ctx->enc) {
+        ret = ossl_cipher_set_aes_initkey(ctx, key, keylen,
+            AES_set_decrypt_key, AES_decrypt, NULL, (cbc128_f)AES_cbc_encrypt,
+            NULL);
+    } else {
+        ctr128_f fn_ctr = NULL;
 #ifdef AES_CTR_ASM
-        if (dat->mode == EVP_CIPH_CTR_MODE)
-            dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
+        fn_ctr = (ctr128_f)AES_ctr32_encrypt;
 #endif
+        ret = ossl_cipher_set_aes_initkey(ctx, key, keylen,
+            AES_set_encrypt_key, AES_encrypt, NULL, (cbc128_f)AES_cbc_encrypt,
+            fn_ctr);
     }

-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
+    return ret;
+}

-    return 1;
+void ossl_cipher_aes_copyctx(PROV_CIPHER_CTX *dst,
+    const PROV_CIPHER_CTX *src)
+{
+    PROV_AES_CTX *sctx = (PROV_AES_CTX *)src;
+    PROV_AES_CTX *dctx = (PROV_AES_CTX *)dst;
+
+    *dctx = *sctx;
+    dst->ks = &dctx->ks.ks;
 }

-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; \
-    }
+static const PROV_CIPHER_HW aes_ecb = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_ecb,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_cbc = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_cbc,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_cfb128 = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_cfb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_cfb8 = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_cfb8,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_cfb1 = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_cfb1,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_ofb128 = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_ofb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_ctr = {
+    ossl_cipher_hw_aes_initkey,
+    ossl_cipher_hw_generic_ctr,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_mode(enum aes_modes mode,
+    size_t keybits)
+{
+    const PROV_CIPHER_HW *aes_hw_mode = NULL;

 #if defined(AESNI_CAPABLE)
-#include "cipher_aes_hw_aesni.inc"
-#elif defined(SPARC_AES_CAPABLE)
-#include "cipher_aes_hw_t4.inc"
-#elif defined(S390X_aes_128_CAPABLE)
-#include "cipher_aes_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"
+    aes_hw_mode = ossl_prov_cipher_hw_aesni(mode, keybits);
 #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)
+    aes_hw_mode = ossl_prov_cipher_hw_arm(mode, keybits);
+#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
+    aes_hw_mode = ossl_prov_cipher_hw_rv32i(mode, keybits);
+#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
+    aes_hw_mode = ossl_prov_cipher_hw_rv64i(mode, keybits);
+#elif defined(S390X_aes_128_CAPABLE)
+    aes_hw_mode = ossl_prov_cipher_hw_s390x(mode, keybits);
+#elif defined(SPARC_AES_CAPABLE)
+    aes_hw_mode = ossl_prov_cipher_hw_t4(mode, keybits);
 #endif

-PROV_CIPHER_HW_aes_mode(cbc)
-    PROV_CIPHER_HW_aes_mode(ecb)
-        PROV_CIPHER_HW_aes_mode(ofb128)
-            PROV_CIPHER_HW_aes_mode(ctr)
+    if (aes_hw_mode == NULL) {
+        switch (mode) {
+        case AES_MODE_ECB:
+            return &aes_ecb;
+        case AES_MODE_CBC:
+            return &aes_cbc;
+        case AES_MODE_CFB128:
+            return &aes_cfb128;
+        case AES_MODE_CFB8:
+            return &aes_cfb8;
+        case AES_MODE_CFB1:
+            return &aes_cfb1;
+        case AES_MODE_OFB128:
+            return &aes_ofb128;
+        case AES_MODE_CTR:
+            return &aes_ctr;
+        }
+    }
+
+    return aes_hw_mode;
+}
+
+#define PROV_CIPHER_HW_aes_mode(ENUM_MODE, mode)                         \
+    const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_##mode(size_t keybits) \
+    {                                                                    \
+        return ossl_prov_cipher_hw_aes_mode(ENUM_MODE, keybits);         \
+    }
+
+PROV_CIPHER_HW_aes_mode(AES_MODE_ECB, ecb)
+PROV_CIPHER_HW_aes_mode(AES_MODE_CBC, cbc)
+PROV_CIPHER_HW_aes_mode(AES_MODE_CFB128, cfb128)
+PROV_CIPHER_HW_aes_mode(AES_MODE_CFB8, cfb8)
+PROV_CIPHER_HW_aes_mode(AES_MODE_CFB1, cfb1)
+PROV_CIPHER_HW_aes_mode(AES_MODE_OFB128, ofb128)
+PROV_CIPHER_HW_aes_mode(AES_MODE_CTR, ctr)
diff --git a/providers/implementations/ciphers/cipher_aes_hw_aesni.c b/providers/implementations/ciphers/cipher_aes_hw_aesni.c
new file mode 100644
index 0000000000..d434874a43
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_aesni.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2001-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-NI support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is used by cipher_aes_hw.c
+ */
+
+#include "internal/deprecated.h"
+#include "cipher_aes.h"
+
+#if defined(AESNI_CAPABLE)
+
+/* generates AES round keys for AES-NI and VAES implementations */
+static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+        && !ctx->enc) {
+        return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+            aesni_set_decrypt_key, aesni_decrypt, NULL,
+            (cbc128_f)aesni_cbc_encrypt, NULL);
+    } else {
+        return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+            aesni_set_encrypt_key, aesni_encrypt, NULL,
+            (cbc128_f)aesni_cbc_encrypt, (ctr128_f)aesni_ctr32_encrypt_blocks);
+    }
+}
+
+static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+    if (len < ctx->blocksize)
+        return 1;
+
+    aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc);
+
+    return 1;
+}
+
+static const PROV_CIPHER_HW aesni_ecb = {
+    cipher_hw_aesni_initkey,
+    cipher_hw_aesni_ecb,
+    ossl_cipher_aes_copyctx
+};
+
+static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+    aesni_cbc_encrypt(in, out, len, ctx->ks, ctx->iv, ctx->enc);
+
+    return 1;
+}
+
+static const PROV_CIPHER_HW aesni_cbc = {
+    cipher_hw_aesni_initkey,
+    cipher_hw_aesni_cbc,
+    ossl_cipher_aes_copyctx
+};
+
+#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64))
+/* active in 64-bit builds when AES-NI, AVX512F, and VAES are detected */
+#define VAES_CFB128_ELIGIBLE 1
+#else
+#define VAES_CFB128_ELIGIBLE 0
+#endif
+
+#if VAES_CFB128_ELIGIBLE
+static int aes_cfb128_vaes_encdec_wrapper(
+    PROV_CIPHER_CTX *ctx,
+    unsigned char *out,
+    const unsigned char *in,
+    size_t len)
+{
+    ossl_ssize_t num;
+
+    num = (ossl_ssize_t)ctx->num;
+
+    if (num < 0) {
+        /* behavior from CRYPTO_cfb128_encrypt */
+        ctx->num = -1;
+        return 1;
+    }
+
+    if (ctx->enc)
+        ossl_aes_cfb128_vaes_enc(in, out, len, ctx->ks, ctx->iv, &num);
+    else
+        ossl_aes_cfb128_vaes_dec(in, out, len, ctx->ks, ctx->iv, &num);
+
+    ctx->num = (int)num;
+
+    return 1;
+}
+
+static const PROV_CIPHER_HW aesni_vaes_cfb128 = {
+    cipher_hw_aesni_initkey,
+    aes_cfb128_vaes_encdec_wrapper,
+    ossl_cipher_aes_copyctx
+};
+#endif /* VAES_CFB128_ELIGIBLE */
+
+static const PROV_CIPHER_HW aesni_cfb128 = {
+    cipher_hw_aesni_initkey,
+    ossl_cipher_hw_generic_cfb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aesni_cfb8 = {
+    cipher_hw_aesni_initkey,
+    ossl_cipher_hw_generic_cfb8,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aesni_cfb1 = {
+    cipher_hw_aesni_initkey,
+    ossl_cipher_hw_generic_cfb1,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aesni_ofb128 = {
+    cipher_hw_aesni_initkey,
+    ossl_cipher_hw_generic_ofb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aesni_ctr = {
+    cipher_hw_aesni_initkey,
+    ossl_cipher_hw_generic_ctr,
+    ossl_cipher_aes_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aesni(enum aes_modes mode,
+    size_t keybits)
+{
+    if (AESNI_CAPABLE) {
+        switch (mode) {
+        case AES_MODE_ECB:
+            return &aesni_ecb;
+        case AES_MODE_CBC:
+            return &aesni_cbc;
+        case AES_MODE_CFB128:
+#if VAES_CFB128_ELIGIBLE
+            if (ossl_aes_cfb128_vaes_eligible())
+                return &aesni_vaes_cfb128;
+#endif
+            return &aesni_cfb128;
+        case AES_MODE_CFB8:
+            return &aesni_cfb8;
+        case AES_MODE_CFB1:
+            return &aesni_cfb1;
+        case AES_MODE_OFB128:
+            return &aesni_ofb128;
+        case AES_MODE_CTR:
+            return &aesni_ctr;
+        default:
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc
deleted file mode 100644
index 7b7084aea7..0000000000
--- a/providers/implementations/ciphers/cipher_aes_hw_aesni.inc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2001-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-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_ctr    ossl_cipher_hw_generic_ctr
-
-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;
-
-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
-        && !dat->enc) {
-        ret = aesni_set_decrypt_key(key, (int)(keylen * 8), ks);
-        dat->block = (block128_f) aesni_decrypt;
-        dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
-            (cbc128_f) aesni_cbc_encrypt : NULL;
-    } else {
-        ret = aesni_set_encrypt_key(key, (int)(keylen * 8), ks);
-        dat->block = (block128_f) aesni_encrypt;
-        if (dat->mode == EVP_CIPH_CBC_MODE)
-            dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
-        else if (dat->mode == EVP_CIPH_CTR_MODE)
-            dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
-        else
-            dat->stream.cbc = NULL;
-    }
-
-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
-
-    return 1;
-}
-
-static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
-                               const unsigned char *in, size_t len)
-{
-    const AES_KEY *ks = ctx->ks;
-
-    aesni_cbc_encrypt(in, out, len, ks, ctx->iv, ctx->enc);
-
-    return 1;
-}
-
-static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
-                               const unsigned char *in, size_t len)
-{
-    if (len < ctx->blocksize)
-        return 1;
-
-    aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc);
-
-    return 1;
-}
-
-#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                                                      \
-};
-#define PROV_CIPHER_HW_select(mode)                                            \
-if (AESNI_CAPABLE)                                                             \
-    return &aesni_##mode;
diff --git a/providers/implementations/ciphers/cipher_aes_hw_armv8.c b/providers/implementations/ciphers/cipher_aes_hw_armv8.c
new file mode 100644
index 0000000000..773e40a411
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_armv8.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Crypto extension support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is used by cipher_aes_hw.c
+ */
+
+#include "internal/deprecated.h"
+#include "cipher_aes.h"
+
+#if defined(ARMv8_HWAES_CAPABLE)
+
+static int cipher_hw_aes_arm_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if (!ossl_cipher_hw_aes_initkey(ctx, key, keylen))
+        return 0;
+
+    if (AES_UNROLL12_EOR3_CAPABLE && ctx->mode == EVP_CIPH_CTR_MODE)
+        ctx->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks_unroll12_eor3;
+
+    return 1;
+}
+
+static const PROV_CIPHER_HW arm_ctr = {
+    cipher_hw_aes_arm_initkey,
+    ossl_cipher_hw_generic_ctr,
+    ossl_cipher_aes_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_arm(enum aes_modes mode,
+    size_t keybits)
+{
+    if (ARMv8_HWAES_CAPABLE && mode == AES_MODE_CTR)
+        return &arm_ctr;
+    return NULL;
+}
+
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw_armv8.inc b/providers/implementations/ciphers/cipher_aes_hw_armv8.inc
deleted file mode 100644
index 3f73c79290..0000000000
--- a/providers/implementations/ciphers/cipher_aes_hw_armv8.inc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Crypto extension support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is included by cipher_aes_hw.c
- */
-
-static int cipher_hw_aes_arm_initkey(PROV_CIPHER_CTX *dat,
-                                                       const unsigned char *key,
-                                                       size_t keylen)
-{
-    int ret = cipher_hw_aes_initkey(dat, key, keylen);
-    if (AES_UNROLL12_EOR3_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE)
-        dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks_unroll12_eor3;
-
-    return ret;
-}
-
-#define PROV_CIPHER_HW_declare(mode)                                           \
-static const PROV_CIPHER_HW aes_arm_##mode = {                                 \
-    cipher_hw_aes_arm_initkey,                                                 \
-    ossl_cipher_hw_generic_##mode,                                             \
-    cipher_hw_aes_copyctx                                                      \
-};
-#define PROV_CIPHER_HW_select(mode)                                            \
-if (ARMv8_HWAES_CAPABLE)                                                         \
-    return &aes_arm_##mode;
diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv32i.c b/providers/implementations/ciphers/cipher_aes_hw_rv32i.c
new file mode 100644
index 0000000000..375f9dc946
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_rv32i.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * RISC-V 32 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is used by cipher_aes_hw.c
+ */
+
+#include "internal/deprecated.h"
+#include "cipher_aes.h"
+
+#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
+
+static int cipher_hw_rv32i_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+        && !ctx->enc) {
+        if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE())
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                rv32i_zbkb_zknd_zkne_set_decrypt_key, rv32i_zknd_decrypt,
+                NULL, NULL, NULL);
+        else
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                rv32i_zknd_zkne_set_decrypt_key, rv32i_zknd_decrypt,
+                NULL, NULL, NULL);
+    } else {
+        if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE())
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt,
+                NULL, NULL, NULL);
+        else
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt,
+                NULL, NULL, NULL);
+    }
+}
+
+static const PROV_CIPHER_HW rv32i_ecb = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_ecb,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv32i_cbc = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_cbc,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv32i_cfb128 = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_cfb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv32i_cfb8 = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_cfb8,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv32i_cfb1 = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_cfb1,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv32i_ofb128 = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_ofb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv32i_ctr = {
+    cipher_hw_rv32i_initkey,
+    ossl_cipher_hw_generic_ctr,
+    ossl_cipher_aes_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv32i(enum aes_modes mode,
+    size_t keybits)
+{
+    if (RISCV_HAS_ZKND_AND_ZKNE()) {
+        switch (mode) {
+        case AES_MODE_ECB:
+            return &rv32i_ecb;
+        case AES_MODE_CBC:
+            return &rv32i_cbc;
+        case AES_MODE_CFB128:
+            return &rv32i_cfb128;
+        case AES_MODE_CFB8:
+            return &rv32i_cfb8;
+        case AES_MODE_CFB1:
+            return &rv32i_cfb1;
+        case AES_MODE_OFB128:
+            return &rv32i_ofb128;
+        case AES_MODE_CTR:
+            return &rv32i_ctr;
+        default:
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv32i.inc b/providers/implementations/ciphers/cipher_aes_hw_rv32i.inc
deleted file mode 100644
index f6c652c32d..0000000000
--- a/providers/implementations/ciphers/cipher_aes_hw_rv32i.inc
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*-
- * RISC-V 32 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is included by cipher_aes_hw.c
- */
-
-#define cipher_hw_rv32i_zknd_zkne_cbc    ossl_cipher_hw_generic_cbc
-#define cipher_hw_rv32i_zknd_zkne_ecb    ossl_cipher_hw_generic_ecb
-#define cipher_hw_rv32i_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128
-#define cipher_hw_rv32i_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128
-#define cipher_hw_rv32i_zknd_zkne_cfb8   ossl_cipher_hw_generic_cfb8
-#define cipher_hw_rv32i_zknd_zkne_cfb1   ossl_cipher_hw_generic_cfb1
-#define cipher_hw_rv32i_zknd_zkne_ctr    ossl_cipher_hw_generic_ctr
-
-#define cipher_hw_rv32i_zbkb_zknd_zkne_cbc    ossl_cipher_hw_generic_cbc
-#define cipher_hw_rv32i_zbkb_zknd_zkne_ecb    ossl_cipher_hw_generic_ecb
-#define cipher_hw_rv32i_zbkb_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128
-#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128
-#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb8   ossl_cipher_hw_generic_cfb8
-#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb1   ossl_cipher_hw_generic_cfb1
-#define cipher_hw_rv32i_zbkb_zknd_zkne_ctr    ossl_cipher_hw_generic_ctr
-
-static int cipher_hw_rv32i_zknd_zkne_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;
-
-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
-        && !dat->enc) {
-        ret = rv32i_zknd_zkne_set_decrypt_key(key, keylen * 8, ks);
-        dat->block = (block128_f) rv32i_zknd_decrypt;
-        dat->stream.cbc = NULL;
-    } else {
-        ret = rv32i_zkne_set_encrypt_key(key, keylen * 8, ks);
-        dat->block = (block128_f) rv32i_zkne_encrypt;
-        dat->stream.cbc = NULL;
-    }
-
-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
-
-    return 1;
-}
-
-static int cipher_hw_rv32i_zbkb_zknd_zkne_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;
-
-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
-        && !dat->enc) {
-        ret = rv32i_zbkb_zknd_zkne_set_decrypt_key(key, keylen * 8, ks);
-        dat->block = (block128_f) rv32i_zknd_decrypt;
-        dat->stream.cbc = NULL;
-    } else {
-        ret = rv32i_zbkb_zkne_set_encrypt_key(key, keylen * 8, ks);
-        dat->block = (block128_f) rv32i_zkne_encrypt;
-        dat->stream.cbc = NULL;
-    }
-
-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
-
-    return 1;
-}
-
-#define PROV_CIPHER_HW_declare(mode)                                           \
-static const PROV_CIPHER_HW rv32i_zknd_zkne_##mode = {                         \
-    cipher_hw_rv32i_zknd_zkne_initkey,                                         \
-    cipher_hw_rv32i_zknd_zkne_##mode,                                          \
-    cipher_hw_aes_copyctx                                                      \
-};                                                                             \
-static const PROV_CIPHER_HW rv32i_zbkb_zknd_zkne_##mode = {                    \
-    cipher_hw_rv32i_zbkb_zknd_zkne_initkey,                                    \
-    cipher_hw_rv32i_zbkb_zknd_zkne_##mode,                                     \
-    cipher_hw_aes_copyctx                                                      \
-};
-#define PROV_CIPHER_HW_select(mode)                                            \
-if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE())                                        \
-    return &rv32i_zbkb_zknd_zkne_##mode;                                       \
-if (RISCV_HAS_ZKND_AND_ZKNE())                                                 \
-    return &rv32i_zknd_zkne_##mode;
diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv64i.c b/providers/implementations/ciphers/cipher_aes_hw_rv64i.c
new file mode 100644
index 0000000000..e13c46813e
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_rv64i.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*-
+ * RISC-V 64 ZKND ZKNE / ZVKNED support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is used by cipher_aes_hw.c
+ */
+
+#include "internal/deprecated.h"
+#include "cipher_aes.h"
+
+#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
+
+static int cipher_hw_rv64i_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
+        /*
+         * Zvkned only supports 128 and 256 bit keys for key schedule
+         * generation. For the AES-192 case, we fallback to the generic
+         * `AES_set_encrypt_key`. All Zvkned-based implementations use the
+         * same `encrypt-key` scheduling for both encryption and decryption.
+         */
+        aes_set_encrypt_key_fn fn_set_key = AES_set_encrypt_key;
+        aes_block128_f fn_block = NULL;
+
+        if (keylen * 8 == 128 || keylen * 8 == 256) {
+            fn_set_key = rv64i_zvkned_set_encrypt_key;
+        }
+        ecb128_f fn_ecb = ctx->enc ? rv64i_zvkned_ecb_encrypt : rv64i_zvkned_ecb_decrypt;
+        cbc128_f fn_cbc = ctx->enc ? rv64i_zvkned_cbc_encrypt : rv64i_zvkned_cbc_decrypt;
+        ctr128_f fn_ctr = RISCV_HAS_ZVKB() ? (ctr128_f)rv64i_zvkb_zvkned_ctr32_encrypt_blocks : NULL;
+
+        /* Zvkned supports aes-128/192/256 encryption and decryption. */
+        if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+            && !ctx->enc) {
+            fn_block = rv64i_zvkned_decrypt;
+        } else {
+            fn_block = (block128_f)rv64i_zvkned_encrypt;
+        }
+        return ossl_cipher_set_aes_initkey(ctx, key, keylen, fn_set_key,
+            fn_block, fn_ecb, fn_cbc, fn_ctr);
+    } else if (RISCV_HAS_ZKND_AND_ZKNE()) {
+        if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+            && !ctx->enc) {
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                rv64i_zknd_set_decrypt_key, rv64i_zknd_decrypt,
+                NULL, NULL, NULL);
+        } else {
+            return ossl_cipher_set_aes_initkey(ctx, key, keylen,
+                rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt,
+                NULL, NULL, NULL);
+        }
+    }
+    return 0;
+}
+
+static const PROV_CIPHER_HW rv64i_ecb = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_ecb,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv64i_cbc = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_cbc,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv64i_cfb128 = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_cfb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv64i_cfb8 = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_cfb8,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv64i_cfb1 = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_cfb1,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv64i_ofb128 = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_ofb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW rv64i_ctr = {
+    cipher_hw_rv64i_initkey,
+    ossl_cipher_hw_generic_ctr,
+    ossl_cipher_aes_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode,
+    size_t keybits)
+{
+    if ((RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
+        || RISCV_HAS_ZKND_AND_ZKNE()) {
+        switch (mode) {
+        case AES_MODE_ECB:
+            return &rv64i_ecb;
+        case AES_MODE_CBC:
+            return &rv64i_cbc;
+        case AES_MODE_CFB128:
+            return &rv64i_cfb128;
+        case AES_MODE_CFB8:
+            return &rv64i_cfb8;
+        case AES_MODE_CFB1:
+            return &rv64i_cfb1;
+        case AES_MODE_OFB128:
+            return &rv64i_ofb128;
+        case AES_MODE_CTR:
+            return &rv64i_ctr;
+        default:
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv64i.inc b/providers/implementations/ciphers/cipher_aes_hw_rv64i.inc
deleted file mode 100644
index 07d479303d..0000000000
--- a/providers/implementations/ciphers/cipher_aes_hw_rv64i.inc
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*-
- * RISC-V 64 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is included by cipher_aes_hw.c
- */
-
-#define cipher_hw_rv64i_zknd_zkne_cbc    ossl_cipher_hw_generic_cbc
-#define cipher_hw_rv64i_zknd_zkne_ecb    ossl_cipher_hw_generic_ecb
-#define cipher_hw_rv64i_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128
-#define cipher_hw_rv64i_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128
-#define cipher_hw_rv64i_zknd_zkne_cfb8   ossl_cipher_hw_generic_cfb8
-#define cipher_hw_rv64i_zknd_zkne_cfb1   ossl_cipher_hw_generic_cfb1
-#define cipher_hw_rv64i_zknd_zkne_ctr    ossl_cipher_hw_generic_ctr
-
-static int cipher_hw_rv64i_zknd_zkne_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;
-
-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
-        && !dat->enc) {
-        ret = rv64i_zknd_set_decrypt_key(key, keylen * 8, ks);
-        dat->block = (block128_f) rv64i_zknd_decrypt;
-        dat->stream.cbc = NULL;
-    } else {
-        ret = rv64i_zkne_set_encrypt_key(key, keylen * 8, ks);
-        dat->block = (block128_f) rv64i_zkne_encrypt;
-        dat->stream.cbc = NULL;
-    }
-
-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
-
-    return 1;
-}
-
-/*-
- * RISC-V RV64 ZVKNED support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is included by cipher_aes_hw.c
- */
-
-#define cipher_hw_rv64i_zvkned_cbc    ossl_cipher_hw_generic_cbc
-#define cipher_hw_rv64i_zvkned_ecb    ossl_cipher_hw_generic_ecb
-#define cipher_hw_rv64i_zvkned_ofb128 ossl_cipher_hw_generic_ofb128
-#define cipher_hw_rv64i_zvkned_cfb128 ossl_cipher_hw_generic_cfb128
-#define cipher_hw_rv64i_zvkned_cfb8   ossl_cipher_hw_generic_cfb8
-#define cipher_hw_rv64i_zvkned_cfb1   ossl_cipher_hw_generic_cfb1
-#define cipher_hw_rv64i_zvkned_ctr    ossl_cipher_hw_generic_ctr
-
-static int cipher_hw_rv64i_zvkned_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;
-
-    /*
-     * Zvkned only supports 128 and 256 bit keys for key schedule generation.
-     * For AES-192 case, we could fallback to `AES_set_encrypt_key`.
-     * All Zvkned-based implementations use the same `encrypt-key` scheduling
-     * for both encryption and decryption.
-     */
-    if (keylen * 8 == 128 || keylen * 8 == 256) {
-        ret = rv64i_zvkned_set_encrypt_key(key, keylen * 8, ks);
-    } else {
-        ret = AES_set_encrypt_key(key, keylen * 8, ks);
-    }
-
-    if (dat->mode == EVP_CIPH_CBC_MODE) {
-        if (dat->enc) {
-            dat->stream.cbc = (cbc128_f) rv64i_zvkned_cbc_encrypt;
-        } else {
-            dat->stream.cbc = (cbc128_f) rv64i_zvkned_cbc_decrypt;
-        }
-    } else if (dat->mode == EVP_CIPH_CTR_MODE) {
-        if (RISCV_HAS_ZVKB()) {
-            dat->stream.ctr = (ctr128_f) rv64i_zvkb_zvkned_ctr32_encrypt_blocks;
-        }
-    } else if (dat->mode == EVP_CIPH_ECB_MODE) {
-        if (dat->enc) {
-            dat->stream.ecb = (ecb128_f) rv64i_zvkned_ecb_encrypt;
-        } else {
-            dat->stream.ecb = (ecb128_f) rv64i_zvkned_ecb_decrypt;
-        }
-    }
-
-    /* Zvkned supports aes-128/192/256 encryption and decryption. */
-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) &&
-        !dat->enc) {
-        dat->block = (block128_f) rv64i_zvkned_decrypt;
-    } else {
-        dat->block = (block128_f) rv64i_zvkned_encrypt;
-    }
-
-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
-
-    return 1;
-}
-
-#define PROV_CIPHER_HW_declare(mode)                                           \
-static const PROV_CIPHER_HW rv64i_zknd_zkne_##mode = {                         \
-    cipher_hw_rv64i_zknd_zkne_initkey,                                         \
-    cipher_hw_rv64i_zknd_zkne_##mode,                                          \
-    cipher_hw_aes_copyctx                                                      \
-};                                                                             \
-static const PROV_CIPHER_HW rv64i_zvkned_##mode = {                            \
-    cipher_hw_rv64i_zvkned_initkey,                                            \
-    cipher_hw_rv64i_zvkned_##mode,                                             \
-    cipher_hw_aes_copyctx                                                      \
-};
-#define PROV_CIPHER_HW_select(mode)                                            \
-if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)                                 \
-    return &rv64i_zvkned_##mode;                                               \
-else if (RISCV_HAS_ZKND_AND_ZKNE())                                            \
-    return &rv64i_zknd_zkne_##mode;
diff --git a/providers/implementations/ciphers/cipher_aes_hw_s390x.c b/providers/implementations/ciphers/cipher_aes_hw_s390x.c
new file mode 100644
index 0000000000..30d30d5de7
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_s390x.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2001-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
+ */
+
+/*
+ * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is used by cipher_aes_hw.c
+ */
+
+#include "internal/deprecated.h"
+#include "cipher_aes.h"
+#include "arch/s390x_arch.h"
+#include <stdio.h>
+
+#if defined(S390X_aes_128_CAPABLE)
+
+static int s390x_aes_ecb_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);
+    memcpy(adat->plat.s390x.param.km.k, key, keylen);
+    return 1;
+}
+
+static int s390x_aes_ecb_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;
+
+    s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
+        &adat->plat.s390x.param.km);
+    return 1;
+}
+
+static const PROV_CIPHER_HW s390x_aes_ecb = {
+    s390x_aes_ecb_initkey,
+    s390x_aes_ecb_cipher_hw,
+    ossl_cipher_aes_copyctx
+};
+
+static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
+    const unsigned char *key, size_t keylen)
+{
+    PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+
+    memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
+    adat->plat.s390x.fc = S390X_AES_FC(keylen);
+    return 1;
+}
+
+static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+    PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
+    int n = dat->num;
+    int rem;
+
+    memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
+    while (n && len) {
+        *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
+        n = (n + 1) & 0xf;
+        --len;
+        ++in;
+        ++out;
+    }
+
+    rem = len & 0xf;
+
+    len &= ~(size_t)0xf;
+    if (len) {
+        s390x_kmo(in, len, out, adat->plat.s390x.fc,
+            &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,
+            adat->plat.s390x.fc,
+            adat->plat.s390x.param.kmo_kmf.k);
+
+        while (rem--) {
+            out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
+            ++n;
+        }
+    }
+
+    memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
+    dat->num = n;
+    return 1;
+}
+
+static const PROV_CIPHER_HW s390x_aes_ofb128 = {
+    s390x_aes_ofb128_initkey,
+    s390x_aes_ofb128_cipher_hw,
+    ossl_cipher_aes_copyctx
+};
+
+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 const PROV_CIPHER_HW s390x_aes_cfb128 = {
+    s390x_aes_cfb128_initkey,
+    s390x_aes_cfb128_cipher_hw,
+    ossl_cipher_aes_copyctx
+};
+
+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;
+}
+
+static const PROV_CIPHER_HW s390x_aes_cfb8 = {
+    s390x_aes_cfb8_initkey,
+    s390x_aes_cfb8_cipher_hw,
+    ossl_cipher_aes_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_s390x(enum aes_modes mode,
+    size_t keybits)
+{
+    switch (mode) {
+    case AES_MODE_ECB:
+        if ((keybits == 128 && S390X_aes_128_ecb_CAPABLE)
+            || (keybits == 192 && S390X_aes_192_ecb_CAPABLE)
+            || (keybits == 256 && S390X_aes_256_ecb_CAPABLE))
+            return &s390x_aes_ecb;
+        break;
+    case AES_MODE_CFB128:
+        if ((keybits == 128 && S390X_aes_128_cfb_CAPABLE)
+            || (keybits == 192 && S390X_aes_192_cfb_CAPABLE)
+            || (keybits == 256 && S390X_aes_256_cfb_CAPABLE))
+            return &s390x_aes_cfb128;
+        break;
+    case AES_MODE_CFB8:
+        if ((keybits == 128 && S390X_aes_128_cfb8_CAPABLE)
+            || (keybits == 192 && S390X_aes_192_cfb8_CAPABLE)
+            || (keybits == 256 && S390X_aes_256_cfb8_CAPABLE))
+            return &s390x_aes_cfb8;
+        break;
+    case AES_MODE_OFB128:
+        if ((keybits == 128 && S390X_aes_128_ofb_CAPABLE)
+            || (keybits == 192 && S390X_aes_192_ofb_CAPABLE)
+            || (keybits == 256 && S390X_aes_256_ofb_CAPABLE))
+            return &s390x_aes_ofb128;
+        break;
+    default:
+        break;
+    }
+    return NULL;
+}
+
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc
deleted file mode 100644
index be82d3be9b..0000000000
--- a/providers/implementations/ciphers/cipher_aes_hw_s390x.inc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2001-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
- */
-
-/*
- * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is included by cipher_aes_hw.c
- */
-
-#include "arch/s390x_arch.h"
-
-#include <stdio.h>
-
-#define s390x_aes_cbc_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_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
-
-static int s390x_aes_ecb_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);
-    memcpy(adat->plat.s390x.param.km.k, key, keylen);
-    return 1;
-}
-
-static int s390x_aes_ecb_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;
-
-    s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
-             &adat->plat.s390x.param.km);
-    return 1;
-}
-
-static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
-                                    const unsigned char *key, size_t keylen)
-{
-    PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
-
-    memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
-    adat->plat.s390x.fc = S390X_AES_FC(keylen);
-    return 1;
-}
-
-static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
-                                      const unsigned char *in, size_t len)
-{
-    PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
-    int n = dat->num;
-    int rem;
-
-    memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
-    while (n && len) {
-        *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
-        n = (n + 1) & 0xf;
-        --len;
-        ++in;
-        ++out;
-    }
-
-    rem = len & 0xf;
-
-    len &= ~(size_t)0xf;
-    if (len) {
-        s390x_kmo(in, len, out, adat->plat.s390x.fc,
-                  &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,
-                 adat->plat.s390x.fc,
-                 adat->plat.s390x.param.kmo_kmf.k);
-
-        while (rem--) {
-            out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
-            ++n;
-        }
-    }
-
-    memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
-    dat->num = n;
-    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;
diff --git a/providers/implementations/ciphers/cipher_aes_hw_t4.c b/providers/implementations/ciphers/cipher_aes_hw_t4.c
new file mode 100644
index 0000000000..6d8e945de5
--- /dev/null
+++ b/providers/implementations/ciphers/cipher_aes_hw_t4.c
@@ -0,0 +1,146 @@
+/*
+ * 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
+ */
+
+/*-
+ * Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr.
+ * This file is used by cipher_aes_hw.c
+ */
+
+#include "internal/deprecated.h"
+#include <openssl/proverr.h>
+#include "cipher_aes.h"
+
+#if defined(SPARC_AES_CAPABLE)
+
+static int t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks)
+{
+    aes_t4_set_encrypt_key(key, bits, ks);
+    return 0;
+}
+
+static int t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks)
+{
+    aes_t4_set_decrypt_key(key, bits, ks);
+    return 0;
+}
+
+static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    cbc128_f fn_cbc = NULL;
+    if ((ctx->mode == EVP_CIPH_ECB_MODE || ctx->mode == EVP_CIPH_CBC_MODE)
+        && !ctx->enc) {
+        switch (keylen) {
+        case 16:
+            fn_cbc = (cbc128_f)aes128_t4_cbc_decrypt;
+            break;
+        case 24:
+            fn_cbc = (cbc128_f)aes192_t4_cbc_decrypt;
+            break;
+        case 32:
+            fn_cbc = (cbc128_f)aes256_t4_cbc_decrypt;
+            break;
+        default:
+            ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+            return 0;
+        }
+        return ossl_cipher_set_aes_initkey(ctx, key, keylen, t4_set_decrypt_key,
+            aes_t4_decrypt, NULL, fn_cbc, NULL);
+    } else {
+        ctr128_f fn_ctr = NULL;
+        switch (keylen) {
+        case 16:
+            fn_cbc = (cbc128_f)aes128_t4_cbc_encrypt;
+            fn_ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
+            break;
+        case 24:
+            fn_cbc = (cbc128_f)aes192_t4_cbc_encrypt;
+            fn_ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
+            break;
+        case 32:
+            fn_cbc = (cbc128_f)aes256_t4_cbc_encrypt;
+            fn_ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
+            break;
+        default:
+            ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
+            return 0;
+        }
+        return ossl_cipher_set_aes_initkey(ctx, key, keylen, t4_set_encrypt_key,
+            aes_t4_encrypt, NULL, fn_cbc, fn_ctr);
+    }
+}
+
+static const PROV_CIPHER_HW aes_t4_ecb = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_ecb,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_t4_cbc = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_cbc,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_t4_cfb128 = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_cfb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_t4_cfb8 = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_cfb8,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_t4_cfb1 = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_cfb1,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_t4_ofb128 = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_ofb128,
+    ossl_cipher_aes_copyctx
+};
+
+static const PROV_CIPHER_HW aes_t4_ctr = {
+    cipher_hw_aes_t4_initkey,
+    ossl_cipher_hw_generic_ctr,
+    ossl_cipher_aes_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_t4(enum aes_modes mode,
+    size_t keybits)
+{
+    if (SPARC_AES_CAPABLE) {
+        switch (mode) {
+        case AES_MODE_ECB:
+            return &aes_t4_ecb;
+        case AES_MODE_CBC:
+            return &aes_t4_cbc;
+        case AES_MODE_CFB128:
+            return &aes_t4_cfb128;
+        case AES_MODE_CFB8:
+            return &aes_t4_cfb8;
+        case AES_MODE_CFB1:
+            return &aes_t4_cfb1;
+        case AES_MODE_OFB128:
+            return &aes_t4_ofb128;
+        case AES_MODE_CTR:
+            return &aes_t4_ctr;
+        default:
+            return NULL;
+        }
+    }
+    return NULL;
+}
+#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_hw_t4.inc
deleted file mode 100644
index 28454fc508..0000000000
--- a/providers/implementations/ciphers/cipher_aes_hw_t4.inc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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
- */
-
-/*-
- * Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is included by cipher_aes_hw.c
- */
-
-static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat,
-                                    const unsigned char *key, size_t keylen)
-{
-    int ret, bits;
-    PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
-    AES_KEY *ks = &adat->ks.ks;
-
-    dat->ks = (const void *)ks; /* used by cipher_hw_generic_XXX */
-
-    bits = keylen * 8;
-    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
-        && !dat->enc) {
-        ret = 0;
-        aes_t4_set_decrypt_key(key, bits, ks);
-        dat->block = (block128_f)aes_t4_decrypt;
-        switch (bits) {
-        case 128:
-            dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
-                (cbc128_f)aes128_t4_cbc_decrypt : NULL;
-            break;
-        case 192:
-            dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
-                (cbc128_f)aes192_t4_cbc_decrypt : NULL;
-            break;
-        case 256:
-            dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
-                (cbc128_f)aes256_t4_cbc_decrypt : NULL;
-            break;
-        default:
-            ret = -1;
-        }
-    } else {
-        ret = 0;
-        aes_t4_set_encrypt_key(key, bits, ks);
-        dat->block = (block128_f)aes_t4_encrypt;
-        switch (bits) {
-        case 128:
-            if (dat->mode == EVP_CIPH_CBC_MODE)
-                dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
-            else if (dat->mode == EVP_CIPH_CTR_MODE)
-                dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
-            else
-                dat->stream.cbc = NULL;
-            break;
-        case 192:
-            if (dat->mode == EVP_CIPH_CBC_MODE)
-                dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
-            else if (dat->mode == EVP_CIPH_CTR_MODE)
-                dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
-            else
-                dat->stream.cbc = NULL;
-            break;
-        case 256:
-            if (dat->mode == EVP_CIPH_CBC_MODE)
-                dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
-            else if (dat->mode == EVP_CIPH_CTR_MODE)
-                dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
-            else
-                dat->stream.cbc = NULL;
-            break;
-        default:
-            ret = -1;
-        }
-    }
-
-    if (ret < 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
-        return 0;
-    }
-
-    return 1;
-}
-
-#define PROV_CIPHER_HW_declare(mode)                                           \
-static const PROV_CIPHER_HW aes_t4_##mode = {                                  \
-    cipher_hw_aes_t4_initkey,                                                  \
-    ossl_cipher_hw_generic_##mode,                                             \
-    cipher_hw_aes_copyctx                                                      \
-};
-#define PROV_CIPHER_HW_select(mode)                                            \
-    if (SPARC_AES_CAPABLE)                                                     \
-        return &aes_t4_##mode;