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