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 
25 #include "nx_secure_tls.h"
26 #include "nx_secure_x509.h"
27 #ifdef NX_SECURE_ENABLE_DTLS
28 #include "nx_secure_dtls.h"
29 #endif /* NX_SECURE_ENABLE_DTLS */
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _nx_secure_tls_send_certificate_request             PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Timothy Stapko, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function populates an NX_PACKET with a CertificateRequest      */
44 /*    message which is used to indicate to the remote client that we wish */
45 /*    to do a Client certificate verification. The Client should respond  */
46 /*    with an appropriate certificate and CertificateVerify message.      */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    tls_session                           TLS control block             */
51 /*    send_packet                           Packet to be filled           */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    status                                Completion status             */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    None                                                                */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    _nx_secure_tls_server_handshake       TLS server state machine      */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
70 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
71 /*                                            resulting in version 6.1    */
72 /*                                                                        */
73 /**************************************************************************/
_nx_secure_tls_send_certificate_request(NX_SECURE_TLS_SESSION * tls_session,NX_PACKET * send_packet)74 UINT _nx_secure_tls_send_certificate_request(NX_SECURE_TLS_SESSION *tls_session,
75                                              NX_PACKET *send_packet)
76 {
77 UINT   length;
78 UCHAR *packet_buffer;
79 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
80 UINT   ext_len_pos = 0;
81 UINT   sighash_len = 0;
82 UINT   i;
83 UINT   sign_alg;
84 #endif
85 
86     /* Structure:
87      * |       1            |    <Cert types count>    |             2              |  <Sig algs length>        |
88      * |  Cert types count  | Cert types (1 byte each) | Sig Hash algorithms length | Algorithms (2 bytes each) |
89      */
90 
91     if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < 11u)
92     {
93 
94         /* Packet buffer is too small. */
95         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
96     }
97 
98     packet_buffer = send_packet -> nx_packet_append_ptr;
99 
100     /* Use our length as an index into the buffer. */
101     length = 0;
102 
103 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
104 
105     if (tls_session -> nx_secure_tls_1_3)
106     {
107 
108         /* Put context here.  */
109         packet_buffer[length] = 0;
110         length++;
111 
112         /* Skip the extensions length.  */
113         ext_len_pos = length;
114         length += 2;
115 
116         /* Add signature_algorithms extension.  */
117         packet_buffer[length] = (UCHAR)(NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS >> 8);
118         packet_buffer[length + 1] = (UCHAR)(NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS);
119         length += 2;
120 
121         /* Skip signature_algorithm length.  */
122         length += 2;
123     }
124     else
125 #endif
126     {
127 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
128         if (tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count != 0)
129         {
130             /* If ECC is initialized, we support RSA and ECDSA signatures. */
131             packet_buffer[length] = 0x2;
132             length += 1;
133 
134             packet_buffer[length] = NX_SECURE_TLS_CERT_TYPE_RSA_SIGN;
135             length += 1;
136 
137             packet_buffer[length] = NX_SECURE_TLS_CERT_TYPE_ECDSA_SIGN;
138             length += 1;
139         }
140         else
141 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
142         {
143 
144             /* ECC is not initialized, we only support RSA signatures for now... */
145             packet_buffer[length] = 0x1;
146             length += 1;
147 
148             packet_buffer[length] = NX_SECURE_TLS_CERT_TYPE_RSA_SIGN;
149             length += 1;
150         }
151     }
152 
153 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
154     /* TLS 1.2 CertificateRequest contains a list of signature algorithms that
155        is not included in earlier TLS versions. */
156 #ifdef NX_SECURE_ENABLE_DTLS
157     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
158         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
159 #else
160     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
161 #endif /* NX_SECURE_ENABLE_DTLS */
162     {
163 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
164         if (tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count != 0)
165         {
166 
167 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
168             if (tls_session -> nx_secure_tls_1_3)
169             {
170                 /* Skip length field.  */
171                 length = length + 2;
172 
173                 /* Add supported signature algorithms.  */
174                 for (i = 0; i < tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count; i++)
175                 {
176                     switch (tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups[i])
177                     {
178                     case (NX_CRYPTO_EC_SECP256R1 & 0x00FF):
179                         sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256;
180                         break;
181                     case (NX_CRYPTO_EC_SECP384R1 & 0x00FF):
182                         sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA384;
183                         break;
184                     case (NX_CRYPTO_EC_SECP521R1 & 0x00FF):
185                         sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512;
186                         break;
187                     default:
188                         continue;
189                     }
190 
191                     if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < (length + 2u))
192                     {
193 
194                         /* Packet buffer is too small. */
195                         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
196                     }
197 
198                     packet_buffer[length] = (UCHAR)(sign_alg >> 8);
199                     packet_buffer[length + 1] = (UCHAR)(sign_alg);
200                     length = length + 2;
201                     sighash_len = sighash_len + 2;
202                 }
203             }
204             else
205 #endif
206             {
207 
208                 /* ECC is initialized. */
209                 /* Length of supported signature algorithms - each entry is 2 bytes so length
210                    is number of entries * 2. */
211                 packet_buffer[length] = (UCHAR)0x0;
212                 packet_buffer[length + 1] = (UCHAR)0x4;
213                 length = length + 2;
214 
215                 /* Extract the signature algorithms. */
216                 packet_buffer[length] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_RSA_SHA256 >> 8);
217                 packet_buffer[length + 1] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_RSA_SHA256);
218                 length = length + 2;
219 
220                 packet_buffer[length] =     (UCHAR)(NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256 >> 8);
221                 packet_buffer[length + 1] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256);
222                 length = length + 2;
223             }
224         }
225         else
226 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
227         {
228             /* Length of supported signature algorithms - each entry is 2 bytes so length
229                is number of entries * 2. */
230             /* Note: We only support 1 one signature algorithm for now... */
231             packet_buffer[length]  = (UCHAR)0x0;
232             packet_buffer[length + 1] = (UCHAR)0x2;
233             length = length + 2;
234 
235             /* Extract the signature algorithms. */
236             packet_buffer[length] =     (UCHAR)(NX_SECURE_TLS_SIGNATURE_RSA_SHA256 >> 8);
237             packet_buffer[length + 1] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_RSA_SHA256);
238             length = length + 2;
239         }
240 
241     }
242 #endif
243 
244 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
245     if (tls_session -> nx_secure_tls_1_3)
246     {
247 
248         /* Set extensions length and signature algorithm length.  */
249         packet_buffer[ext_len_pos] = (UCHAR)((sighash_len + 6) >> 8);
250         packet_buffer[ext_len_pos + 1] = (UCHAR)(sighash_len + 6);
251         packet_buffer[ext_len_pos + 4] = (UCHAR)((sighash_len + 2) >> 8);
252         packet_buffer[ext_len_pos + 5] = (UCHAR)(sighash_len + 2);
253         packet_buffer[ext_len_pos + 6] = (UCHAR)(sighash_len >> 8);
254         packet_buffer[ext_len_pos + 7] = (UCHAR)(sighash_len);
255     }
256     else
257 #endif
258     {
259 
260         /* Distinguished names length - right now we do not support this. */
261         packet_buffer[length] = (UCHAR)0x0;
262         packet_buffer[length + 1] = (UCHAR)0x0;
263         length = length + 2;
264     }
265 
266     /* The remainder of the message is the Certificate Authorities list. It can be used
267        to select a certificate in a particular authorization chain.  */
268 
269     /* Let the caller know how many bytes we wrote. */
270     send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + (length);
271     send_packet -> nx_packet_length = send_packet -> nx_packet_length + (length);
272 
273     return(NX_SUCCESS);
274 }
275 
276