Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2023-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 : : #if (LIBSPDM_ECDSA_SUPPORT) && (LIBSPDM_SHA2_SUPPORT)
14 : : /* Test vector (key, message, nonce and signature) from the NIST CAVP:
15 : : * ECDSA SigGen.txt, [P-256,SHA-256/SHA-384/SHA-512], first record.
16 : : * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/digital-signatures
17 : : * At least one of SHA-256/SHA-384/SHA-512 is required for the ECDSA FIPS self-test to run;
18 : : * the strongest one enabled at build time is used.
19 : : */
20 : : #if LIBSPDM_SHA512_SUPPORT
21 : : /*hardcode random for ecdsa*/
22 : 6 : static int libspdm_hardcode_random_number_ecdsa(void *rng_state, unsigned char *output, size_t len)
23 : : {
24 : : /*Random number*/
25 : 6 : const uint8_t random[] = {
26 : : 0x91, 0x06, 0x19, 0x21, 0x70, 0xcc, 0xb3, 0xc6,
27 : : 0x46, 0x84, 0xd4, 0x82, 0x87, 0xbb, 0x81, 0xbb,
28 : : 0xed, 0x51, 0xb4, 0x0d, 0x50, 0x34, 0x62, 0xc9,
29 : : 0x00, 0xe5, 0xc7, 0xaa, 0xe4, 0x3e, 0x38, 0x0a
30 : : };
31 : 6 : libspdm_copy_mem(output, len, random, sizeof(random));
32 : :
33 : 6 : return 0;
34 : : }
35 : : #elif LIBSPDM_SHA384_SUPPORT
36 : : /*hardcode random for ecdsa*/
37 : : static int libspdm_hardcode_random_number_ecdsa(void *rng_state, unsigned char *output, size_t len)
38 : : {
39 : : /*Random number*/
40 : : const uint8_t random[] = {
41 : : 0x99, 0x80, 0xb9, 0xcd, 0xfc, 0xef, 0x3a, 0xb8,
42 : : 0xe2, 0x19, 0xb9, 0x82, 0x7e, 0xd6, 0xaf, 0xdd,
43 : : 0x4d, 0xbf, 0x20, 0xbd, 0x92, 0x7e, 0x9c, 0xd0,
44 : : 0x1f, 0x15, 0x76, 0x27, 0x03, 0x48, 0x70, 0x07
45 : : };
46 : : libspdm_copy_mem(output, len, random, sizeof(random));
47 : :
48 : : return 0;
49 : : }
50 : : #elif LIBSPDM_SHA256_SUPPORT
51 : : /*hardcode random for ecdsa*/
52 : : static int libspdm_hardcode_random_number_ecdsa(void *rng_state, unsigned char *output, size_t len)
53 : : {
54 : : /*Random number*/
55 : : const uint8_t random[] = {
56 : : 0x94, 0xa1, 0xbb, 0xb1, 0x4b, 0x90, 0x6a, 0x61,
57 : : 0xa2, 0x80, 0xf2, 0x45, 0xf9, 0xe9, 0x3c, 0x7f,
58 : : 0x3b, 0x4a, 0x62, 0x47, 0x82, 0x4f, 0x5d, 0x33,
59 : : 0xb9, 0x67, 0x07, 0x87, 0x64, 0x2a, 0x68, 0xde
60 : : };
61 : : libspdm_copy_mem(output, len, random, sizeof(random));
62 : :
63 : : return 0;
64 : : }
65 : : #endif /* LIBSPDM_SHA512_SUPPORT */
66 : : #endif /* (LIBSPDM_ECDSA_SUPPORT) && (LIBSPDM_SHA2_SUPPORT) */
67 : :
68 : 8 : void libspdm_fips_selftest_ecdsa(void *fips_selftest_context)
69 : : {
70 : : #if (LIBSPDM_ECDSA_SUPPORT) && (LIBSPDM_SHA2_SUPPORT)
71 : 8 : bool result = true;
72 : :
73 : 8 : libspdm_fips_selftest_context_t *context = fips_selftest_context;
74 : 8 : LIBSPDM_ASSERT(fips_selftest_context != NULL);
75 : :
76 : : /* any test fail cause the FIPS fail*/
77 [ + + ]: 8 : if (context->tested_algo != context->self_test_result) {
78 : 4 : return;
79 : : }
80 : :
81 : : /* check if run before.*/
82 [ + + ]: 6 : if ((context->tested_algo & LIBSPDM_FIPS_SELF_TEST_ECDSA) != 0) {
83 : 2 : return;
84 : : }
85 : :
86 : : uint8_t signature[32 * 2];
87 : : size_t sig_size;
88 : : void *ec_context;
89 : : size_t hash_nid;
90 : :
91 : 4 : sig_size = sizeof(signature);
92 : 4 : libspdm_zero_mem(signature, sig_size);
93 : :
94 : : #if LIBSPDM_SHA512_SUPPORT
95 : 4 : hash_nid = LIBSPDM_CRYPTO_NID_SHA512;
96 : :
97 : : /* The message to sign. */
98 : 4 : const uint8_t message[] = {
99 : : 0x6c, 0x85, 0x72, 0xb6, 0xa3, 0xa4, 0xa9, 0xe8,
100 : : 0xe0, 0x3d, 0xbe, 0xed, 0x99, 0x33, 0x4d, 0x41,
101 : : 0x66, 0x1b, 0x8a, 0x84, 0x17, 0x07, 0x4f, 0x33,
102 : : 0x5a, 0xb1, 0x84, 0x5f, 0x6c, 0xc8, 0x52, 0xad,
103 : : 0xb8, 0xc0, 0x1d, 0x98, 0x20, 0xfc, 0xf8, 0xe1,
104 : : 0x06, 0x99, 0xcc, 0x82, 0x7a, 0x8f, 0xbd, 0xca,
105 : : 0x2c, 0xbd, 0x46, 0xcc, 0x66, 0xe4, 0xe6, 0xb7,
106 : : 0xba, 0x41, 0xec, 0x3e, 0xfa, 0x73, 0x35, 0x87,
107 : : 0xe4, 0xa3, 0x0e, 0xc5, 0x52, 0xcd, 0x8d, 0xda,
108 : : 0xb8, 0x16, 0x3e, 0x14, 0x8e, 0x50, 0xf4, 0xd0,
109 : : 0x90, 0x78, 0x28, 0x97, 0xf3, 0xdd, 0xac, 0x84,
110 : : 0xa4, 0x1e, 0x1f, 0xcf, 0xe8, 0xc5, 0x6b, 0x61,
111 : : 0x52, 0xc0, 0x09, 0x7b, 0x0d, 0x63, 0x4b, 0x41,
112 : : 0x01, 0x14, 0x71, 0xff, 0xd0, 0x04, 0xf4, 0x3e,
113 : : 0xb4, 0xaa, 0xfc, 0x03, 0x81, 0x97, 0xec, 0x6b,
114 : : 0xae, 0x2b, 0x44, 0x70, 0xe8, 0x69, 0xbd, 0xed
115 : : };
116 : :
117 : : /* Private Key */
118 : 4 : const uint8_t priv_key[] = {
119 : : 0x9d, 0xd0, 0xd3, 0xa3, 0xd5, 0x14, 0xc2, 0xa8,
120 : : 0xad, 0xb1, 0x62, 0xb8, 0x1e, 0x3a, 0xdf, 0xba,
121 : : 0x32, 0x99, 0x30, 0x9f, 0x7d, 0x20, 0x18, 0xf6,
122 : : 0x07, 0xbd, 0xb1, 0x5b, 0x1a, 0x25, 0xf4, 0x99
123 : : };
124 : :
125 : : /* Public Key */
126 : 4 : const uint8_t public_key[] = {
127 : : 0x6b, 0x73, 0x8d, 0xe3, 0x39, 0x8b, 0x6a, 0xc5,
128 : : 0x7b, 0x95, 0x91, 0xf9, 0xd7, 0x98, 0x5d, 0xd4,
129 : : 0xf3, 0x21, 0x37, 0xad, 0x34, 0x60, 0xdc, 0xf8,
130 : : 0x97, 0x0c, 0x13, 0x90, 0xcb, 0x9e, 0xaf, 0x8d,
131 : : 0x83, 0xbc, 0x61, 0xe2, 0x6d, 0x2b, 0xbb, 0xd3,
132 : : 0xcf, 0x2d, 0x2a, 0xb4, 0x45, 0xa2, 0xbc, 0x4a,
133 : : 0xb5, 0xdd, 0xe4, 0x1f, 0x4a, 0x13, 0x07, 0x8f,
134 : : 0xd1, 0xd3, 0xcc, 0x36, 0xab, 0x59, 0x6d, 0x57
135 : : };
136 : :
137 : : /* Expected signature*/
138 : 4 : const uint8_t expected_signature[] = {
139 : : 0x27, 0x5f, 0xa7, 0x60, 0x87, 0x8b, 0x4d, 0xc0,
140 : : 0x5e, 0x9d, 0x15, 0x7f, 0xed, 0xfd, 0x8e, 0x9b,
141 : : 0x1c, 0x9c, 0x86, 0x12, 0x22, 0xa7, 0x12, 0x74,
142 : : 0x8c, 0xb4, 0xb7, 0x75, 0x4c, 0x04, 0x3f, 0xb1,
143 : : 0x69, 0x9d, 0x90, 0x6b, 0xb8, 0x43, 0x5a, 0x05,
144 : : 0x34, 0x5a, 0xf3, 0xb3, 0x7e, 0x3b, 0x35, 0x77,
145 : : 0x86, 0x93, 0x9e, 0x94, 0xca, 0xae, 0x25, 0x78,
146 : : 0x52, 0xf0, 0x50, 0x3a, 0xdb, 0x1e, 0x0f, 0x7e
147 : : };
148 : : #elif LIBSPDM_SHA384_SUPPORT
149 : : hash_nid = LIBSPDM_CRYPTO_NID_SHA384;
150 : :
151 : : /* The message to sign. */
152 : : const uint8_t message[] = {
153 : : 0xe0, 0xb8, 0x59, 0x6b, 0x37, 0x5f, 0x33, 0x06,
154 : : 0xbb, 0xc6, 0xe7, 0x7a, 0x0b, 0x42, 0xf7, 0x46,
155 : : 0x9d, 0x7e, 0x83, 0x63, 0x59, 0x90, 0xe7, 0x4a,
156 : : 0xa6, 0xd7, 0x13, 0x59, 0x4a, 0x3a, 0x24, 0x49,
157 : : 0x8f, 0xef, 0xf5, 0x00, 0x67, 0x90, 0x74, 0x2d,
158 : : 0x9c, 0x2e, 0x9b, 0x47, 0xd7, 0x14, 0xbe, 0xe9,
159 : : 0x32, 0x43, 0x5d, 0xb7, 0x47, 0xc6, 0xe7, 0x33,
160 : : 0xe3, 0xd8, 0xde, 0x41, 0xf2, 0xf9, 0x13, 0x11,
161 : : 0xf2, 0xe9, 0xfd, 0x8e, 0x02, 0x56, 0x51, 0x63,
162 : : 0x1f, 0xfd, 0x84, 0xf6, 0x67, 0x32, 0xd3, 0x47,
163 : : 0x3f, 0xbd, 0x16, 0x27, 0xe6, 0x3d, 0xc7, 0x19,
164 : : 0x40, 0x48, 0xeb, 0xec, 0x93, 0xc9, 0x5c, 0x15,
165 : : 0x9b, 0x50, 0x39, 0xab, 0x5e, 0x79, 0xe4, 0x2c,
166 : : 0x80, 0xb4, 0x84, 0xa9, 0x43, 0xf1, 0x25, 0xde,
167 : : 0x3d, 0xa1, 0xe0, 0x4e, 0x5b, 0xf9, 0xc1, 0x66,
168 : : 0x71, 0xad, 0x55, 0xa1, 0x11, 0x7d, 0x33, 0x06
169 : : };
170 : :
171 : : /* Private Key */
172 : : const uint8_t priv_key[] = {
173 : : 0xb6, 0xfa, 0xf2, 0xc8, 0x92, 0x22, 0x35, 0xc5,
174 : : 0x89, 0xc2, 0x73, 0x68, 0xa3, 0xb3, 0xe6, 0xe2,
175 : : 0xf4, 0x2e, 0xb6, 0x07, 0x3b, 0xf9, 0x50, 0x7f,
176 : : 0x19, 0xee, 0xd0, 0x74, 0x6c, 0x79, 0xdc, 0xed
177 : : };
178 : :
179 : : /* Public Key */
180 : : const uint8_t public_key[] = {
181 : : 0xe0, 0xe7, 0xb9, 0x9b, 0xc6, 0x2d, 0x8d, 0xd6,
182 : : 0x78, 0x83, 0xe3, 0x9e, 0xd9, 0xfa, 0x06, 0x57,
183 : : 0x78, 0x9c, 0x5f, 0xf5, 0x56, 0xcc, 0x1f, 0xd8,
184 : : 0xdd, 0x1e, 0x2a, 0x55, 0xe9, 0xe3, 0xf2, 0x43,
185 : : 0x63, 0xfb, 0xfd, 0x02, 0x32, 0xb9, 0x55, 0x78,
186 : : 0x07, 0x5c, 0x90, 0x3a, 0x4d, 0xbf, 0x85, 0xad,
187 : : 0x58, 0xf8, 0x35, 0x05, 0x16, 0xe1, 0xec, 0x89,
188 : : 0xb0, 0xee, 0x1f, 0x5e, 0x13, 0x62, 0xda, 0x69
189 : : };
190 : :
191 : : /* Expected signature*/
192 : : const uint8_t expected_signature[] = {
193 : : 0xf5, 0x08, 0x78, 0x78, 0xe2, 0x12, 0xb7, 0x03,
194 : : 0x57, 0x8f, 0x5c, 0x66, 0xf4, 0x34, 0x88, 0x3f,
195 : : 0x3e, 0xf4, 0x14, 0xdc, 0x23, 0xe2, 0xe8, 0xd8,
196 : : 0xab, 0x6a, 0x8d, 0x15, 0x9e, 0xd5, 0xad, 0x83,
197 : : 0x30, 0x6b, 0x4c, 0x6c, 0x20, 0x21, 0x37, 0x07,
198 : : 0x98, 0x2d, 0xff, 0xbb, 0x30, 0xfb, 0xa9, 0x9b,
199 : : 0x96, 0xe7, 0x92, 0x16, 0x3d, 0xd5, 0x9d, 0xbe,
200 : : 0x60, 0x6e, 0x73, 0x43, 0x28, 0xdd, 0x7c, 0x8a
201 : : };
202 : : #elif LIBSPDM_SHA256_SUPPORT
203 : : hash_nid = LIBSPDM_CRYPTO_NID_SHA256;
204 : :
205 : : /* The message to sign. */
206 : : const uint8_t message[] = {
207 : : 0x59, 0x05, 0x23, 0x88, 0x77, 0xc7, 0x74, 0x21,
208 : : 0xf7, 0x3e, 0x43, 0xee, 0x3d, 0xa6, 0xf2, 0xd9,
209 : : 0xe2, 0xcc, 0xad, 0x5f, 0xc9, 0x42, 0xdc, 0xec,
210 : : 0x0c, 0xbd, 0x25, 0x48, 0x29, 0x35, 0xfa, 0xaf,
211 : : 0x41, 0x69, 0x83, 0xfe, 0x16, 0x5b, 0x1a, 0x04,
212 : : 0x5e, 0xe2, 0xbc, 0xd2, 0xe6, 0xdc, 0xa3, 0xbd,
213 : : 0xf4, 0x6c, 0x43, 0x10, 0xa7, 0x46, 0x1f, 0x9a,
214 : : 0x37, 0x96, 0x0c, 0xa6, 0x72, 0xd3, 0xfe, 0xb5,
215 : : 0x47, 0x3e, 0x25, 0x36, 0x05, 0xfb, 0x1d, 0xdf,
216 : : 0xd2, 0x80, 0x65, 0xb5, 0x3c, 0xb5, 0x85, 0x8a,
217 : : 0x8a, 0xd2, 0x81, 0x75, 0xbf, 0x9b, 0xd3, 0x86,
218 : : 0xa5, 0xe4, 0x71, 0xea, 0x7a, 0x65, 0xc1, 0x7c,
219 : : 0xc9, 0x34, 0xa9, 0xd7, 0x91, 0xe9, 0x14, 0x91,
220 : : 0xeb, 0x37, 0x54, 0xd0, 0x37, 0x99, 0x79, 0x0f,
221 : : 0xe2, 0xd3, 0x08, 0xd1, 0x61, 0x46, 0xd5, 0xc9,
222 : : 0xb0, 0xd0, 0xde, 0xbd, 0x97, 0xd7, 0x9c, 0xe8
223 : : };
224 : :
225 : : /* Private Key */
226 : : const uint8_t priv_key[] = {
227 : : 0x51, 0x9b, 0x42, 0x3d, 0x71, 0x5f, 0x8b, 0x58,
228 : : 0x1f, 0x4f, 0xa8, 0xee, 0x59, 0xf4, 0x77, 0x1a,
229 : : 0x5b, 0x44, 0xc8, 0x13, 0x0b, 0x4e, 0x3e, 0xac,
230 : : 0xca, 0x54, 0xa5, 0x6d, 0xda, 0x72, 0xb4, 0x64
231 : : };
232 : :
233 : : /* Public Key */
234 : : const uint8_t public_key[] = {
235 : : 0x1c, 0xcb, 0xe9, 0x1c, 0x07, 0x5f, 0xc7, 0xf4,
236 : : 0xf0, 0x33, 0xbf, 0xa2, 0x48, 0xdb, 0x8f, 0xcc,
237 : : 0xd3, 0x56, 0x5d, 0xe9, 0x4b, 0xbf, 0xb1, 0x2f,
238 : : 0x3c, 0x59, 0xff, 0x46, 0xc2, 0x71, 0xbf, 0x83,
239 : : 0xce, 0x40, 0x14, 0xc6, 0x88, 0x11, 0xf9, 0xa2,
240 : : 0x1a, 0x1f, 0xdb, 0x2c, 0x0e, 0x61, 0x13, 0xe0,
241 : : 0x6d, 0xb7, 0xca, 0x93, 0xb7, 0x40, 0x4e, 0x78,
242 : : 0xdc, 0x7c, 0xcd, 0x5c, 0xa8, 0x9a, 0x4c, 0xa9
243 : : };
244 : :
245 : : /* Expected signature*/
246 : : const uint8_t expected_signature[] = {
247 : : 0xf3, 0xac, 0x80, 0x61, 0xb5, 0x14, 0x79, 0x5b,
248 : : 0x88, 0x43, 0xe3, 0xd6, 0x62, 0x95, 0x27, 0xed,
249 : : 0x2a, 0xfd, 0x6b, 0x1f, 0x6a, 0x55, 0x5a, 0x7a,
250 : : 0xca, 0xbb, 0x5e, 0x6f, 0x79, 0xc8, 0xc2, 0xac,
251 : : 0x8b, 0xf7, 0x78, 0x19, 0xca, 0x05, 0xa6, 0xb2,
252 : : 0x78, 0x6c, 0x76, 0x26, 0x2b, 0xf7, 0x37, 0x1c,
253 : : 0xef, 0x97, 0xb2, 0x18, 0xe9, 0x6f, 0x17, 0x5a,
254 : : 0x3c, 0xcd, 0xda, 0x2a, 0xcc, 0x05, 0x89, 0x03
255 : : };
256 : : #endif
257 : :
258 : 4 : ec_context = libspdm_ec_new_by_nid(LIBSPDM_CRYPTO_NID_ECDSA_NIST_P256);
259 [ - + ]: 4 : if (ec_context == NULL) {
260 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ec_context new failed \n"));
261 : 0 : result = false;
262 : 0 : goto update;
263 : : }
264 : :
265 : 4 : result = libspdm_ec_set_pub_key(ec_context, public_key, sizeof(public_key));
266 [ - + ]: 4 : if (!result) {
267 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ec_context set pub_key failed \n"));
268 : 0 : libspdm_ec_free(ec_context);
269 : 0 : result = false;
270 : 0 : goto update;
271 : : }
272 : :
273 : 4 : result = libspdm_ec_set_priv_key(ec_context, priv_key, sizeof(priv_key));
274 [ - + ]: 4 : if (!result) {
275 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ec_context set priv_key failed \n"));
276 : 0 : libspdm_ec_free(ec_context);
277 : 0 : result = false;
278 : 0 : goto update;
279 : : }
280 : :
281 : : /*ECDSA KAT test*/
282 : 4 : result = libspdm_ecdsa_sign_fips(ec_context, hash_nid,
283 : : message, sizeof(message),
284 : : signature, &sig_size,
285 : : libspdm_hardcode_random_number_ecdsa);
286 [ - + ]: 4 : if (!result) {
287 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ECDSA sign failed \n"));
288 : 0 : libspdm_ec_free(ec_context);
289 : 0 : result = false;
290 : 0 : goto update;
291 : : }
292 : :
293 [ - + ]: 4 : if (sig_size != sizeof(expected_signature)) {
294 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ECDSA KAT failed \n"));
295 : 0 : libspdm_ec_free(ec_context);
296 : 0 : result = false;
297 : 0 : goto update;
298 : : }
299 : :
300 [ - + ]: 4 : if (!libspdm_consttime_is_mem_equal(signature, expected_signature,
301 : : sizeof(expected_signature))) {
302 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ECDSA KAT failed \n"));
303 : 0 : libspdm_ec_free(ec_context);
304 : 0 : result = false;
305 : 0 : goto update;
306 : : }
307 : :
308 : 4 : result = libspdm_ecdsa_verify_fips(ec_context, hash_nid,
309 : : message, sizeof(message),
310 : : signature, sig_size);
311 [ - + ]: 4 : if (!result) {
312 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ECDSA selftest failed \n"));
313 : 0 : libspdm_ec_free(ec_context);
314 : 0 : result = false;
315 : 0 : goto update;
316 : : }
317 : :
318 : 4 : libspdm_ec_free(ec_context);
319 : :
320 : 4 : update:
321 : : /* mark it as tested*/
322 : 4 : context->tested_algo |= LIBSPDM_FIPS_SELF_TEST_ECDSA;
323 : :
324 : : /* record test result*/
325 [ + - ]: 4 : if (result) {
326 : 4 : context->self_test_result |= LIBSPDM_FIPS_SELF_TEST_ECDSA;
327 : : } else {
328 : 0 : context->self_test_result &= ~LIBSPDM_FIPS_SELF_TEST_ECDSA;
329 : : }
330 : :
331 : : #endif/*(LIBSPDM_ECDSA_SUPPORT) && (LIBSPDM_SHA2_SUPPORT)*/
332 : : }
333 : :
334 : : #endif/*LIBSPDM_FIPS_MODE*/
|