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 #include "nx_secure_tls.h"
26 #include "nx_secure_x509.h"
27 
28 /**************************************************************************/
29 /*                                                                        */
30 /*  FUNCTION                                               RELEASE        */
31 /*                                                                        */
32 /*    _nx_secure_tls_remote_certificate_verify            PORTABLE C      */
33 /*                                                           6.2.1        */
34 /*  AUTHOR                                                                */
35 /*                                                                        */
36 /*    Timothy Stapko, Microsoft Corporation                               */
37 /*                                                                        */
38 /*  DESCRIPTION                                                           */
39 /*                                                                        */
40 /*    This function verifies the authenticity of a certificate provided   */
41 /*    by the remote host by checking its digital signature against the    */
42 /*    trusted store, checking the certificate's validity period, and      */
43 /*    optionally checking the Common Name against the Top-Level Domain    */
44 /*    (TLD) name used to access the remote host.                          */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    tls_session                           TLS session                   */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    status                                Certificate validity status   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _nx_secure_x509_remote_endpoint_certificate_get                     */
57 /*                                          Get remote host certificate   */
58 /*    [nx_secure_remote_certificate_verify] Verify the remote certificate */
59 /*    [nx_secure_tls_session_certificate_callback]                        */
60 /*                                          Session certificate callback  */
61 /*    [nx_secure_tls_session_time_function] Session time callback         */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    _nx_secure_tls_process_remote_certificate                           */
66 /*                                          Process server certificate    */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
73 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*  04-02-2021     Timothy Stapko           Modified comment(s),          */
76 /*                                            updated X.509 return value, */
77 /*                                            resulting in version 6.1.6  */
78 /*  01-31-2022     Timothy Stapko           Modified comment(s), and      */
79 /*                                            improved code coverage      */
80 /*                                            results,                    */
81 /*                                            resulting in version 6.1.10 */
82 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
83 /*                                            checked expiration for all  */
84 /*                                            the certs in the chain,     */
85 /*                                            resulting in version 6.1.12 */
86 /*  10-31-2022     Yanwu Cai                Modified comment(s), added    */
87 /*                                            custom secret generation,   */
88 /*                                            resulting in version 6.2.0  */
89 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
90 /*                                            fixed compiler errors when  */
91 /*                                            x509 is disabled,           */
92 /*                                            resulting in version 6.2.1  */
93 /*                                                                        */
94 /**************************************************************************/
_nx_secure_tls_remote_certificate_verify(NX_SECURE_TLS_SESSION * tls_session)95 UINT _nx_secure_tls_remote_certificate_verify(NX_SECURE_TLS_SESSION *tls_session)
96 {
97 #ifndef NX_SECURE_DISABLE_X509
98 UINT                              status;
99 NX_SECURE_X509_CERT              *remote_certificate;
100 NX_SECURE_X509_CERTIFICATE_STORE *store;
101 ULONG                             current_time;
102 
103 
104     /* We need to find the remote certificate that represents the endpoint - the leaf in the PKI. */
105 
106     /* Process, following X509 basic certificate authentication (RFC 5280):
107      *    1. Last certificate in chain is the end entity - start with it.
108      *    2. Build chain from issuer to issuer - linked list of issuers. Find in stores: [ Remote, Trusted ]
109      *    3. Walk list from end certificate back to a root CA in the trusted store, verifying each signature.
110      *       Additionally, any policy enforcement should be done at each step.
111      */
112     store = &tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store;
113 
114     /* Extract the remote certificate processed earlier. */
115     status = _nx_secure_x509_remote_endpoint_certificate_get(store, &remote_certificate);
116 
117     if (status)
118     {
119         /* No certificate found, error! */
120         return(NX_SECURE_TLS_NO_CERT_SPACE_ALLOCATED);
121     }
122 
123     /* Assign the TLS Session metadata areas to the certificate for later use. */
124     remote_certificate -> nx_secure_x509_public_cipher_metadata_area = tls_session -> nx_secure_public_cipher_metadata_area;
125     remote_certificate -> nx_secure_x509_public_cipher_metadata_size = tls_session -> nx_secure_public_cipher_metadata_size;
126 
127     remote_certificate -> nx_secure_x509_hash_metadata_area = tls_session -> nx_secure_hash_mac_metadata_area;
128     remote_certificate -> nx_secure_x509_hash_metadata_size = tls_session -> nx_secure_hash_mac_metadata_size;
129 
130     /* See if we have a timestamp function to get the current time. */
131     current_time = 0;
132     if (tls_session -> nx_secure_tls_session_time_function != NX_NULL)
133     {
134         /* Get the current time from our callback. */
135         current_time = tls_session -> nx_secure_tls_session_time_function();
136     }
137 
138     /* Now verify our remote certificate chain. If the certificate can be linked to an issuer in the trusted store
139        through an issuer chain, this function will return NX_SUCCESS. */
140     status = tls_session -> nx_secure_remote_certificate_verify(store, remote_certificate, current_time);
141 
142     if (status != NX_SUCCESS)
143     {
144         return(status);
145     }
146 
147     /* Now, see if the application has defined a callback to check additional certificate information. */
148     if (tls_session -> nx_secure_tls_session_certificate_callback != NX_NULL)
149     {
150         /* Call the user-defined callback to allow the application to perform additional validation. */
151         status = tls_session -> nx_secure_tls_session_certificate_callback(tls_session, remote_certificate);
152     }
153 
154     /* If remote certificate verification was a success, we have received credentials
155        from the remote host and may now pass Finished message processing once received.
156        If this is a TLS Server, defer setting the remote credentials flag until after
157        we have received and processed the CertificateVerify message. */
158     if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT && status == NX_SUCCESS)
159     {
160         tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE;
161     }
162 
163     return(status);
164 #else
165     NX_PARAMETER_NOT_USED(tls_session);
166 
167     return(NX_NOT_SUPPORTED);
168 #endif
169 }
170 
171