summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2026-05-16 08:20:41 +0000
committerjsing <>2026-05-16 08:20:41 +0000
commit4aaf2a3333ff91e8329e1dddd19d905b9c523c02 (patch)
tree5809aca387325aef045e2152f28a8ac583810f9d
parent62c0685f0e88cb58cba8344db87c9f6b6c25adc2 (diff)
downloadopenbsd-4aaf2a3333ff91e8329e1dddd19d905b9c523c02.tar.gz
openbsd-4aaf2a3333ff91e8329e1dddd19d905b9c523c02.tar.bz2
openbsd-4aaf2a3333ff91e8329e1dddd19d905b9c523c02.zip
Introduce and use dtls12_handshake_msg.
Add struct dtls12_handshake_msg and various related functions, which allow for the construction of DTLS handshake messages and associated fragments. Use this on the DTLS write path for sending handshake message fragments. This means that we no longer modify the init buffer, which also fixes a bug where the message callback is called with a corrupted handshake message when multiple fragments have been sent. We also now correctly track fragment offsets when sending a handshake message that results in multiple calls to dtls1_do_write_handshake_message(). This is the first step towards further untangling of the write path in the legacy TLS stack. ok kenjiro@ tb@
-rw-r--r--src/lib/libssl/Makefile3
-rw-r--r--src/lib/libssl/d1_both.c148
-rw-r--r--src/lib/libssl/d1_lib.c7
-rw-r--r--src/lib/libssl/dtls12_handshake_msg.c231
-rw-r--r--src/lib/libssl/dtls12_internal.h46
-rw-r--r--src/lib/libssl/dtls_local.h5
6 files changed, 363 insertions, 77 deletions
diff --git a/src/lib/libssl/Makefile b/src/lib/libssl/Makefile
index 7e423b0b43..0d5934508a 100644
--- a/src/lib/libssl/Makefile
+++ b/src/lib/libssl/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.86 2026/04/03 07:26:20 jsing Exp $ 1# $OpenBSD: Makefile,v 1.87 2026/05/16 08:20:41 jsing Exp $
2 2
3.include <bsd.own.mk> 3.include <bsd.own.mk>
4.ifndef NOMAN 4.ifndef NOMAN
@@ -43,6 +43,7 @@ SRCS= \
43 d1_lib.c \ 43 d1_lib.c \
44 d1_pkt.c \ 44 d1_pkt.c \
45 d1_srtp.c \ 45 d1_srtp.c \
46 dtls12_handshake_msg.c \
46 pqueue.c \ 47 pqueue.c \
47 s3_cbc.c \ 48 s3_cbc.c \
48 s3_lib.c \ 49 s3_lib.c \
diff --git a/src/lib/libssl/d1_both.c b/src/lib/libssl/d1_both.c
index de915fa4b2..2af307f594 100644
--- a/src/lib/libssl/d1_both.c
+++ b/src/lib/libssl/d1_both.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: d1_both.c,v 1.93 2026/05/06 15:06:35 jsing Exp $ */ 1/* $OpenBSD: d1_both.c,v 1.94 2026/05/16 08:20:41 jsing Exp $ */
2/* 2/*
3 * DTLS implementation written by Nagendra Modadugu 3 * DTLS implementation written by Nagendra Modadugu
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -205,12 +205,48 @@ dtls1_hm_fragment_free(hm_fragment *frag)
205} 205}
206 206
207static int 207static int
208dtls12_create_handshake_msg(SSL *s)
209{
210 CBB cbb;
211
212 OPENSSL_assert(s->init_off == 0);
213 OPENSSL_assert(s->init_num == (int)s->d1->w_msg_hdr.msg_len +
214 DTLS1_HM_HEADER_LENGTH);
215
216 /* Skip over the existing header. */
217 s->init_off += DTLS1_HM_HEADER_LENGTH;
218 s->init_num -= DTLS1_HM_HEADER_LENGTH;
219
220 if (s->d1->hs_msg != NULL)
221 goto err;
222
223 if ((s->d1->hs_msg = dtls12_handshake_msg_new()) == NULL)
224 goto err;
225 if (!dtls12_handshake_msg_start(s->d1->hs_msg, &cbb,
226 s->d1->w_msg_hdr.type, s->d1->w_msg_hdr.seq))
227 goto err;
228 if (!CBB_add_bytes(&cbb, &s->init_buf->data[s->init_off],
229 s->init_num))
230 goto err;
231 if (!dtls12_handshake_msg_finish(s->d1->hs_msg))
232 goto err;
233
234 return 1;
235
236 err:
237 dtls12_handshake_msg_free(s->d1->hs_msg);
238 s->d1->hs_msg = NULL;
239
240 return 0;
241}
242
243static int
208dtls1_do_write_handshake_message(SSL *s) 244dtls1_do_write_handshake_message(SSL *s)
209{ 245{
210 int ret; 246 int curr_mtu, written;
211 int curr_mtu;
212 unsigned int len, frag_off;
213 size_t overhead; 247 size_t overhead;
248 CBS cbs;
249 int ret;
214 250
215 /* AHA! Figure out the MTU, and stick to the right size */ 251 /* AHA! Figure out the MTU, and stick to the right size */
216 if (s->d1->mtu < dtls1_min_mtu() && 252 if (s->d1->mtu < dtls1_min_mtu() &&
@@ -234,15 +270,15 @@ dtls1_do_write_handshake_message(SSL *s)
234 OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); 270 OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu());
235 /* should have something reasonable now */ 271 /* should have something reasonable now */
236 272
237 if (s->init_off == 0) 273 if (s->d1->hs_msg == NULL) {
238 OPENSSL_assert(s->init_num == 274 if (!dtls12_create_handshake_msg(s))
239 (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); 275 return -1;
276 }
240 277
241 if (!tls12_record_layer_write_overhead(s->rl, &overhead)) 278 if (!tls12_record_layer_write_overhead(s->rl, &overhead))
242 return -1; 279 return -1;
243 280
244 frag_off = 0; 281 do {
245 while (s->init_num > 0) {
246 curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - 282 curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) -
247 DTLS1_RT_HEADER_LENGTH - overhead; 283 DTLS1_RT_HEADER_LENGTH - overhead;
248 284
@@ -255,35 +291,14 @@ dtls1_do_write_handshake_message(SSL *s)
255 overhead; 291 overhead;
256 } 292 }
257 293
258 if (s->init_num > curr_mtu) 294 OPENSSL_assert(curr_mtu >= DTLS1_HM_HEADER_LENGTH);
259 len = curr_mtu;
260 else
261 len = s->init_num;
262
263 if (s->init_off != 0) {
264 OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
265 s->init_off -= DTLS1_HM_HEADER_LENGTH;
266 s->init_num += DTLS1_HM_HEADER_LENGTH;
267
268 if (s->init_num > curr_mtu)
269 len = curr_mtu;
270 else
271 len = s->init_num;
272 }
273
274 OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH);
275
276 s->d1->w_msg_hdr.frag_off = frag_off;
277 s->d1->w_msg_hdr.frag_len = len - DTLS1_HM_HEADER_LENGTH;
278 295
279 if (!dtls1_write_message_header(&s->d1->w_msg_hdr, 296 if (!dtls12_handshake_msg_fragment_build(s->d1->hs_msg,
280 s->d1->w_msg_hdr.frag_off, s->d1->w_msg_hdr.frag_len, 297 curr_mtu - DTLS1_HM_HEADER_LENGTH, &cbs))
281 (unsigned char *)&s->init_buf->data[s->init_off]))
282 return -1; 298 return -1;
283 299
284 ret = dtls1_write_bytes(s, SSL3_RT_HANDSHAKE, 300 if ((written = dtls1_write_bytes(s, SSL3_RT_HANDSHAKE,
285 &s->init_buf->data[s->init_off], len); 301 CBS_data(&cbs), CBS_len(&cbs))) < 0) {
286 if (ret < 0) {
287 /* 302 /*
288 * Might need to update MTU here, but we don't know 303 * Might need to update MTU here, but we don't know
289 * which previous packet caused the failure -- so 304 * which previous packet caused the failure -- so
@@ -293,7 +308,7 @@ dtls1_do_write_handshake_message(SSL *s)
293 */ 308 */
294 if (BIO_ctrl(SSL_get_wbio(s), 309 if (BIO_ctrl(SSL_get_wbio(s),
295 BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) <= 0) 310 BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) <= 0)
296 return (-1); 311 return -1;
297 312
298 s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), 313 s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
299 BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); 314 BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
@@ -306,49 +321,34 @@ dtls1_do_write_handshake_message(SSL *s)
306 * handshake message got sent. but why would 321 * handshake message got sent. but why would
307 * this happen? 322 * this happen?
308 */ 323 */
309 OPENSSL_assert(len == (unsigned int)ret); 324 OPENSSL_assert(CBS_len(&cbs) == (size_t)written);
310 325
311 if (!s->d1->retransmitting) { 326 if (!dtls12_handshake_msg_fragment_next(s->d1->hs_msg))
312 /* 327 return -1;
313 * Should not be done for 'Hello Request's,
314 * but in that case we'll ignore the result
315 * anyway
316 */
317 unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
318 const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
319 int xlen;
320
321 if (frag_off == 0) {
322 /*
323 * Reconstruct message header is if it
324 * is being sent in single fragment
325 */
326 if (!dtls1_write_message_header(msg_hdr,
327 0, msg_hdr->msg_len, p))
328 return (-1);
329 xlen = ret;
330 } else {
331 p += DTLS1_HM_HEADER_LENGTH;
332 xlen = ret - DTLS1_HM_HEADER_LENGTH;
333 }
334
335 tls1_transcript_record(s, p, xlen);
336 }
337 328
338 if (ret == s->init_num) { 329 } while (dtls12_handshake_msg_fragment_pending(s->d1->hs_msg));
339 ssl_msg_callback(s, 1, SSL3_RT_HANDSHAKE,
340 s->init_buf->data, s->init_off + s->init_num);
341 330
342 s->init_off = 0; 331 dtls12_handshake_msg_data(s->d1->hs_msg, &cbs);
343 s->init_num = 0;
344 332
345 return (1); 333 if (!s->d1->retransmitting) {
346 } 334 /*
347 s->init_off += ret; 335 * The TLS transcript is based on each handshake message being
348 s->init_num -= ret; 336 * sent as a single fragment - see RFC 6347 section 4.2.6. This
349 frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); 337 * should not be called for a HelloRequest, however the result
338 * will be ignored.
339 */
340 tls1_transcript_record(s, CBS_data(&cbs), CBS_len(&cbs));
350 } 341 }
351 return (0); 342
343 ssl_msg_callback(s, 1, SSL3_RT_HANDSHAKE, CBS_data(&cbs), CBS_len(&cbs));
344
345 dtls12_handshake_msg_free(s->d1->hs_msg);
346 s->d1->hs_msg = NULL;
347
348 s->init_off = 0;
349 s->init_num = 0;
350
351 return 1;
352} 352}
353 353
354static int 354static int
diff --git a/src/lib/libssl/d1_lib.c b/src/lib/libssl/d1_lib.c
index 69db8a0df4..fa546b381c 100644
--- a/src/lib/libssl/d1_lib.c
+++ b/src/lib/libssl/d1_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: d1_lib.c,v 1.65 2024/07/23 14:40:53 jsing Exp $ */ 1/* $OpenBSD: d1_lib.c,v 1.66 2026/05/16 08:20:41 jsing Exp $ */
2/* 2/*
3 * DTLS implementation written by Nagendra Modadugu 3 * DTLS implementation written by Nagendra Modadugu
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -179,6 +179,8 @@ dtls1_free(SSL *s)
179 pqueue_free(s->d1->sent_messages); 179 pqueue_free(s->d1->sent_messages);
180 pqueue_free(s->d1->buffered_app_data.q); 180 pqueue_free(s->d1->buffered_app_data.q);
181 181
182 dtls12_handshake_msg_free(s->d1->hs_msg);
183
182 freezero(s->d1, sizeof(*s->d1)); 184 freezero(s->d1, sizeof(*s->d1));
183 s->d1 = NULL; 185 s->d1 = NULL;
184} 186}
@@ -199,6 +201,9 @@ dtls1_clear(SSL *s)
199 buffered_app_data = s->d1->buffered_app_data.q; 201 buffered_app_data = s->d1->buffered_app_data.q;
200 mtu = s->d1->mtu; 202 mtu = s->d1->mtu;
201 203
204 dtls12_handshake_msg_free(s->d1->hs_msg);
205 s->d1->hs_msg = NULL;
206
202 dtls1_clear_queues(s); 207 dtls1_clear_queues(s);
203 208
204 memset(s->d1, 0, sizeof(*s->d1)); 209 memset(s->d1, 0, sizeof(*s->d1));
diff --git a/src/lib/libssl/dtls12_handshake_msg.c b/src/lib/libssl/dtls12_handshake_msg.c
new file mode 100644
index 0000000000..7874aa8598
--- /dev/null
+++ b/src/lib/libssl/dtls12_handshake_msg.c
@@ -0,0 +1,231 @@
1/* $OpenBSD: dtls12_handshake_msg.c,v 1.1 2026/05/16 08:20:41 jsing Exp $ */
2/*
3 * Copyright (c) 2026 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "bytestring.h"
23#include "dtls12_internal.h"
24
25#define DTLS12_HANDSHAKE_MSG_HEADER_LEN 12
26#define DTLS12_HANDSHAKE_MSG_INITIAL_LEN 256
27
28#define DTLS12_HANDSHAKE_MSG_FRAGMENT_LENGTH_OFFSET 9
29
30struct dtls12_handshake_msg {
31 uint8_t msg_type;
32 uint32_t msg_len;
33 uint16_t msg_seq;
34
35 uint32_t fragment_offset;
36 uint32_t fragment_len;
37 uint8_t *fragment_data;
38 size_t fragment_data_len;
39 int fragment_pending;
40
41 uint8_t *data;
42 size_t data_len;
43
44 CBS cbs;
45 CBB cbb;
46};
47
48struct dtls12_handshake_msg *
49dtls12_handshake_msg_new(void)
50{
51 struct dtls12_handshake_msg *msg = NULL;
52
53 if ((msg = calloc(1, sizeof(struct dtls12_handshake_msg))) == NULL)
54 return NULL;
55
56 return msg;
57}
58
59void
60dtls12_handshake_msg_free(struct dtls12_handshake_msg *msg)
61{
62 if (msg == NULL)
63 return;
64
65 CBB_cleanup(&msg->cbb);
66
67 freezero(msg->data, msg->data_len);
68 freezero(msg->fragment_data, msg->fragment_data_len);
69
70 freezero(msg, sizeof(struct dtls12_handshake_msg));
71}
72
73void
74dtls12_handshake_msg_data(struct dtls12_handshake_msg *msg, CBS *cbs)
75{
76 CBS_init(cbs, msg->data, msg->data_len);
77}
78
79uint8_t
80dtls12_handshake_msg_type(struct dtls12_handshake_msg *msg)
81{
82 return msg->msg_type;
83}
84
85int
86dtls12_handshake_msg_content(struct dtls12_handshake_msg *msg, CBS *cbs)
87{
88 dtls12_handshake_msg_data(msg, cbs);
89
90 return CBS_skip(cbs, DTLS12_HANDSHAKE_MSG_HEADER_LEN);
91}
92
93int
94dtls12_handshake_msg_start(struct dtls12_handshake_msg *msg, CBB *body,
95 uint8_t msg_type, size_t msg_seq)
96{
97 msg->msg_type = msg_type;
98 msg->msg_seq = msg_seq;
99
100 msg->msg_len = 0;
101 msg->fragment_offset = 0;
102
103 if (!CBB_init(&msg->cbb, DTLS12_HANDSHAKE_MSG_INITIAL_LEN))
104 return 0;
105 if (!CBB_add_u8(&msg->cbb, msg->msg_type))
106 return 0;
107 if (!CBB_add_u24(&msg->cbb, msg->msg_len))
108 return 0;
109 if (!CBB_add_u16(&msg->cbb, msg->msg_seq))
110 return 0;
111 if (!CBB_add_u24(&msg->cbb, msg->fragment_offset))
112 return 0;
113 if (!CBB_add_u24_length_prefixed(&msg->cbb, body))
114 return 0;
115
116 return 1;
117}
118
119int
120dtls12_handshake_msg_finish(struct dtls12_handshake_msg *msg)
121{
122 CBS cbs;
123
124 if (!CBB_finish(&msg->cbb, &msg->data, &msg->data_len))
125 return 0;
126
127 /* Update message length to match fragment length. */
128 CBS_init(&cbs, msg->data, msg->data_len);
129 if (!CBS_skip(&cbs, DTLS12_HANDSHAKE_MSG_FRAGMENT_LENGTH_OFFSET))
130 return 0;
131 if (!CBS_get_u24(&cbs, &msg->msg_len))
132 return 0;
133
134 if (!CBB_init_fixed(&msg->cbb, msg->data, msg->data_len))
135 return 0;
136 if (!CBB_add_u8(&msg->cbb, msg->msg_type))
137 return 0;
138 if (!CBB_add_u24(&msg->cbb, msg->msg_len))
139 return 0;
140 if (!CBB_finish(&msg->cbb, NULL, NULL))
141 return 0;
142
143 dtls12_handshake_msg_fragment_reset(msg);
144
145 return 1;
146}
147
148int
149dtls12_handshake_msg_fragment_reset(struct dtls12_handshake_msg *msg)
150{
151 freezero(msg->fragment_data, msg->fragment_data_len);
152 msg->fragment_data = NULL;
153 msg->fragment_data_len = 0;
154
155 msg->fragment_offset = 0;
156 msg->fragment_pending = 1;
157
158 return dtls12_handshake_msg_content(msg, &msg->cbs);
159}
160
161int
162dtls12_handshake_msg_fragment_build(struct dtls12_handshake_msg *msg,
163 size_t max_fragment_len, CBS *cbs)
164{
165 CBB body;
166
167 CBS_init(cbs, NULL, 0);
168
169 if (msg->fragment_offset > msg->msg_len)
170 return 0;
171 if (msg->msg_len - msg->fragment_offset > CBS_len(&msg->cbs))
172 return 0;
173
174 freezero(msg->fragment_data, msg->fragment_data_len);
175 msg->fragment_data = NULL;
176 msg->fragment_data_len = 0;
177
178 if ((msg->fragment_len = CBS_len(&msg->cbs)) > max_fragment_len)
179 msg->fragment_len = max_fragment_len;
180
181 /* Build the fragment. */
182 if (!CBB_init(&msg->cbb, DTLS12_HANDSHAKE_MSG_INITIAL_LEN))
183 goto err;
184 if (!CBB_add_u8(&msg->cbb, msg->msg_type))
185 goto err;
186 if (!CBB_add_u24(&msg->cbb, msg->msg_len))
187 goto err;
188 if (!CBB_add_u16(&msg->cbb, msg->msg_seq))
189 goto err;
190 if (!CBB_add_u24(&msg->cbb, msg->fragment_offset))
191 goto err;
192 if (!CBB_add_u24_length_prefixed(&msg->cbb, &body))
193 goto err;
194 if (!CBB_add_bytes(&body, CBS_data(&msg->cbs), msg->fragment_len))
195 goto err;
196 if (!CBB_finish(&msg->cbb, &msg->fragment_data, &msg->fragment_data_len))
197 goto err;
198
199 CBS_init(cbs, msg->fragment_data, msg->fragment_data_len);
200
201 return 1;
202
203 err:
204 CBB_cleanup(&msg->cbb);
205
206 return 0;
207}
208
209int
210dtls12_handshake_msg_fragment_next(struct dtls12_handshake_msg *msg)
211{
212 if (msg->fragment_offset > msg->msg_len)
213 return 0;
214 if (msg->msg_len - msg->fragment_offset < msg->fragment_len)
215 return 0;
216
217 if (!CBS_skip(&msg->cbs, msg->fragment_len))
218 return 0;
219
220 msg->fragment_offset += msg->fragment_len;
221
222 msg->fragment_pending = (CBS_len(&msg->cbs) > 0);
223
224 return 1;
225}
226
227int
228dtls12_handshake_msg_fragment_pending(struct dtls12_handshake_msg *msg)
229{
230 return msg->fragment_pending;
231}
diff --git a/src/lib/libssl/dtls12_internal.h b/src/lib/libssl/dtls12_internal.h
new file mode 100644
index 0000000000..f3fa9b7490
--- /dev/null
+++ b/src/lib/libssl/dtls12_internal.h
@@ -0,0 +1,46 @@
1/* $OpenBSD: dtls12_internal.h,v 1.1 2026/05/16 08:20:41 jsing Exp $ */
2/*
3 * Copyright (c) 2026 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef HEADER_DTLS12_INTERNAL_H
19#define HEADER_DTLS12_INTERNAL_H
20
21#include <stddef.h>
22#include <stdint.h>
23
24#include "bytestring.h"
25
26__BEGIN_HIDDEN_DECLS
27
28struct dtls12_handshake_msg;
29
30struct dtls12_handshake_msg *dtls12_handshake_msg_new(void);
31void dtls12_handshake_msg_free(struct dtls12_handshake_msg *msg);
32void dtls12_handshake_msg_data(struct dtls12_handshake_msg *msg, CBS *cbs);
33uint8_t dtls12_handshake_msg_type(struct dtls12_handshake_msg *msg);
34int dtls12_handshake_msg_content(struct dtls12_handshake_msg *msg, CBS *cbs);
35int dtls12_handshake_msg_start(struct dtls12_handshake_msg *msg, CBB *body,
36 uint8_t msg_type, size_t msg_seq);
37int dtls12_handshake_msg_finish(struct dtls12_handshake_msg *msg);
38int dtls12_handshake_msg_fragment_build(struct dtls12_handshake_msg *msg,
39 size_t max_fragment_len, CBS *cbs);
40int dtls12_handshake_msg_fragment_next(struct dtls12_handshake_msg *msg);
41int dtls12_handshake_msg_fragment_pending(struct dtls12_handshake_msg *msg);
42int dtls12_handshake_msg_fragment_reset(struct dtls12_handshake_msg *msg);
43
44__END_HIDDEN_DECLS
45
46#endif
diff --git a/src/lib/libssl/dtls_local.h b/src/lib/libssl/dtls_local.h
index 5a85bba607..8691663eb3 100644
--- a/src/lib/libssl/dtls_local.h
+++ b/src/lib/libssl/dtls_local.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: dtls_local.h,v 1.4 2026/05/06 15:06:35 jsing Exp $ */ 1/* $OpenBSD: dtls_local.h,v 1.5 2026/05/16 08:20:41 jsing Exp $ */
2/* 2/*
3 * DTLS implementation written by Nagendra Modadugu 3 * DTLS implementation written by Nagendra Modadugu
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -65,6 +65,7 @@
65#include <openssl/dtls1.h> 65#include <openssl/dtls1.h>
66 66
67#include "ssl_local.h" 67#include "ssl_local.h"
68#include "dtls12_internal.h"
68#include "tls_content.h" 69#include "tls_content.h"
69 70
70__BEGIN_HIDDEN_DECLS 71__BEGIN_HIDDEN_DECLS
@@ -179,6 +180,8 @@ struct dtls1_state_st {
179 180
180 unsigned int retransmitting; 181 unsigned int retransmitting;
181 unsigned int change_cipher_spec_ok; 182 unsigned int change_cipher_spec_ok;
183
184 struct dtls12_handshake_msg *hs_msg;
182}; 185};
183 186
184int dtls1_do_write(SSL *s, int type); 187int dtls1_do_write(SSL *s, int type);