Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2025-2026 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : #include "internal/libspdm_crypt_lib.h"
8 : #include "internal/libspdm_common_lib.h"
9 : #include "internal/libspdm_fips_lib.h"
10 :
11 : #if LIBSPDM_FIPS_MODE
12 :
13 1 : bool libspdm_fips_selftest_mlkem(void *fips_selftest_context)
14 : {
15 1 : bool result = true;
16 :
17 : #if LIBSPDM_ML_KEM_SUPPORT
18 : libspdm_fips_selftest_context_t *context = fips_selftest_context;
19 : LIBSPDM_ASSERT(fips_selftest_context != NULL);
20 :
21 : /* any test fail cause the FIPS fail*/
22 : if (context->tested_algo != context->self_test_result) {
23 : return false;
24 : }
25 :
26 : /* check if run before.*/
27 : if ((context->tested_algo & LIBSPDM_FIPS_SELF_TEST_ML_KEM) != 0) {
28 : return true;
29 : }
30 :
31 : void *kem_context;
32 : uint8_t shared_secret[32];
33 : size_t shared_secret_size;
34 : uint8_t *cipher_text;
35 : size_t cipher_text_size;
36 :
37 : shared_secret_size = sizeof(shared_secret);
38 : libspdm_zero_mem(shared_secret, shared_secret_size);
39 :
40 : cipher_text_size = 1568;
41 : LIBSPDM_ASSERT(context->selftest_buffer_size >= cipher_text_size);
42 : LIBSPDM_ASSERT(context->selftest_buffer != NULL);
43 : libspdm_zero_mem(context->selftest_buffer, context->selftest_buffer_size);
44 : cipher_text = context->selftest_buffer;
45 :
46 : extern uint8_t peer_encap_key_mlkem_1024[1568];
47 : extern uint8_t decap_key_mlkem_1024[3168];
48 : extern uint8_t expected_cipher_text_mlkem_1024[1568];
49 : extern uint8_t expected_shared_secret_mlkem_1024[32];
50 : extern uint8_t random_value_mlkem_1024[32];
51 :
52 : kem_context = libspdm_mlkem_new_by_name(LIBSPDM_CRYPTO_NID_ML_KEM_1024);
53 : if (kem_context == NULL) {
54 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM new failed \n"));
55 : result = false;
56 : goto update;
57 : }
58 :
59 : result = libspdm_mlkem_encapsulate_ex(kem_context, peer_encap_key_mlkem_1024,
60 : sizeof(peer_encap_key_mlkem_1024),
61 : cipher_text, &cipher_text_size,
62 : shared_secret, &shared_secret_size,
63 : random_value_mlkem_1024, sizeof(random_value_mlkem_1024));
64 : if (!result) {
65 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM encapsulate failed \n"));
66 : libspdm_mlkem_free(kem_context);
67 : result = false;
68 : goto update;
69 : }
70 :
71 : /*KAT test*/
72 : if (cipher_text_size != sizeof(expected_cipher_text_mlkem_1024)) {
73 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM KAT failed \n"));
74 : libspdm_mlkem_free(kem_context);
75 : result = false;
76 : goto update;
77 : }
78 :
79 : if (!libspdm_consttime_is_mem_equal(cipher_text, expected_cipher_text_mlkem_1024,
80 : sizeof(expected_cipher_text_mlkem_1024))) {
81 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM KAT failed \n"));
82 : libspdm_mlkem_free(kem_context);
83 : result = false;
84 : goto update;
85 : }
86 :
87 : if (shared_secret_size != sizeof(expected_shared_secret_mlkem_1024)) {
88 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM KAT failed \n"));
89 : libspdm_mlkem_free(kem_context);
90 : result = false;
91 : goto update;
92 : }
93 :
94 : if (!libspdm_consttime_is_mem_equal(shared_secret, expected_shared_secret_mlkem_1024,
95 : sizeof(expected_shared_secret_mlkem_1024))) {
96 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM KAT failed \n"));
97 : libspdm_mlkem_free(kem_context);
98 : result = false;
99 : goto update;
100 : }
101 :
102 : result = libspdm_mlkem_set_privkey(kem_context, decap_key_mlkem_1024, sizeof(decap_key_mlkem_1024));
103 : if (!result) {
104 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM set private key failed \n"));
105 : libspdm_mlkem_free(kem_context);
106 : result = false;
107 : goto update;
108 : }
109 :
110 : result = libspdm_mlkem_decapsulate(kem_context, cipher_text, cipher_text_size,
111 : shared_secret, &shared_secret_size);
112 : if (!result) {
113 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM decapsulate failed \n"));
114 : libspdm_mlkem_free(kem_context);
115 : result = false;
116 : goto update;
117 : }
118 :
119 : if (shared_secret_size != sizeof(expected_shared_secret_mlkem_1024)) {
120 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM KAT failed \n"));
121 : libspdm_mlkem_free(kem_context);
122 : result = false;
123 : goto update;
124 : }
125 :
126 : if (!libspdm_consttime_is_mem_equal(shared_secret, expected_shared_secret_mlkem_1024,
127 : sizeof(expected_shared_secret_mlkem_1024))) {
128 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ML-KEM KAT failed \n"));
129 : libspdm_mlkem_free(kem_context);
130 : result = false;
131 : goto update;
132 : }
133 :
134 : update:
135 : /* mark it as tested*/
136 : context->tested_algo |= LIBSPDM_FIPS_SELF_TEST_ML_KEM;
137 :
138 : /* record test result*/
139 : if (result) {
140 : context->self_test_result |= LIBSPDM_FIPS_SELF_TEST_ML_KEM;
141 : } else {
142 : context->self_test_result &= ~LIBSPDM_FIPS_SELF_TEST_ML_KEM;
143 : }
144 :
145 : #endif/*LIBSPDM_ML_KEM_SUPPORT*/
146 :
147 1 : return result;
148 : }
149 :
150 : #endif/*LIBSPDM_FIPS_MODE*/
|