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 Secure Component */
16 /** */
17 /** Transport Layer Security (TLS) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_secure_crypto_table_self_test.h"
28
29
30 #ifdef NX_SECURE_POWER_ON_SELF_TEST_MODULE_INTEGRITY_CHECK
31
32 static const NX_SECURE_CRYPTO_SELF_TEST nx_crypto_self_test_map[] =
33 {
34 {NX_CRYPTO_ENCRYPTION_AES_CBC, _nx_secure_crypto_method_self_test_aes},
35 {NX_CRYPTO_ENCRYPTION_AES_CTR, _nx_secure_crypto_method_self_test_aes},
36 {NX_CRYPTO_ENCRYPTION_AES_GCM_16, _nx_secure_crypto_method_self_test_aes},
37 {NX_CRYPTO_ENCRYPTION_DES_CBC, _nx_secure_crypto_method_self_test_des},
38 {NX_CRYPTO_ENCRYPTION_3DES_CBC, _nx_secure_crypto_method_self_test_3des},
39 {NX_CRYPTO_HASH_SHA1, _nx_secure_crypto_method_self_test_sha},
40 {NX_CRYPTO_HASH_SHA256, _nx_secure_crypto_method_self_test_sha},
41 {NX_CRYPTO_HASH_SHA384, _nx_secure_crypto_method_self_test_sha},
42 {NX_CRYPTO_HASH_SHA512, _nx_secure_crypto_method_self_test_sha},
43 {NX_CRYPTO_HASH_MD5, _nx_secure_crypto_method_self_test_md5},
44 {NX_CRYPTO_KEY_EXCHANGE_RSA, _nx_secure_crypto_method_self_test_rsa},
45 {NX_CRYPTO_AUTHENTICATION_HMAC_SHA1_96, _nx_secure_crypto_method_self_test_hmac_sha},
46 {NX_CRYPTO_AUTHENTICATION_HMAC_SHA1_160, _nx_secure_crypto_method_self_test_hmac_sha},
47 {NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256, _nx_secure_crypto_method_self_test_hmac_sha},
48 {NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_384, _nx_secure_crypto_method_self_test_hmac_sha},
49 {NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_512, _nx_secure_crypto_method_self_test_hmac_sha},
50 {NX_CRYPTO_AUTHENTICATION_HMAC_MD5_96, _nx_secure_crypto_method_self_test_hmac_md5},
51 {NX_CRYPTO_AUTHENTICATION_HMAC_MD5_128, _nx_secure_crypto_method_self_test_hmac_md5},
52 {NX_CRYPTO_PRF_HMAC_SHA1, _nx_secure_crypto_method_self_test_prf},
53 {NX_CRYPTO_PRF_HMAC_SHA2_256, _nx_secure_crypto_method_self_test_prf},
54 };
55
56 /* Define an array to avoid duplicate self testing for identical crypto method. */
57 static const NX_CRYPTO_METHOD *nx_crypto_self_test_methods[sizeof(nx_crypto_self_test_map) / sizeof(NX_SECURE_CRYPTO_SELF_TEST)];
58
59 UINT _nx_secure_crypto_method_self_test(const NX_CRYPTO_METHOD *crypto_method,
60 VOID *metadata, UINT metadata_size);
61
62 #endif
63
64 /**************************************************************************/
65 /* */
66 /* FUNCTION RELEASE */
67 /* */
68 /* _nx_secure_crypto_table_self_test PORTABLE C */
69 /* 6.1 */
70 /* AUTHOR */
71 /* */
72 /* Timothy Stapko, Microsoft Corporation */
73 /* */
74 /* DESCRIPTION */
75 /* */
76 /* This function runs through the TLS crypto table self test. */
77 /* The self test is in the form of Known Answer Test. */
78 /* NetX Secure provides a number of vectors that can be used to test */
79 /* crypto methods supported by NetX Secure. */
80 /* */
81 /* INPUT */
82 /* */
83 /* crypto_table Pointer to the crypto method */
84 /* table to be tested */
85 /* metadata_buffer Crypto metadata area */
86 /* metadata_size crypto metadata size */
87 /* */
88 /* OUTPUT */
89 /* */
90 /* status Completion status */
91 /* */
92 /* CALLS */
93 /* */
94 /* None */
95 /* */
96 /* CALLED BY */
97 /* */
98 /* Application Code */
99 /* */
100 /* RELEASE HISTORY */
101 /* */
102 /* DATE NAME DESCRIPTION */
103 /* */
104 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
105 /* 09-30-2020 Timothy Stapko Modified comment(s), */
106 /* resulting in version 6.1 */
107 /* */
108 /**************************************************************************/
_nx_secure_crypto_table_self_test(const NX_SECURE_TLS_CRYPTO * crypto_table,VOID * metadata,UINT metadata_size)109 UINT _nx_secure_crypto_table_self_test(const NX_SECURE_TLS_CRYPTO *crypto_table,
110 VOID *metadata, UINT metadata_size)
111 {
112 #ifdef NX_SECURE_POWER_ON_SELF_TEST_MODULE_INTEGRITY_CHECK
113 UINT i;
114 UINT crypto_table_size;
115 NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite;
116 #ifndef NX_SECURE_DISABLE_X509
117 NX_SECURE_X509_CRYPTO *x509_crypto;
118 #endif
119 UINT status = NX_SECURE_TLS_SUCCESS;
120
121 /* Validate the crypto method */
122 if(crypto_table == NX_NULL)
123 return(NX_PTR_ERROR);
124
125 /* Initialize the crypto method list that is tested. */
126 NX_CRYPTO_MEMSET(nx_crypto_self_test_methods, 0, sizeof(nx_crypto_self_test_methods));
127
128 /* Go through our internal Known Answer Test table, and run through the matching
129 test. */
130 /* For now we shall be able to test the following algorithms, based on the value in
131 nx_crypto_algorithm:
132 NX_CRYPTO_KEY_EXCHANGE_RSA (1024/2048/4096 bit key)
133 NX_CRYPTO_ENCRYPTION_DES_CBC
134 NX_CRYPTO_ENCRYPTION_3DES_CBC
135 NX_CRYPTO_ENCRYPTION_AES_CBC (check key_size field)
136 NX_CRYPTO_ENCRYPTION_AES_CTR
137 NX_CRYPTO_HASH_SHA1
138 NX_CRYPTO_HASH_SHA256
139 NX_CRYPTO_HASH_SHA384
140 NX_CRYPTO_HASH_SHA512
141 NX_CRYPTO_HASH_MD5
142 NX_CRYPTO_AUTHENTICATION_HMAC_SHA1_96
143 NX_CRYPTO_AUTHENTICATION_HMAC_SHA1_160
144 NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256
145 NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_384
146 NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_512
147 NX_CRYPTO_AUTHENTICATION_HMAC_MD5_96
148 NX_CRYPTO_AUTHENTICATION_HMAC_MD5_128
149 NX_CRYPTO_PRF_HMAC_SHA1
150 NX_CRYPTO_PRF_HMAC_SHA2_256
151 */
152
153 crypto_table_size = crypto_table -> nx_secure_tls_ciphersuite_lookup_table_size;
154
155 /* Loop through cipher table and perform self tests. */
156 for (i = 0; i < crypto_table_size; ++i)
157 {
158 ciphersuite = &crypto_table -> nx_secure_tls_ciphersuite_lookup_table[i];
159 status = _nx_secure_crypto_method_self_test(ciphersuite -> nx_secure_tls_public_cipher, metadata, metadata_size);
160 if (status)
161 {
162 return(status);
163 }
164
165 status = _nx_secure_crypto_method_self_test(ciphersuite -> nx_secure_tls_public_auth, metadata, metadata_size);
166 if (status)
167 {
168 return(status);
169 }
170
171 status = _nx_secure_crypto_method_self_test(ciphersuite -> nx_secure_tls_session_cipher, metadata, metadata_size);
172 if (status)
173 {
174 return(status);
175 }
176
177 status = _nx_secure_crypto_method_self_test(ciphersuite -> nx_secure_tls_hash, metadata, metadata_size);
178 if (status)
179 {
180 return(status);
181 }
182
183 status = _nx_secure_crypto_method_self_test(ciphersuite -> nx_secure_tls_prf, metadata, metadata_size);
184 if (status)
185 {
186 return(status);
187 }
188
189 }
190
191 #ifndef NX_SECURE_DISABLE_X509
192 crypto_table_size = crypto_table -> nx_secure_tls_x509_cipher_table_size;
193
194 /* Loop through X.509 crypto table and perform self tests. */
195 for (i = 0; i < crypto_table_size; ++i)
196 {
197 x509_crypto = &crypto_table -> nx_secure_tls_x509_cipher_table[i];
198
199 status = _nx_secure_crypto_method_self_test(x509_crypto -> nx_secure_x509_public_cipher_method, metadata, metadata_size);
200 if (status)
201 {
202 return(status);
203 }
204
205 status = _nx_secure_crypto_method_self_test(x509_crypto -> nx_secure_x509_hash_method, metadata, metadata_size);
206 if (status)
207 {
208 return(status);
209 }
210
211 }
212 #endif
213
214
215 /* We will also need to maintain the testing information. If a crypto method has been
216 tested, we don't want to test it again. This happens when the same algorithm apeears
217 multiple times in the lookup table.
218 */
219
220
221 return(NX_CRYPTO_SUCCESS);
222 #else
223 NX_PARAMETER_NOT_USED(crypto_table);
224 NX_PARAMETER_NOT_USED(metadata);
225 NX_PARAMETER_NOT_USED(metadata_size);
226 return(NX_CRYPTO_SUCCESS);
227 #endif
228 }
229 #ifdef NX_SECURE_POWER_ON_SELF_TEST_MODULE_INTEGRITY_CHECK
230
_nx_secure_crypto_method_self_test(const NX_CRYPTO_METHOD * crypto_method,VOID * metadata,UINT metadata_size)231 UINT _nx_secure_crypto_method_self_test(const NX_CRYPTO_METHOD *crypto_method,
232 VOID *metadata, UINT metadata_size)
233 {
234 UINT i;
235 UINT crypto_algorithm;
236 UINT status;
237
238 /* Validate the crypto method */
239 if(crypto_method == NX_NULL)
240 return(NX_PTR_ERROR);
241
242 crypto_algorithm = crypto_method -> nx_crypto_algorithm;
243
244 /* No necessary to verify NULL or None algorithms. */
245 if ((crypto_algorithm == NX_CRYPTO_ENCRYPTION_NULL) ||
246 (crypto_algorithm == NX_CRYPTO_NONE) ||
247 (crypto_algorithm == NX_CRYPTO_AUTHENTICATION_NONE) ||
248 (crypto_algorithm == NX_CRYPTO_HASH_NONE) ||
249 (crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_NONE))
250 return(NX_CRYPTO_SUCCESS);
251
252 /* Loop through the self test map and find the self test function for the crypto method. */
253 for (i = 0; i < sizeof(nx_crypto_self_test_map) / sizeof(NX_SECURE_CRYPTO_SELF_TEST); ++i)
254 {
255 if (crypto_algorithm == nx_crypto_self_test_map[i].nx_crypto_algorithm)
256 {
257 if (crypto_method != nx_crypto_self_test_methods[i])
258 {
259 /* Cast away const since self-test functions take non-const methods (but shouldn't!). */
260 status = nx_crypto_self_test_map[i].self_test_function((NX_CRYPTO_METHOD*)crypto_method, metadata, metadata_size);
261 nx_crypto_self_test_methods[i] = crypto_method;
262 return(status);
263 }
264 else
265 {
266
267 /* Duplicate crypto method. */
268 return(NX_SECURE_TLS_SUCCESS);
269 }
270 }
271 }
272
273 /* Unknown crypto method. */
274 return(NX_NOT_SUCCESSFUL);
275 }
276 #endif
277