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