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 
27 /**************************************************************************/
28 /*                                                                        */
29 /*  FUNCTION                                               RELEASE        */
30 /*                                                                        */
31 /*    _nx_secure_tls_send_certificate                     PORTABLE C      */
32 /*                                                           6.3.0        */
33 /*  AUTHOR                                                                */
34 /*                                                                        */
35 /*    Timothy Stapko, Microsoft Corporation                               */
36 /*                                                                        */
37 /*  DESCRIPTION                                                           */
38 /*                                                                        */
39 /*    This function populates an NX_PACKET with the TLS Certificate       */
40 /*    message, which contains the identity certificate for this device.   */
41 /*                                                                        */
42 /*  INPUT                                                                 */
43 /*                                                                        */
44 /*    tls_session                           TLS control block             */
45 /*    send_packet                           Packet to be filled           */
46 /*    wait_option                           Controls timeout actions      */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    status                                Completion status             */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    _nx_secure_x509_distinguished_name_compare                          */
55 /*                                          Compare distinguished name    */
56 /*    _nx_secure_x509_local_device_certificate_get                        */
57 /*                                          Get local certificate to send */
58 /*    nx_packet_data_append                 Append data to packet         */
59 /*    tx_mutex_get                          Get protection mutex          */
60 /*    tx_mutex_put                          Put protection mutex          */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _nx_secure_dtls_client_handshake      DTLS client state machine     */
65 /*    _nx_secure_dtls_server_handshake      DTLS server state machine     */
66 /*    _nx_secure_tls_client_handshake       TLS client state machine      */
67 /*    _nx_secure_tls_server_handshake       TLS server state machine      */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
74 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
75 /*                                            resulting in version 6.1    */
76 /*  04-02-2021     Timothy Stapko           Modified comment(s),          */
77 /*                                            updated X.509 return value, */
78 /*                                            resulting in version 6.1.6  */
79 /*  04-25-2022     Zhen Kong                Modified comment(s), removed  */
80 /*                                            unreachable error code,     */
81 /*                                            resulting in version 6.1.11 */
82 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
83 /*                                            fixed compiler errors when  */
84 /*                                            x509 is disabled,           */
85 /*                                            resulting in version 6.2.1  */
86 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
87 /*                                            fixed packet buffer overrun,*/
88 /*                                            resulting in version 6.3.0  */
89 /*                                                                        */
90 /**************************************************************************/
_nx_secure_tls_send_certificate(NX_SECURE_TLS_SESSION * tls_session,NX_PACKET * send_packet,ULONG wait_option)91 UINT _nx_secure_tls_send_certificate(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet,
92                                      ULONG wait_option)
93 {
94 #ifndef NX_SECURE_DISABLE_X509
95 UINT                 length;
96 UINT                 total_length;
97 UCHAR                length_buffer[3];
98 UINT                 status = NX_SECURE_TLS_SUCCESS;
99 NX_SECURE_X509_CERT *cert;
100 INT                  compare_result = 0;
101 UCHAR               *record_start;
102 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
103 USHORT               extensions_length;
104 #endif
105 
106 
107     /* Structure:
108      * |      3       |                     <Total Length>                      |
109      * | Total length |       3        |   <Cert[0] Length> | 3 + <Cert[x] Len> |
110      * |              | Cert[0] Length |   Certificate[0]   |    More certs...  |
111      */
112 
113     /* TLS 1.3 Structure:
114      * |    1    | <Ctx Len> |      3       |                     <Total Length>                         |
115      * | Ctx Len | Context   | Total length |       3        |   <Cert[x] Length> |   2    |   <ExtLen>  |
116      * |                                    | Cert[x] Length |   Certificate[x]   | ExtLen |  Extensions |
117      */
118 
119     /* See if the local certificate has been overridden. If so, use that instead. */
120     if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate != NX_NULL)
121     {
122         cert = tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate;
123     }
124     else
125     {
126         /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
127         status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store,
128                                                               NX_NULL, &cert);
129     }
130 
131 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
132     /* See if this is a TLS client sending a certificate in response to a certificate request from
133        the remote server. */
134     if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT &&
135         (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND))
136     {
137         /* If this is a TLS client, as per the RFC we can have no certificate assigned in which
138            case our response to the server that has requested our certificate will contain
139            an empty certificate field. */
140         cert = NX_NULL;
141 
142         /* Clear the requested flag so no further certificate-specific messages are sent. */
143         tls_session -> nx_secure_tls_client_certificate_requested = NX_FALSE;
144     }
145     else
146 #endif
147     {
148         if (status)
149         {
150 
151             /* _nx_secure_x509_local_device_certificate_get can only return
152                 NX_SECURE_X509_CERTIFICATE_NOT_FOUND in this case. */
153             return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
154         }
155     }
156 
157     if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < 3u)
158     {
159 
160         /* Packet buffer is too small to hold random and ID. */
161         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
162     }
163 
164 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
165     /* In TLS 1.3, the context length is the first field, followed by the context itself (if necessary). */
166     if(tls_session->nx_secure_tls_1_3)
167     {
168         send_packet -> nx_packet_append_ptr[0] = 0;
169         send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + 1;
170         send_packet -> nx_packet_length = send_packet -> nx_packet_length + (USHORT)(1);
171     }
172 #endif
173 
174     /* Save a reference to the start of our record. */
175     record_start = send_packet -> nx_packet_append_ptr;
176 
177     /* Pointer to where we are going to place the next certificate. */
178     /* The first 3 bytes hold the total length field.  Therefore
179        certificate data starts from offset 3.*/
180     send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + 3;
181     send_packet -> nx_packet_length = send_packet -> nx_packet_length + (USHORT)(3);
182 
183     /* Total length is the length of all certificates and is the first 3 bytes of the message. */
184     total_length = 0;
185 
186     while (status == NX_SUCCESS)
187     {
188         /* Place certificate data into the packet buffer with the appropriate length.
189            NOTE: We need to use the RAW data of the certificate when sending, not the parsed certificate! */
190         length = cert -> nx_secure_x509_certificate_raw_data_length;
191 
192         /* Total length is increased by the length of the certificate plus the 3 bytes for
193            the certificate length parameter. */
194         total_length += (length + 3);
195 
196         /* Put the length of this certificate into the buffer. */
197         length_buffer[0] = (UCHAR)((length & 0xFF0000) >> 16);
198         length_buffer[1] = (UCHAR)((length & 0xFF00) >> 8);
199         length_buffer[2] = (UCHAR)(length & 0xFF);
200 
201         /* Release the protection before suspending on nx_packet_data_append. */
202         tx_mutex_put(&_nx_secure_tls_protection);
203 
204         /* Put the length into the buffer. */
205         status = nx_packet_data_append(send_packet, length_buffer, 3,
206                                        tls_session -> nx_secure_tls_packet_pool, wait_option);
207 
208         /* Get the protection after nx_packet_data_append. */
209         tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
210 
211         if (status != NX_SUCCESS)
212         {
213             return(status);
214         }
215 
216         /* Release the protection before suspending on nx_packet_data_append. */
217         tx_mutex_put(&_nx_secure_tls_protection);
218 
219         /* Put the certificate data into the buffer. */
220         status = nx_packet_data_append(send_packet, cert -> nx_secure_x509_certificate_raw_data, length,
221                                        tls_session -> nx_secure_tls_packet_pool, wait_option);
222 
223         /* Get the protection after nx_packet_data_append. */
224         tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
225 
226 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
227         /* Check for TLS 1.3 extensions following each certificate. */
228         if (tls_session -> nx_secure_tls_1_3)
229         {
230             extensions_length = 0;
231             NX_CHANGE_USHORT_ENDIAN(extensions_length);
232 
233             /* Add extension length to packet. */
234             status = nx_packet_data_append(send_packet, &extensions_length,
235                                            sizeof(extensions_length),
236                                            tls_session -> nx_secure_tls_packet_pool,
237                                            wait_option);
238             if (status != NX_SUCCESS)
239             {
240                 return(status);
241             }
242 
243             total_length += 2;
244         }
245 #endif
246 
247 
248         if (status != NX_SUCCESS)
249         {
250             return(status);
251         }
252 
253         /* Get certificate issuer - if it exists in the store, send it, otherwise we are done. */
254         status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store,
255                                                               &cert -> nx_secure_x509_issuer, &cert);
256 
257         /* If certificate was not found, don't try to dereference. */
258         if (status == NX_SUCCESS)
259         {
260             /* Prevent infinite loop if certificate is self-signed. */
261             compare_result = _nx_secure_x509_distinguished_name_compare(&cert -> nx_secure_x509_distinguished_name,
262                                                                         &cert -> nx_secure_x509_issuer, NX_SECURE_X509_NAME_ALL_FIELDS);
263             if (compare_result == 0)
264             {
265                 break;
266             }
267         }
268 
269         /* If an issuer certificate was not found, that is OK - this should actually be the common case
270          * as any certificate that is not self-signed should not have its root CA certificate on the
271          * same device.
272          */
273     }
274 
275     /* Put the total length of all certificates into the buffer. */
276     record_start[0] = (UCHAR)((total_length & 0xFF0000) >> 16);
277     record_start[1] = (UCHAR)((total_length & 0xFF00) >> 8);
278     record_start[2] = (UCHAR)(total_length & 0xFF);
279 
280     return(NX_SUCCESS);
281 #else
282     NX_PARAMETER_NOT_USED(tls_session);
283     NX_PARAMETER_NOT_USED(send_packet);
284     NX_PARAMETER_NOT_USED(wait_option);
285 
286     return(NX_NOT_SUPPORTED);
287 #endif
288 }
289