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 
26 /**************************************************************************/
27 /*                                                                        */
28 /*  FUNCTION                                               RELEASE        */
29 /*                                                                        */
30 /*    _nx_secure_tls_send_newsessionticket                PORTABLE C      */
31 /*                                                           6.1          */
32 /*  AUTHOR                                                                */
33 /*                                                                        */
34 /*    Timothy Stapko, Microsoft Corporation                               */
35 /*                                                                        */
36 /*  DESCRIPTION                                                           */
37 /*                                                                        */
38 /*    This function generates a NewSessionTicket message for a TLS Server.*/
39 /*    The message contains data used to generate a PSK that can be used   */
40 /*    for session resumption should the same client attempt another       */
41 /*    connection within the lifespan of the ticket.                       */
42 /*                                                                        */
43 /*  INPUT                                                                 */
44 /*                                                                        */
45 /*    tls_session                           TLS control block             */
46 /*    send_packet                           Packet used to send message   */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    status                                Completion status             */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    NX_RAND                               Generate ticket data          */
55 /*                                                                        */
56 /*  CALLED BY                                                             */
57 /*                                                                        */
58 /*    _nx_secure_tls_server_handshake       TLS server state machine      */
59 /*                                                                        */
60 /*  RELEASE HISTORY                                                       */
61 /*                                                                        */
62 /*    DATE              NAME                      DESCRIPTION             */
63 /*                                                                        */
64 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
65 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
66 /*                                            verified memcpy use cases,  */
67 /*                                            resulting in version 6.1    */
68 /*                                                                        */
69 /**************************************************************************/
70 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
_nx_secure_tls_send_newsessionticket(NX_SECURE_TLS_SESSION * tls_session,NX_PACKET * send_packet)71 UINT _nx_secure_tls_send_newsessionticket(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet)
72 {
73 UINT             status = NX_SUCCESS;
74 UINT             length;
75 UINT             lifetime;
76 UINT             age_add;
77 UINT             nonce;
78 UINT             nonce_len;
79 UINT             ticket_len;
80 UCHAR            *ticket;
81 UINT             extensions_len;
82 UCHAR            *packet_buffer;
83 
84     /* From RFC 8446:
85        struct {
86           uint32 ticket_lifetime;
87           uint32 ticket_age_add;
88           opaque ticket_nonce<0..255>;
89           opaque ticket<1..2^16-1>;
90           Extension extensions<0..2^16-2>;
91        } NewSessionTicket;
92 
93        |    4     |    4    |     1     | <nonce_len> |     2      | <ticket_len> |       2        | <extensions_len> |
94        | lifetime | age add | nonce_len |    nonce    | ticket_len |    ticket    | extensions_len |    extensions    |
95 
96        ticket_lifetime:  Indicates the lifetime in seconds as a 32-bit
97           unsigned integer in network byte order from the time of ticket
98           issuance.  Servers MUST NOT use any value greater than
99           604800 seconds (7 days).  The value of zero indicates that the
100           ticket should be discarded immediately.  Clients MUST NOT cache
101           tickets for longer than 7 days, regardless of the ticket_lifetime,
102           and MAY delete tickets earlier based on local policy.  A server
103           MAY treat a ticket as valid for a shorter period of time than what
104           is stated in the ticket_lifetime.
105 
106        ticket_age_add:  A securely generated, random 32-bit value that is
107           used to obscure the age of the ticket that the client includes in
108           the "pre_shared_key" extension.  The client-side ticket age is
109           added to this value modulo 2^32 to obtain the value that is
110           transmitted by the client.  The server MUST generate a fresh value
111           for each ticket it sends.
112 
113        ticket_nonce:  A per-ticket value that is unique across all tickets
114           issued on this connection.
115 
116        ticket:  The value of the ticket to be used as the PSK identity.  The
117           ticket itself is an opaque label.  It MAY be either a database
118           lookup key or a self-encrypted and self-authenticated value.
119 
120        extensions:  A set of extension values for the ticket.  The
121           "Extension" format is defined in Section 4.2.  Clients MUST ignore
122           unrecognized extensions.
123 
124        The sole extension currently defined for NewSessionTicket is
125        "early_data", indicating that the ticket may be used to send 0-RTT
126        data (Section 4.2.10).  It contains the following value:
127 
128        max_early_data_size:  The maximum amount of 0-RTT data that the
129           client is allowed to send when using this ticket, in bytes.  Only
130           Application Data payload (i.e., plaintext but not padding or the
131           inner content type byte) is counted.  A server receiving more than
132           max_early_data_size bytes of 0-RTT data SHOULD terminate the
133           connection with an "unexpected_message" alert.  Note that servers
134           that reject early data due to lack of cryptographic material will
135           be unable to differentiate padding from content, so clients
136           SHOULD NOT depend on being able to send large quantities of
137           padding in early data records.
138 
139        The PSK associated with the ticket is computed as:
140 
141            HKDF-Expand-Label(resumption_master_secret,
142                             "resumption", ticket_nonce, Hash.length)
143 
144 
145     */
146 
147      NX_PARAMETER_NOT_USED(tls_session);
148 
149     if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < 13u)
150     {
151 
152         /* Packet buffer too small. */
153         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
154     }
155 
156     length = 0;
157     packet_buffer = send_packet -> nx_packet_append_ptr;
158 
159     /* First, the ticket lifetime in ms - 604800 is the maximum. */
160     lifetime = 604800;
161     packet_buffer[length]     = (UCHAR)((lifetime & 0xFF000000) >> 24);
162     packet_buffer[length + 1] = (UCHAR)((lifetime & 0x00FF0000) >> 16);
163     packet_buffer[length + 2] = (UCHAR)((lifetime & 0x0000FF00) >> 8);
164     packet_buffer[length + 3] = (UCHAR) (lifetime & 0x000000FF);
165     length += 4;
166 
167     /* The age_add is a cryptographically secure random 32-bit number. */
168     age_add = (UINT)NX_RAND();
169     packet_buffer[length]     = (UCHAR)((age_add & 0xFF000000) >> 24);
170     packet_buffer[length + 1] = (UCHAR)((age_add & 0x00FF0000) >> 16);
171     packet_buffer[length + 2] = (UCHAR)((age_add & 0x0000FF00) >> 8);
172     packet_buffer[length + 3] = (UCHAR) (age_add & 0x000000FF);
173     length += 4;
174 
175 
176     /* Set up the nonce - 4 bytes of random data. */
177     nonce = (UINT)NX_RAND();
178     nonce_len = 4;
179 
180     /* Add in the nonce length. */
181     packet_buffer[length] = (UCHAR)(nonce_len & 0xFF);
182     length += 1;
183 
184     /*  Nonces are currently max 32 bits */
185     packet_buffer[length]     = (UCHAR)((nonce & 0xFF000000) >> 24);
186     packet_buffer[length + 1] = (UCHAR)((nonce & 0x00FF0000) >> 16);
187     packet_buffer[length + 2] = (UCHAR)((nonce & 0x0000FF00) >> 8);
188     packet_buffer[length + 3] = (UCHAR) (nonce & 0x000000FF);
189     length += nonce_len;
190 
191 
192     /* Now for the ticket ID itself. 16-bit length with the ticket being a label
193        used as the PSK identity. */
194     ticket =  (UCHAR *)("NewSessionTicket");
195     ticket_len = sizeof("NewSessionTicket");
196 
197     if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < (17u + ticket_len))
198     {
199 
200         /* Packet buffer too small. */
201         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
202     }
203 
204     /* Insert ticket length. */
205     packet_buffer[length]     = (UCHAR)((ticket_len & 0xFF00) >> 8);
206     packet_buffer[length + 1] = (UCHAR)(ticket_len & 0x00FF);
207     length += 2;
208 
209     /* Copy in ticket. */
210     NX_SECURE_MEMCPY(&packet_buffer[length], ticket, ticket_len); /* Use case of memcpy is verified. */
211     length += ticket_len;
212 
213     /* Add in extensions if available. */
214     extensions_len = 0;
215     packet_buffer[length]     = (UCHAR)((extensions_len & 0xFF00) >> 8);
216     packet_buffer[length + 1] = (UCHAR) (extensions_len & 0x00FF);
217     length += 2;
218 
219     /* Adjust the packet into which we just wrote the finished hash. */
220     send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + length;
221     send_packet -> nx_packet_length = send_packet -> nx_packet_length + length;
222 
223     return(status);
224 }
225 
226 #endif
227