Line data Source code
1 : /* ssl/d1_lib.c */
2 : /*
3 : * DTLS implementation written by Nagendra Modadugu
4 : * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * openssl-core@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include <stdio.h>
61 : #define USE_SOCKETS
62 : #include <openssl/objects.h>
63 : #include "ssl_locl.h"
64 :
65 : #if defined(OPENSSL_SYS_VMS)
66 : # include <sys/timeb.h>
67 : #endif
68 :
69 : static void get_current_time(struct timeval *t);
70 : static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
71 : static int dtls1_handshake_write(SSL *s);
72 : const char dtls1_version_str[] = "DTLSv1" OPENSSL_VERSION_PTEXT;
73 : int dtls1_listen(SSL *s, struct sockaddr *client);
74 :
75 : SSL3_ENC_METHOD DTLSv1_enc_data = {
76 : tls1_enc,
77 : tls1_mac,
78 : tls1_setup_key_block,
79 : tls1_generate_master_secret,
80 : tls1_change_cipher_state,
81 : tls1_final_finish_mac,
82 : TLS1_FINISH_MAC_LENGTH,
83 : tls1_cert_verify_mac,
84 : TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
85 : TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
86 : tls1_alert_code,
87 : tls1_export_keying_material,
88 : SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV,
89 : DTLS1_HM_HEADER_LENGTH,
90 : dtls1_set_handshake_header,
91 : dtls1_handshake_write
92 : };
93 :
94 : SSL3_ENC_METHOD DTLSv1_2_enc_data = {
95 : tls1_enc,
96 : tls1_mac,
97 : tls1_setup_key_block,
98 : tls1_generate_master_secret,
99 : tls1_change_cipher_state,
100 : tls1_final_finish_mac,
101 : TLS1_FINISH_MAC_LENGTH,
102 : tls1_cert_verify_mac,
103 : TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
104 : TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
105 : tls1_alert_code,
106 : tls1_export_keying_material,
107 : SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS
108 : | SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS,
109 : DTLS1_HM_HEADER_LENGTH,
110 : dtls1_set_handshake_header,
111 : dtls1_handshake_write
112 : };
113 :
114 0 : long dtls1_default_timeout(void)
115 : {
116 : /*
117 : * 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for
118 : * http, the cache would over fill
119 : */
120 0 : return (60 * 60 * 2);
121 : }
122 :
123 0 : int dtls1_new(SSL *s)
124 : {
125 : DTLS1_STATE *d1;
126 :
127 0 : if (!ssl3_new(s))
128 : return (0);
129 0 : if ((d1 = OPENSSL_malloc(sizeof *d1)) == NULL)
130 : return (0);
131 : memset(d1, 0, sizeof *d1);
132 :
133 : /* d1->handshake_epoch=0; */
134 :
135 0 : d1->unprocessed_rcds.q = pqueue_new();
136 0 : d1->processed_rcds.q = pqueue_new();
137 0 : d1->buffered_messages = pqueue_new();
138 0 : d1->sent_messages = pqueue_new();
139 0 : d1->buffered_app_data.q = pqueue_new();
140 :
141 0 : if (s->server) {
142 0 : d1->cookie_len = sizeof(s->d1->cookie);
143 : }
144 :
145 0 : d1->link_mtu = 0;
146 0 : d1->mtu = 0;
147 :
148 0 : if (!d1->unprocessed_rcds.q || !d1->processed_rcds.q
149 0 : || !d1->buffered_messages || !d1->sent_messages
150 0 : || !d1->buffered_app_data.q) {
151 0 : if (d1->unprocessed_rcds.q)
152 0 : pqueue_free(d1->unprocessed_rcds.q);
153 0 : if (d1->processed_rcds.q)
154 0 : pqueue_free(d1->processed_rcds.q);
155 0 : if (d1->buffered_messages)
156 0 : pqueue_free(d1->buffered_messages);
157 0 : if (d1->sent_messages)
158 0 : pqueue_free(d1->sent_messages);
159 0 : if (d1->buffered_app_data.q)
160 0 : pqueue_free(d1->buffered_app_data.q);
161 0 : OPENSSL_free(d1);
162 0 : return (0);
163 : }
164 :
165 0 : s->d1 = d1;
166 0 : s->method->ssl_clear(s);
167 0 : return (1);
168 : }
169 :
170 0 : static void dtls1_clear_queues(SSL *s)
171 : {
172 : pitem *item = NULL;
173 : hm_fragment *frag = NULL;
174 : DTLS1_RECORD_DATA *rdata;
175 :
176 0 : while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
177 0 : rdata = (DTLS1_RECORD_DATA *)item->data;
178 0 : if (rdata->rbuf.buf) {
179 0 : OPENSSL_free(rdata->rbuf.buf);
180 : }
181 0 : OPENSSL_free(item->data);
182 0 : pitem_free(item);
183 : }
184 :
185 0 : while ((item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) {
186 0 : rdata = (DTLS1_RECORD_DATA *)item->data;
187 0 : if (rdata->rbuf.buf) {
188 0 : OPENSSL_free(rdata->rbuf.buf);
189 : }
190 0 : OPENSSL_free(item->data);
191 0 : pitem_free(item);
192 : }
193 :
194 0 : while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
195 0 : frag = (hm_fragment *)item->data;
196 0 : dtls1_hm_fragment_free(frag);
197 0 : pitem_free(item);
198 : }
199 :
200 0 : while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
201 0 : frag = (hm_fragment *)item->data;
202 0 : dtls1_hm_fragment_free(frag);
203 0 : pitem_free(item);
204 : }
205 :
206 0 : while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
207 0 : rdata = (DTLS1_RECORD_DATA *)item->data;
208 0 : if (rdata->rbuf.buf) {
209 0 : OPENSSL_free(rdata->rbuf.buf);
210 : }
211 0 : OPENSSL_free(item->data);
212 0 : pitem_free(item);
213 : }
214 0 : }
215 :
216 0 : void dtls1_free(SSL *s)
217 : {
218 0 : ssl3_free(s);
219 :
220 0 : dtls1_clear_queues(s);
221 :
222 0 : pqueue_free(s->d1->unprocessed_rcds.q);
223 0 : pqueue_free(s->d1->processed_rcds.q);
224 0 : pqueue_free(s->d1->buffered_messages);
225 0 : pqueue_free(s->d1->sent_messages);
226 0 : pqueue_free(s->d1->buffered_app_data.q);
227 :
228 0 : OPENSSL_free(s->d1);
229 0 : s->d1 = NULL;
230 0 : }
231 :
232 0 : void dtls1_clear(SSL *s)
233 : {
234 : pqueue unprocessed_rcds;
235 : pqueue processed_rcds;
236 : pqueue buffered_messages;
237 : pqueue sent_messages;
238 : pqueue buffered_app_data;
239 : unsigned int mtu;
240 : unsigned int link_mtu;
241 :
242 0 : if (s->d1) {
243 0 : unprocessed_rcds = s->d1->unprocessed_rcds.q;
244 0 : processed_rcds = s->d1->processed_rcds.q;
245 0 : buffered_messages = s->d1->buffered_messages;
246 0 : sent_messages = s->d1->sent_messages;
247 0 : buffered_app_data = s->d1->buffered_app_data.q;
248 0 : mtu = s->d1->mtu;
249 0 : link_mtu = s->d1->link_mtu;
250 :
251 0 : dtls1_clear_queues(s);
252 :
253 0 : memset(s->d1, 0, sizeof(*(s->d1)));
254 :
255 0 : if (s->server) {
256 0 : s->d1->cookie_len = sizeof(s->d1->cookie);
257 : }
258 :
259 0 : if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
260 0 : s->d1->mtu = mtu;
261 0 : s->d1->link_mtu = link_mtu;
262 : }
263 :
264 0 : s->d1->unprocessed_rcds.q = unprocessed_rcds;
265 0 : s->d1->processed_rcds.q = processed_rcds;
266 0 : s->d1->buffered_messages = buffered_messages;
267 0 : s->d1->sent_messages = sent_messages;
268 0 : s->d1->buffered_app_data.q = buffered_app_data;
269 : }
270 :
271 0 : ssl3_clear(s);
272 0 : if (s->options & SSL_OP_CISCO_ANYCONNECT)
273 0 : s->client_version = s->version = DTLS1_BAD_VER;
274 0 : else if (s->method->version == DTLS_ANY_VERSION)
275 0 : s->version = DTLS1_2_VERSION;
276 : else
277 0 : s->version = s->method->version;
278 0 : }
279 :
280 0 : long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
281 : {
282 : int ret = 0;
283 :
284 0 : switch (cmd) {
285 : case DTLS_CTRL_GET_TIMEOUT:
286 0 : if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) {
287 : ret = 1;
288 : }
289 : break;
290 : case DTLS_CTRL_HANDLE_TIMEOUT:
291 0 : ret = dtls1_handle_timeout(s);
292 0 : break;
293 : case DTLS_CTRL_LISTEN:
294 0 : ret = dtls1_listen(s, parg);
295 0 : break;
296 : case SSL_CTRL_CHECK_PROTO_VERSION:
297 : /*
298 : * For library-internal use; checks that the current protocol is the
299 : * highest enabled version (according to s->ctx->method, as version
300 : * negotiation may have changed s->method).
301 : */
302 0 : if (s->version == s->ctx->method->version)
303 : return 1;
304 : /*
305 : * Apparently we're using a version-flexible SSL_METHOD (not at its
306 : * highest protocol version).
307 : */
308 0 : if (s->ctx->method->version == DTLS_method()->version) {
309 : #if DTLS_MAX_VERSION != DTLS1_2_VERSION
310 : # error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
311 : #endif
312 0 : if (!(s->options & SSL_OP_NO_DTLSv1_2))
313 0 : return s->version == DTLS1_2_VERSION;
314 0 : if (!(s->options & SSL_OP_NO_DTLSv1))
315 0 : return s->version == DTLS1_VERSION;
316 : }
317 : return 0; /* Unexpected state; fail closed. */
318 : case DTLS_CTRL_SET_LINK_MTU:
319 0 : if (larg < (long)dtls1_link_min_mtu())
320 : return 0;
321 0 : s->d1->link_mtu = larg;
322 0 : return 1;
323 : case DTLS_CTRL_GET_LINK_MIN_MTU:
324 0 : return (long)dtls1_link_min_mtu();
325 : case SSL_CTRL_SET_MTU:
326 : /*
327 : * We may not have a BIO set yet so can't call dtls1_min_mtu()
328 : * We'll have to make do with dtls1_link_min_mtu() and max overhead
329 : */
330 0 : if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
331 : return 0;
332 0 : s->d1->mtu = larg;
333 0 : return larg;
334 : default:
335 0 : ret = ssl3_ctrl(s, cmd, larg, parg);
336 0 : break;
337 : }
338 0 : return (ret);
339 : }
340 :
341 : /*
342 : * As it's impossible to use stream ciphers in "datagram" mode, this
343 : * simple filter is designed to disengage them in DTLS. Unfortunately
344 : * there is no universal way to identify stream SSL_CIPHER, so we have
345 : * to explicitly list their SSL_* codes. Currently RC4 is the only one
346 : * available, but if new ones emerge, they will have to be added...
347 : */
348 0 : const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
349 : {
350 0 : const SSL_CIPHER *ciph = ssl3_get_cipher(u);
351 :
352 0 : if (ciph != NULL) {
353 0 : if (ciph->algorithm_enc == SSL_RC4)
354 : return NULL;
355 : }
356 :
357 0 : return ciph;
358 : }
359 :
360 0 : void dtls1_start_timer(SSL *s)
361 : {
362 : #ifndef OPENSSL_NO_SCTP
363 : /* Disable timer for SCTP */
364 : if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
365 : memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
366 : return;
367 : }
368 : #endif
369 :
370 : /* If timer is not set, initialize duration with 1 second */
371 0 : if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
372 0 : s->d1->timeout_duration = 1;
373 : }
374 :
375 : /* Set timeout to current time */
376 0 : get_current_time(&(s->d1->next_timeout));
377 :
378 : /* Add duration to current time */
379 0 : s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
380 0 : BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
381 0 : &(s->d1->next_timeout));
382 0 : }
383 :
384 0 : struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft)
385 : {
386 : struct timeval timenow;
387 :
388 : /* If no timeout is set, just return NULL */
389 0 : if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
390 : return NULL;
391 : }
392 :
393 : /* Get current time */
394 : get_current_time(&timenow);
395 :
396 : /* If timer already expired, set remaining time to 0 */
397 0 : if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
398 0 : (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
399 0 : s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
400 : memset(timeleft, 0, sizeof(struct timeval));
401 0 : return timeleft;
402 : }
403 :
404 : /* Calculate time left until timer expires */
405 0 : memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
406 0 : timeleft->tv_sec -= timenow.tv_sec;
407 0 : timeleft->tv_usec -= timenow.tv_usec;
408 0 : if (timeleft->tv_usec < 0) {
409 0 : timeleft->tv_sec--;
410 0 : timeleft->tv_usec += 1000000;
411 : }
412 :
413 : /*
414 : * If remaining time is less than 15 ms, set it to 0 to prevent issues
415 : * because of small devergences with socket timeouts.
416 : */
417 0 : if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
418 : memset(timeleft, 0, sizeof(struct timeval));
419 : }
420 :
421 0 : return timeleft;
422 : }
423 :
424 0 : int dtls1_is_timer_expired(SSL *s)
425 : {
426 : struct timeval timeleft;
427 :
428 : /* Get time left until timeout, return false if no timer running */
429 0 : if (dtls1_get_timeout(s, &timeleft) == NULL) {
430 : return 0;
431 : }
432 :
433 : /* Return false if timer is not expired yet */
434 0 : if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
435 : return 0;
436 : }
437 :
438 : /* Timer expired, so return true */
439 0 : return 1;
440 : }
441 :
442 0 : void dtls1_double_timeout(SSL *s)
443 : {
444 0 : s->d1->timeout_duration *= 2;
445 0 : if (s->d1->timeout_duration > 60)
446 0 : s->d1->timeout_duration = 60;
447 0 : dtls1_start_timer(s);
448 0 : }
449 :
450 0 : void dtls1_stop_timer(SSL *s)
451 : {
452 : /* Reset everything */
453 0 : memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
454 0 : memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
455 0 : s->d1->timeout_duration = 1;
456 0 : BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
457 0 : &(s->d1->next_timeout));
458 : /* Clear retransmission buffer */
459 0 : dtls1_clear_record_buffer(s);
460 0 : }
461 :
462 0 : int dtls1_check_timeout_num(SSL *s)
463 : {
464 : unsigned int mtu;
465 :
466 0 : s->d1->timeout.num_alerts++;
467 :
468 : /* Reduce MTU after 2 unsuccessful retransmissions */
469 0 : if (s->d1->timeout.num_alerts > 2
470 0 : && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
471 0 : mtu =
472 0 : BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0,
473 : NULL);
474 0 : if (mtu < s->d1->mtu)
475 0 : s->d1->mtu = mtu;
476 : }
477 :
478 0 : if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
479 : /* fail the connection, enough alerts have been sent */
480 0 : SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED);
481 0 : return -1;
482 : }
483 :
484 : return 0;
485 : }
486 :
487 0 : int dtls1_handle_timeout(SSL *s)
488 : {
489 : /* if no timer is expired, don't do anything */
490 0 : if (!dtls1_is_timer_expired(s)) {
491 : return 0;
492 : }
493 :
494 0 : dtls1_double_timeout(s);
495 :
496 0 : if (dtls1_check_timeout_num(s) < 0)
497 : return -1;
498 :
499 0 : s->d1->timeout.read_timeouts++;
500 0 : if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
501 0 : s->d1->timeout.read_timeouts = 1;
502 : }
503 : #ifndef OPENSSL_NO_HEARTBEATS
504 0 : if (s->tlsext_hb_pending) {
505 0 : s->tlsext_hb_pending = 0;
506 0 : return dtls1_heartbeat(s);
507 : }
508 : #endif
509 :
510 0 : dtls1_start_timer(s);
511 0 : return dtls1_retransmit_buffered_messages(s);
512 : }
513 :
514 : static void get_current_time(struct timeval *t)
515 : {
516 : #if defined(_WIN32)
517 : SYSTEMTIME st;
518 : union {
519 : unsigned __int64 ul;
520 : FILETIME ft;
521 : } now;
522 :
523 : GetSystemTime(&st);
524 : SystemTimeToFileTime(&st, &now.ft);
525 : # ifdef __MINGW32__
526 : now.ul -= 116444736000000000ULL;
527 : # else
528 : now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */
529 : # endif
530 : t->tv_sec = (long)(now.ul / 10000000);
531 : t->tv_usec = ((int)(now.ul % 10000000)) / 10;
532 : #elif defined(OPENSSL_SYS_VMS)
533 : struct timeb tb;
534 : ftime(&tb);
535 : t->tv_sec = (long)tb.time;
536 : t->tv_usec = (long)tb.millitm * 1000;
537 : #else
538 0 : gettimeofday(t, NULL);
539 : #endif
540 : }
541 :
542 0 : int dtls1_listen(SSL *s, struct sockaddr *client)
543 : {
544 : int ret;
545 :
546 : /* Ensure there is no state left over from a previous invocation */
547 0 : SSL_clear(s);
548 :
549 0 : SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
550 0 : s->d1->listen = 1;
551 :
552 0 : ret = SSL_accept(s);
553 0 : if (ret <= 0)
554 : return ret;
555 :
556 0 : (void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
557 0 : return 1;
558 : }
559 :
560 0 : static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len)
561 : {
562 0 : unsigned char *p = (unsigned char *)s->init_buf->data;
563 0 : dtls1_set_message_header(s, p, htype, len, 0, len);
564 0 : s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH;
565 0 : s->init_off = 0;
566 : /* Buffer the message to handle re-xmits */
567 0 : dtls1_buffer_message(s, 0);
568 0 : }
569 :
570 0 : static int dtls1_handshake_write(SSL *s)
571 : {
572 0 : return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
573 : }
|