Commit c684325ca0 for openssl.org

commit c684325ca05c226387b4abe328000985b9898a56
Author: Simo Sorce <simo@redhat.com>
Date:   Thu Dec 4 14:07:06 2025 -0500

    Unify FIPS self-test KAT data structures

    Refactor the FIPS self-test Known Answer Test (KAT) data definitions to use a
    single, unified structure.

    A new generic `ST_DEFINITION` struct is introduced to replace the various
    algorithm-specific `ST_KAT_*` structs. This new struct contains fields common
    to all tests and uses a union to hold the parameters specific to each test
    category (cipher, digest, KEM, etc.).

    A helper `ST_BUFFER` struct is also added to combine data pointers and their
    lengths, simplifying data handling. This refactoring makes the self-test
    framework more consistent, easier to maintain, and more extensible.

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

    Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/29222)

diff --git a/providers/fips/self_test.h b/providers/fips/self_test.h
index bad0c3ab67..6ca547e5b2 100644
--- a/providers/fips/self_test.h
+++ b/providers/fips/self_test.h
@@ -37,15 +37,26 @@ int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,

 void SELF_TEST_disable_conditional_error_state(void);

-#define CIPHER_MODE_ENCRYPT 1
-#define CIPHER_MODE_DECRYPT 2
-#define CIPHER_MODE_ALL (CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT)
-
-/* FIPS 140-3 only allows DSA verification for legacy purposes */
-#define SIGNATURE_MODE_VERIFY_ONLY 1
-#define SIGNATURE_MODE_SIGN_ONLY 2
-#define SIGNATURE_MODE_DIGESTED 4
-#define SIGNATURE_MODE_SIG_DIGESTED 8
+/* KAT tests categories */
+enum st_test_category {
+    SELF_TEST_INTEGRITY = 0, /* currently unused */
+    SELF_TEST_KAT_CIPHER,
+    SELF_TEST_KAT_ASYM_CIPHER,
+    SELF_TEST_KAT_ASYM_KEYGEN,
+    SELF_TEST_KAT_KEM,
+    SELF_TEST_KAT_DIGEST,
+    SELF_TEST_KAT_SIGNATURE,
+    SELF_TEST_KAT_KDF,
+    SELF_TEST_KAT_KAS,
+    SELF_TEST_KAT_MAC, /* currently unused */
+    SELF_TEST_DRBG
+};
+
+enum st_test_state {
+    SELF_TEST_STATE_INIT = 0,
+    SELF_TEST_STATE_IN_PROGRESS,
+    SELF_TEST_STATE_PASSED,
+};

 #define SELF_TEST_ONLOAD 0
 #define SELF_TEST_DEFERRED 1
@@ -58,140 +69,97 @@ typedef struct st_kat_param_st {
     size_t data_len; /* the length of the data */
 } ST_KAT_PARAM;

-typedef struct st_kat_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
-    const unsigned char *pt;
-    size_t pt_len;
-    const unsigned char *expected;
-    size_t expected_len;
-} ST_KAT;
+typedef struct st_const_buffer_st {
+    const unsigned char *buf;
+    size_t len;
+} ST_BUFFER;
+
+#define CIPHER_MODE_ENCRYPT 1
+#define CIPHER_MODE_DECRYPT 2
+#define CIPHER_MODE_ALL (CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT)

-typedef ST_KAT ST_KAT_DIGEST;
 typedef struct st_kat_cipher_st {
-    ST_KAT base;
     int mode;
-    const unsigned char *key;
-    size_t key_len;
-    const unsigned char *iv;
-    size_t iv_len;
-    const unsigned char *aad;
-    size_t aad_len;
-    const unsigned char *tag;
-    size_t tag_len;
+    ST_BUFFER key;
+    ST_BUFFER iv;
+    ST_BUFFER aad;
+    ST_BUFFER tag;
 } ST_KAT_CIPHER;

-typedef struct st_kat_kdf_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
-    const ST_KAT_PARAM *params;
-    const unsigned char *expected;
-    size_t expected_len;
-} ST_KAT_KDF;
-
-typedef struct st_kat_drbg_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
-    const char *param_name;
-    char *param_value;
-    const unsigned char *entropyin;
-    size_t entropyinlen;
-    const unsigned char *nonce;
-    size_t noncelen;
-    const unsigned char *persstr;
-    size_t persstrlen;
-    const unsigned char *entropyinpr1;
-    size_t entropyinpr1len;
-    const unsigned char *entropyinpr2;
-    size_t entropyinpr2len;
-    const unsigned char *entropyaddin1;
-    size_t entropyaddin1len;
-    const unsigned char *entropyaddin2;
-    size_t entropyaddin2len;
-    const unsigned char *expected;
-    size_t expectedlen;
-} ST_KAT_DRBG;
-
-typedef struct st_kat_kas_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
-
-    const ST_KAT_PARAM *key_group;
-    const ST_KAT_PARAM *key_host_data;
-    const ST_KAT_PARAM *key_peer_data;
-
-    const unsigned char *expected;
-    size_t expected_len;
-} ST_KAT_KAS;
-
-typedef struct st_kat_sign_st {
-    const char *desc;
-    const char *keytype;
-    const char *sigalgorithm;
-    int deferred;
-    int mode;
-    const ST_KAT_PARAM *key;
-    const unsigned char *msg;
-    size_t msg_len;
-    const unsigned char *entropy;
-    size_t entropy_len;
-    const unsigned char *nonce;
-    size_t nonce_len;
-    const unsigned char *persstr;
-    size_t persstr_len;
-    const unsigned char *sig_expected; /* Set to NULL if this value changes */
-    size_t sig_expected_len;
-    const ST_KAT_PARAM *init;
-    const ST_KAT_PARAM *verify;
-} ST_KAT_SIGN;
-
 typedef struct st_kat_asym_cipher_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
     int encrypt;
     const ST_KAT_PARAM *key;
     const ST_KAT_PARAM *postinit;
-    const unsigned char *in;
-    size_t in_len;
-    const unsigned char *expected;
-    size_t expected_len;
 } ST_KAT_ASYM_CIPHER;

 typedef struct st_kat_keygen_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
     const ST_KAT_PARAM *keygen_params;
     const ST_KAT_PARAM *expected_params;
 } ST_KAT_ASYM_KEYGEN;

 typedef struct st_kat_kem_st {
-    const char *desc;
-    const char *algorithm;
-    int deferred;
     const ST_KAT_PARAM *key;
-    const unsigned char *cipher_text;
-    size_t cipher_text_len;
-    const unsigned char *entropy;
-    size_t entropy_len;
-    const unsigned char *secret;
-    size_t secret_len;
-    const unsigned char *reject_secret;
+    ST_BUFFER cipher_text;
+    ST_BUFFER entropy;
+    ST_BUFFER secret;
+    ST_BUFFER reject_secret;
 } ST_KAT_KEM;

-#ifndef OPENSSL_NO_LMS
-typedef struct st_kat_lms_s {
+/* FIPS 140-3 only allows DSA verification for legacy purposes */
+#define SIGNATURE_MODE_VERIFY_ONLY 1
+#define SIGNATURE_MODE_SIGN_ONLY 2
+#define SIGNATURE_MODE_DIGESTED 4
+#define SIGNATURE_MODE_SIG_DIGESTED 8
+
+typedef struct st_kat_sign_st {
+    const char *keytype;
+    int mode;
+    const ST_KAT_PARAM *key;
+    ST_BUFFER entropy;
+    ST_BUFFER nonce;
+    ST_BUFFER persstr;
+    const ST_KAT_PARAM *init;
+    const ST_KAT_PARAM *verify;
+} ST_KAT_SIGN;
+
+typedef struct st_kat_kdf_st {
+    const ST_KAT_PARAM *params;
+} ST_KAT_KDF;
+
+typedef struct st_kat_kas_st {
+    const ST_KAT_PARAM *key_group;
+    const ST_KAT_PARAM *key_host_data;
+    const ST_KAT_PARAM *key_peer_data;
+} ST_KAT_KAS;
+
+typedef struct st_kat_drbg_st {
+    const char *param_name;
+    const char *param_value;
+    ST_BUFFER entropyin;
+    ST_BUFFER nonce;
+    ST_BUFFER persstr;
+    ST_BUFFER entropyinpr1;
+    ST_BUFFER entropyinpr2;
+    ST_BUFFER entropyaddin1;
+    ST_BUFFER entropyaddin2;
+} ST_KAT_DRBG;
+
+typedef struct self_test_st {
+    const char *algorithm;
+    const char *desc;
+    enum st_test_category category;
     int deferred;
-    const unsigned char *pub;
-    size_t publen;
-    const unsigned char *msg;
-    size_t msglen;
-    const unsigned char *sig;
-    size_t siglen;
-} ST_KAT_LMS;
-#endif
+    enum st_test_state state;
+    ST_BUFFER pt;
+    ST_BUFFER expected; /* Set to NULL if this value changes */
+    union {
+        ST_KAT_CIPHER cipher;
+        ST_KAT_ASYM_CIPHER ac;
+        ST_KAT_ASYM_KEYGEN akgen;
+        ST_KAT_KEM kem;
+        ST_KAT_SIGN sig;
+        ST_KAT_KDF kdf;
+        ST_KAT_KAS kas;
+        ST_KAT_DRBG drbg;
+    } u;
+} ST_DEFINITION;
diff --git a/providers/fips/self_test_data.c b/providers/fips/self_test_data.c
index 6bd20355ba..8607c8d0bb 100644
--- a/providers/fips/self_test_data.c
+++ b/providers/fips/self_test_data.c
@@ -25,6 +25,10 @@
 /* Macros to build Self test data */
 #define ITM(x) ((const void *)&x), sizeof(x)
 #define ITM_STR(x) ((const void *)&x), (sizeof(x) - 1)
