Commit aa23e0cd7a for openssl.org

commit aa23e0cd7a5d9de2654ffe1eab943213c2bb109e
Author: Simo Sorce <simo@redhat.com>
Date:   Thu Jun 11 18:32:37 2026 -0400

    Consolidate RISC-V 64 AES hardware code

    Merge the RISC-V 64 hardware-accelerated AES mode implementations (GCM, CCM,
    and XTS) into a single file (`cipher_aes_hw_rv64i.c`). This removes the need
    for separate files for GCM and CCM, and extracts RV64-specific XTS code from
    the generic XTS hardware file, improving code organization.

    Additionally, remove the unused `keybits` parameter from the RV64 AES hardware
    retrieval functions.

    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:54 2026
    (Merged from https://github.com/openssl/openssl/pull/31472)

diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info
index 671351743b..70e41b3e34 100644
--- a/providers/implementations/ciphers/build.info
+++ b/providers/implementations/ciphers/build.info
@@ -109,10 +109,8 @@ SOURCE[$AES_GOAL]=\
         cipher_aes_xts.c cipher_aes_xts_hw.c \
         cipher_aes_gcm.c cipher_aes_gcm_hw.c \
         cipher_aes_gcm_hw_ppc.c \
-        cipher_aes_gcm_hw_rv64i.c \
         cipher_aes_gcm_hw_s390x.c cipher_aes_gcm_hw_t4.c \
         cipher_aes_ccm.c cipher_aes_ccm_hw.c \
-        cipher_aes_ccm_hw_rv64i.c \
         cipher_aes_ccm_hw_s390x.c cipher_aes_ccm_hw_t4.c \
         cipher_aes_wrp.c \
         cipher_aes_cbc_hmac_sha.c \
diff --git a/providers/implementations/ciphers/cipher_aes.h b/providers/implementations/ciphers/cipher_aes.h
index 05028053f2..05e46d204a 100644
--- a/providers/implementations/ciphers/cipher_aes.h
+++ b/providers/implementations/ciphers/cipher_aes.h
@@ -92,8 +92,7 @@ const PROV_CIPHER_HW *ossl_prov_cipher_hw_arm(enum aes_modes mode);
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
 const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv32i(enum aes_modes mode);
 #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);
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode);
 #elif defined(S390X_aes_128_CAPABLE)
 const PROV_CIPHER_HW *ossl_prov_cipher_hw_s390x(enum aes_modes mode,
     size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_ccm.h b/providers/implementations/ciphers/cipher_aes_ccm.h
index 2fa59dca75..636f5e687b 100644
--- a/providers/implementations/ciphers/cipher_aes_ccm.h
+++ b/providers/implementations/ciphers/cipher_aes_ccm.h
@@ -62,7 +62,7 @@ const PROV_CCM_HW *ossl_prov_aes_hw_ccm_aesni(void);
 const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv32i(void);
 #endif
 #if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv64i(size_t keybits);
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv64i(void);
 #endif
 #if defined(S390X_aes_128_CAPABLE)
 const PROV_CCM_HW *ossl_prov_aes_hw_ccm_s390x(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw.c b/providers/implementations/ciphers/cipher_aes_ccm_hw.c
index 2a69a1427d..a3ee92c542 100644
--- a/providers/implementations/ciphers/cipher_aes_ccm_hw.c
+++ b/providers/implementations/ciphers/cipher_aes_ccm_hw.c
@@ -77,7 +77,7 @@ const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
     aes_ccm_hw = ossl_prov_aes_hw_ccm_rv32i();
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-    aes_ccm_hw = ossl_prov_aes_hw_ccm_rv64i(keybits);
+    aes_ccm_hw = ossl_prov_aes_hw_ccm_rv64i();
 #elif defined(S390X_aes_128_CAPABLE)
     aes_ccm_hw = ossl_prov_aes_hw_ccm_s390x(keybits);
 #elif defined(SPARC_AES_CAPABLE)
diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_rv64i.c b/providers/implementations/ciphers/cipher_aes_ccm_hw_rv64i.c
deleted file mode 100644
index 506e286e77..0000000000
--- a/providers/implementations/ciphers/cipher_aes_ccm_hw_rv64i.c
+++ /dev/null
@@ -1,72 +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 CCM.
- * This file is used by cipher_aes_ccm_hw.c
- */
-
-#include "internal/deprecated.h"
-#include "cipher_aes_ccm.h"
-
-#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-
-static int ccm_rv64i_zknd_zkne_initkey(PROV_CCM_CTX *ctx,
-    const unsigned char *key, size_t keylen)
-{
-    return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen,
-        rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, NULL, NULL);
-}
-
-static const PROV_CCM_HW rv64i_zknd_zkne_ccm = {
-    ccm_rv64i_zknd_zkne_initkey,
-    ossl_ccm_generic_setiv,
-    ossl_ccm_generic_setaad,
-    ossl_ccm_generic_auth_encrypt,
-    ossl_ccm_generic_auth_decrypt,
-    ossl_ccm_generic_gettag
-};
-
-/*-
- * RISC-V RV64 ZVKNED support for AES CCM.
- * This file is included by cipher_aes_ccm_hw.c
- */
-
-static int ccm_rv64i_zvkned_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
-    size_t keylen)
-{
-    /* Zvkned only supports 128 and 256 bit keys for key schedule generation. */
-    if (keylen * 8 == 128 || keylen * 8 == 256) {
-        return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen,
-            rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL);
-    } else {
-        return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen,
-            AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL);
-    }
-}
-
-static const PROV_CCM_HW rv64i_zvkned_ccm = {
-    ccm_rv64i_zvkned_initkey,
-    ossl_ccm_generic_setiv,
-    ossl_ccm_generic_setaad,
-    ossl_ccm_generic_auth_encrypt,
-    ossl_ccm_generic_auth_decrypt,
-    ossl_ccm_generic_gettag
-};
-
-const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv64i(size_t keybits)
-{
-    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
-        return &rv64i_zvkned_ccm;
-    else if (RISCV_HAS_ZKND_AND_ZKNE())
-        return &rv64i_zknd_zkne_ccm;
-    else
-        return NULL;
-}
-#endif
diff --git a/providers/implementations/ciphers/cipher_aes_gcm.h b/providers/implementations/ciphers/cipher_aes_gcm.h
index 88ad752e92..43cba79541 100644
--- a/providers/implementations/ciphers/cipher_aes_gcm.h
+++ b/providers/implementations/ciphers/cipher_aes_gcm.h
@@ -66,7 +66,7 @@ const PROV_GCM_HW *ossl_prov_aes_hw_gcm_ppc(size_t keybits);
 const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv32i(void);
 #endif
 #if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv64i(size_t keybits);
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv64i(void);
 #endif
 #if defined(S390X_aes_128_CAPABLE)
 const PROV_GCM_HW *ossl_prov_aes_hw_gcm_s390x(size_t keybits);
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_hw.c
index 87e46e71b3..8493451688 100644
--- a/providers/implementations/ciphers/cipher_aes_gcm_hw.c
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw.c
@@ -164,7 +164,7 @@ const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
     aes_gcm_hw = ossl_prov_aes_hw_gcm_rv32i();
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-    aes_gcm_hw = ossl_prov_aes_hw_gcm_rv64i(keybits);
+    aes_gcm_hw = ossl_prov_aes_hw_gcm_rv64i();
 #elif defined(S390X_aes_128_CAPABLE)
     aes_gcm_hw = ossl_prov_aes_hw_gcm_s390x(keybits);
 #elif defined(SPARC_AES_CAPABLE)
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.c b/providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.c
deleted file mode 100644
index 7d88ff7e43..0000000000
--- a/providers/implementations/ciphers/cipher_aes_gcm_hw_rv64i.c
+++ /dev/null
@@ -1,112 +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 support for AES GCM.
- * This file is used by cipher_aes_gcm_hw.c
- */
-#include "internal/deprecated.h"
-#include "cipher_aes_gcm.h"
-
-#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-
-/*-
- * RISC-V 64 ZKND and ZKNE support for AES GCM.
- */
-static int rv64i_zknd_zkne_gcm_initkey(PROV_GCM_CTX *ctx,
-    const unsigned char *key, size_t keylen)
-{
-    return aes_gcm_hw_initkey(ctx, key, keylen,
-        rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, NULL);
-}
-
-static const PROV_GCM_HW rv64i_zknd_zkne_gcm = {
-    rv64i_zknd_zkne_gcm_initkey,
-    ossl_gcm_setiv,
-    ossl_gcm_aad_update,
-    generic_aes_gcm_cipher_update,
-    ossl_gcm_cipher_final,
-    ossl_gcm_one_shot
-};
-
-/*-
- * RISC-V RV64 ZVKNED support for AES GCM.
- */
-static int rv64i_zvkned_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
-    size_t keylen)
-{
-    /*
-     * Zvkned only supports 128 and 256 bit keys for key schedule generation.
-     * For AES-192 case, we could fallback to `AES_set_encrypt_key`.
-     */
-    if (keylen * 8 == 128 || keylen * 8 == 256) {
-        return aes_gcm_hw_initkey(ctx, key, keylen,
-            rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, NULL);
-    } else {
-        return aes_gcm_hw_initkey(ctx, key, keylen,
-            AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL);
-    }
-}
-
-static const PROV_GCM_HW rv64i_zvkned_gcm = {
-    rv64i_zvkned_gcm_initkey,
-    ossl_gcm_setiv,
-    ossl_gcm_aad_update,
-    generic_aes_gcm_cipher_update,
-    ossl_gcm_cipher_final,
-    ossl_gcm_one_shot
-};
-
-/*-
- * RISC-V RV64 ZVKB, ZVKG and ZVKNED support for AES GCM.
- */
-static int rv64i_zvkb_zvkg_zvkned_gcm_initkey(PROV_GCM_CTX *ctx,
-    const unsigned char *key,
-    size_t keylen)
-{
-    /*
-     * Zvkned only supports 128 and 256 bit keys for key schedule generation.
-     * For AES-192 case, we could fallback to `AES_set_encrypt_key`.
-     */
-    if (keylen * 8 == 128 || keylen * 8 == 256) {
-        return aes_gcm_hw_initkey(ctx, key, keylen,
-            rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt,
-            rv64i_zvkb_zvkned_ctr32_encrypt_blocks);
-    } else {
-        return aes_gcm_hw_initkey(ctx, key, keylen,
-            AES_set_encrypt_key, rv64i_zvkned_encrypt,
-            rv64i_zvkb_zvkned_ctr32_encrypt_blocks);
-    }
-}
-
-static const PROV_GCM_HW rv64i_zvkb_zvkg_zvkned_gcm = {
-    rv64i_zvkb_zvkg_zvkned_gcm_initkey,
-    ossl_gcm_setiv,
-    ossl_gcm_aad_update,
-    generic_aes_gcm_cipher_update,
-    ossl_gcm_cipher_final,
-    ossl_gcm_one_shot
-};
-
-const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv64i(size_t keybits)
-{
-    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
-        if (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKG())
-            return &rv64i_zvkb_zvkg_zvkned_gcm;
-        return &rv64i_zvkned_gcm;
-    }
-
-    if (RISCV_HAS_ZKND_AND_ZKNE()) {
-        return &rv64i_zknd_zkne_gcm;
-    }
-
-    return NULL;
-}
-
-#endif
diff --git a/providers/implementations/ciphers/cipher_aes_hw.c b/providers/implementations/ciphers/cipher_aes_hw.c
index 34b28bb196..294b2dea7d 100644
--- a/providers/implementations/ciphers/cipher_aes_hw.c
+++ b/providers/implementations/ciphers/cipher_aes_hw.c
@@ -223,7 +223,7 @@ static const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_mode(enum aes_modes mode,
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
     aes_hw_mode = ossl_prov_cipher_hw_rv32i(mode);
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-    aes_hw_mode = ossl_prov_cipher_hw_rv64i(mode, keybits);
+    aes_hw_mode = ossl_prov_cipher_hw_rv64i(mode);
 #elif defined(S390X_aes_128_CAPABLE)
     aes_hw_mode = ossl_prov_cipher_hw_s390x(mode, keybits);
 #elif defined(SPARC_AES_CAPABLE)
diff --git a/providers/implementations/ciphers/cipher_aes_hw_rv64i.c b/providers/implementations/ciphers/cipher_aes_hw_rv64i.c
index e13c46813e..82e41096f5 100644
--- a/providers/implementations/ciphers/cipher_aes_hw_rv64i.c
+++ b/providers/implementations/ciphers/cipher_aes_hw_rv64i.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2022-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
@@ -8,15 +8,19 @@
  */

 /*-
- * RISC-V 64 ZKND ZKNE / ZVKNED support for AES modes ecb, cbc, ofb, cfb, ctr.
- * This file is used by cipher_aes_hw.c
+ * RISC-V 64 ZKND ZKNE / ZVKNED support for all hardware accelerated AES modes.
  */

 #include "internal/deprecated.h"
 #include "cipher_aes.h"
+#include "cipher_aes_gcm.h"
+#include "cipher_aes_ccm.h"
+#include "cipher_aes_xts.h"

 #if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64

+/* MODES: ecb, cbc, cfb, ofb, ctr */
+
 static int cipher_hw_rv64i_initkey(PROV_CIPHER_CTX *ctx,
     const unsigned char *key, size_t keylen)
 {
@@ -33,8 +37,8 @@ static int cipher_hw_rv64i_initkey(PROV_CIPHER_CTX *ctx,
         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;
+        ecb128_f fn_ecb = ctx->enc ? (ecb128_f)rv64i_zvkned_ecb_encrypt : (ecb128_f)rv64i_zvkned_ecb_decrypt;
+        cbc128_f fn_cbc = ctx->enc ? (cbc128_f)rv64i_zvkned_cbc_encrypt : (cbc128_f)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. */
@@ -42,7 +46,7 @@ static int cipher_hw_rv64i_initkey(PROV_CIPHER_CTX *ctx,
             && !ctx->enc) {
             fn_block = rv64i_zvkned_decrypt;
         } else {
-            fn_block = (block128_f)rv64i_zvkned_encrypt;
+            fn_block = rv64i_zvkned_encrypt;
         }
         return ossl_cipher_set_aes_initkey(ctx, key, keylen, fn_set_key,
             fn_block, fn_ecb, fn_cbc, fn_ctr);
@@ -103,8 +107,7 @@ static const PROV_CIPHER_HW rv64i_ctr = {
     ossl_cipher_aes_copyctx
 };

-const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode,
-    size_t keybits)
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode)
 {
     if ((RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
         || RISCV_HAS_ZKND_AND_ZKNE()) {
@@ -130,4 +133,207 @@ const PROV_CIPHER_HW *ossl_prov_cipher_hw_rv64i(enum aes_modes mode,
     return NULL;
 }

+/* MODES: GCM */
+
+/*-
+ * RISC-V 64 ZKND and ZKNE support for AES GCM.
+ */
+static int rv64i_zknd_zkne_gcm_initkey(PROV_GCM_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    return aes_gcm_hw_initkey(ctx, key, keylen,
+        rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, NULL);
+}
+
+static const PROV_GCM_HW rv64i_zknd_zkne_gcm = {
+    rv64i_zknd_zkne_gcm_initkey,
+    ossl_gcm_setiv,
+    ossl_gcm_aad_update,
+    generic_aes_gcm_cipher_update,
+    ossl_gcm_cipher_final,
+    ossl_gcm_one_shot
+};
+
+/*-
+ * RISC-V RV64 ZVKNED support for AES GCM.
+ */
+static int rv64i_zvkned_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+    size_t keylen)
+{
+    /*
+     * Zvkned only supports 128 and 256 bit keys for key schedule generation.
+     * For AES-192 case, we could fallback to `AES_set_encrypt_key`.
+     */
+    if (keylen * 8 == 128 || keylen * 8 == 256) {
+        return aes_gcm_hw_initkey(ctx, key, keylen,
+            rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, NULL);
+    } else {
+        return aes_gcm_hw_initkey(ctx, key, keylen,
+            AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL);
+    }
+}
+
+static const PROV_GCM_HW rv64i_zvkned_gcm = {
+    rv64i_zvkned_gcm_initkey,
+    ossl_gcm_setiv,
+    ossl_gcm_aad_update,
+    generic_aes_gcm_cipher_update,
+    ossl_gcm_cipher_final,
+    ossl_gcm_one_shot
+};
+
+/*-
+ * RISC-V RV64 ZVKB, ZVKG and ZVKNED support for AES GCM.
+ */
+static int rv64i_zvkb_zvkg_zvkned_gcm_initkey(PROV_GCM_CTX *ctx,
+    const unsigned char *key,
+    size_t keylen)
+{
+    /*
+     * Zvkned only supports 128 and 256 bit keys for key schedule generation.
+     * For AES-192 case, we could fallback to `AES_set_encrypt_key`.
+     */
+    if (keylen * 8 == 128 || keylen * 8 == 256) {
+        return aes_gcm_hw_initkey(ctx, key, keylen,
+            rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt,
+            rv64i_zvkb_zvkned_ctr32_encrypt_blocks);
+    } else {
+        return aes_gcm_hw_initkey(ctx, key, keylen,
+            AES_set_encrypt_key, rv64i_zvkned_encrypt,
+            rv64i_zvkb_zvkned_ctr32_encrypt_blocks);
+    }
+}
+
+static const PROV_GCM_HW rv64i_zvkb_zvkg_zvkned_gcm = {
+    rv64i_zvkb_zvkg_zvkned_gcm_initkey,
+    ossl_gcm_setiv,
+    ossl_gcm_aad_update,
+    generic_aes_gcm_cipher_update,
+    ossl_gcm_cipher_final,
+    ossl_gcm_one_shot
+};
+
+const PROV_GCM_HW *ossl_prov_aes_hw_gcm_rv64i(void)
+{
+    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
+        if (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKG())
+            return &rv64i_zvkb_zvkg_zvkned_gcm;
+        return &rv64i_zvkned_gcm;
+    }
+
+    if (RISCV_HAS_ZKND_AND_ZKNE()) {
+        return &rv64i_zknd_zkne_gcm;
+    }
+
+    return NULL;
+}
+
+/* MODES: CCM */
+
+static int ccm_rv64i_zknd_zkne_initkey(PROV_CCM_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen,
+        rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt, NULL, NULL);
+}
+
+static const PROV_CCM_HW rv64i_zknd_zkne_ccm = {
+    ccm_rv64i_zknd_zkne_initkey,
+    ossl_ccm_generic_setiv,
+    ossl_ccm_generic_setaad,
+    ossl_ccm_generic_auth_encrypt,
+    ossl_ccm_generic_auth_decrypt,
+    ossl_ccm_generic_gettag
+};
+
+/*-
+ * RISC-V RV64 ZVKNED support for AES CCM.
+ * This file is included by cipher_aes_ccm_hw.c
+ */
+
+static int ccm_rv64i_zvkned_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
+    size_t keylen)
+{
+    /* Zvkned only supports 128 and 256 bit keys for key schedule generation. */
+    if (keylen * 8 == 128 || keylen * 8 == 256) {
+        return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen,
+            rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL);
+    } else {
+        return ossl_cipher_set_ccm_aes_initkey(ctx, key, keylen,
+            AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL);
+    }
+}
+
+static const PROV_CCM_HW rv64i_zvkned_ccm = {
+    ccm_rv64i_zvkned_initkey,
+    ossl_ccm_generic_setiv,
+    ossl_ccm_generic_setaad,
+    ossl_ccm_generic_auth_encrypt,
+    ossl_ccm_generic_auth_decrypt,
+    ossl_ccm_generic_gettag
+};
+
+const PROV_CCM_HW *ossl_prov_aes_hw_ccm_rv64i(void)
+{
+    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
+        return &rv64i_zvkned_ccm;
+    else if (RISCV_HAS_ZKND_AND_ZKNE())
+        return &rv64i_zknd_zkne_ccm;
+    else
+        return NULL;
+}
+
+/* MODES: XTS */
+
+static int cipher_hw_aes_xts_rv64i_initkey(PROV_CIPHER_CTX *ctx,
+    const unsigned char *key, size_t keylen)
+{
+    if (RISCV_HAS_ZVBB() && RISCV_HAS_ZVKG() && RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
+        /* Zvkned only supports 128 and 256 bit keys. */
+        if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2)
+            return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
+                rv64i_zvkned_set_encrypt_key, rv64i_zvkned_set_decrypt_key,
+                rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
+                rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt,
+                rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt);
+
+        return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
+            AES_set_encrypt_key, AES_set_encrypt_key,
+            rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL);
+    }
+
+    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
+        /* Zvkned only supports 128 and 256 bit keys. */
+        if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2)
+            return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
+                rv64i_zvkned_set_encrypt_key, rv64i_zvkned_set_decrypt_key,
+                rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL);
+
+        return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
+            AES_set_encrypt_key, AES_set_encrypt_key,
+            rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL);
+    }
+
+    if (RISCV_HAS_ZKND_AND_ZKNE())
+        return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
+            rv64i_zkne_set_encrypt_key, rv64i_zknd_set_decrypt_key,
+            rv64i_zkne_encrypt, rv64i_zknd_decrypt, NULL, NULL);
+
+    return 0;
+}
+
+static const PROV_CIPHER_HW aes_xts_rv64i = {
+    cipher_hw_aes_xts_rv64i_initkey,
+    NULL,
+    ossl_cipher_hw_aes_xts_copyctx
+};
+
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv64i(void)
+{
+    if ((RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
+        || RISCV_HAS_ZKND_AND_ZKNE())
+        return &aes_xts_rv64i;
+    return NULL;
+}
+
 #endif
diff --git a/providers/implementations/ciphers/cipher_aes_xts.h b/providers/implementations/ciphers/cipher_aes_xts.h
index 908e6ab937..5a626144e0 100644
--- a/providers/implementations/ciphers/cipher_aes_xts.h
+++ b/providers/implementations/ciphers/cipher_aes_xts.h
@@ -78,6 +78,10 @@ const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_aesni(void);
 const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv32i(void);
 #endif

+#if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
+const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv64i(void);
+#endif
+
 #ifdef AES_XTS_S390X
 int s390x_aes_xts_cipher_stream(PROV_AES_XTS_CTX *xctx,
     unsigned char *out, size_t *outl,
diff --git a/providers/implementations/ciphers/cipher_aes_xts_hw.c b/providers/implementations/ciphers/cipher_aes_xts_hw.c
index 4bf4462442..537786a7aa 100644
--- a/providers/implementations/ciphers/cipher_aes_xts_hw.c
+++ b/providers/implementations/ciphers/cipher_aes_xts_hw.c
@@ -142,59 +142,6 @@ static const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_t4()
     return NULL;
 }

-#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-
-static int cipher_hw_aes_xts_rv64i_initkey(PROV_CIPHER_CTX *ctx,
-    const unsigned char *key, size_t keylen)
-{
-    if (RISCV_HAS_ZVBB() && RISCV_HAS_ZVKG() && RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
-        /* Zvkned only supports 128 and 256 bit keys. */
-        if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2)
-            return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
-                rv64i_zvkned_set_encrypt_key, rv64i_zvkned_set_decrypt_key,
-                rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
-                rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt,
-                rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt);
-
-        return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
-            AES_set_encrypt_key, AES_set_encrypt_key,
-            rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL);
-    }
-
-    if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) {
-        /* Zvkned only supports 128 and 256 bit keys. */
-        if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2)
-            return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
-                rv64i_zvkned_set_encrypt_key, rv64i_zvkned_set_decrypt_key,
-                rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL);
-
-        return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
-            AES_set_encrypt_key, AES_set_encrypt_key,
-            rv64i_zvkned_encrypt, rv64i_zvkned_decrypt, NULL, NULL);
-    }
-
-    if (RISCV_HAS_ZKND_AND_ZKNE())
-        return ossl_cipher_set_aes_xts_initkey(ctx, key, keylen,
-            rv64i_zkne_set_encrypt_key, rv64i_zknd_set_decrypt_key,
-            rv64i_zkne_encrypt, rv64i_zknd_decrypt, NULL, NULL);
-
-    return 0;
-}
-
-static const PROV_CIPHER_HW aes_xts_rv64i = {
-    cipher_hw_aes_xts_rv64i_initkey,
-    NULL,
-    ossl_cipher_hw_aes_xts_copyctx
-};
-
-static const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts_rv64i()
-{
-    if ((RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
-        || RISCV_HAS_ZKND_AND_ZKNE())
-        return &aes_xts_rv64i;
-    return NULL;
-}
-
 #elif defined(AES_XTS_S390X)

 int s390x_aes_xts_cipher_stream(PROV_AES_XTS_CTX *xctx,
@@ -349,10 +296,10 @@ const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits)
     aes_xts_hw = ossl_prov_cipher_hw_aes_xts_aesni();
 #elif defined(SPARC_AES_CAPABLE)
     aes_xts_hw = ossl_prov_cipher_hw_aes_xts_t4();
-#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
-    aes_xts_hw = ossl_prov_cipher_hw_aes_xts_rv64i();
 #elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
     aes_xts_hw = ossl_prov_cipher_hw_aes_xts_rv32i();
+#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
+    aes_xts_hw = ossl_prov_cipher_hw_aes_xts_rv64i();
 #elif defined(AES_XTS_S390X)
     aes_xts_hw = ossl_prov_cipher_hw_aes_xts_s390x(keybits);
 #endif