• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * DTLS implementation written by Nagendra Modadugu
3  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
59  * All rights reserved.
60  *
61  * This package is an SSL implementation written
62  * by Eric Young (eay@cryptsoft.com).
63  * The implementation was written so as to conform with Netscapes SSL.
64  *
65  * This library is free for commercial and non-commercial use as long as
66  * the following conditions are aheared to.  The following conditions
67  * apply to all code found in this distribution, be it the RC4, RSA,
68  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
69  * included with this distribution is covered by the same copyright terms
70  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
71  *
72  * Copyright remains Eric Young's, and as such any Copyright notices in
73  * the code are not to be removed.
74  * If this package is used in a product, Eric Young should be given attribution
75  * as the author of the parts of the library used.
76  * This can be in the form of a textual message at program startup or
77  * in documentation (online or textual) provided with the package.
78  *
79  * Redistribution and use in source and binary forms, with or without
80  * modification, are permitted provided that the following conditions
81  * are met:
82  * 1. Redistributions of source code must retain the copyright
83  *    notice, this list of conditions and the following disclaimer.
84  * 2. Redistributions in binary form must reproduce the above copyright
85  *    notice, this list of conditions and the following disclaimer in the
86  *    documentation and/or other materials provided with the distribution.
87  * 3. All advertising materials mentioning features or use of this software
88  *    must display the following acknowledgement:
89  *    "This product includes cryptographic software written by
90  *     Eric Young (eay@cryptsoft.com)"
91  *    The word 'cryptographic' can be left out if the rouines from the library
92  *    being used are not cryptographic related :-).
93  * 4. If you include any Windows specific code (or a derivative thereof) from
94  *    the apps directory (application code) you must include an acknowledgement:
95  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
96  *
97  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
98  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
99  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
100  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
101  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
102  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
103  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
104  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
105  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
106  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
107  * SUCH DAMAGE.
108  *
109  * The licence and distribution terms for any publically available version or
110  * derivative of this code cannot be changed.  i.e. this code cannot simply be
111  * copied and put under another distribution licence
112  * [including the GNU Public Licence.]
113  */
114 
115 #include <openssl/ssl.h>
116 
117 #include <assert.h>
118 #include <stdio.h>
119 
120 #include <openssl/bn.h>
121 #include <openssl/buf.h>
122 #include <openssl/dh.h>
123 #include <openssl/err.h>
124 #include <openssl/evp.h>
125 #include <openssl/md5.h>
126 #include <openssl/obj.h>
127 #include <openssl/rand.h>
128 #include <openssl/x509.h>
129 
130 #include "internal.h"
131 
132 
dtls1_accept(SSL * ssl)133 int dtls1_accept(SSL *ssl) {
134   BUF_MEM *buf = NULL;
135   void (*cb)(const SSL *ssl, int type, int value) = NULL;
136   uint32_t alg_a;
137   int ret = -1;
138   int new_state, state, skip = 0;
139 
140   assert(ssl->handshake_func == dtls1_accept);
141   assert(ssl->server);
142   assert(SSL_IS_DTLS(ssl));
143 
144   ERR_clear_error();
145   ERR_clear_system_error();
146 
147   if (ssl->info_callback != NULL) {
148     cb = ssl->info_callback;
149   } else if (ssl->ctx->info_callback != NULL) {
150     cb = ssl->ctx->info_callback;
151   }
152 
153   ssl->in_handshake++;
154 
155   for (;;) {
156     state = ssl->state;
157 
158     switch (ssl->state) {
159       case SSL_ST_ACCEPT:
160         if (cb != NULL) {
161           cb(ssl, SSL_CB_HANDSHAKE_START, 1);
162         }
163 
164         if (ssl->init_buf == NULL) {
165           buf = BUF_MEM_new();
166           if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
167             ret = -1;
168             goto end;
169           }
170           ssl->init_buf = buf;
171           buf = NULL;
172         }
173 
174         ssl->init_num = 0;
175 
176         if (!ssl_init_wbio_buffer(ssl, 1)) {
177           ret = -1;
178           goto end;
179         }
180 
181         if (!ssl3_init_handshake_buffer(ssl)) {
182           OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
183           ret = -1;
184           goto end;
185         }
186 
187         ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
188         break;
189 
190       case SSL3_ST_SR_CLNT_HELLO_A:
191       case SSL3_ST_SR_CLNT_HELLO_B:
192       case SSL3_ST_SR_CLNT_HELLO_C:
193       case SSL3_ST_SR_CLNT_HELLO_D:
194         ssl->shutdown = 0;
195         ret = ssl3_get_client_hello(ssl);
196         if (ret <= 0) {
197           goto end;
198         }
199         dtls1_stop_timer(ssl);
200         ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
201         ssl->init_num = 0;
202         break;
203 
204       case SSL3_ST_SW_SRVR_HELLO_A:
205       case SSL3_ST_SW_SRVR_HELLO_B:
206         dtls1_start_timer(ssl);
207         ret = ssl3_send_server_hello(ssl);
208         if (ret <= 0) {
209           goto end;
210         }
211 
212         if (ssl->hit) {
213           if (ssl->tlsext_ticket_expected) {
214             ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
215           } else {
216             ssl->state = SSL3_ST_SW_CHANGE_A;
217           }
218         } else {
219           ssl->state = SSL3_ST_SW_CERT_A;
220         }
221         ssl->init_num = 0;
222         break;
223 
224       case SSL3_ST_SW_CERT_A:
225       case SSL3_ST_SW_CERT_B:
226         if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
227           dtls1_start_timer(ssl);
228           ret = ssl3_send_server_certificate(ssl);
229           if (ret <= 0) {
230             goto end;
231           }
232           if (ssl->s3->tmp.certificate_status_expected) {
233             ssl->state = SSL3_ST_SW_CERT_STATUS_A;
234           } else {
235             ssl->state = SSL3_ST_SW_KEY_EXCH_A;
236           }
237         } else {
238           skip = 1;
239           ssl->state = SSL3_ST_SW_KEY_EXCH_A;
240         }
241         ssl->init_num = 0;
242         break;
243 
244       case SSL3_ST_SW_CERT_STATUS_A:
245       case SSL3_ST_SW_CERT_STATUS_B:
246         ret = ssl3_send_certificate_status(ssl);
247         if (ret <= 0) {
248           goto end;
249         }
250         ssl->state = SSL3_ST_SW_KEY_EXCH_A;
251         ssl->init_num = 0;
252         break;
253 
254       case SSL3_ST_SW_KEY_EXCH_A:
255       case SSL3_ST_SW_KEY_EXCH_B:
256       case SSL3_ST_SW_KEY_EXCH_C:
257         alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
258 
259         /* Send a ServerKeyExchange message if:
260          * - The key exchange is ephemeral or anonymous
261          *   Diffie-Hellman.
262          * - There is a PSK identity hint.
263          *
264          * TODO(davidben): This logic is currently duplicated
265          * in s3_srvr.c. Fix this. In the meantime, keep them
266          * in sync. */
267         if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
268             ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
269           dtls1_start_timer(ssl);
270           ret = ssl3_send_server_key_exchange(ssl);
271           if (ret <= 0) {
272             goto end;
273           }
274         } else {
275           skip = 1;
276         }
277 
278         ssl->state = SSL3_ST_SW_CERT_REQ_A;
279         ssl->init_num = 0;
280         break;
281 
282       case SSL3_ST_SW_CERT_REQ_A:
283       case SSL3_ST_SW_CERT_REQ_B:
284         if (ssl->s3->tmp.cert_request) {
285           dtls1_start_timer(ssl);
286           ret = ssl3_send_certificate_request(ssl);
287           if (ret <= 0) {
288             goto end;
289           }
290         } else {
291           skip = 1;
292         }
293         ssl->state = SSL3_ST_SW_SRVR_DONE_A;
294         ssl->init_num = 0;
295         break;
296 
297       case SSL3_ST_SW_SRVR_DONE_A:
298       case SSL3_ST_SW_SRVR_DONE_B:
299         dtls1_start_timer(ssl);
300         ret = ssl3_send_server_done(ssl);
301         if (ret <= 0) {
302           goto end;
303         }
304         ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
305         ssl->state = SSL3_ST_SW_FLUSH;
306         ssl->init_num = 0;
307         break;
308 
309       case SSL3_ST_SW_FLUSH:
310         ssl->rwstate = SSL_WRITING;
311         if (BIO_flush(ssl->wbio) <= 0) {
312           ret = -1;
313           goto end;
314         }
315         ssl->rwstate = SSL_NOTHING;
316         ssl->state = ssl->s3->tmp.next_state;
317         break;
318 
319       case SSL3_ST_SR_CERT_A:
320       case SSL3_ST_SR_CERT_B:
321         if (ssl->s3->tmp.cert_request) {
322           ret = ssl3_get_client_certificate(ssl);
323           if (ret <= 0) {
324             goto end;
325           }
326         }
327         ssl->init_num = 0;
328         ssl->state = SSL3_ST_SR_KEY_EXCH_A;
329         break;
330 
331       case SSL3_ST_SR_KEY_EXCH_A:
332       case SSL3_ST_SR_KEY_EXCH_B:
333       case SSL3_ST_SR_KEY_EXCH_C:
334         ret = ssl3_get_client_key_exchange(ssl);
335         if (ret <= 0) {
336           goto end;
337         }
338         ssl->state = SSL3_ST_SR_CERT_VRFY_A;
339         ssl->init_num = 0;
340         break;
341 
342       case SSL3_ST_SR_CERT_VRFY_A:
343       case SSL3_ST_SR_CERT_VRFY_B:
344         ret = ssl3_get_cert_verify(ssl);
345         if (ret <= 0) {
346           goto end;
347         }
348         ssl->state = SSL3_ST_SR_CHANGE;
349         ssl->init_num = 0;
350         break;
351 
352       case SSL3_ST_SR_CHANGE:
353         ret = ssl->method->ssl_read_change_cipher_spec(ssl);
354         if (ret <= 0) {
355           goto end;
356         }
357 
358         if (!ssl3_do_change_cipher_spec(ssl)) {
359           ret = -1;
360           goto end;
361         }
362 
363         ssl->state = SSL3_ST_SR_FINISHED_A;
364         break;
365 
366       case SSL3_ST_SR_FINISHED_A:
367       case SSL3_ST_SR_FINISHED_B:
368         ret = ssl3_get_finished(ssl, SSL3_ST_SR_FINISHED_A,
369                                 SSL3_ST_SR_FINISHED_B);
370         if (ret <= 0) {
371           goto end;
372         }
373         dtls1_stop_timer(ssl);
374         if (ssl->hit) {
375           ssl->state = SSL_ST_OK;
376         } else if (ssl->tlsext_ticket_expected) {
377           ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
378         } else {
379           ssl->state = SSL3_ST_SW_CHANGE_A;
380         }
381         ssl->init_num = 0;
382         break;
383 
384       case SSL3_ST_SW_SESSION_TICKET_A:
385       case SSL3_ST_SW_SESSION_TICKET_B:
386         ret = ssl3_send_new_session_ticket(ssl);
387         if (ret <= 0) {
388           goto end;
389         }
390         ssl->state = SSL3_ST_SW_CHANGE_A;
391         ssl->init_num = 0;
392         break;
393 
394       case SSL3_ST_SW_CHANGE_A:
395       case SSL3_ST_SW_CHANGE_B:
396         ssl->session->cipher = ssl->s3->tmp.new_cipher;
397         if (!ssl->enc_method->setup_key_block(ssl)) {
398           ret = -1;
399           goto end;
400         }
401 
402         ret = dtls1_send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A,
403                                             SSL3_ST_SW_CHANGE_B);
404 
405         if (ret <= 0) {
406           goto end;
407         }
408 
409         ssl->state = SSL3_ST_SW_FINISHED_A;
410         ssl->init_num = 0;
411 
412         if (!ssl->enc_method->change_cipher_state(
413                 ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
414           ret = -1;
415           goto end;
416         }
417         break;
418 
419       case SSL3_ST_SW_FINISHED_A:
420       case SSL3_ST_SW_FINISHED_B:
421         ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
422                                  SSL3_ST_SW_FINISHED_B,
423                                  ssl->enc_method->server_finished_label,
424                                  ssl->enc_method->server_finished_label_len);
425         if (ret <= 0) {
426           goto end;
427         }
428         ssl->state = SSL3_ST_SW_FLUSH;
429         if (ssl->hit) {
430           ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
431         } else {
432           ssl->s3->tmp.next_state = SSL_ST_OK;
433         }
434         ssl->init_num = 0;
435         break;
436 
437       case SSL_ST_OK:
438         ssl3_cleanup_key_block(ssl);
439 
440         /* remove buffering on output */
441         ssl_free_wbio_buffer(ssl);
442 
443         ssl->init_num = 0;
444         ssl->s3->initial_handshake_complete = 1;
445 
446         ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
447 
448         if (cb != NULL) {
449           cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
450         }
451 
452         ret = 1;
453 
454         /* done handshaking, next message is client hello */
455         ssl->d1->handshake_read_seq = 0;
456         /* next message is server hello */
457         ssl->d1->handshake_write_seq = 0;
458         ssl->d1->next_handshake_write_seq = 0;
459         goto end;
460 
461       default:
462         OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
463         ret = -1;
464         goto end;
465     }
466 
467     if (!ssl->s3->tmp.reuse_message && !skip) {
468       if (cb != NULL && ssl->state != state) {
469         new_state = ssl->state;
470         ssl->state = state;
471         cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
472         ssl->state = new_state;
473       }
474     }
475     skip = 0;
476   }
477 
478 end:
479   ssl->in_handshake--;
480   BUF_MEM_free(buf);
481   if (cb != NULL) {
482     cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
483   }
484   return ret;
485 }
486