+#define ITM_BUF(x) \
+    { ((const unsigned char *)&x), sizeof(x) }
+#define ITM_BUF_STR(x) \
+    { ((const unsigned char *)&x), (sizeof(x) - 1) }

 #define ST_KAT_PARAM_END() { "", 0, NULL, 0 }
 #define ST_KAT_PARAM_BIGNUM(name, data) \
@@ -66,27 +70,33 @@ static const unsigned char sha3_256_digest[] = {
  *  SHA256 is tested by higher level algorithms so a
  *  CAST is not needed.
  */
-const ST_KAT_DIGEST st_kat_digest_tests[] = {
+const ST_DEFINITION st_kat_digest_tests[] = {
     {
-        OSSL_SELF_TEST_DESC_MD_SHA1,
         "SHA1",
+        OSSL_SELF_TEST_DESC_MD_SHA1,
+        SELF_TEST_KAT_DIGEST,
         SELF_TEST_ONLOAD,
-        ITM_STR(sha1_pt),
-        ITM(sha1_digest),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(sha1_pt),
+        ITM_BUF(sha1_digest),
     },
     {
-        OSSL_SELF_TEST_DESC_MD_SHA2,
         "SHA512",
+        OSSL_SELF_TEST_DESC_MD_SHA2,
+        SELF_TEST_KAT_DIGEST,
         SELF_TEST_ONLOAD,
-        ITM_STR(sha512_pt),
-        ITM(sha512_digest),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(sha512_pt),
+        ITM_BUF(sha512_digest),
     },
     {
-        OSSL_SELF_TEST_DESC_MD_SHA3,
         "SHA3-256",
+        OSSL_SELF_TEST_DESC_MD_SHA3,
+        SELF_TEST_KAT_DIGEST,
         SELF_TEST_ONLOAD,
-        ITM(sha3_256_pt),
-        ITM(sha3_256_digest),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(sha3_256_pt),
+        ITM_BUF(sha3_256_digest),
     },
 };
 int st_kat_digest_tests_size = OSSL_NELEM(st_kat_digest_tests);
@@ -154,43 +164,49 @@ static const unsigned char tdes_pt[] = {
 };
 #endif

-const ST_KAT_CIPHER st_kat_cipher_tests[] = {
+const ST_DEFINITION st_kat_cipher_tests[] = {
     {
-        {
-            OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
-            "AES-256-GCM",
-            SELF_TEST_ONLOAD,
-            ITM(aes_256_gcm_pt),
-            ITM(aes_256_gcm_ct),
+        "AES-256-GCM",
+        OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
+        SELF_TEST_KAT_CIPHER,
+        SELF_TEST_ONLOAD,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(aes_256_gcm_pt),
+        ITM_BUF(aes_256_gcm_ct),
+        .u.cipher = {
+            CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT,
+            ITM_BUF(aes_256_gcm_key),
+            ITM_BUF(aes_256_gcm_iv),
+            ITM_BUF(aes_256_gcm_aad),
+            ITM_BUF(aes_256_gcm_tag),
         },
-        CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT,
-        ITM(aes_256_gcm_key),
-        ITM(aes_256_gcm_iv),
-        ITM(aes_256_gcm_aad),
-        ITM(aes_256_gcm_tag),
     },
     {
-        {
-            OSSL_SELF_TEST_DESC_CIPHER_AES_ECB,
-            "AES-128-ECB",
-            SELF_TEST_ONLOAD,
-            ITM(aes_128_ecb_pt),
-            ITM(aes_128_ecb_ct),
+        "AES-128-ECB",
+        OSSL_SELF_TEST_DESC_CIPHER_AES_ECB,
+        SELF_TEST_KAT_CIPHER,
+        SELF_TEST_ONLOAD,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(aes_128_ecb_pt),
+        ITM_BUF(aes_128_ecb_ct),
+        .u.cipher = {
+            CIPHER_MODE_DECRYPT,
+            ITM_BUF(aes_128_ecb_key),
         },
-        CIPHER_MODE_DECRYPT,
-        ITM(aes_128_ecb_key),
     },
 #ifndef OPENSSL_NO_DES
     {
-        {
-            OSSL_SELF_TEST_DESC_CIPHER_TDES,
-            "DES-EDE3-ECB",
-            SELF_TEST_ONLOAD,
-            ITM(tdes_pt),
-            ITM(tdes_ct),
+        "DES-EDE3-ECB",
+        OSSL_SELF_TEST_DESC_CIPHER_TDES,
+        SELF_TEST_KAT_CIPHER,
+        SELF_TEST_ONLOAD,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(tdes_pt),
+        ITM_BUF(tdes_ct),
+        .u.cipher = {
+            CIPHER_MODE_DECRYPT,
+            ITM_BUF(tdes_key),
         },
-        CIPHER_MODE_DECRYPT,
-        ITM(tdes_key),
     }
 #endif
 };
@@ -322,11 +338,33 @@ static const unsigned char sha256_192_sig[] = {
     0xd3, 0x4b, 0x40, 0xb6, 0x9d, 0xd9, 0xf3, 0xc1
 };

-const ST_KAT_LMS st_kat_lms_test = {
+static const ST_KAT_PARAM lms_key[] = {
+    ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, sha256_192_pub),
+    ST_KAT_PARAM_END()
+};
+
+/*
+ * FIPS 140-3 IG 10.3.A Note 5 mandates a CAST for LMS.
+ *
+ * It permits this to be omitted if HSS is also implemented and has
+ * the relevant self tests.  Once HSS is implemented, this test can be
+ * removed.  This IG permits the digest's CAST to be subsumed into this
+ * test, however, because this will be removed, the underlying digest
+ * test has been retained elsewhere lest it is accidentally omitted.
+ */
+const ST_DEFINITION st_kat_lms_test = {
+    "LMS",
+    OSSL_SELF_TEST_DESC_SIGN_LMS,
+    SELF_TEST_KAT_SIGNATURE,
     SELF_TEST_ONLOAD,
-    ITM(sha256_192_pub),
-    ITM(sha256_192_msg),
-    ITM(sha256_192_sig),
+    SELF_TEST_STATE_INIT,
+    ITM_BUF(sha256_192_msg),
+    ITM_BUF(sha256_192_sig),
+    .u.sig = {
+        "LMS",
+        SIGNATURE_MODE_VERIFY_ONLY,
+        lms_key,
+    }
 };
 #endif /* OPENSSL_NO_LMS */

@@ -695,65 +733,97 @@ static const ST_KAT_PARAM tls13_kdf_client_early_secret_params[] = {
  * According to FIPS 140-3 10.3.A Note18: SSH KDF is not required, since it is
  * sufficient to self-test the underlying SHA hash functions.
  */
-const ST_KAT_KDF st_kat_kdf_tests[] = {
+const ST_DEFINITION st_kat_kdf_tests[] = {
     {
-        OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT,
         OSSL_KDF_NAME_TLS1_3_KDF,
+        OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        tls13_kdf_early_secret_params,
-        ITM(tls13_kdf_early_secret),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(tls13_kdf_early_secret),
+        .u.kdf = {
+            tls13_kdf_early_secret_params,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND,
         OSSL_KDF_NAME_TLS1_3_KDF,
+        OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        tls13_kdf_client_early_secret_params,
-        ITM(tls13_kdf_client_early_traffic_secret),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(tls13_kdf_client_early_traffic_secret),
+        .u.kdf = {
+            tls13_kdf_client_early_secret_params,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_KDF_TLS12_PRF,
         OSSL_KDF_NAME_TLS1_PRF,
+        OSSL_SELF_TEST_DESC_KDF_TLS12_PRF,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        tls12prf_params,
-        ITM(tls12prf_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(tls12prf_expected),
+        .u.kdf = {
+            tls12prf_params,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_KDF_PBKDF2,
         OSSL_KDF_NAME_PBKDF2,
+        OSSL_SELF_TEST_DESC_KDF_PBKDF2,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        pbkdf2_params,
-        ITM(pbkdf2_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(pbkdf2_expected),
+        .u.kdf = {
+            pbkdf2_params,
+        },
     },
 #ifndef OPENSSL_NO_KBKDF
     {
-        OSSL_SELF_TEST_DESC_KDF_KBKDF,
         OSSL_KDF_NAME_KBKDF,
+        OSSL_SELF_TEST_DESC_KDF_KBKDF,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        kbkdf_params,
-        ITM(kbkdf_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(kbkdf_expected),
+        .u.kdf = {
+            kbkdf_params,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_KDF_KBKDF_KMAC,
         OSSL_KDF_NAME_KBKDF,
+        OSSL_SELF_TEST_DESC_KDF_KBKDF_KMAC,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        kbkdf_kmac_params,
-        ITM(kbkdf_kmac_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(kbkdf_kmac_expected),
+        .u.kdf = {
+            kbkdf_kmac_params,
+        },
     },
 #endif
     {
-        OSSL_SELF_TEST_DESC_KDF_HKDF,
         OSSL_KDF_NAME_HKDF,
+        OSSL_SELF_TEST_DESC_KDF_HKDF,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        hkdf_params,
-        ITM(hkdf_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(hkdf_expected),
+        .u.kdf = {
+            hkdf_params,
+        },
     },
 #ifndef OPENSSL_NO_SNMPKDF
     {
-        OSSL_SELF_TEST_DESC_KDF_SNMPKDF,
         OSSL_KDF_NAME_SNMPKDF,
-        0,
-        snmpkdf_params,
-        ITM(snmpkdf_expected)
+        OSSL_SELF_TEST_DESC_KDF_SNMPKDF,
+        SELF_TEST_KAT_KDF,
+        SELF_TEST_ONLOAD,
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(snmpkdf_expected),
+        .u.kdf = {
+            snmpkdf_params,
+        },
     },
 #endif
 #ifndef OPENSSL_NO_SRTPKDF
@@ -767,29 +837,41 @@ const ST_KAT_KDF st_kat_kdf_tests[] = {
 #endif
 #ifndef OPENSSL_NO_SSKDF
     {
-        OSSL_SELF_TEST_DESC_KDF_SSKDF,
         OSSL_KDF_NAME_SSKDF,
+        OSSL_SELF_TEST_DESC_KDF_SSKDF,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        sskdf_params,
-        ITM(sskdf_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(sskdf_expected),
+        .u.kdf = {
+            sskdf_params,
+        },
     },
 #endif
 #ifndef OPENSSL_NO_X963KDF
     {
-        OSSL_SELF_TEST_DESC_KDF_X963KDF,
         OSSL_KDF_NAME_X963KDF,
+        OSSL_SELF_TEST_DESC_KDF_X963KDF,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        x963kdf_params,
-        ITM(x963kdf_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(x963kdf_expected),
+        .u.kdf = {
+            x963kdf_params,
+        },
     },
 #endif
 #ifndef OPENSSL_NO_X942KDF
     {
-        OSSL_SELF_TEST_DESC_KDF_X942KDF,
         OSSL_KDF_NAME_X942KDF_ASN1,
+        OSSL_SELF_TEST_DESC_KDF_X942KDF,
+        SELF_TEST_KAT_KDF,
         SELF_TEST_ONLOAD,
-        x942kdf_params,
-        ITM(x942kdf_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(x942kdf_expected),
+        .u.kdf = {
+            x942kdf_params,
+        },
     },
 #endif
 };
@@ -984,51 +1066,63 @@ static const unsigned char drbg_hmac_sha2_pr_expected[] = {
     0x8e, 0x30, 0x05, 0x0e, 0x04, 0x97, 0xfb, 0x0a
 };

-const ST_KAT_DRBG st_kat_drbg_tests[] = {
+const ST_DEFINITION st_kat_drbg_tests[] = {
     {
-        OSSL_SELF_TEST_DESC_DRBG_HASH,
         "HASH-DRBG",
+        OSSL_SELF_TEST_DESC_DRBG_HASH,
+        SELF_TEST_DRBG,
         SELF_TEST_ONLOAD,
-        "digest",
-        "SHA256",
-        ITM(drbg_hash_sha256_pr_entropyin),
-        ITM(drbg_hash_sha256_pr_nonce),
-        ITM(drbg_hash_sha256_pr_persstr),
-        ITM(drbg_hash_sha256_pr_entropyinpr0),
-        ITM(drbg_hash_sha256_pr_entropyinpr1),
-        ITM(drbg_hash_sha256_pr_addin0),
-        ITM(drbg_hash_sha256_pr_addin1),
-        ITM(drbg_hash_sha256_pr_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(drbg_hash_sha256_pr_expected),
+        .u.drbg = {
+            "digest",
+            "SHA256",
+            ITM_BUF(drbg_hash_sha256_pr_entropyin),
+            ITM_BUF(drbg_hash_sha256_pr_nonce),
+            ITM_BUF(drbg_hash_sha256_pr_persstr),
+            ITM_BUF(drbg_hash_sha256_pr_entropyinpr0),
+            ITM_BUF(drbg_hash_sha256_pr_entropyinpr1),
+            ITM_BUF(drbg_hash_sha256_pr_addin0),
+            ITM_BUF(drbg_hash_sha256_pr_addin1),
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_DRBG_CTR,
         "CTR-DRBG",
+        OSSL_SELF_TEST_DESC_DRBG_CTR,
+        SELF_TEST_DRBG,
         SELF_TEST_ONLOAD,
-        "cipher",
-        "AES-128-CTR",
-        ITM(drbg_ctr_aes128_pr_df_entropyin),
-        ITM(drbg_ctr_aes128_pr_df_nonce),
-        ITM(drbg_ctr_aes128_pr_df_persstr),
-        ITM(drbg_ctr_aes128_pr_df_entropyinpr0),
-        ITM(drbg_ctr_aes128_pr_df_entropyinpr1),
-        ITM(drbg_ctr_aes128_pr_df_addin0),
-        ITM(drbg_ctr_aes128_pr_df_addin1),
-        ITM(drbg_ctr_aes128_pr_df_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(drbg_ctr_aes128_pr_df_expected),
+        .u.drbg = {
+            "cipher",
+            "AES-128-CTR",
+            ITM_BUF(drbg_ctr_aes128_pr_df_entropyin),
+            ITM_BUF(drbg_ctr_aes128_pr_df_nonce),
+            ITM_BUF(drbg_ctr_aes128_pr_df_persstr),
+            ITM_BUF(drbg_ctr_aes128_pr_df_entropyinpr0),
+            ITM_BUF(drbg_ctr_aes128_pr_df_entropyinpr1),
+            ITM_BUF(drbg_ctr_aes128_pr_df_addin0),
+            ITM_BUF(drbg_ctr_aes128_pr_df_addin1),
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_DRBG_HMAC,
         "HMAC-DRBG",
+        OSSL_SELF_TEST_DESC_DRBG_HMAC,
+        SELF_TEST_DRBG,
         SELF_TEST_ONLOAD,
-        "digest",
-        "SHA256",
-        ITM(drbg_hmac_sha2_pr_entropyin),
-        ITM(drbg_hmac_sha2_pr_nonce),
-        ITM(drbg_hmac_sha2_pr_persstr),
-        ITM(drbg_hmac_sha2_pr_entropyinpr0),
-        ITM(drbg_hmac_sha2_pr_entropyinpr1),
-        ITM(drbg_hmac_sha2_pr_addin0),
-        ITM(drbg_hmac_sha2_pr_addin1),
-        ITM(drbg_hmac_sha2_pr_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(drbg_hmac_sha2_pr_expected),
+        .u.drbg = {
+            "digest",
+            "SHA256",
+            ITM_BUF(drbg_hmac_sha2_pr_entropyin),
+            ITM_BUF(drbg_hmac_sha2_pr_nonce),
+            ITM_BUF(drbg_hmac_sha2_pr_persstr),
+            ITM_BUF(drbg_hmac_sha2_pr_entropyinpr0),
+            ITM_BUF(drbg_hmac_sha2_pr_entropyinpr1),
+            ITM_BUF(drbg_hmac_sha2_pr_addin0),
+            ITM_BUF(drbg_hmac_sha2_pr_addin1),
+        },
     }
 };
 int st_kat_drbg_tests_size = OSSL_NELEM(st_kat_drbg_tests);
@@ -1221,25 +1315,32 @@ static const unsigned char ecdh_secret_expected[] = {
 #endif /* OPENSSL_NO_EC */

 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
-const ST_KAT_KAS st_kat_kas_tests[] = {
+const ST_DEFINITION st_kat_kas_tests[] = {
 #ifndef OPENSSL_NO_DH
-    { OSSL_SELF_TEST_DESC_KA_DH,
-        "DH",
+    { "DH",
+        OSSL_SELF_TEST_DESC_KA_DH,
+        SELF_TEST_KAT_KAS,
         SELF_TEST_ONLOAD,
-        dh_group,
-        dh_host_key,
-        dh_peer_key,
-        ITM(dh_secret_expected) },
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(dh_secret_expected),
+        .u.kas = {
+            dh_group,
+            dh_host_key,
+            dh_peer_key } },
 #endif /* OPENSSL_NO_DH */
 #ifndef OPENSSL_NO_EC
     {
-        OSSL_SELF_TEST_DESC_KA_ECDH,
         "EC",
+        OSSL_SELF_TEST_DESC_KA_ECDH,
+        SELF_TEST_KAT_KAS,
         SELF_TEST_ONLOAD,
-        ecdh_group,
-        ecdh_host_key,
-        ecdh_peer_key,
-        ITM(ecdh_secret_expected),
+        SELF_TEST_STATE_INIT,
+        .expected = ITM_BUF(ecdh_secret_expected),
+        .u.kas = {
+            ecdh_group,
+            ecdh_host_key,
+            ecdh_peer_key,
+        },
     },
 #endif /* OPENSSL_NO_EC */
 };
@@ -3137,137 +3238,145 @@ static const unsigned char sig_kat_persstr[] = {
     0xac, 0x54, 0x4f, 0xce, 0x57, 0xf1, 0x5e, 0x11
 };

-const ST_KAT_SIGN st_kat_sign_tests[] = {
+const ST_DEFINITION st_kat_sign_tests[] = {
     {
-        OSSL_SELF_TEST_DESC_SIGN_RSA,
-        "RSA",
         "RSA-SHA256",
+        OSSL_SELF_TEST_DESC_SIGN_RSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        rsa_crt_key,
-        ITM_STR(rsa_sig_msg),
-        ITM(sig_kat_entropyin),
-        ITM(sig_kat_nonce),
-        ITM(sig_kat_persstr),
-        ITM(rsa_expected_sig),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(rsa_sig_msg),
+        ITM_BUF(rsa_expected_sig),
+        .u.sig = {
+            "RSA",
+            0,
+            rsa_crt_key,
+            ITM_BUF(sig_kat_entropyin),
+            ITM_BUF(sig_kat_nonce),
+            ITM_BUF(sig_kat_persstr),
+        },
     },
 #ifndef OPENSSL_NO_EC
     {
-        OSSL_SELF_TEST_DESC_SIGN_ECDSA,
-        "EC",
         "ECDSA-SHA256",
+        OSSL_SELF_TEST_DESC_SIGN_ECDSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        ecdsa_prime_key,
-        ITM_STR(rsa_sig_msg),
-        ITM(sig_kat_entropyin),
-        ITM(sig_kat_nonce),
-        ITM(sig_kat_persstr),
-        ITM(ecdsa_prime_expected_sig),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(rsa_sig_msg),
+        ITM_BUF(ecdsa_prime_expected_sig),
+        .u.sig = {
+            "EC",
+            0,
+            ecdsa_prime_key,
+            ITM_BUF(sig_kat_entropyin),
+            ITM_BUF(sig_kat_nonce),
+            ITM_BUF(sig_kat_persstr),
+        },
     },
 #ifndef OPENSSL_NO_HMAC_DRBG_KDF
     {
-        OSSL_SELF_TEST_DESC_SIGN_DetECDSA,
-        "EC",
         "ECDSA-SHA256",
+        OSSL_SELF_TEST_DESC_SIGN_DetECDSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        ecdsa_prime_key,
-        ITM_STR(rsa_sig_msg),
-        NULL,
-        0,
-        NULL,
-        0,
-        NULL,
-        0,
-        ITM(ecdsa_prime_expected_detsig),
-        ecdsa_sig_params,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(rsa_sig_msg),
+        ITM_BUF(ecdsa_prime_expected_detsig),
+        .u.sig = {
+            "EC",
+            0,
+            ecdsa_prime_key,
+            .init = ecdsa_sig_params,
+        },
     },
 #endif
 #ifndef OPENSSL_NO_EC2M
     {
-        OSSL_SELF_TEST_DESC_SIGN_ECDSA,
-        "EC",
         "ECDSA-SHA256",
+        OSSL_SELF_TEST_DESC_SIGN_ECDSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        ecdsa_bin_key,
-        ITM_STR(rsa_sig_msg),
-        ITM(sig_kat_entropyin),
-        ITM(sig_kat_nonce),
-        ITM(sig_kat_persstr),
-        ITM(ecdsa_bin_expected_sig),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(rsa_sig_msg),
+        ITM_BUF(ecdsa_bin_expected_sig),
+        .u.sig = {
+            "EC",
+            0,
+            ecdsa_bin_key,
+            ITM_BUF(sig_kat_entropyin),
+            ITM_BUF(sig_kat_nonce),
+            ITM_BUF(sig_kat_persstr),
+        },
     },
 #endif
 #ifndef OPENSSL_NO_ECX
     {
-        OSSL_SELF_TEST_DESC_SIGN_EDDSA,
-        "ED448",
         "ED448",
+        OSSL_SELF_TEST_DESC_SIGN_EDDSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        ed448_key,
-        ITM(ecx_sig_msg),
-        NULL,
-        0,
-        NULL,
-        0,
-        NULL,
-        0,
-        ITM(ed448_expected_sig),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(ecx_sig_msg),
+        ITM_BUF(ed448_expected_sig),
+        .u.sig = {
+            "ED448",
+            0,
+            ed448_key,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_SIGN_EDDSA,
-        "ED25519",
         "ED25519",
+        OSSL_SELF_TEST_DESC_SIGN_EDDSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        ed25519_key,
-        ITM(ecx_sig_msg),
-        NULL,
-        0,
-        NULL,
-        0,
-        NULL,
-        0,
-        ITM(ed25519_expected_sig),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(ecx_sig_msg),
+        ITM_BUF(ed25519_expected_sig),
+        .u.sig = {
+            "ED25519",
+            0,
+            ed25519_key,
+        },
     },
 #endif /* OPENSSL_NO_ECX */
 #endif /* OPENSSL_NO_EC */
 #ifndef OPENSSL_NO_DSA
     {
-        OSSL_SELF_TEST_DESC_SIGN_DSA,
-        "DSA",
         "DSA-SHA256",
+        OSSL_SELF_TEST_DESC_SIGN_DSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        SIGNATURE_MODE_VERIFY_ONLY,
-        dsa_key,
-        ITM_STR(rsa_sig_msg),
-        ITM(sig_kat_entropyin),
-        ITM(sig_kat_nonce),
-        ITM(sig_kat_persstr),
-        ITM(dsa_expected_sig),
+        SELF_TEST_STATE_INIT,
+        ITM_BUF_STR(rsa_sig_msg),
+        ITM_BUF(dsa_expected_sig),
+        .u.sig = {
+            "DSA",
+            SIGNATURE_MODE_VERIFY_ONLY,
+            dsa_key,
+            ITM_BUF(sig_kat_entropyin),
+            ITM_BUF(sig_kat_nonce),
+            ITM_BUF(sig_kat_persstr),
+        },
     },
 #endif /* OPENSSL_NO_DSA */

 #ifndef OPENSSL_NO_ML_DSA
     {
-        OSSL_SELF_TEST_DESC_SIGN_ML_DSA,
-        "ML-DSA-65",
         "ML-DSA-65",
+        OSSL_SELF_TEST_DESC_SIGN_ML_DSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_ONLOAD,
-        0,
-        ml_dsa_key,
-        ITM(ml_dsa_65_msg),
-        NULL,
-        0,
-        NULL,
-        0,
-        NULL,
-        0,
-        ITM(ml_dsa_65_sig),
-        ml_dsa_sig_init,
-        ml_dsa_sig_init,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(ml_dsa_65_msg),
+        ITM_BUF(ml_dsa_65_sig),
+        .u.sig = {
+            "ML-DSA-65",
+            0,
+            ml_dsa_key,
+            .init = ml_dsa_sig_init,
+            .verify = ml_dsa_sig_init,
+        },
     },
 #endif /* OPENSSL_NO_ML_DSA */
 #ifndef OPENSSL_NO_SLH_DSA
@@ -3282,42 +3391,41 @@ const ST_KAT_SIGN st_kat_sign_tests[] = {
      * here.
      */
     {
-        OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
-        "SLH-DSA-SHA2-128f",
         "SLH-DSA-SHA2-128f",
+        OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_DEFERRED,
-        SIGNATURE_MODE_SIG_DIGESTED,
-        slh_dsa_sha2_128f_key_params,
-        ITM(slh_dsa_sha2_sig_msg),
-        NULL,
-        0,
-        NULL,
-        0,
-        NULL,
-        0,
-        ITM(slh_dsa_sha2_128f_sig_digest),
-        slh_dsa_sig_params,
-        slh_dsa_sig_params,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(slh_dsa_sha2_sig_msg),
+        ITM_BUF(slh_dsa_sha2_128f_sig_digest),
+        .u.sig = {
+            "SLH-DSA-SHA2-128f",
+            SIGNATURE_MODE_SIG_DIGESTED,
+            slh_dsa_sha2_128f_key_params,
+            .init = slh_dsa_sig_params,
+            .verify = slh_dsa_sig_params,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
-        "SLH-DSA-SHAKE-128f",
         "SLH-DSA-SHAKE-128f",
+        OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
+        SELF_TEST_KAT_SIGNATURE,
         SELF_TEST_DEFERRED,
-        SIGNATURE_MODE_SIG_DIGESTED,
-        slh_dsa_shake_128f_key_params,
-        ITM(slh_dsa_shake_sig_msg),
-        NULL,
-        0,
-        NULL,
-        0,
-        NULL,
-        0,
-        ITM(slh_dsa_shake_128f_sig_digest),
-        slh_dsa_sig_params,
-        slh_dsa_sig_params,
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(slh_dsa_shake_sig_msg),
+        ITM_BUF(slh_dsa_shake_128f_sig_digest),
+        .u.sig = {
+            "SLH-DSA-SHAKE-128f",
+            SIGNATURE_MODE_SIG_DIGESTED,
+            slh_dsa_shake_128f_key_params,
+            .init = slh_dsa_sig_params,
+            .verify = slh_dsa_sig_params,
+        },
     },
 #endif /* OPENSSL_NO_SLH_DSA */
+#ifndef OPENSSL_NO_LMS
+    st_kat_lms_test,
+#endif /* OPENSSL_NO_LMS */
 };
 int st_kat_sign_tests_size = OSSL_NELEM(st_kat_sign_tests);

@@ -3688,87 +3796,109 @@ static const ST_KAT_PARAM ml_kem_key[] = {
     ST_KAT_PARAM_END()
 };

-const ST_KAT_KEM st_kat_kem_tests[] = {
-    {
+const ST_DEFINITION st_kat_kem_tests[] = {
+    { "ML-KEM-512",
         OSSL_SELF_TEST_DESC_KEM,
-        "ML-KEM-512", SELF_TEST_ONLOAD,
-        ml_kem_key,
-        ITM(ml_kem_512_cipher_text),
-        ITM(ml_kem_512_entropy),
-        ITM(ml_kem_512_secret),
-        ml_kem_512_reject_secret, /* No length because same as _secret's */
-    },
+        SELF_TEST_KAT_KEM,
+        SELF_TEST_ONLOAD,
+        SELF_TEST_STATE_INIT,
+        .u.kem = {
+            ml_kem_key,
+            ITM_BUF(ml_kem_512_cipher_text),
+            ITM_BUF(ml_kem_512_entropy),
+            ITM_BUF(ml_kem_512_secret),
+            ITM_BUF(ml_kem_512_reject_secret) } },
 };
 int st_kat_kem_tests_size = OSSL_NELEM(st_kat_kem_tests);
 #endif /* OPENSSL_NO_ML_KEM */

 #if !defined(OPENSSL_NO_ML_KEM) || !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA)
-const ST_KAT_ASYM_KEYGEN st_kat_asym_keygen_tests[] = {
+const ST_DEFINITION st_kat_asym_keygen_tests[] = {
 #if !defined(OPENSSL_NO_ML_KEM)
     /*
      * FIPS 140-3 IG 10.3.A resolution 14 mandates a CAST for ML-KEM
      * key generation.
      */
     {
-        OSSL_SELF_TEST_DESC_KEYGEN_ML_KEM,
         "ML-KEM-512",
+        OSSL_SELF_TEST_DESC_KEYGEN_ML_KEM,
+        SELF_TEST_KAT_ASYM_CIPHER,
         SELF_TEST_ONLOAD,
-        ml_kem_keygen_params,
-        ml_kem_key,
-    },
+        SELF_TEST_STATE_INIT,
+        .u.akgen = {
+            ml_kem_keygen_params,
+            ml_kem_key } },
 #endif
 #if !defined(OPENSSL_NO_ML_DSA)
     {
-        OSSL_SELF_TEST_DESC_KEYGEN_ML_DSA,
         "ML-DSA-65",
+        OSSL_SELF_TEST_DESC_KEYGEN_ML_DSA,
+        SELF_TEST_KAT_ASYM_CIPHER,
         SELF_TEST_ONLOAD,
-        ml_dsa_keygen_params,
-        ml_dsa_key,
+        SELF_TEST_STATE_INIT,
+        .u.akgen = {
+            ml_dsa_keygen_params,
+            ml_dsa_key,
+        },
     },
 #endif
 #if !defined(OPENSSL_NO_SLH_DSA)
     {
-        OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA,
         "SLH-DSA-SHA2-128f",
+        OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA,
+        SELF_TEST_KAT_ASYM_CIPHER,
         SELF_TEST_DEFERRED,
-        slh_dsa_sha2_128f_keygen_init_params,
-        slh_dsa_128f_keygen_expected_params,
+        SELF_TEST_STATE_INIT,
+        .u.akgen = {
+            slh_dsa_sha2_128f_keygen_init_params,
+            slh_dsa_128f_keygen_expected_params,
+        },
     },
 #endif
 };
 int st_kat_asym_keygen_tests_size = OSSL_NELEM(st_kat_asym_keygen_tests);
 #endif /* !OPENSSL_NO_ML_DSA || !OPENSSL_NO_SLH_DSA */

-const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = {
-    {
+const ST_DEFINITION st_kat_asym_cipher_tests[] = {
+    { "RSA",
         OSSL_SELF_TEST_DESC_ASYM_RSA_ENC,
-        "RSA",
+        SELF_TEST_KAT_ASYM_CIPHER,
         SELF_TEST_ONLOAD,
-        1,
-        rsa_pub_key,
-        rsa_enc_params,
-        ITM(rsa_asym_plaintext_encrypt),
-        ITM(rsa_asym_expected_encrypt),
-    },
+        SELF_TEST_STATE_INIT,
+        ITM_BUF(rsa_asym_plaintext_encrypt),
+        ITM_BUF(rsa_asym_expected_encrypt),
+        .u.ac = {
+            1,
+            rsa_pub_key,
+            rsa_enc_params,
+        } },
     {
-        OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
         "RSA",
+        OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+        SELF_TEST_KAT_ASYM_CIPHER,
         SELF_TEST_ONLOAD,
-        0,
-        rsa_priv_key,
-        rsa_enc_params,
+        SELF_TEST_STATE_INIT,
         ITM(rsa_asym_expected_encrypt),
         ITM(rsa_asym_plaintext_encrypt),
+        .u.ac = {
+            0,
+            rsa_priv_key,
+            rsa_enc_params,
+        },
     },
     {
-        OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
         "RSA",
+        OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+        SELF_TEST_KAT_ASYM_CIPHER,
         SELF_TEST_ONLOAD,
-        0,
-        rsa_crt_key,
-        rsa_enc_params,
+        SELF_TEST_STATE_INIT,
         ITM(rsa_asym_expected_encrypt),
         ITM(rsa_asym_plaintext_encrypt),
+        .u.ac = {
+            0,
+            rsa_crt_key,
+            rsa_enc_params,
+        },
     },
 };
 int st_kat_asym_cipher_tests_size = OSSL_NELEM(st_kat_asym_cipher_tests);
diff --git a/providers/fips/self_test_data.h b/providers/fips/self_test_data.h
index 92b8995e0b..bfa3d54ae5 100644
--- a/providers/fips/self_test_data.h
+++ b/providers/fips/self_test_data.h
@@ -16,30 +16,30 @@
  * they are tested as part of a higher level algorithm (such as HMAC).
  */

-extern const ST_KAT_DIGEST st_kat_digest_tests[];
+extern const ST_DEFINITION st_kat_digest_tests[];
 extern int st_kat_digest_tests_size;
-extern const ST_KAT_CIPHER st_kat_cipher_tests[];
+extern const ST_DEFINITION st_kat_cipher_tests[];
 extern int st_kat_cipher_tests_size;
 #ifndef OPENSSL_NO_LMS
-extern const ST_KAT_LMS st_kat_lms_test;
+extern const ST_DEFINITION st_kat_lms_test;
 #endif
-extern const ST_KAT_KDF st_kat_kdf_tests[];
+extern const ST_DEFINITION st_kat_kdf_tests[];
 extern int st_kat_kdf_tests_size;
-extern const ST_KAT_DRBG st_kat_drbg_tests[];
+extern const ST_DEFINITION st_kat_drbg_tests[];
 extern int st_kat_drbg_tests_size;
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
-extern const ST_KAT_KAS st_kat_kas_tests[];
+extern const ST_DEFINITION st_kat_kas_tests[];
 extern int st_kat_kas_tests_size;
 #endif
-extern const ST_KAT_SIGN st_kat_sign_tests[];
+extern const ST_DEFINITION st_kat_sign_tests[];
 extern int st_kat_sign_tests_size;
 #ifndef OPENSSL_NO_ML_KEM
-extern const ST_KAT_KEM st_kat_kem_tests[];
+extern const ST_DEFINITION st_kat_kem_tests[];
 extern int st_kat_kem_tests_size;
 #endif
 #if !defined(OPENSSL_NO_ML_KEM) || !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA)
-extern const ST_KAT_ASYM_KEYGEN st_kat_asym_keygen_tests[];
+extern const ST_DEFINITION st_kat_asym_keygen_tests[];
 extern int st_kat_asym_keygen_tests_size;
 #endif
-extern const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[];
+extern const ST_DEFINITION st_kat_asym_cipher_tests[];
 extern int st_kat_asym_cipher_tests_size;
diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c
index aa18d830b0..d3d1e02831 100644
--- a/providers/fips/self_test_kats.c
+++ b/providers/fips/self_test_kats.c
@@ -26,7 +26,7 @@ static int set_kat_drbg(OSSL_LIB_CTX *ctx,
     const unsigned char *persstr, size_t persstr_len);
 static int reset_main_drbg(OSSL_LIB_CTX *ctx);

-static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
+static int self_test_digest(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ok = 0;
@@ -40,15 +40,15 @@ static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
     if (ctx == NULL
         || md == NULL
         || !EVP_DigestInit_ex(ctx, md, NULL)
-        || !EVP_DigestUpdate(ctx, t->pt, t->pt_len)
+        || !EVP_DigestUpdate(ctx, t->pt.buf, t->pt.len)
         || !EVP_DigestFinal(ctx, out, &out_len))
         goto err;

     /* Optional corruption */
     OSSL_SELF_TEST_oncorrupt_byte(st, out);

-    if (out_len != t->expected_len
-        || memcmp(out, t->expected, out_len) != 0)
+    if (out_len != t->expected.len
+        || memcmp(out, t->expected.buf, out_len) != 0)
         goto err;
     ok = 1;
 err:
@@ -70,29 +70,29 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,

     /* Flag required for Key wrapping */
     EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
-    if (t->tag == NULL) {
+    if (t->tag.buf == NULL) {
         /* Use a normal cipher init */
-        return EVP_CipherInit_ex(ctx, cipher, NULL, t->key, t->iv, enc)
+        return EVP_CipherInit_ex(ctx, cipher, NULL, t->key.buf, t->iv.buf, enc)
             && EVP_CIPHER_CTX_set_padding(ctx, pad);
     }

     /* The authenticated cipher init */
     if (!enc)
-        in_tag = (unsigned char *)t->tag;
+        in_tag = (unsigned char *)t->tag.buf;

     return EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)
-        && (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, (int)t->iv_len, NULL) > 0)
+        && (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, (int)t->iv.len, NULL) > 0)
         && (in_tag == NULL
-            || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)t->tag_len,
+            || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)t->tag.len,
                    in_tag)
                 > 0)
-        && EVP_CipherInit_ex(ctx, NULL, NULL, t->key, t->iv, enc)
+        && EVP_CipherInit_ex(ctx, NULL, NULL, t->key.buf, t->iv.buf, enc)
         && EVP_CIPHER_CTX_set_padding(ctx, pad)
-        && EVP_CipherUpdate(ctx, NULL, &tmp, t->aad, (int)t->aad_len);
+        && EVP_CipherUpdate(ctx, NULL, &tmp, t->aad.buf, (int)t->aad.len);
 }

 /* Test a single KAT for encrypt/decrypt */
-static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_SELF_TEST *st,
+static int self_test_cipher(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ret = 0, encrypt = 1, len = 0, ct_len = 0, pt_len = 0;
@@ -101,51 +101,51 @@ static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_SELF_TEST *st,
     unsigned char ct_buf[256] = { 0 };
     unsigned char pt_buf[256] = { 0 };

-    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
+    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->desc);

     ctx = EVP_CIPHER_CTX_new();
     if (ctx == NULL)
         goto err;
-    cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, NULL);
+    cipher = EVP_CIPHER_fetch(libctx, t->algorithm, NULL);
     if (cipher == NULL)
         goto err;

     /* Encrypt plain text message */
-    if ((t->mode & CIPHER_MODE_ENCRYPT) != 0) {
-        if (!cipher_init(ctx, cipher, t, encrypt)
-            || !EVP_CipherUpdate(ctx, ct_buf, &len, t->base.pt,
-                (int)t->base.pt_len)
+    if ((t->u.cipher.mode & CIPHER_MODE_ENCRYPT) != 0) {
+        if (!cipher_init(ctx, cipher, &t->u.cipher, encrypt)
+            || !EVP_CipherUpdate(ctx, ct_buf, &len, t->pt.buf,
+                (int)t->pt.len)
             || !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
             goto err;

         OSSL_SELF_TEST_oncorrupt_byte(st, ct_buf);
         ct_len += len;
-        if (ct_len != (int)t->base.expected_len
-            || memcmp(t->base.expected, ct_buf, ct_len) != 0)
+        if (ct_len != (int)t->expected.len
+            || memcmp(t->expected.buf, ct_buf, ct_len) != 0)
             goto err;

-        if (t->tag != NULL) {
+        if (t->u.cipher.tag.buf != NULL) {
             unsigned char tag[16] = { 0 };

-            if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, (int)t->tag_len,
-                    tag)
+            if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
+                    (int)t->u.cipher.tag.len, tag)
                     <= 0
-                || memcmp(tag, t->tag, t->tag_len) != 0)
+                || memcmp(tag, t->u.cipher.tag.buf, t->u.cipher.tag.len) != 0)
                 goto err;
         }
     }

     /* Decrypt cipher text */
-    if ((t->mode & CIPHER_MODE_DECRYPT) != 0) {
-        if (!(cipher_init(ctx, cipher, t, !encrypt)
+    if ((t->u.cipher.mode & CIPHER_MODE_DECRYPT) != 0) {
+        if (!(cipher_init(ctx, cipher, &t->u.cipher, !encrypt)
                 && EVP_CipherUpdate(ctx, pt_buf, &len,
-                    t->base.expected, (int)t->base.expected_len)
+                    t->expected.buf, (int)t->expected.len)
                 && EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
             goto err;
         OSSL_SELF_TEST_oncorrupt_byte(st, pt_buf);
         pt_len += len;
-        if (pt_len != (int)t->base.pt_len
-            || memcmp(pt_buf, t->base.pt, pt_len) != 0)
+        if (pt_len != (int)t->pt.len
+            || memcmp(pt_buf, t->pt.buf, pt_len) != 0)
             goto err;
     }

@@ -245,7 +245,7 @@ err:
     return params;
 }

-static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st,
+static int self_test_kdf(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -264,18 +264,18 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st,
     if (ctx == NULL)
         goto err;

-    params = kat_params_to_ossl_params(libctx, t->params, NULL);
+    params = kat_params_to_ossl_params(libctx, t->u.kdf.params, NULL);
     if (params == NULL)
         goto err;

-    if (t->expected_len > sizeof(out))
+    if (t->expected.len > sizeof(out))
         goto err;
-    if (EVP_KDF_derive(ctx, out, t->expected_len, params) <= 0)
+    if (EVP_KDF_derive(ctx, out, t->expected.len, params) <= 0)
         goto err;

     OSSL_SELF_TEST_oncorrupt_byte(st, out);

-    if (memcmp(out, t->expected, t->expected_len) != 0)
+    if (memcmp(out, t->expected.buf, t->expected.len) != 0)
         goto err;

     ret = 1;
@@ -287,7 +287,7 @@ err:
     return ret;
 }

-static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,
+static int self_test_drbg(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -327,36 +327,38 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,

     strength = EVP_RAND_get_strength(drbg);

-    drbg_params[0] = OSSL_PARAM_construct_utf8_string(t->param_name,
-        t->param_value, 0);
+    drbg_params[0] = OSSL_PARAM_construct_utf8_string(t->u.drbg.param_name,
+        (char *)t->u.drbg.param_value, 0);
     if (!EVP_RAND_CTX_set_params(drbg, drbg_params))
         goto err;

     drbg_params[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
-        (void *)t->entropyin,
-        t->entropyinlen);
+        (void *)t->u.drbg.entropyin.buf,
+        t->u.drbg.entropyin.len);
     drbg_params[1] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
-        (void *)t->nonce, t->noncelen);
+        (void *)t->u.drbg.nonce.buf,
+        t->u.drbg.nonce.len);
     if (!EVP_RAND_instantiate(test, strength, 0, NULL, 0, drbg_params))
         goto err;
-    if (!EVP_RAND_instantiate(drbg, strength, 0, t->persstr, t->persstrlen,
-            NULL))
+    if (!EVP_RAND_instantiate(drbg, strength, 0, t->u.drbg.persstr.buf,
+            t->u.drbg.persstr.len, NULL))
         goto err;

     drbg_params[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
-        (void *)t->entropyinpr1,
-        t->entropyinpr1len);
+        (void *)t->u.drbg.entropyinpr1.buf,
+        t->u.drbg.entropyinpr1.len);
     if (!EVP_RAND_CTX_set_params(test, drbg_params))
         goto err;

-    if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength,
+    if (!EVP_RAND_generate(drbg, out, t->expected.len, strength,
             prediction_resistance,
-            t->entropyaddin1, t->entropyaddin1len))
+            t->u.drbg.entropyaddin1.buf,
+            t->u.drbg.entropyaddin1.len))
         goto err;

     drbg_params[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
-        (void *)t->entropyinpr2,
-        t->entropyinpr2len);
+        (void *)t->u.drbg.entropyinpr2.buf,
+        t->u.drbg.entropyinpr2.len);
     if (!EVP_RAND_CTX_set_params(test, drbg_params))
         goto err;

@@ -364,14 +366,15 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,
      * This calls ossl_prov_drbg_reseed() internally when
      * prediction_resistance = 1
      */
-    if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength,
+    if (!EVP_RAND_generate(drbg, out, t->expected.len, strength,
             prediction_resistance,
-            t->entropyaddin2, t->entropyaddin2len))
+            t->u.drbg.entropyaddin2.buf,
+            t->u.drbg.entropyaddin2.len))
         goto err;

     OSSL_SELF_TEST_oncorrupt_byte(st, out);

-    if (memcmp(out, t->expected, t->expectedlen) != 0)
+    if (memcmp(out, t->expected.buf, t->expected.len) != 0)
         goto err;

     if (!EVP_RAND_uninstantiate(drbg))
@@ -392,7 +395,7 @@ err:
 }

 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
-static int self_test_ka(const ST_KAT_KAS *t,
+static int self_test_ka(const ST_DEFINITION *t,
     OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -401,17 +404,17 @@ static int self_test_ka(const ST_KAT_KAS *t,
     OSSL_PARAM *params = NULL;
     OSSL_PARAM *params_peer = NULL;
     unsigned char secret[256];
-    size_t secret_len = t->expected_len;
+    size_t secret_len = t->expected.len;

     OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KA, t->desc);

     if (secret_len > sizeof(secret))
         goto err;

-    params = kat_params_to_ossl_params(libctx, t->key_group,
-        t->key_host_data, NULL);
-    params_peer = kat_params_to_ossl_params(libctx, t->key_group,
-        t->key_peer_data, NULL);
+    params = kat_params_to_ossl_params(libctx, t->u.kas.key_group,
+        t->u.kas.key_host_data, NULL);
+    params_peer = kat_params_to_ossl_params(libctx, t->u.kas.key_group,
+        t->u.kas.key_peer_data, NULL);
     if (params == NULL || params_peer == NULL)
         goto err;

@@ -438,8 +441,8 @@ static int self_test_ka(const ST_KAT_KAS *t,

     OSSL_SELF_TEST_oncorrupt_byte(st, secret);

-    if (secret_len != t->expected_len
-        || memcmp(secret, t->expected, t->expected_len) != 0)
+    if (secret_len != t->expected.len
+        || memcmp(secret, t->expected.buf, t->expected.len) != 0)
         goto err;
     ret = 1;
 err:
@@ -474,54 +477,7 @@ static int digest_signature(const uint8_t *sig, size_t sig_len,
     return ret;
 }

-#ifndef OPENSSL_NO_LMS
-static int self_test_LMS(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
-{
-    int ret = 0;
-    OSSL_PARAM pm[2];
-    const ST_KAT_LMS *t = &st_kat_lms_test;
-    EVP_PKEY_CTX *ctx = NULL;
-    EVP_PKEY *pkey = NULL;
-    EVP_SIGNATURE *sig = NULL;
-
-    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_SIGNATURE,
-        OSSL_SELF_TEST_DESC_SIGN_LMS);
-
-    pm[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
-        (unsigned char *)t->pub,
-        t->publen);
-    pm[1] = OSSL_PARAM_construct_end();
-
-    ctx = EVP_PKEY_CTX_new_from_name(libctx, "LMS", "");
-    if (ctx == NULL
-        || EVP_PKEY_fromdata_init(ctx) <= 0
-        || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, pm) <= 0)
-        goto err;
-    EVP_PKEY_CTX_free(ctx);
-    ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "");
-    if (ctx == NULL)
-        goto err;
-
-    sig = EVP_SIGNATURE_fetch(libctx, "LMS", NULL);
-    if (sig == NULL
-        || EVP_PKEY_verify_message_init(ctx, sig, NULL) <= 0
-        || EVP_PKEY_verify(ctx, t->sig, t->siglen,
-               t->msg, t->msglen)
-            <= 0)
-        goto err;
-
-    ret = 1;
-err:
-    EVP_PKEY_free(pkey);
-    EVP_PKEY_CTX_free(ctx);
-    EVP_SIGNATURE_free(sig);
-
-    OSSL_SELF_TEST_onend(st, ret);
-    return ret;
-}
-#endif /* OPENSSL_NO_LMS */
-
-static int self_test_digest_sign(const ST_KAT_SIGN *t,
+static int self_test_digest_sign(const ST_DEFINITION *t,
     OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -535,25 +491,26 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
     int digested = 0;
     const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE;

-    if (t->sig_expected_len > sizeof(sig))
+    if (t->expected.len > sizeof(sig))
         goto err;

-    if (t->sig_expected == NULL)
+    if (t->expected.buf == NULL)
         typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE;

     OSSL_SELF_TEST_onbegin(st, typ, t->desc);

-    if (t->entropy != NULL) {
-        if (!set_kat_drbg(libctx, t->entropy, t->entropy_len,
-                t->nonce, t->nonce_len, t->persstr, t->persstr_len))
+    if (t->u.sig.entropy.buf != NULL) {
+        if (!set_kat_drbg(libctx, t->u.sig.entropy.buf, t->u.sig.entropy.len,
+                t->u.sig.nonce.buf, t->u.sig.nonce.len,
+                t->u.sig.persstr.buf, t->u.sig.persstr.len))
             goto err;
     }

-    paramskey = kat_params_to_ossl_params(libctx, t->key, NULL);
-    paramsinit = kat_params_to_ossl_params(libctx, t->init, NULL);
-    paramsverify = kat_params_to_ossl_params(libctx, t->verify, NULL);
+    paramskey = kat_params_to_ossl_params(libctx, t->u.sig.key, NULL);
+    paramsinit = kat_params_to_ossl_params(libctx, t->u.sig.init, NULL);
+    paramsverify = kat_params_to_ossl_params(libctx, t->u.sig.verify, NULL);

-    fromctx = EVP_PKEY_CTX_new_from_name(libctx, t->keytype, NULL);
+    fromctx = EVP_PKEY_CTX_new_from_name(libctx, t->u.sig.keytype, NULL);
     if (fromctx == NULL
         || paramskey == NULL
         || paramsinit == NULL
@@ -563,18 +520,18 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
         || EVP_PKEY_fromdata(fromctx, &pkey, EVP_PKEY_KEYPAIR, paramskey) <= 0)
         goto err;

-    sigalg = EVP_SIGNATURE_fetch(libctx, t->sigalgorithm, NULL);
+    sigalg = EVP_SIGNATURE_fetch(libctx, t->algorithm, NULL);
     if (sigalg == NULL)
         goto err;
     ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL);
     if (ctx == NULL)
         goto err;

-    digested = ((t->mode & SIGNATURE_MODE_DIGESTED) != 0);
+    digested = ((t->u.sig.mode & SIGNATURE_MODE_DIGESTED) != 0);

-    if ((t->mode & SIGNATURE_MODE_VERIFY_ONLY) != 0) {
-        siglen = t->sig_expected_len;
-        memcpy(psig, t->sig_expected, siglen);
+    if ((t->u.sig.mode & SIGNATURE_MODE_VERIFY_ONLY) != 0) {
+        siglen = t->expected.len;
+        memcpy(psig, t->expected.buf, siglen);
     } else {
         if (digested) {
             if (EVP_PKEY_sign_init_ex2(ctx, sigalg, paramsinit) <= 0)
@@ -584,8 +541,8 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
                 goto err;
         }
         siglen = sizeof(sig);
-        if ((t->mode & SIGNATURE_MODE_SIG_DIGESTED) != 0) {
-            if (EVP_PKEY_sign(ctx, NULL, &siglen, t->msg, t->msg_len) <= 0)
+        if ((t->u.sig.mode & SIGNATURE_MODE_SIG_DIGESTED) != 0) {
+            if (EVP_PKEY_sign(ctx, NULL, &siglen, t->pt.buf, t->pt.len) <= 0)
                 goto err;
             if (siglen > sizeof(sig)) {
                 psig = OPENSSL_malloc(siglen);
@@ -593,28 +550,28 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
                     goto err;
             }
         }
-        if (EVP_PKEY_sign(ctx, psig, &siglen, t->msg, t->msg_len) <= 0)
+        if (EVP_PKEY_sign(ctx, psig, &siglen, t->pt.buf, t->pt.len) <= 0)
             goto err;

-        if (t->sig_expected != NULL) {
-            if ((t->mode & SIGNATURE_MODE_SIG_DIGESTED) != 0) {
+        if (t->expected.buf != NULL) {
+            if ((t->u.sig.mode & SIGNATURE_MODE_SIG_DIGESTED) != 0) {
                 uint8_t digested_sig[EVP_MAX_MD_SIZE];
                 size_t digested_sig_len = 0;

                 if (!digest_signature(psig, siglen, digested_sig,
                         &digested_sig_len, libctx)
-                    || digested_sig_len != t->sig_expected_len
-                    || memcmp(digested_sig, t->sig_expected, t->sig_expected_len) != 0)
+                    || digested_sig_len != t->expected.len
+                    || memcmp(digested_sig, t->expected.buf, t->expected.len) != 0)
                     goto err;
             } else {
-                if (siglen != t->sig_expected_len
-                    || memcmp(psig, t->sig_expected, t->sig_expected_len) != 0)
+                if (siglen != t->expected.len
+                    || memcmp(psig, t->expected.buf, t->expected.len) != 0)
                     goto err;
             }
         }
     }

-    if ((t->mode & SIGNATURE_MODE_SIGN_ONLY) == 0) {
+    if ((t->u.sig.mode & SIGNATURE_MODE_SIGN_ONLY) == 0) {
         if (digested) {
             if (EVP_PKEY_verify_init_ex2(ctx, sigalg, paramsverify) <= 0)
                 goto err;
@@ -623,7 +580,7 @@ static int self_test_digest_sign(const ST_KAT_SIGN *t,
                 goto err;
         }
         OSSL_SELF_TEST_oncorrupt_byte(st, psig);
-        if (EVP_PKEY_verify(ctx, psig, siglen, t->msg, t->msg_len) <= 0)
+        if (EVP_PKEY_verify(ctx, psig, siglen, t->pt.buf, t->pt.len) <= 0)
             goto err;
     }
     ret = 1;
@@ -637,7 +594,7 @@ err:
     OSSL_PARAM_free(paramskey);
     OSSL_PARAM_free(paramsinit);
     OSSL_PARAM_free(paramsverify);
-    if (t->entropy != NULL) {
+    if (t->u.sig.entropy.buf != NULL) {
         if (!reset_main_drbg(libctx))
             ret = 0;
     }
@@ -649,7 +606,7 @@ err:
 /*
  * Test that a deterministic key generation produces the correct key
  */
-static int self_test_asym_keygen(const ST_KAT_ASYM_KEYGEN *t, OSSL_SELF_TEST *st,
+static int self_test_asym_keygen(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -665,8 +622,9 @@ static int self_test_asym_keygen(const ST_KAT_ASYM_KEYGEN *t, OSSL_SELF_TEST *st
     key_ctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
     if (key_ctx == NULL)
         goto err;
-    if (t->keygen_params != NULL) {
-        key_params = kat_params_to_ossl_params(libctx, t->keygen_params, NULL);
+    if (t->u.akgen.keygen_params != NULL) {
+        key_params = kat_params_to_ossl_params(libctx, t->u.akgen.keygen_params,
+            NULL);
         if (key_params == NULL)
             goto err;
     }
@@ -675,7 +633,7 @@ static int self_test_asym_keygen(const ST_KAT_ASYM_KEYGEN *t, OSSL_SELF_TEST *st
         || EVP_PKEY_generate(key_ctx, &key) != 1)
         goto err;

-    for (expected = t->expected_params; expected->data != NULL; ++expected) {
+    for (expected = t->u.akgen.expected_params; expected->data != NULL; ++expected) {
         if (expected->type != OSSL_PARAM_OCTET_STRING
             || !EVP_PKEY_get_octet_string_param(key, expected->name,
                 out, sizeof(out), &out_len))
@@ -707,7 +665,7 @@ static int self_test_kem_encapsulate(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,
     int ret = 0;
     EVP_PKEY_CTX *ctx;
     unsigned char *wrapped = NULL, *secret = NULL;
-    size_t wrappedlen = t->cipher_text_len, secretlen = t->secret_len;
+    size_t wrappedlen = t->cipher_text.len, secretlen = t->secret.len;
     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };

     OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KEM,
@@ -718,8 +676,8 @@ static int self_test_kem_encapsulate(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,
         goto err;

     *params = OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
-        (unsigned char *)t->entropy,
-        t->entropy_len);
+        (unsigned char *)t->entropy.buf,
+        t->entropy.len);
     if (EVP_PKEY_encapsulate_init(ctx, params) <= 0)
         goto err;

@@ -735,13 +693,13 @@ static int self_test_kem_encapsulate(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,

     /* Compare outputs */
     OSSL_SELF_TEST_oncorrupt_byte(st, wrapped);
-    if (wrappedlen != t->cipher_text_len
-        || memcmp(wrapped, t->cipher_text, t->cipher_text_len) != 0)
+    if (wrappedlen != t->cipher_text.len
+        || memcmp(wrapped, t->cipher_text.buf, t->cipher_text.len) != 0)
         goto err;

     OSSL_SELF_TEST_oncorrupt_byte(st, secret);
-    if (secretlen != t->secret_len
-        || memcmp(secret, t->secret, t->secret_len) != 0)
+    if (secretlen != t->secret.len
+        || memcmp(secret, t->secret.buf, t->secret.len) != 0)
         goto err;

     ret = 1;
@@ -764,19 +722,19 @@ static int self_test_kem_decapsulate(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,
     int ret = 0;
     EVP_PKEY_CTX *ctx = NULL;
     unsigned char *secret = NULL, *alloced = NULL;
-    const unsigned char *test_secret = t->secret;
-    const unsigned char *cipher_text = t->cipher_text;
-    size_t secretlen = t->secret_len;
+    const unsigned char *test_secret = t->secret.buf;
+    const unsigned char *cipher_text = t->cipher_text.buf;
+    size_t secretlen = t->secret.len;

     OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KEM,
         reject ? OSSL_SELF_TEST_DESC_DECAP_KEM_FAIL
                : OSSL_SELF_TEST_DESC_DECAP_KEM);

     if (reject) {
-        cipher_text = alloced = OPENSSL_zalloc(t->cipher_text_len);
+        cipher_text = alloced = OPENSSL_zalloc(t->cipher_text.len);
         if (alloced == NULL)
             goto err;
-        test_secret = t->reject_secret;
+        test_secret = t->reject_secret.buf;
     }

     ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "");
@@ -793,14 +751,14 @@ static int self_test_kem_decapsulate(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,

     /* Decapsulate */
     if (EVP_PKEY_decapsulate(ctx, secret, &secretlen,
-            cipher_text, t->cipher_text_len)
+            cipher_text, t->cipher_text.len)
         <= 0)
         goto err;

     /* Compare output */
     OSSL_SELF_TEST_oncorrupt_byte(st, secret);
-    if (secretlen != t->secret_len
-        || memcmp(secret, test_secret, t->secret_len) != 0)
+    if (secretlen != t->secret.len
+        || memcmp(secret, test_secret, t->secret.len) != 0)
         goto err;

     ret = 1;
@@ -821,7 +779,7 @@ err:
  * 2b  ML-KEM decapsulation implicit rejection path
  * 3   ML-KEM key generation
  */
-static int self_test_kem(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,
+static int self_test_kem(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -832,7 +790,7 @@ static int self_test_kem(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,
     ctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
     if (ctx == NULL)
         goto err;
-    params = kat_params_to_ossl_params(libctx, t->key, NULL);
+    params = kat_params_to_ossl_params(libctx, t->u.kem.key, NULL);
     if (params == NULL)
         goto err;

@@ -840,9 +798,9 @@ static int self_test_kem(const ST_KAT_KEM *t, OSSL_SELF_TEST *st,
         || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
         goto err;

-    if (!self_test_kem_encapsulate(t, st, libctx, pkey)
-        || !self_test_kem_decapsulate(t, st, libctx, pkey, 0)
-        || !self_test_kem_decapsulate(t, st, libctx, pkey, 1))
+    if (!self_test_kem_encapsulate(&t->u.kem, st, libctx, pkey)
+        || !self_test_kem_decapsulate(&t->u.kem, st, libctx, pkey, 0)
+        || !self_test_kem_decapsulate(&t->u.kem, st, libctx, pkey, 1))
         goto err;

     ret = 1;
@@ -860,7 +818,7 @@ err:
  * FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt
  * and decrypt..
  */
-static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st,
+static int self_test_asym_cipher(const ST_DEFINITION *t, OSSL_SELF_TEST *st,
     OSSL_LIB_CTX *libctx)
 {
     int ret = 0;
@@ -881,7 +839,7 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st
     /* Load a public or private key from data */
     keybld = OSSL_PARAM_BLD_new();
     if (keybld == NULL
-        || !add_params(keybld, t->key, bnctx))
+        || !add_params(keybld, t->u.ac.key, bnctx))
         goto err;
     keyparams = OSSL_PARAM_BLD_to_param(keybld);
     keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
@@ -894,16 +852,16 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st
     /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */
     encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL);
     if (encctx == NULL
-        || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0)
-        || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0))
+        || (t->u.ac.encrypt && EVP_PKEY_encrypt_init(encctx) <= 0)
+        || (!t->u.ac.encrypt && EVP_PKEY_decrypt_init(encctx) <= 0))
         goto err;

     /* Add any additional parameters such as padding */
-    if (t->postinit != NULL) {
+    if (t->u.ac.postinit != NULL) {
         initbld = OSSL_PARAM_BLD_new();
         if (initbld == NULL)
             goto err;
-        if (!add_params(initbld, t->postinit, bnctx))
+        if (!add_params(initbld, t->u.ac.postinit, bnctx))
             goto err;
         initparams = OSSL_PARAM_BLD_to_param(initbld);
         if (initparams == NULL)
@@ -912,21 +870,21 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st
             goto err;
     }

-    if (t->encrypt) {
+    if (t->u.ac.encrypt) {
         if (EVP_PKEY_encrypt(encctx, out, &outlen,
-                t->in, t->in_len)
+                t->pt.buf, t->pt.len)
             <= 0)
             goto err;
     } else {
         if (EVP_PKEY_decrypt(encctx, out, &outlen,
-                t->in, t->in_len)
+                t->pt.buf, t->pt.len)
             <= 0)
             goto err;
     }
     /* Check the KAT */
     OSSL_SELF_TEST_oncorrupt_byte(st, out);
-    if (outlen != t->expected_len
-        || memcmp(out, t->expected, t->expected_len) != 0)
+    if (outlen != t->expected.len
+        || memcmp(out, t->expected.buf, t->expected.len) != 0)
         goto err;

     ret = 1;
@@ -970,7 +928,7 @@ static int self_test_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
     int i, ret = 1;

     for (i = 0; i < st_kat_cipher_tests_size; ++i) {
-        if (RUN_TEST(st_kat_cipher_tests[i].base))
+        if (RUN_TEST(st_kat_cipher_tests[i]))
             if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx))
                 ret = 0;
     }
@@ -1245,19 +1203,6 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx, int do_deferred)
         ret = 0;
     if (!self_test_ciphers(st, libctx, do_deferred))
         ret = 0;
-#ifndef OPENSSL_NO_LMS
-    /*
-     * FIPS 140-3 IG 10.3.A Note 5 mandates a CAST for LMS.
-     *
-     * It permits this to be omitted if HSS is also implemented and has
-     * the relevant self tests.  Once HSS is implemented, this test can be
-     * removed.  This IG permits the digest's CAST to be subsumed into this
-     * test, however, because this will be removed, the underlying digest
-     * test has been retained elsewhere lest it is accidentally omitted.
-     */
-    if (!self_test_LMS(st, libctx))
-        ret = 0;
-#endif /* OPENSSL_NO_LMS */
     if (!self_test_signatures(st, libctx, do_deferred))
         ret = 0;
     if (!self_test_kdfs(st, libctx, do_deferred))
@@ -1312,7 +1257,7 @@ int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,

     case FIPS_DEFERRED_KAT_CIPHER:
         for (i = 0; i < st_kat_cipher_tests_size; ++i) {
-            if (strcmp(st_kat_cipher_tests[i].base.algorithm, alg_name) == 0) {
+            if (strcmp(st_kat_cipher_tests[i].algorithm, alg_name) == 0) {
                 found = 1;
                 if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx)) {
                     ret = 0;
@@ -1323,21 +1268,9 @@ int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
         break;

     case FIPS_DEFERRED_KAT_SIGNATURE:
-
-#ifndef OPENSSL_NO_LMS
-        if (strcmp("LMS", alg_name) == 0) {
-            found = 1;
-            if (!self_test_LMS(st, libctx)) {
-                ret = 0;
-                goto done;
-            }
-            break;
-        }
-#endif /* OPENSSL_NO_LMS */
-
         for (i = 0; i < st_kat_sign_tests_size; ++i) {
-            if (strcmp(st_kat_sign_tests[i].sigalgorithm, alg_name) == 0
-                || strcmp(st_kat_sign_tests[i].keytype, alg_name) == 0) {
+            if (strcmp(st_kat_sign_tests[i].algorithm, alg_name) == 0
+                || strcmp(st_kat_sign_tests[i].u.sig.keytype, alg_name) == 0) {
                 found = 1;
                 if (!self_test_digest_sign(&st_kat_sign_tests[i], st, libctx)) {
                     ret = 0;