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