1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2025-present Eclipse ThreadX Contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** NetX Secure Component */
/** */
/** Transport Layer Security (TLS) */
/** */
/**************************************************************************/
/**************************************************************************/
#define NX_SECURE_SOURCE_CODE
#include "nx_secure_tls.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_secure_tls_send_handshake_record PORTABLE C */
/* 6.4.3 */
/* AUTHOR */
/* */
/* Timothy Stapko, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sends a TLS Handshake record, populating the header */
/* in the NX_PACKET structure before passing the packet along to the */
/* generic TLS record send function. */
/* */
/* INPUT */
/* */
/* tls_session TLS control block */
/* send_packet Packet to be sent */
/* handshake_type TLS handshake message type */
/* wait_option Controls TCP send options */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_secure_tls_handshake_hash_update Update Finished message hash */
/* _nx_secure_tls_send_record Send the TLS record */
/* nx_secure_tls_packet_release Release packet */
/* */
/* CALLED BY */
/* */
/* _nx_secure_tls_client_handshake TLS client state machine */
/* _nx_secure_tls_server_handshake TLS server state machine */
/* _nx_secure_tls_session_start Start TLS session */
/* _nx_secure_tls_session_renegotiate Renegotiate TLS session */
/* */
/**************************************************************************/
UINT _nx_secure_tls_send_handshake_record(NX_SECURE_TLS_SESSION *tls_session,
NX_PACKET *send_packet, UCHAR handshake_type,
ULONG wait_option)
{
UINT status;
UCHAR *packet_buffer;
ULONG length;
NX_PACKET *current_packet;
UINT buffer_offset;
/* Build up the TLS handshake header.
* Structure:
* | 1 | 3 |
* | Type | Length |
*/
/* Length of the data in the packet. */
length = send_packet -> nx_packet_length;
/* Back off the prepend_ptr by NX_SECURE_TLS_RECORD_HEADER_SIZE. This adds to the length because
we are reclaiming the data from before the prepend pointer. */
send_packet -> nx_packet_prepend_ptr -= NX_SECURE_TLS_HANDSHAKE_HEADER_SIZE;
send_packet -> nx_packet_length += NX_SECURE_TLS_HANDSHAKE_HEADER_SIZE;
/* Pick up the address where the handshake message starts. */
packet_buffer = send_packet -> nx_packet_prepend_ptr;
/* First byte is the message type. */
packet_buffer[0] = handshake_type;
/* Next up is the length field (3 bytes). */
packet_buffer[1] = (UCHAR)((length & 0xFF0000) >> 16);
packet_buffer[2] = (UCHAR)((length & 0xFF00) >> 8);
packet_buffer[3] = (UCHAR)(length & 0xFF);
/* Account for the 4 bytes of header in the length. */
length = length + (USHORT)NX_SECURE_TLS_HANDSHAKE_HEADER_SIZE;
/* Hash this handshake message. We do not hash HelloRequest messages so check that we aren't doing that.
Hashes include the handshake layer header but not the record layer header. */
if (handshake_type != NX_SECURE_TLS_HELLO_REQUEST)
{
/* Account for large records that exceed the packet size and are chained in multiple packets
such as large certificate messages with multiple certificates. */
current_packet = send_packet;
buffer_offset = 0;
do
{
/* Update the handshake hash with the data. */
length = (ULONG)(current_packet -> nx_packet_append_ptr - current_packet -> nx_packet_prepend_ptr);
/* If using TLS 1.3 and no ciphersuite is chosen, we don't yet know what the handshake hash routine will be,
so cache the message data to be hashed later. */
#if (NX_SECURE_TLS_TLS_1_3_ENABLED)
if((tls_session->nx_secure_tls_1_3 && tls_session->nx_secure_tls_session_ciphersuite == 0x0) ||
(handshake_type == NX_SECURE_TLS_CLIENT_HELLO))
#else
if (handshake_type == NX_SECURE_TLS_CLIENT_HELLO)
#endif /* (NX_SECURE_TLS_TLS_1_3_ENABLED) */
{
NX_SECURE_MEMCPY(&tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache[buffer_offset], /* lgtm[cpp/banned-api-usage-required-any] */
current_packet -> nx_packet_prepend_ptr, (UINT)length); /* Use case of memcpy is verified. */
/* Advance the length. */
buffer_offset += (UINT)length;
tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache_length += (UINT)length;
}
else
{
_nx_secure_tls_handshake_hash_update(tls_session, current_packet -> nx_packet_prepend_ptr,
(UINT)length);
}
/* Advance the packet pointer to the next packet in the chain. */
current_packet = current_packet -> nx_packet_next;
} while (current_packet != NX_NULL);
}
/* Finally, send the record off to the client. */
status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_HANDSHAKE, wait_option);
if (status != NX_SUCCESS)
{
/* Release packet on send error. */
nx_secure_tls_packet_release(send_packet);
}
return(status);
}
|