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