1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Crypto Component */
16 /** */
17 /** Crypto Self Test */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_CRYPTO_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26 #include "nx_crypto_method_self_test.h"
27 #include "nx_crypto_ecdsa.h"
28
29 #ifdef NX_CRYPTO_SELF_TEST
30
31 extern NX_CRYPTO_METHOD crypto_method_ec_secp256;
32 extern NX_CRYPTO_METHOD crypto_method_sha256;
33
34 static UCHAR msg_p256_sha256[] = {
35 0xdb, 0x34, 0x4a, 0x78, 0x9b, 0x77, 0xde, 0x2e, 0x52, 0x75, 0xa9, 0xaf, 0x0e, 0xe6, 0x47, 0xff,
36 0x87, 0x86, 0x6f, 0x3b, 0x66, 0xdd, 0x89, 0x1e, 0x55, 0x80, 0x18, 0xed, 0xec, 0x70, 0x3b, 0xde,
37 0x9f, 0x7b, 0x4a, 0xc6, 0xc2, 0xc3, 0xe9, 0xdc, 0x14, 0x8e, 0x8b, 0xb8, 0x97, 0x4a, 0x21, 0x1f,
38 0x76, 0x8e, 0x43, 0xa9, 0x29, 0x86, 0xc1, 0x6f, 0x8f, 0xc3, 0x5a, 0xe9, 0xca, 0x9c, 0x14, 0x61,
39 0xb6, 0x8d, 0xab, 0x06, 0x1e, 0x97, 0x93, 0x55, 0xf8, 0x82, 0x8e, 0xeb, 0xfc, 0xd5, 0xa3, 0x62,
40 0xf7, 0x10, 0x87, 0xb4, 0x30, 0xd3, 0x5e, 0xd4, 0x70, 0xf8, 0xaa, 0x5c, 0x12, 0xbd, 0xde, 0xef,
41 0x83, 0xb9, 0xc3, 0x24, 0x48, 0x7c, 0x3b, 0x6d, 0x07, 0x51, 0xd9, 0xca, 0x7e, 0x9f, 0xb8, 0x1e,
42 0xda, 0x17, 0xea, 0xa6, 0xf9, 0x39, 0xeb, 0x42, 0x5f, 0xf3, 0x48, 0x96, 0xb6, 0xad, 0xa9, 0x75,
43 };
44
45 /* Output. */
46 static UCHAR output[400];
47 static UCHAR scratch_buffer[4000];
48
49 /**************************************************************************/
50 /* */
51 /* FUNCTION RELEASE */
52 /* */
53 /* nx_crypto_method_self_test_ecdsa PORTABLE C */
54 /* 6.1.7 */
55 /* AUTHOR */
56 /* */
57 /* Timothy Stapko, Microsoft Corporation */
58 /* */
59 /* DESCRIPTION */
60 /* */
61 /* This function performs the Known Answer Test for ECDSA crypto */
62 /* method. */
63 /* */
64 /* INPUT */
65 /* */
66 /* method_ptr Pointer to the crypto method */
67 /* to be tested. */
68 /* */
69 /* OUTPUT */
70 /* */
71 /* status Completion status */
72 /* */
73 /* CALLS */
74 /* */
75 /* None */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* Application Code */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
86 /* 09-30-2020 Timothy Stapko Modified comment(s), */
87 /* resulting in version 6.1 */
88 /* 06-02-2021 Bhupendra Naphade Modified comment(s), */
89 /* renamed FIPS symbol to */
90 /* self-test, */
91 /* resulting in version 6.1.7 */
92 /* */
93 /**************************************************************************/
_nx_crypto_method_self_test_ecdsa(NX_CRYPTO_METHOD * crypto_method_ecdsa,VOID * metadata,UINT metadata_size)94 NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_ecdsa(NX_CRYPTO_METHOD *crypto_method_ecdsa,
95 VOID *metadata, UINT metadata_size)
96 {
97 UINT status;
98 VOID *handler = NX_CRYPTO_NULL;
99 NX_CRYPTO_HUGE_NUMBER private_key;
100 NX_CRYPTO_EC_POINT public_key;
101 UCHAR *privkey;
102 UCHAR *pubkey;
103 UINT pubkey_length;
104 NX_CRYPTO_METHOD *curve_method;
105 NX_CRYPTO_METHOD *hash_method;
106 UINT buffer_size;
107 UINT curve_size;
108 HN_UBASE *scratch;
109 NX_CRYPTO_EC *curve = NX_CRYPTO_NULL;
110 UCHAR *msg;
111 UINT msg_length;
112 ULONG sig_length;
113 NX_CRYPTO_EXTENDED_OUTPUT extended_output;
114
115
116 /* Validate the crypto method */
117 if(crypto_method_ecdsa == NX_CRYPTO_NULL)
118 return(NX_CRYPTO_PTR_ERROR);
119
120 /* Set the test data. */
121 curve_method = &crypto_method_ec_secp256;
122 hash_method = &crypto_method_sha256;
123 msg = msg_p256_sha256;
124 msg_length = sizeof(msg_p256_sha256);
125
126 /* Clear the output buffer. */
127 NX_CRYPTO_MEMSET(output, 0, sizeof(output));
128
129 /* Call the crypto initialization function. */
130 if (crypto_method_ecdsa -> nx_crypto_init)
131 {
132 status = crypto_method_ecdsa -> nx_crypto_init(crypto_method_ecdsa,
133 NX_CRYPTO_NULL,
134 0,
135 &handler,
136 metadata,
137 metadata_size);
138
139 if(status != NX_CRYPTO_SUCCESS)
140 {
141 return(status);
142 }
143 }
144
145 if (crypto_method_ecdsa -> nx_crypto_operation == NX_CRYPTO_NULL)
146 {
147 return(NX_CRYPTO_PTR_ERROR);
148 }
149
150 /* Set hash method. */
151 status = crypto_method_ecdsa -> nx_crypto_operation(NX_CRYPTO_HASH_METHOD_SET,
152 handler,
153 crypto_method_ecdsa,
154 NX_CRYPTO_NULL,
155 0,
156 (UCHAR *)hash_method,
157 sizeof(NX_CRYPTO_METHOD *),
158 NX_CRYPTO_NULL,
159 NX_CRYPTO_NULL,
160 0,
161 metadata,
162 metadata_size,
163 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
164
165 /* Check the status. */
166 if(status != NX_CRYPTO_SUCCESS)
167 {
168 return(status);
169 }
170
171 /* Set EC curve. */
172 status = crypto_method_ecdsa -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET,
173 handler,
174 crypto_method_ecdsa,
175 NX_CRYPTO_NULL,
176 0,
177 (UCHAR *)curve_method,
178 sizeof(NX_CRYPTO_METHOD *),
179 NX_CRYPTO_NULL,
180 NX_CRYPTO_NULL,
181 0,
182 metadata,
183 metadata_size,
184 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
185
186 /* Check the status. */
187 if(status != NX_CRYPTO_SUCCESS)
188 {
189 return(status);
190 }
191
192 /* Get EC curve. */
193 status = curve_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET,
194 NX_CRYPTO_NULL,
195 curve_method,
196 NX_CRYPTO_NULL,
197 0,
198 NX_CRYPTO_NULL,
199 0,
200 NX_CRYPTO_NULL,
201 (UCHAR *)&curve,
202 0,
203 NX_CRYPTO_NULL,
204 0,
205 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
206
207 /* Check the status. */
208 if(status != NX_CRYPTO_SUCCESS)
209 {
210 return(status);
211 }
212
213 buffer_size = curve -> nx_crypto_ec_n.nx_crypto_huge_buffer_size;
214 curve_size = curve -> nx_crypto_ec_bits >> 3;
215 if (curve -> nx_crypto_ec_bits & 7)
216 {
217 curve_size++;
218 }
219
220 scratch = (HN_UBASE*)(&scratch_buffer[3 * buffer_size + 4]);
221 privkey = scratch_buffer;
222 pubkey = &scratch_buffer[buffer_size];
223 NX_CRYPTO_EC_POINT_INITIALIZE(&public_key, NX_CRYPTO_EC_POINT_AFFINE, scratch, buffer_size);
224 NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&private_key, scratch, buffer_size + 8);
225
226 /* Generate the key pair. */
227 status = _nx_crypto_ec_key_pair_generation_extra(curve, &curve -> nx_crypto_ec_g, &private_key,
228 &public_key, scratch);
229
230 if (status)
231 {
232 return(status);
233 }
234
235
236 status = _nx_crypto_huge_number_extract_fixed_size(&private_key, privkey, buffer_size);
237 if (status)
238 {
239 return(status);
240 }
241
242 pubkey_length = 0;
243 _nx_crypto_ec_point_extract_uncompressed(curve, &public_key, pubkey, 4 + 2 * buffer_size, &pubkey_length);
244
245
246 extended_output.nx_crypto_extended_output_data = output;
247 extended_output.nx_crypto_extended_output_length_in_byte = sizeof(output);
248 /* Sign the hash data using ECDSA. */
249 status = crypto_method_ecdsa -> nx_crypto_operation(NX_CRYPTO_SIGNATURE_GENERATE,
250 handler,
251 crypto_method_ecdsa,
252 privkey,
253 buffer_size << 3,
254 msg,
255 msg_length,
256 NX_CRYPTO_NULL,
257 (UCHAR *)&extended_output,
258 sizeof(extended_output),
259 metadata,
260 metadata_size,
261 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
262
263 /* Check the status. */
264 if(status != NX_CRYPTO_SUCCESS)
265 {
266 return(status);
267 }
268 sig_length = extended_output.nx_crypto_extended_output_actual_size;
269
270 /* Verify the signature. */
271 status = crypto_method_ecdsa -> nx_crypto_operation(NX_CRYPTO_SIGNATURE_VERIFY,
272 handler,
273 crypto_method_ecdsa,
274 pubkey,
275 pubkey_length << 3,
276 msg,
277 msg_length,
278 NX_CRYPTO_NULL,
279 output,
280 sig_length,
281 metadata,
282 metadata_size,
283 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
284
285 /* Check the status. */
286 if(status != NX_CRYPTO_SUCCESS)
287 {
288 return(status);
289 }
290
291 if (crypto_method_ecdsa -> nx_crypto_cleanup)
292 {
293 status = crypto_method_ecdsa -> nx_crypto_cleanup(metadata);
294 }
295
296 return(status);
297 }
298 #endif
299