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