Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions include/hal/library/cryptlib/cryptlib_mldsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,32 @@ extern bool libspdm_mldsa_sign(void *dsa_context,
const uint8_t *message, size_t message_size,
uint8_t *signature, size_t *sig_size);

#if LIBSPDM_FIPS_MODE
/**
* Carries out the MLDSA signature generation. This API can be used for FIPS test.
*
* @param[in] dsa_context Pointer to DSA context for signature generation.
* @param[in] context The MLDSA signing context.
* @param[in] context_size Size of MLDSA signing context.
* @param[in] message Pointer to octet message to be signed.
* @param[in] message_size Size of the message in bytes.
* @param[out] signature Pointer to buffer to receive DSA signature.
* @param[in, out] sig_size On input, the size of signature buffer in bytes.
* On output, the size of data returned in signature buffer in bytes.
* @param[in] deterministic If true, then generate the signature in deterministic way.
*
* @retval true signature successfully generated.
* @retval false signature generation failed.
* @retval false sig_size is too small.
* @retval false This interface is not supported.
**/
extern bool libspdm_mldsa_sign_ex(void *dsa_context,
const uint8_t *context, size_t context_size,
const uint8_t *message, size_t message_size,
uint8_t *signature, size_t *sig_size,
bool deterministic);
#endif /* LIBSPDM_FIPS_MODE */

/**
* Verifies the MLDSA signature.
*
Expand Down
6 changes: 6 additions & 0 deletions include/internal/libspdm_fips_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define LIBSPDM_FIPS_SELF_TEST_EDDSA 0x00008000
#define LIBSPDM_FIPS_SELF_TEST_RSA_PSS 0x00010000
#define LIBSPDM_FIPS_SELF_TEST_ML_KEM 0x00020000
#define LIBSPDM_FIPS_SELF_TEST_ML_DSA 0x00040000

#if LIBSPDM_SLH_DSA_SUPPORT
#define LIBSPDM_FIPS_REQUIRED_BUFFER_SIZE 7856 /* SLH_DSA_SHA2_128S_SIG_SIZE */
Expand Down Expand Up @@ -119,4 +120,9 @@ bool libspdm_fips_selftest_eddsa(void *fips_selftest_context);
**/
bool libspdm_fips_selftest_mlkem(void *fips_selftest_context);

/**
* ML-DSA self_test
**/
bool libspdm_fips_selftest_mldsa(void *fips_selftest_context);

#endif/*LIBSPDM_FIPS_MODE*/
2 changes: 2 additions & 0 deletions library/spdm_crypt_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ target_sources(spdm_crypt_lib
fips/libspdm_selftest_eddsa.c
fips/libspdm_selftest_mlkem.c
fips/libspdm_selftest_mlkem_vec.c
fips/libspdm_selftest_mldsa.c
fips/libspdm_selftest_mldsa_vec.c
)
2 changes: 2 additions & 0 deletions library/spdm_crypt_lib/fips/libspdm_selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ bool libspdm_fips_run_selftest(void *fips_selftest_context)

libspdm_fips_selftest_mlkem(context);

libspdm_fips_selftest_mldsa(context);

return (context->tested_algo == context->self_test_result);
}

Expand Down
131 changes: 131 additions & 0 deletions library/spdm_crypt_lib/fips/libspdm_selftest_mldsa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Copyright Notice:
* Copyright 2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

#include "internal/libspdm_crypt_lib.h"
#include "internal/libspdm_common_lib.h"
#include "internal/libspdm_fips_lib.h"

#if LIBSPDM_FIPS_MODE

/**
* mldsa self_test
**/
bool libspdm_fips_selftest_mldsa(void *fips_selftest_context)
{
bool result = true;

#if LIBSPDM_ML_DSA_SUPPORT
libspdm_fips_selftest_context_t *context = fips_selftest_context;
LIBSPDM_ASSERT(fips_selftest_context != NULL);

/* any test fail cause the FIPS fail*/
if (context->tested_algo != context->self_test_result) {
return false;
}

/* check if run before.*/
if ((context->tested_algo & LIBSPDM_FIPS_SELF_TEST_ML_DSA) != 0) {
return true;
}

uint8_t *signature;
size_t sig_size;
void *dsa_context;

sig_size = 4627;
LIBSPDM_ASSERT(context->selftest_buffer_size >= sig_size);
LIBSPDM_ASSERT(context->selftest_buffer != NULL);
libspdm_zero_mem(context->selftest_buffer, context->selftest_buffer_size);
signature = context->selftest_buffer;

/* KAT Vectors */
extern const uint8_t message_hash_mldsa_87[94];
extern const uint8_t priv_key_mldsa_87[4896];
extern const uint8_t public_key_mldsa_87[2592];
extern const uint8_t sign_context_mldsa_87[208];
extern const uint8_t expected_signature_mldsa_87[4627];

dsa_context = libspdm_mldsa_new(LIBSPDM_CRYPTO_NID_ML_DSA_87);
if (dsa_context == NULL) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "dsa_context new failed \n"));
result = false;
goto update;
}

result = libspdm_mldsa_set_pubkey(dsa_context, public_key_mldsa_87, sizeof(public_key_mldsa_87));
if (!result) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "dsa_context set public_key failed \n"));
libspdm_mldsa_free(dsa_context);
result = false;
goto update;
}

result = libspdm_mldsa_set_privkey(dsa_context, priv_key_mldsa_87, sizeof(priv_key_mldsa_87));
if (!result) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "dsa_context set priv_key failed \n"));
libspdm_mldsa_free(dsa_context);
result = false;
goto update;
}

/*mldsa KAT test*/
result = libspdm_mldsa_sign_ex(dsa_context,
sign_context_mldsa_87, sizeof(sign_context_mldsa_87),
message_hash_mldsa_87, sizeof(message_hash_mldsa_87),
signature, &sig_size,
true);
if (!result) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-DSA-87 sign failed \n"));
libspdm_mldsa_free(dsa_context);
result = false;
goto update;
}

if (sig_size != sizeof(expected_signature_mldsa_87)) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-DSA-87 KAT failed \n"));
libspdm_mldsa_free(dsa_context);
result = false;
goto update;
}

if (!libspdm_consttime_is_mem_equal(signature, expected_signature_mldsa_87,
sizeof(expected_signature_mldsa_87))) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-DSA-87 KAT failed \n"));
libspdm_mldsa_free(dsa_context);
result = false;
goto update;
}

result = libspdm_mldsa_verify(dsa_context,
sign_context_mldsa_87, sizeof(sign_context_mldsa_87),
message_hash_mldsa_87, sizeof(message_hash_mldsa_87),
signature, sig_size);
if (!result) {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-DSA-87 selftest failed \n"));
libspdm_mldsa_free(dsa_context);
result = false;
goto update;
}

libspdm_mldsa_free(dsa_context);

update:
/* mark it as tested*/
context->tested_algo |= LIBSPDM_FIPS_SELF_TEST_ML_DSA;

/* record test result*/
if (result) {
context->self_test_result |= LIBSPDM_FIPS_SELF_TEST_ML_DSA;
} else {
context->self_test_result &= ~LIBSPDM_FIPS_SELF_TEST_ML_DSA;
}

#endif/*LIBSPDM_ML_DSA_SUPPORT*/

return result;
}

#endif/*LIBSPDM_FIPS_MODE*/
Loading