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