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