1 /* 2 * DTLS implementation written by Nagendra Modadugu 3 * (nagendra (at) 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 (at) 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 (at) cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh (at) cryptsoft.com). 56 * 57 */ 58 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 59 * All rights reserved. 60 * 61 * This package is an SSL implementation written 62 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 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