• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* DTLS implementation written by Nagendra Modadugu
2  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. */
3 /* ====================================================================
4  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. All advertising materials mentioning features or use of this
19  *    software must display the following acknowledgment:
20  *    "This product includes software developed by the OpenSSL Project
21  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22  *
23  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24  *    endorse or promote products derived from this software without
25  *    prior written permission. For written permission, please contact
26  *    openssl-core@openssl.org.
27  *
28  * 5. Products derived from this software may not be called "OpenSSL"
29  *    nor may "OpenSSL" appear in their names without prior written
30  *    permission of the OpenSSL Project.
31  *
32  * 6. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by the OpenSSL Project
35  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48  * OF THE POSSIBILITY OF SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This product includes cryptographic software written by Eric Young
52  * (eay@cryptsoft.com).  This product includes software written by Tim
53  * Hudson (tjh@cryptsoft.com).
54  *
55  */
56 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
57  * All rights reserved.
58  *
59  * This package is an SSL implementation written
60  * by Eric Young (eay@cryptsoft.com).
61  * The implementation was written so as to conform with Netscapes SSL.
62  *
63  * This library is free for commercial and non-commercial use as long as
64  * the following conditions are aheared to.  The following conditions
65  * apply to all code found in this distribution, be it the RC4, RSA,
66  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
67  * included with this distribution is covered by the same copyright terms
68  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
69  *
70  * Copyright remains Eric Young's, and as such any Copyright notices in
71  * the code are not to be removed.
72  * If this package is used in a product, Eric Young should be given attribution
73  * as the author of the parts of the library used.
74  * This can be in the form of a textual message at program startup or
75  * in documentation (online or textual) provided with the package.
76  *
77  * Redistribution and use in source and binary forms, with or without
78  * modification, are permitted provided that the following conditions
79  * are met:
80  * 1. Redistributions of source code must retain the copyright
81  *    notice, this list of conditions and the following disclaimer.
82  * 2. Redistributions in binary form must reproduce the above copyright
83  *    notice, this list of conditions and the following disclaimer in the
84  *    documentation and/or other materials provided with the distribution.
85  * 3. All advertising materials mentioning features or use of this software
86  *    must display the following acknowledgement:
87  *    "This product includes cryptographic software written by
88  *     Eric Young (eay@cryptsoft.com)"
89  *    The word 'cryptographic' can be left out if the rouines from the library
90  *    being used are not cryptographic related :-).
91  * 4. If you include any Windows specific code (or a derivative thereof) from
92  *    the apps directory (application code) you must include an acknowledgement:
93  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
94  *
95  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
96  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
99  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
105  * SUCH DAMAGE.
106  *
107  * The licence and distribution terms for any publically available version or
108  * derivative of this code cannot be changed.  i.e. this code cannot simply be
109  * copied and put under another distribution licence
110  * [including the GNU Public Licence.] */
111 
112 #include <openssl/ssl.h>
113 
114 #include <assert.h>
115 #include <string.h>
116 
117 #include <openssl/bio.h>
118 #include <openssl/buf.h>
119 #include <openssl/bytestring.h>
120 #include <openssl/mem.h>
121 #include <openssl/evp.h>
122 #include <openssl/err.h>
123 #include <openssl/rand.h>
124 
125 #include "../crypto/internal.h"
126 #include "internal.h"
127 
128 
dtls1_get_record(SSL * ssl)129 int dtls1_get_record(SSL *ssl) {
130 again:
131   switch (ssl->s3->recv_shutdown) {
132     case ssl_shutdown_none:
133       break;
134     case ssl_shutdown_fatal_alert:
135       OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
136       return -1;
137     case ssl_shutdown_close_notify:
138       return 0;
139   }
140 
141   /* Read a new packet if there is no unconsumed one. */
142   if (ssl_read_buffer_len(ssl) == 0) {
143     int read_ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */);
144     if (read_ret < 0 && dtls1_is_timer_expired(ssl)) {
145       /* Historically, timeouts were handled implicitly if the caller did not
146        * handle them.
147        *
148        * TODO(davidben): This was to support blocking sockets but affected
149        * non-blocking sockets. Can it be removed? */
150       int timeout_ret = DTLSv1_handle_timeout(ssl);
151       if (timeout_ret <= 0) {
152         return timeout_ret;
153       }
154       goto again;
155     }
156     if (read_ret <= 0) {
157       return read_ret;
158     }
159   }
160   assert(ssl_read_buffer_len(ssl) > 0);
161 
162   CBS body;
163   uint8_t type, alert;
164   size_t consumed;
165   enum ssl_open_record_t open_ret =
166       dtls_open_record(ssl, &type, &body, &consumed, &alert,
167                        ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
168   ssl_read_buffer_consume(ssl, consumed);
169   switch (open_ret) {
170     case ssl_open_record_partial:
171       /* Impossible in DTLS. */
172       break;
173 
174     case ssl_open_record_success: {
175       if (CBS_len(&body) > 0xffff) {
176         OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
177         return -1;
178       }
179 
180       SSL3_RECORD *rr = &ssl->s3->rrec;
181       rr->type = type;
182       rr->length = (uint16_t)CBS_len(&body);
183       rr->data = (uint8_t *)CBS_data(&body);
184       return 1;
185     }
186 
187     case ssl_open_record_discard:
188       goto again;
189 
190     case ssl_open_record_close_notify:
191       return 0;
192 
193     case ssl_open_record_fatal_alert:
194       return -1;
195 
196     case ssl_open_record_error:
197       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
198       return -1;
199   }
200 
201   assert(0);
202   OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
203   return -1;
204 }
205 
dtls1_read_app_data(SSL * ssl,int * out_got_handshake,uint8_t * buf,int len,int peek)206 int dtls1_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
207                         int peek) {
208   assert(!SSL_in_init(ssl));
209 
210   *out_got_handshake = 0;
211   SSL3_RECORD *rr = &ssl->s3->rrec;
212 
213 again:
214   if (rr->length == 0) {
215     int ret = dtls1_get_record(ssl);
216     if (ret <= 0) {
217       return ret;
218     }
219   }
220 
221   if (rr->type == SSL3_RT_HANDSHAKE) {
222     /* Parse the first fragment header to determine if this is a pre-CCS or
223      * post-CCS handshake record. DTLS resets handshake message numbers on each
224      * handshake, so renegotiations and retransmissions are ambiguous. */
225     CBS cbs, body;
226     struct hm_header_st msg_hdr;
227     CBS_init(&cbs, rr->data, rr->length);
228     if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
229       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
230       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
231       return -1;
232     }
233 
234     if (msg_hdr.type == SSL3_MT_FINISHED &&
235         msg_hdr.seq == ssl->d1->handshake_read_seq - 1) {
236       if (msg_hdr.frag_off == 0) {
237         /* Retransmit our last flight of messages. If the peer sends the second
238          * Finished, they may not have received ours. Only do this for the
239          * first fragment, in case the Finished was fragmented. */
240         if (dtls1_check_timeout_num(ssl) < 0) {
241           return -1;
242         }
243 
244         dtls1_retransmit_outgoing_messages(ssl);
245       }
246 
247       rr->length = 0;
248       goto again;
249     }
250 
251     /* Otherwise, this is a pre-CCS handshake message from an unsupported
252      * renegotiation attempt. Fall through to the error path. */
253   }
254 
255   if (rr->type != SSL3_RT_APPLICATION_DATA) {
256     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
257     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
258     return -1;
259   }
260 
261   /* Discard empty records. */
262   if (rr->length == 0) {
263     goto again;
264   }
265 
266   if (len <= 0) {
267     return len;
268   }
269 
270   if ((unsigned)len > rr->length) {
271     len = rr->length;
272   }
273 
274   OPENSSL_memcpy(buf, rr->data, len);
275   if (!peek) {
276     /* TODO(davidben): Should the record be truncated instead? This is a
277      * datagram transport. See https://crbug.com/boringssl/65. */
278     rr->length -= len;
279     rr->data += len;
280     if (rr->length == 0) {
281       /* The record has been consumed, so we may now clear the buffer. */
282       ssl_read_buffer_discard(ssl);
283     }
284   }
285 
286   return len;
287 }
288 
dtls1_read_change_cipher_spec(SSL * ssl)289 int dtls1_read_change_cipher_spec(SSL *ssl) {
290   SSL3_RECORD *rr = &ssl->s3->rrec;
291 
292 again:
293   if (rr->length == 0) {
294     int ret = dtls1_get_record(ssl);
295     if (ret <= 0) {
296       return ret;
297     }
298   }
299 
300   /* Drop handshake records silently. The epochs match, so this must be a
301    * retransmit of a message we already received. */
302   if (rr->type == SSL3_RT_HANDSHAKE) {
303     rr->length = 0;
304     goto again;
305   }
306 
307   /* Other record types are illegal in this epoch. Note all application data
308    * records come in the encrypted epoch. */
309   if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
310     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
311     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
312     return -1;
313   }
314 
315   if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) {
316     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
317     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
318     return -1;
319   }
320 
321   ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data,
322                       rr->length);
323 
324   rr->length = 0;
325   ssl_read_buffer_discard(ssl);
326   return 1;
327 }
328 
dtls1_read_close_notify(SSL * ssl)329 void dtls1_read_close_notify(SSL *ssl) {
330   /* Bidirectional shutdown doesn't make sense for an unordered transport. DTLS
331    * alerts also aren't delivered reliably, so we may even time out because the
332    * peer never received our close_notify. Report to the caller that the channel
333    * has fully shut down. */
334   if (ssl->s3->recv_shutdown == ssl_shutdown_none) {
335     ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
336   }
337 }
338 
dtls1_write_app_data(SSL * ssl,int * out_needs_handshake,const uint8_t * buf,int len)339 int dtls1_write_app_data(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
340                          int len) {
341   assert(!SSL_in_init(ssl));
342   *out_needs_handshake = 0;
343 
344   if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
345     OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
346     return -1;
347   }
348 
349   if (len < 0) {
350     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
351     return -1;
352   }
353 
354   if (len == 0) {
355     return 0;
356   }
357 
358   int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, buf, (size_t)len,
359                                dtls1_use_current_epoch);
360   if (ret <= 0) {
361     return ret;
362   }
363   return len;
364 }
365 
dtls1_write_record(SSL * ssl,int type,const uint8_t * buf,size_t len,enum dtls1_use_epoch_t use_epoch)366 int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len,
367                        enum dtls1_use_epoch_t use_epoch) {
368   assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
369   /* There should never be a pending write buffer in DTLS. One can't write half
370    * a datagram, so the write buffer is always dropped in
371    * |ssl_write_buffer_flush|. */
372   assert(!ssl_write_buffer_is_pending(ssl));
373 
374   if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
375     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
376     return -1;
377   }
378 
379   size_t max_out = len + SSL_max_seal_overhead(ssl);
380   uint8_t *out;
381   size_t ciphertext_len;
382   if (!ssl_write_buffer_init(ssl, &out, max_out) ||
383       !dtls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len,
384                         use_epoch)) {
385     ssl_write_buffer_clear(ssl);
386     return -1;
387   }
388   ssl_write_buffer_set_len(ssl, ciphertext_len);
389 
390   int ret = ssl_write_buffer_flush(ssl);
391   if (ret <= 0) {
392     return ret;
393   }
394   return 1;
395 }
396 
dtls1_dispatch_alert(SSL * ssl)397 int dtls1_dispatch_alert(SSL *ssl) {
398   int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2,
399                                dtls1_use_current_epoch);
400   if (ret <= 0) {
401     return ret;
402   }
403   ssl->s3->alert_dispatch = 0;
404 
405   /* If the alert is fatal, flush the BIO now. */
406   if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
407     BIO_flush(ssl->wbio);
408   }
409 
410   ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert,
411                       2);
412 
413   int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
414   ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
415 
416   return 1;
417 }
418