int dtls1_query_mtu(SSL *s) { if (s->d1->link_mtu) { s->d1->mtu = s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s)); s->d1->link_mtu = 0; } /* AHA! Figure out the MTU, and stick to the right size */ if (s->d1->mtu < dtls1_min_mtu(s)) { if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); /* * I've seen the kernel return bogus numbers when it doesn't know * (initial write), so just make sure we have a reasonable number */ if (s->d1->mtu < dtls1_min_mtu(s)) { /* Set to min mtu */ s->d1->mtu = dtls1_min_mtu(s); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, (long)s->d1->mtu, NULL); } } else return 0; } return 1; }
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { const unsigned char cryptopro_ext[36] = { 0xfd, 0xe8, /* 65000 */ 0x00, 0x20, /* 32 bytes length */ 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17 }; if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80 && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81) || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0) return EXT_RETURN_NOT_SENT; if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
void dtls1_clear(SSL *s) { pqueue unprocessed_rcds; pqueue processed_rcds; pqueue buffered_messages; pqueue sent_messages; pqueue buffered_app_data; unsigned int mtu; if (s->d1) { unprocessed_rcds = s->d1->unprocessed_rcds.q; processed_rcds = s->d1->processed_rcds.q; buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; buffered_app_data = s->d1->buffered_app_data.q; mtu = s->d1->mtu; dtls1_clear_queues(s); pq_64bit_free(&(s->d1->bitmap.map)); pq_64bit_free(&(s->d1->bitmap.max_seq_num)); pq_64bit_free(&(s->d1->next_bitmap.map)); pq_64bit_free(&(s->d1->next_bitmap.max_seq_num)); memset(s->d1, 0, sizeof(*(s->d1))); if (s->server) { s->d1->cookie_len = sizeof(s->d1->cookie); } if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { s->d1->mtu = mtu; } s->d1->unprocessed_rcds.q = unprocessed_rcds; s->d1->processed_rcds.q = processed_rcds; s->d1->buffered_messages = buffered_messages; s->d1->sent_messages = sent_messages; s->d1->buffered_app_data.q = buffered_app_data; #if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST) s->d1->bitmap.length = 64; #else s->d1->bitmap.length = sizeof(s->d1->bitmap.map) * 8; #endif pq_64bit_init(&(s->d1->bitmap.map)); pq_64bit_init(&(s->d1->bitmap.max_seq_num)); s->d1->next_bitmap.length = s->d1->bitmap.length; pq_64bit_init(&(s->d1->next_bitmap.map)); pq_64bit_init(&(s->d1->next_bitmap.max_seq_num)); } ssl3_clear(s); if (s->options & SSL_OP_CISCO_ANYCONNECT) s->version = DTLS1_BAD_VER; else s->version = DTLS1_VERSION; }
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; unsigned char *ret = p; ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL) { if (limit - ret - 4 < 0) return NULL; s2n(TLSEXT_TYPE_server_name,ret); s2n(0,ret); } if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) { if (limit - ret - 4 < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); s2n(0,ret); } if ((extdatalen = ret-p-2)== 0) return p; s2n(extdatalen,p); return ret; }
/* OpenSSL < 0.9.8m does not have SSL_clear_options() */ long HsOpenSSL_SSL_clear_options(SSL* ssl, long options) { #if defined(SSL_clear_options) return SSL_clear_options(ssl, options); #else long tmp = SSL_get_options(ssl); return SSL_set_options(ssl, tmp & ~options); #endif }
static int checksslv2(int test, int sslv2) { int options; if (test == TEST_SSL_CTX) { options = SSL_CTX_get_options(ctx); } else { options = SSL_get_options(ssl); } return ((options & SSL_OP_NO_SSLv2) == 0) ^ (sslv2 == SSLV2OFF); }
int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, const unsigned char *limit, SSL_SESSION **ret) { /* Point after session ID in client hello */ const unsigned char *p = session_id + len; unsigned short i; /* If tickets disabled behave as if no ticket present * to permit stateful resumption. */ if (SSL_get_options(s) & SSL_OP_NO_TICKET) return 1; if ((s->version <= SSL3_VERSION) || !limit) return 1; if (p >= limit) return -1; /* Skip past cipher list */ n2s(p, i); p+= i; if (p >= limit) return -1; /* Skip past compression algorithm list */ i = *(p++); p += i; if (p > limit) return -1; /* Now at start of extensions */ if ((p + 2) >= limit) return 1; n2s(p, i); while ((p + 4) <= limit) { unsigned short type, size; n2s(p, type); n2s(p, size); if (p + size > limit) return 1; if (type == TLSEXT_TYPE_session_ticket) { /* If zero length note client will accept a ticket * and indicate cache miss to trigger full handshake */ if (size == 0) { s->tlsext_ticket_expected = 1; return 0; /* Cache miss */ } return tls_decrypt_ticket(s, p, size, session_id, len, ret); } p += size; } return 1; }
void dtls1_clear (SSL * s) { pqueue unprocessed_rcds; pqueue processed_rcds; pqueue buffered_messages; pqueue sent_messages; pqueue buffered_app_data; unsigned int mtu; unsigned int link_mtu; if (s->d1) { unprocessed_rcds = s->d1->unprocessed_rcds.q; processed_rcds = s->d1->processed_rcds.q; buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; buffered_app_data = s->d1->buffered_app_data.q; mtu = s->d1->mtu; link_mtu = s->d1->link_mtu; dtls1_clear_queues (s); memset (s->d1, 0, sizeof (*(s->d1))); if (s->server) { s->d1->cookie_len = sizeof (s->d1->cookie); } if (SSL_get_options (s) & SSL_OP_NO_QUERY_MTU) { s->d1->mtu = mtu; s->d1->link_mtu = link_mtu; } s->d1->unprocessed_rcds.q = unprocessed_rcds; s->d1->processed_rcds.q = processed_rcds; s->d1->buffered_messages = buffered_messages; s->d1->sent_messages = sent_messages; s->d1->buffered_app_data.q = buffered_app_data; } ssl3_clear (s); if (s->options & SSL_OP_CISCO_ANYCONNECT) s->version = DTLS1_BAD_VER; else s->version = DTLS1_VERSION; }
int dtls1_clear(SSL *s) { pqueue *buffered_messages; pqueue *sent_messages; size_t mtu; size_t link_mtu; DTLS_RECORD_LAYER_clear(&s->rlayer); if (s->d1) { buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; mtu = s->d1->mtu; link_mtu = s->d1->link_mtu; dtls1_clear_queues(s); memset(s->d1, 0, sizeof(*s->d1)); if (s->server) { s->d1->cookie_len = sizeof(s->d1->cookie); } if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { s->d1->mtu = mtu; s->d1->link_mtu = link_mtu; } s->d1->buffered_messages = buffered_messages; s->d1->sent_messages = sent_messages; } if (!ssl3_clear(s)) return 0; if (s->method->version == DTLS_ANY_VERSION) s->version = DTLS_MAX_VERSION; #ifndef OPENSSL_NO_DTLS1_METHOD else if (s->options & SSL_OP_CISCO_ANYCONNECT) s->client_version = s->version = DTLS1_BAD_VER; #endif else s->version = s->method->version; return 1; }
void dtls1_clear(SSL *s) { struct dtls1_state_internal_st *internal; pqueue unprocessed_rcds; pqueue processed_rcds; pqueue buffered_messages; pqueue sent_messages; pqueue buffered_app_data; unsigned int mtu; if (s->d1) { unprocessed_rcds = D1I(s)->unprocessed_rcds.q; processed_rcds = D1I(s)->processed_rcds.q; buffered_messages = D1I(s)->buffered_messages; sent_messages = s->d1->sent_messages; buffered_app_data = D1I(s)->buffered_app_data.q; mtu = D1I(s)->mtu; dtls1_clear_queues(s); memset(s->d1->internal, 0, sizeof(*s->d1->internal)); internal = s->d1->internal; memset(s->d1, 0, sizeof(*s->d1)); s->d1->internal = internal; if (s->server) { D1I(s)->cookie_len = sizeof(D1I(s)->cookie); } if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { D1I(s)->mtu = mtu; } D1I(s)->unprocessed_rcds.q = unprocessed_rcds; D1I(s)->processed_rcds.q = processed_rcds; D1I(s)->buffered_messages = buffered_messages; s->d1->sent_messages = sent_messages; D1I(s)->buffered_app_data.q = buffered_app_data; } ssl3_clear(s); s->version = DTLS1_VERSION; }
enum ssl_session_result_t ssl_get_prev_session( SSL *ssl, SSL_SESSION **out_session, int *out_tickets_supported, int *out_renew_ticket, const SSL_CLIENT_HELLO *client_hello) { /* This is used only by servers. */ assert(ssl->server); SSL_SESSION *session = NULL; int renew_ticket = 0; /* If tickets are disabled, always behave as if no tickets are present. */ const uint8_t *ticket = NULL; size_t ticket_len = 0; const int tickets_supported = !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) && ssl->version > SSL3_VERSION && SSL_early_callback_ctx_extension_get( client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len); if (tickets_supported && ticket_len > 0) { switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len, client_hello->session_id, client_hello->session_id_len)) { case ssl_ticket_aead_success: break; case ssl_ticket_aead_ignore_ticket: assert(session == NULL); break; case ssl_ticket_aead_error: return ssl_session_error; case ssl_ticket_aead_retry: return ssl_session_ticket_retry; } } else { /* The client didn't send a ticket, so the session ID is a real ID. */ enum ssl_session_result_t lookup_ret = ssl_lookup_session( ssl, &session, client_hello->session_id, client_hello->session_id_len); if (lookup_ret != ssl_session_success) { return lookup_ret; } } *out_session = session; *out_tickets_supported = tickets_supported; *out_renew_ticket = renew_ticket; return ssl_session_success; }
int dtls1_check_timeout_num(SSL *ssl) { ssl->d1->num_timeouts++; /* Reduce MTU after 2 unsuccessful retransmissions */ if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS && !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) { ssl->d1->mtu = (unsigned)mtu; } } if (ssl->d1->num_timeouts > DTLS1_MAX_TIMEOUTS) { /* fail the connection, enough alerts have been sent */ OPENSSL_PUT_ERROR(SSL, SSL_R_READ_TIMEOUT_EXPIRED); return -1; } return 0; }
void dtls1_clear(SSL *s) { pqueue buffered_messages; pqueue sent_messages; unsigned int mtu; unsigned int link_mtu; DTLS_RECORD_LAYER_clear(&s->rlayer); if (s->d1) { buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; mtu = s->d1->mtu; link_mtu = s->d1->link_mtu; dtls1_clear_queues(s); memset(s->d1, 0, sizeof(*s->d1)); if (s->server) { s->d1->cookie_len = sizeof(s->d1->cookie); } if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { s->d1->mtu = mtu; s->d1->link_mtu = link_mtu; } s->d1->buffered_messages = buffered_messages; s->d1->sent_messages = sent_messages; } ssl3_clear(s); if (s->options & SSL_OP_CISCO_ANYCONNECT) s->client_version = s->version = DTLS1_BAD_VER; else if (s->method->version == DTLS_ANY_VERSION) s->version = DTLS1_2_VERSION; else s->version = s->method->version; }
int dtls1_check_timeout_num(SSL *s) { unsigned int mtu; s->d1->timeout.num_alerts++; /* Reduce MTU after 2 unsuccessful retransmissions */ if (s->d1->timeout.num_alerts > 2 && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); if (mtu < s->d1->mtu) s->d1->mtu = mtu; } if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { /* fail the connection, enough alerts have been sent */ SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED); return -1; } return 0; }
/* handle_connect_results assumes that select or poll have already shown the * descriptor to be active */ void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status status) { int optval; socklen_t optlen = sizeof(int); struct niod *iod = nse->iod; #if HAVE_OPENSSL int sslerr; int rc = 0; int sslconnect_inprogress = nse->type == NSE_TYPE_CONNECT_SSL && nse->iod && (nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ || nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE); #else int sslconnect_inprogress = 0; #endif if (status == NSE_STATUS_TIMEOUT || status == NSE_STATUS_CANCELLED) { nse->status = status; nse->event_done = 1; } else if (sslconnect_inprogress) { /* Do nothing */ } else if (status == NSE_STATUS_SUCCESS) { /* First we want to determine whether the socket really is connected */ if (getsockopt(iod->sd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) != 0) optval = socket_errno(); /* Stupid Solaris */ switch (optval) { case 0: nse->status = NSE_STATUS_SUCCESS; break; /* EACCES can be caused by ICMPv6 dest-unreach-admin, or when a port is blocked by Windows Firewall (WSAEACCES). */ case EACCES: case ECONNREFUSED: case EHOSTUNREACH: case ENETDOWN: case ENETUNREACH: case ENETRESET: case ECONNABORTED: case ETIMEDOUT: case EHOSTDOWN: case ECONNRESET: #ifdef WIN32 case WSAEADDRINUSE: case WSAEADDRNOTAVAIL: #endif #ifndef WIN32 case EPIPE: /* Has been seen after connect on Linux. */ case ENOPROTOOPT: /* Also seen on Linux, perhaps in response to protocol unreachable. */ #endif nse->status = NSE_STATUS_ERROR; nse->errnum = optval; break; default: /* I'd like for someone to report it */ fatal("Strange connect error from %s (%d): %s", inet_ntop_ez(&iod->peer, iod->peerlen), optval, socket_strerror(optval)); } /* Now special code for the SSL case where the TCP connection was successful. */ if (nse->type == NSE_TYPE_CONNECT_SSL && nse->status == NSE_STATUS_SUCCESS) { #if HAVE_OPENSSL assert(ms->sslctx != NULL); /* Reuse iod->ssl if present. If set, this is the second try at connection without the SSL_OP_NO_SSLv2 option set. */ if (iod->ssl == NULL) { iod->ssl = SSL_new(ms->sslctx); if (!iod->ssl) fatal("SSL_new failed: %s", ERR_error_string(ERR_get_error(), NULL)); } #if HAVE_SSL_SET_TLSEXT_HOST_NAME if (iod->hostname != NULL) { if (SSL_set_tlsext_host_name(iod->ssl, iod->hostname) != 1) fatal("SSL_set_tlsext_host_name failed: %s", ERR_error_string(ERR_get_error(), NULL)); } #endif /* Associate our new SSL with the connected socket. It will inherit the * non-blocking nature of the sd */ if (SSL_set_fd(iod->ssl, iod->sd) != 1) fatal("SSL_set_fd failed: %s", ERR_error_string(ERR_get_error(), NULL)); /* Event not done -- need to do SSL connect below */ nse->sslinfo.ssl_desire = SSL_ERROR_WANT_CONNECT; #endif } else { /* This is not an SSL connect (in which case we are always done), or the * TCP connect() underlying the SSL failed (in which case we are also done */ nse->event_done = 1; } } else { fatal("Unknown status (%d)", status); } /* At this point the TCP connection is done, whether successful or not. * Therefore decrease the read/write listen counts that were incremented in * nsock_pool_add_event. In the SSL case, we may increase one of the counts depending * on whether SSL_connect returns an error of SSL_ERROR_WANT_READ or * SSL_ERROR_WANT_WRITE. In that case we will re-enter this function, but we * don't want to execute this block again. */ if (iod->sd != -1 && !sslconnect_inprogress) { int ev = EV_NONE; ev |= socket_count_read_dec(iod); ev |= socket_count_write_dec(iod); ev |= EV_EXCEPT; update_events(iod, ms, EV_NONE, ev); } #if HAVE_OPENSSL if (nse->type == NSE_TYPE_CONNECT_SSL && !nse->event_done) { /* Lets now start/continue/finish the connect! */ if (iod->ssl_session) { rc = SSL_set_session(iod->ssl, iod->ssl_session); if (rc == 0) nsock_log_error("Uh-oh: SSL_set_session() failed - please tell [email protected]"); iod->ssl_session = NULL; /* No need for this any more */ } /* If this is a reinvocation of handle_connect_result, clear out the listen * bits that caused it, based on the previous SSL desire. */ if (sslconnect_inprogress) { int ev; ev = socket_count_dec_ssl_desire(nse); update_events(iod, ms, EV_NONE, ev); } rc = SSL_connect(iod->ssl); if (rc == 1) { /* Woop! Connect is done! */ nse->event_done = 1; /* Check that certificate verification was okay, if requested. */ if (nsi_ssl_post_connect_verify(iod)) { nse->status = NSE_STATUS_SUCCESS; } else { nsock_log_error("certificate verification error for EID %li: %s", nse->id, ERR_error_string(ERR_get_error(), NULL)); nse->status = NSE_STATUS_ERROR; } } else { long options = SSL_get_options(iod->ssl); sslerr = SSL_get_error(iod->ssl, rc); if (rc == -1 && sslerr == SSL_ERROR_WANT_READ) { nse->sslinfo.ssl_desire = sslerr; socket_count_read_inc(iod); update_events(iod, ms, EV_READ, EV_NONE); } else if (rc == -1 && sslerr == SSL_ERROR_WANT_WRITE) { nse->sslinfo.ssl_desire = sslerr; socket_count_write_inc(iod); update_events(iod, ms, EV_WRITE, EV_NONE); } else if (!(options & SSL_OP_NO_SSLv2)) { int saved_ev; /* SSLv3-only and TLSv1-only servers can't be connected to when the * SSL_OP_NO_SSLv2 option is not set, which is the case when the pool * was initialized with nsock_pool_ssl_init_max_speed. Try reconnecting * with SSL_OP_NO_SSLv2. Never downgrade a NO_SSLv2 connection to one * that might use SSLv2. */ nsock_log_info("EID %li reconnecting with SSL_OP_NO_SSLv2", nse->id); saved_ev = iod->watched_events; nsock_engine_iod_unregister(ms, iod); close(iod->sd); nsock_connect_internal(ms, nse, SOCK_STREAM, iod->lastproto, &iod->peer, iod->peerlen, nsock_iod_get_peerport(iod)); nsock_engine_iod_register(ms, iod, saved_ev); SSL_clear(iod->ssl); if(!SSL_clear(iod->ssl)) fatal("SSL_clear failed: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_set_options(iod->ssl, options | SSL_OP_NO_SSLv2); socket_count_read_inc(nse->iod); socket_count_write_inc(nse->iod); update_events(iod, ms, EV_READ|EV_WRITE, EV_NONE); nse->sslinfo.ssl_desire = SSL_ERROR_WANT_CONNECT; } else { nsock_log_info("EID %li %s", nse->id, ERR_error_string(ERR_get_error(), NULL)); nse->event_done = 1; nse->status = NSE_STATUS_ERROR; nse->errnum = EIO; } } } #endif }
int dtls1_accept(SSL *s) { void (*cb)(const SSL *ssl, int type, int val) = NULL; unsigned long alg_k; int ret = -1; int new_state, state, skip = 0; int listen; ERR_clear_error(); errno = 0; if (s->info_callback != NULL) cb = s->info_callback; else if (s->ctx->info_callback != NULL) cb = s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; if (s->cert == NULL) { SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_NO_CERTIFICATE_SET); return (-1); } for (;;) { state = s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate = 1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server = 1; if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } s->type = SSL_ST_ACCEPT; if (s->init_buf == NULL) { BUF_MEM *buf; if ((buf = BUF_MEM_new()) == NULL) { ret = -1; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { BUF_MEM_free(buf); ret = -1; goto end; } s->init_buf = buf; } if (!ssl3_setup_buffers(s)) { ret = -1; goto end; } s->init_num = 0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; goto end; } if (!ssl3_init_finished_mac(s)) { ret = -1; goto end; } s->state = SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state = SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown = 0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret = dtls1_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; s->state = SSL3_ST_SW_FLUSH; s->init_num = 0; if (!ssl3_init_finished_mac(s)) { ret = -1; goto end; } break; case SSL3_ST_SW_HELLO_REQ_C: s->state = SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown = 0; ret = ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num = 0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_FLUSH; s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ if (s->version != DTLS1_BAD_VER) { if (!ssl3_init_finished_mac(s)) { ret = -1; goto end; } } break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret = dtls1_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) { if (s->tlsext_ticket_expected) s->state = SSL3_ST_SW_SESSION_TICKET_A; else s->state = SSL3_ST_SW_CHANGE_A; } else s->state = SSL3_ST_SW_CERT_A; s->init_num = 0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH. */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) { dtls1_start_timer(s); ret = dtls1_send_server_certificate(s); if (ret <= 0) goto end; if (s->tlsext_status_expected) s->state = SSL3_ST_SW_CERT_STATUS_A; else s->state = SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; s->state = SSL3_ST_SW_KEY_EXCH_A; } s->init_num = 0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* Only send if using a DH key exchange. */ if (alg_k & (SSL_kDHE|SSL_kECDHE)) { dtls1_start_timer(s); ret = dtls1_send_server_key_exchange(s); if (ret <= 0) goto end; } else skip = 1; s->state = SSL3_ST_SW_CERT_REQ_A; s->init_num = 0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: /* * Determine whether or not we need to request a * certificate. * * Do not request a certificate if: * * - We did not ask for it (SSL_VERIFY_PEER is unset). * * - SSL_VERIFY_CLIENT_ONCE is set and we are * renegotiating. * * - We are using an anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246) ... except when the application * insists on verification (against the specs, but * s3_clnt.c accepts this for SSL 3). */ if (!(s->verify_mode & SSL_VERIFY_PEER) || ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { /* no cert request */ skip = 1; s->s3->tmp.cert_request = 0; s->state = SSL3_ST_SW_SRVR_DONE_A; } else { s->s3->tmp.cert_request = 1; dtls1_start_timer(s); ret = dtls1_send_certificate_request(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_SRVR_DONE_A; s->init_num = 0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret = dtls1_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; s->state = SSL3_ST_SW_FLUSH; s->init_num = 0; break; case SSL3_ST_SW_FLUSH: s->rwstate = SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate = SSL_NOTHING; s->state = s->s3->tmp.next_state; } ret = -1; goto end; } s->rwstate = SSL_NOTHING; s->state = s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: /* Check for second client hello (MS SGC) */ ret = ssl3_check_client_hello(s); if (ret <= 0) goto end; if (ret == 2) { dtls1_stop_timer(s); s->state = SSL3_ST_SR_CLNT_HELLO_C; } else { /* could be sent for a DH cert, even if we * have not asked for it :-) */ ret = ssl3_get_client_certificate(s); if (ret <= 0) goto end; s->init_num = 0; s->state = SSL3_ST_SR_KEY_EXCH_A; } break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: ret = ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. */ s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; } else { s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret = ssl3_get_cert_verify(s); if (ret <= 0) goto end; s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->hit) s->state = SSL_ST_OK; else if (s->tlsext_ticket_expected) s->state = SSL3_ST_SW_SESSION_TICKET_A; else s->state = SSL3_ST_SW_CHANGE_A; s->init_num = 0; break; case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret = dtls1_send_newsession_ticket(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_CHANGE_A; s->init_num = 0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret = ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_KEY_EXCH_A; s->init_num = 0; break; case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher = s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret = -1; goto end; } ret = dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A, SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; s->state = SSL3_ST_SW_FINISHED_A; s->init_num = 0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret = -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret = dtls1_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state = SSL3_ST_SW_FLUSH; if (s->hit) { s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A; } else { s->s3->tmp.next_state = SSL_ST_OK; } s->init_num = 0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num = 0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate = 0; s->new_session = 0; ssl_update_cache(s, SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func = dtls1_accept; if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_DONE, 1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; /* break; */ default: SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_UNKNOWN_STATE); ret = -1; goto end; /* break; */ } if (!s->s3->tmp.reuse_message && !skip) { if (s->debug) { if ((ret = BIO_flush(s->wbio)) <= 0) goto end; } if ((cb != NULL) && (s->state != state)) { new_state = s->state; s->state = state; cb(s, SSL_CB_ACCEPT_LOOP, 1); s->state = new_state; } } skip = 0; } end: /* BIO_flush(s->wbio); */ s->in_handshake--; if (cb != NULL) cb(s, SSL_CB_ACCEPT_EXIT, ret); return (ret); }
/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ int dtls1_do_write(SSL *s, int type) { int ret; int curr_mtu; unsigned int len, frag_off, mac_size, blocksize; /* AHA! Figure out the MTU, and stick to the right size */ if (s->d1->mtu < dtls1_min_mtu() && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); /* I've seen the kernel return bogus numbers when it doesn't know * (initial write), so just make sure we have a reasonable number */ if (s->d1->mtu < dtls1_min_mtu()) { s->d1->mtu = 0; s->d1->mtu = dtls1_guess_mtu(s->d1->mtu); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, s->d1->mtu, NULL); } } #if 0 mtu = s->d1->mtu; fprintf(stderr, "using MTU = %d\n", mtu); mtu -= (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); curr_mtu = mtu - BIO_wpending(SSL_get_wbio(s)); if ( curr_mtu > 0) mtu = curr_mtu; else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0) return ret; if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu) { ret = BIO_flush(SSL_get_wbio(s)); if ( ret <= 0) return ret; mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); } #endif OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); /* should have something reasonable now */ if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE) OPENSSL_assert(s->init_num == (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); if (s->write_hash) mac_size = EVP_MD_size(s->write_hash); else mac_size = 0; if (s->enc_write_ctx && (EVP_CIPHER_mode( s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher); else blocksize = 0; frag_off = 0; while( s->init_num) { curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH) { /* grr.. we could get an error if MTU picked was wrong */ ret = BIO_flush(SSL_get_wbio(s)); if ( ret <= 0) return ret; curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; } if ( s->init_num > curr_mtu) len = curr_mtu; else len = s->init_num; /* XDTLS: this function is too long. split out the CCS part */ if ( type == SSL3_RT_HANDSHAKE) { if ( s->init_off != 0) { OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH); s->init_off -= DTLS1_HM_HEADER_LENGTH; s->init_num += DTLS1_HM_HEADER_LENGTH; if ( s->init_num > curr_mtu) len = curr_mtu; else len = s->init_num; } dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH); dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]); OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH); } ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off], len); if (ret < 0) { /* might need to update MTU here, but we don't know * which previous packet caused the failure -- so can't * really retransmit anything. continue as if everything * is fine and wait for an alert to handle the * retransmit */ if ( BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 ) s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); else return(-1); } else { /* bad if this assert fails, only part of the handshake * message got sent. but why would this happen? */ OPENSSL_assert(len == (unsigned int)ret); if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting) { /* should not be done for 'Hello Request's, but in that case * we'll ignore the result anyway */ unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off]; const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; int xlen; if (frag_off == 0 && s->client_version != DTLS1_BAD_VER) { /* reconstruct message header is if it * is being sent in single fragment */ *p++ = msg_hdr->type; l2n3(msg_hdr->msg_len,p); s2n (msg_hdr->seq,p); l2n3(0,p); l2n3(msg_hdr->msg_len,p); p -= DTLS1_HM_HEADER_LENGTH; xlen = ret; } else { p += DTLS1_HM_HEADER_LENGTH; xlen = ret - DTLS1_HM_HEADER_LENGTH; } ssl3_finish_mac(s, p, xlen); } if (ret == s->init_num) { if (s->msg_callback) s->msg_callback(1, s->version, type, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg); s->init_off = 0; /* done writing this message */ s->init_num = 0; return(1); } s->init_off+=ret; s->init_num-=ret; frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); } } return(0); }
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; unsigned char *ret = p; ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ if (s->tlsext_hostname != NULL) { /* Add TLS extension servername to the Client Hello message */ unsigned long size_str; long lenmax; /* check for enough space. 4 for the servername type and entension length 2 for servernamelist length 1 for the hostname type 2 for hostname length + hostname length */ if ((lenmax = limit - ret - 9) < 0 || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL; /* extension type and length */ s2n(TLSEXT_TYPE_server_name,ret); s2n(size_str+5,ret); /* length of servername list */ s2n(size_str+3,ret); /* hostname type, length and hostname */ *(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name; s2n(size_str,ret); memcpy(ret, s->tlsext_hostname, size_str); ret+=size_str; } if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { int ticklen; if (s->session && s->session->tlsext_tick) ticklen = s->session->tlsext_ticklen; else ticklen = 0; /* Check for enough room 2 for extension type, 2 for len * rest for ticket */ if (limit - ret - 4 - ticklen < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); s2n(ticklen,ret); if (ticklen) { memcpy(ret, s->session->tlsext_tick, ticklen); ret += ticklen; } } if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) { int i; long extlen, idlen, itmp; OCSP_RESPID *id; idlen = 0; for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); itmp = i2d_OCSP_RESPID(id, NULL); if (itmp <= 0) return NULL; idlen += itmp + 2; } if (s->tlsext_ocsp_exts) { extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL); if (extlen < 0) return NULL; } else extlen = 0; if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL; s2n(TLSEXT_TYPE_status_request, ret); if (extlen + idlen > 0xFFF0) return NULL; s2n(extlen + idlen + 5, ret); *(ret++) = TLSEXT_STATUSTYPE_ocsp; s2n(idlen, ret); for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { /* save position of id len */ unsigned char *q = ret; id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); /* skip over id len */ ret += 2; itmp = i2d_OCSP_RESPID(id, &ret); /* write id len */ s2n(itmp, q); } s2n(extlen, ret); if (extlen > 0) i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); } if ((extdatalen = ret-p-2)== 0) return p; s2n(extdatalen,p); return ret; }
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { unsigned short length; unsigned short type; unsigned short size; unsigned char *data = *p; int tlsext_servername = 0; int renegotiate_seen = 0; if (data >= (d+n-2)) goto ri_check; n2s(data,length); if (data+length != d+n) { *al = SSL_AD_DECODE_ERROR; return 0; } while(data <= (d+n-4)) { n2s(data,type); n2s(data,size); if (data+size > (d+n)) goto ri_check; if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 1, type, data, size, s->tlsext_debug_arg); if (type == TLSEXT_TYPE_server_name) { if (s->tlsext_hostname == NULL || size > 0) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } tlsext_servername = 1; } else if (type == TLSEXT_TYPE_session_ticket) { if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || (size > 0)) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; } s->tlsext_ticket_expected = 1; } else if (type == TLSEXT_TYPE_status_request && s->version != DTLS1_VERSION) { /* MUST be empty and only sent if we've requested * a status request message. */ if ((s->tlsext_status_type == -1) || (size > 0)) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; } /* Set flag to expect CertificateStatus message */ s->tlsext_status_expected = 1; } else if (type == TLSEXT_TYPE_renegotiate) { if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) return 0; renegotiate_seen = 1; } data+=size; } if (data != d+n) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit && tlsext_servername == 1) { if (s->tlsext_hostname) { if (s->session->tlsext_hostname == NULL) { s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname); if (!s->session->tlsext_hostname) { *al = SSL_AD_UNRECOGNIZED_NAME; return 0; } } else { *al = SSL_AD_DECODE_ERROR; return 0; } } } *p = data; ri_check: /* Determine if we need to see RI. Strictly speaking if we want to * avoid an attack we should *always* see RI even on initial server * hello because the client doesn't see any renegotiation during an * attack. However this would mean we could not connect to any server * which doesn't support RI so for the immediate future tolerate RI * absence on initial connect only. */ if (!renegotiate_seen && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); return 0; } return 1; }
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; unsigned char *ret = p; /* don't add extensions for SSLv3, unless doing secure renegotiation */ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) return p; ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL) { if ((long)(limit - ret - 4) < 0) return NULL; s2n(TLSEXT_TYPE_server_name,ret); s2n(0,ret); } if(s->s3->send_connection_binding) { int el; if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } if((limit - p - 4 - el) < 0) return NULL; s2n(TLSEXT_TYPE_renegotiate,ret); s2n(el,ret); if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } ret += el; } #ifndef OPENSSL_NO_EC if (s->tlsext_ecpointformatlist != NULL && s->version != DTLS1_VERSION) { /* Add TLS extension ECPointFormats to the ServerHello message */ long lenmax; if ((lenmax = limit - ret - 5) < 0) return NULL; if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL; if (s->tlsext_ecpointformatlist_length > 255) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } s2n(TLSEXT_TYPE_ec_point_formats,ret); s2n(s->tlsext_ecpointformatlist_length + 1,ret); *(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length; memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length); ret+=s->tlsext_ecpointformatlist_length; } /* Currently the server should not respond with a SupportedCurves extension */ #endif /* OPENSSL_NO_EC */ if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) { if ((long)(limit - ret - 4) < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); s2n(0,ret); } if (s->tlsext_status_expected) { if ((long)(limit - ret - 4) < 0) return NULL; s2n(TLSEXT_TYPE_status_request,ret); s2n(0,ret); } #ifdef TLSEXT_TYPE_opaque_prf_input if (s->s3->server_opaque_prf_input != NULL && s->version != DTLS1_VERSION) { size_t sol = s->s3->server_opaque_prf_input_len; if ((long)(limit - ret - 6 - sol) < 0) return NULL; if (sol > 0xFFFD) /* can't happen */ return NULL; s2n(TLSEXT_TYPE_opaque_prf_input, ret); s2n(sol + 2, ret); s2n(sol, ret); memcpy(ret, s->s3->server_opaque_prf_input, sol); ret += sol; } #endif if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) && (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG)) { const unsigned char cryptopro_ext[36] = { 0xfd, 0xe8, /*65000*/ 0x00, 0x20, /*32 bytes length*/ 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17}; if (limit-ret<36) return NULL; memcpy(ret,cryptopro_ext,36); ret+=36; } if ((extdatalen = ret-p-2)== 0) return p; s2n(extdatalen,p); return ret; }
static int ssl_servername_cb(SSL *cnx, int *al, void *arg) { CertResult result; const char *sni_name; (void) al; (void) arg; if ((sni_name = SSL_get_servername(cnx, TLSEXT_NAMETYPE_host_name)) == NULL || *sni_name == 0 || validate_sni_name(sni_name) != 0) { return SSL_TLSEXT_ERR_NOACK; } logfile(LOG_INFO, "SNI: [%s]", sni_name); if (chrooted != 0 || loggedin != 0) { return SSL_TLSEXT_ERR_NOACK; } if (use_extcert == 0) { return SSL_TLSEXT_ERR_OK; } memset(&result, 0, sizeof result); tls_extcert_get(&result, sni_name); if (result.cert_ok != 1) { die(400, LOG_ERR, "Cert handler not ready"); } if (result.action == CERT_ACTION_DENY) { die(400, LOG_INFO, MSG_LOGOUT); } if (result.action == CERT_ACTION_DEFAULT) { return SSL_TLSEXT_ERR_OK; } if (result.cert_file == NULL) { if (result.action == CERT_ACTION_STRICT) { die(400, LOG_ERR, "Missing certificate"); } else { return SSL_TLSEXT_ERR_OK; } } if (result.key_file == NULL) { result.key_file = result.cert_file; } SSL_CTX_free(tls_ctx); tls_ctx = NULL; if (tls_create_new_context(result.cert_file, result.key_file) != 0) { if (result.action != CERT_ACTION_FALLBACK) { die(400, LOG_ERR, "Invalid certificate"); } if (tls_create_new_context(cert_file, key_file) != 0) { die(400, LOG_ERR, "SSL error"); } } if ((client_sni_name = strdup(sni_name)) == NULL) { die_mem(); } if (tls_cnx != NULL) { const long ctx_options = SSL_CTX_get_options(tls_ctx); SSL_set_SSL_CTX(tls_cnx, tls_ctx); # ifdef SSL_CTRL_CLEAR_OPTIONS SSL_clear_options(tls_cnx, SSL_get_options(tls_cnx) & ~ctx_options); # endif SSL_set_options(tls_cnx, ctx_options); } if (tls_data_cnx != NULL) { const long ctx_options = SSL_CTX_get_options(tls_ctx); SSL_set_SSL_CTX(tls_data_cnx, tls_ctx); # ifdef SSL_CTRL_CLEAR_OPTIONS SSL_clear_options(tls_data_cnx, SSL_get_options(tls_cnx) & ~ctx_options); # endif SSL_set_options(tls_data_cnx, ctx_options); } return SSL_TLSEXT_ERR_OK; }
int dtls1_accept(SSL *s) { BUF_MEM *buf; unsigned long Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; unsigned long alg_k; int ret= -1; int new_state,state,skip=0; int listen; #ifndef OPENSSL_NO_SCTP unsigned char sctpauthkey[64]; char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)]; #endif RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; #ifndef OPENSSL_NO_SCTP /* Notify SCTP BIO socket to enter handshake * mode and prevent stream identifier other * than 0. Will be ignored if no SCTP is used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL); #endif if (s->cert == NULL) { SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET); return(-1); } #ifndef OPENSSL_NO_HEARTBEATS /* If we're awaiting a HeartbeatResponse, pretend we * already got and don't await it anymore, because * Heartbeats don't make sense during handshakes anyway. */ if (s->tlsext_hb_pending) { dtls1_stop_timer(s); s->tlsext_hb_pending = 0; s->tlsext_hb_seq++; } #endif for (;;) { state=s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ #ifndef OPENSSL_NO_SCTP if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) #endif if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret=ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if ( ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ if (s->version != DTLS1_BAD_VER) ssl3_init_finished_mac(s); break; #ifndef OPENSSL_NO_SCTP case DTLS1_SCTP_ST_SR_READ_SOCK: if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) { s->s3->in_read_app_data=2; s->rwstate=SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } s->state=SSL3_ST_SR_FINISHED_A; break; case DTLS1_SCTP_ST_SW_WRITE_SOCK: ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s)); if (ret < 0) goto end; if (ret == 0) { if (s->d1->next_state != SSL_ST_OK) { s->s3->in_read_app_data=2; s->rwstate=SSL_READING; BIO_clear_retry_flags(SSL_get_rbio(s)); BIO_set_retry_read(SSL_get_rbio(s)); ret = -1; goto end; } } s->state=s->d1->next_state; break; #endif case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret=ssl3_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) { #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; #else s->state=SSL3_ST_SW_CHANGE_A; #endif } else s->state=SSL3_ST_SW_CERT_A; s->init_num=0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or normal PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_status_expected) s->state=SSL3_ST_SW_CERT_STATUS_A; else s->state=SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; s->state=SSL3_ST_SW_KEY_EXCH_A; } #else } else skip=1; s->state=SSL3_ST_SW_KEY_EXCH_A; #endif s->init_num=0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* clear this, it may get reset by * send_server_key_exchange */ if ((s->options & SSL_OP_EPHEMERAL_RSA) #ifndef OPENSSL_NO_KRB5 && !(alg_k & SSL_kKRB5) #endif /* OPENSSL_NO_KRB5 */ ) /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key * even when forbidden by protocol specs * (handshake may fail as clients are not required to * be able to handle this) */ s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; /* only send if a DH key exchange or * RSA but we have a sign only certificate */ if (s->s3->tmp.use_rsa_tmp /* PSK: send ServerKeyExchange if PSK identity * hint if provided */ #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif || (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd)) || (alg_k & SSL_kECDHE) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) ) ) ) ) { dtls1_start_timer(s); ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; } else skip=1; s->state=SSL3_ST_SW_CERT_REQ_A; s->init_num=0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* never request cert in anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246): */ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && /* ... except when the application insists on verification * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) /* With normal PSK Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; s->s3->tmp.cert_request=0; s->state=SSL3_ST_SW_SRVR_DONE_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif } else { s->s3->tmp.cert_request=1; dtls1_start_timer(s); ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A; s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif #else s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif #endif s->init_num=0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret=ssl3_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; break; case SSL3_ST_SW_FLUSH: s->rwstate=SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; } ret= -1; goto end; } s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: /* Check for second client hello (MS SGC) */ ret = ssl3_check_client_hello(s); if (ret <= 0) goto end; if (ret == 2) { dtls1_stop_timer(s); s->state = SSL3_ST_SR_CLNT_HELLO_C; } else { /* could be sent for a DH cert, even if we * have not asked for it :-) */ ret=ssl3_get_client_certificate(s); if (ret <= 0) goto end; s->init_num=0; s->state=SSL3_ST_SR_KEY_EXCH_A; } break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: ret=ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP /* Add new shared key for SCTP-Auth, * will be ignored if no SCTP used. */ snprintf((char *) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL), DTLS1_SCTP_AUTH_LABEL); SSL_export_keying_material(s, sctpauthkey, sizeof(sctpauthkey), labelbuffer, sizeof(labelbuffer), NULL, 0, 0); BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY, sizeof(sctpauthkey), sctpauthkey); #endif s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. */ s->state=SSL3_ST_SR_FINISHED_A; s->init_num = 0; } else if (SSL_USE_SIGALGS(s)) { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (!s->session->peer) break; /* For sigalgs freeze the handshake buffer * at this point and digest cached records. */ if (!s->s3->handshake_buffer) { SSLerr(SSL_F_DTLS1_ACCEPT,ERR_R_INTERNAL_ERROR); return -1; } s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; if (!ssl3_digest_cached_records(s)) return -1; } else { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s)) && state == SSL_ST_RENEGOTIATE) s->state=DTLS1_SCTP_ST_SR_READ_SOCK; else #endif s->state=SSL3_ST_SR_FINISHED_A; s->init_num=0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->hit) s->state=SSL_ST_OK; #ifndef OPENSSL_NO_TLSEXT else if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; #endif else s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret=ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret=ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_KEY_EXCH_A; s->init_num=0; break; #endif case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; goto end; } ret=dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP if (!s->hit) { /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); } #endif s->state=SSL3_ST_SW_FINISHED_A; s->init_num=0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret= -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) { s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; #ifndef OPENSSL_NO_SCTP /* Change to new shared key of SCTP-Auth, * will be ignored if no SCTP used. */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL); #endif } else { s->s3->tmp.next_state=SSL_ST_OK; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) { s->d1->next_state = s->s3->tmp.next_state; s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK; } #endif } s->init_num=0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); #if 0 BUF_MEM_free(s->init_buf); s->init_buf=NULL; #endif /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num=0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=dtls1_accept; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; /* break; */ default: SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ }
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; unsigned char *ret = p; ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ if (s->tlsext_hostname != NULL) { /* Add TLS extension servername to the Client Hello message */ unsigned long size_str; long lenmax; /* check for enough space. 4 for the servername type and entension length 2 for servernamelist length 1 for the hostname type 2 for hostname length + hostname length */ if ((lenmax = limit - ret - 9) < 0 || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL; /* extension type and length */ s2n(TLSEXT_TYPE_server_name,ret); s2n(size_str+5,ret); /* length of servername list */ s2n(size_str+3,ret); /* hostname type, length and hostname */ *(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name; s2n(size_str,ret); memcpy(ret, s->tlsext_hostname, size_str); ret+=size_str; } if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { int ticklen; if (s->session && s->session->tlsext_tick) ticklen = s->session->tlsext_ticklen; else ticklen = 0; /* Check for enough room 2 for extension type, 2 for len * rest for ticket */ if (limit - ret - 4 - ticklen < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); s2n(ticklen,ret); if (ticklen) { memcpy(ret, s->session->tlsext_tick, ticklen); ret += ticklen; } } if ((extdatalen = ret-p-2)== 0) return p; s2n(extdatalen,p); return ret; }
int dtls1_accept(SSL *s) { BUF_MEM *buf; void (*cb)(const SSL *ssl,int type,int val)=NULL; unsigned long alg_a; int ret= -1; int new_state,state,skip=0; int listen; ERR_clear_error(); ERR_clear_system_error(); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; if (s->cert == NULL) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_NO_CERTIFICATE_SET); return(-1); } for (;;) { state=s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); return -1; } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) * ...but not with SCTP :-) */ if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); ret=ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: case SSL3_ST_SR_CLNT_HELLO_D: s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if ( ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC */ ssl3_init_finished_mac(s); break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); ret=ssl3_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) { if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; } else s->state=SSL3_ST_SW_CERT_A; s->init_num=0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or normal PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; if (s->tlsext_status_expected) s->state=SSL3_ST_SW_CERT_STATUS_A; else s->state=SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; s->state=SSL3_ST_SW_KEY_EXCH_A; } s->init_num=0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* Send a ServerKeyExchange message if: * - The key exchange is ephemeral or anonymous * Diffie-Hellman. * - There is a PSK identity hint. * * TODO(davidben): This logic is currently duplicated * in s3_srvr.c. Fix this. In the meantime, keep them * in sync. */ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || ((alg_a & SSL_aPSK) && s->session->psk_identity_hint)) { dtls1_start_timer(s); ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; } else skip=1; s->state=SSL3_ST_SW_CERT_REQ_A; s->init_num=0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* never request cert in anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246): */ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && /* ... except when the application insists on verification * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* With normal PSK Certificates and * Certificate Requests are omitted */ (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; s->s3->tmp.cert_request=0; s->state=SSL3_ST_SW_SRVR_DONE_A; } else { s->s3->tmp.cert_request=1; dtls1_start_timer(s); ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; #else s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; #endif s->init_num=0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret=ssl3_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; break; case SSL3_ST_SW_FLUSH: s->rwstate=SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { /* If the write error was fatal, stop trying */ if (!BIO_should_retry(s->wbio)) { s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; } ret= -1; goto end; } s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: if (s->s3->tmp.cert_request) { ret=ssl3_get_client_certificate(s); if (ret <= 0) goto end; } s->init_num=0; s->state=SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: ret=ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* TODO(davidben): These two blocks are different * between SSL and DTLS. Resolve the difference and code * duplication. */ if (SSL_USE_SIGALGS(s)) { if (!s->session->peer) break; /* For sigalgs freeze the handshake buffer * at this point and digest cached records. */ if (!s->s3->handshake_buffer) { OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR); return -1; } s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; if (!ssl3_digest_cached_records(s)) return -1; } else { /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; s->state=SSL3_ST_SR_FINISHED_A; s->init_num=0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->hit) s->state=SSL_ST_OK; else if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret=ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret=ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_KEY_EXCH_A; s->init_num=0; break; case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; goto end; } ret=dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FINISHED_A; s->init_num=0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret= -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) { s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; } else { s->s3->tmp.next_state=SSL_ST_OK; } s->init_num=0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); #if 0 BUF_MEM_free(s->init_buf); s->init_buf=NULL; #endif /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num=0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=dtls1_accept; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; /* break; */ default: OPENSSL_PUT_ERROR(SSL, dtls1_accept, SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ } if (!s->s3->tmp.reuse_message && !skip) { if (s->debug) { if ((ret=BIO_flush(s->wbio)) <= 0) goto end; } if ((cb != NULL) && (s->state != state)) { new_state=s->state; s->state=state; cb(s,SSL_CB_ACCEPT_LOOP,1); s->state=new_state; } } skip=0; } end: /* BIO_flush(s->wbio); */ s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_ACCEPT_EXIT,ret); return(ret); }
int dtls1_accept(SSL *s) { BUF_MEM *buf; unsigned long l,Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state,skip=0; int listen; RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; listen = s->d1->listen; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->d1->listen = listen; if (s->cert == NULL) { SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET); return(-1); } for (;;) { state=s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->new_session=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) */ if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; dtls1_start_timer(s); ret=dtls1_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; else s->state = SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; /* Reflect ClientHello sequence to remain stateless while listening */ if (listen) { memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence)); } /* If we're just listening, stop here */ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) { ret = 2; s->d1->listen = 0; /* Set expected sequence numbers * to continue the handshake. */ s->d1->handshake_read_seq = 2; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; goto end; } break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: ret = dtls1_send_hello_verify_request(s); if ( ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequests resets Finished MAC */ if (s->client_version != DTLS1_BAD_VER) ssl3_init_finished_mac(s); break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: s->new_session = 2; dtls1_start_timer(s); ret=dtls1_send_server_hello(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->hit) { if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; } #else if (s->hit) s->state=SSL3_ST_SW_CHANGE_A; #endif else s->state=SSL3_ST_SW_CERT_A; s->init_num=0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH */ if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)) { dtls1_start_timer(s); ret=dtls1_send_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_status_expected) s->state=SSL3_ST_SW_CERT_STATUS_A; else s->state=SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; s->state=SSL3_ST_SW_KEY_EXCH_A; } #else } else skip=1; s->state=SSL3_ST_SW_KEY_EXCH_A; #endif s->init_num=0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: l=s->s3->tmp.new_cipher->algorithms; /* clear this, it may get reset by * send_server_key_exchange */ if ((s->options & SSL_OP_EPHEMERAL_RSA) #ifndef OPENSSL_NO_KRB5 && !(l & SSL_KRB5) #endif /* OPENSSL_NO_KRB5 */ ) /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key * even when forbidden by protocol specs * (handshake may fail as clients are not required to * be able to handle this) */ s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; /* only send if a DH key exchange, fortezza or * RSA but we have a sign only certificate */ if (s->s3->tmp.use_rsa_tmp || (l & (SSL_DH|SSL_kFZA)) || ((l & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) ) ) ) ) { dtls1_start_timer(s); ret=dtls1_send_server_key_exchange(s); if (ret <= 0) goto end; } else skip=1; s->state=SSL3_ST_SW_CERT_REQ_A; s->init_num=0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* never request cert in anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246): */ ((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) && /* ... except when the application insists on verification * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5)) { /* no cert request */ skip=1; s->s3->tmp.cert_request=0; s->state=SSL3_ST_SW_SRVR_DONE_A; } else { s->s3->tmp.cert_request=1; dtls1_start_timer(s); ret=dtls1_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; #else s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; #endif s->init_num=0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); ret=dtls1_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; break; case SSL3_ST_SW_FLUSH: s->rwstate=SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { ret= -1; goto end; } s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: /* Check for second client hello (MS SGC) */ ret = ssl3_check_client_hello(s); if (ret <= 0) goto end; dtls1_stop_timer(s); if (ret == 2) s->state = SSL3_ST_SR_CLNT_HELLO_C; else { /* could be sent for a DH cert, even if we * have not asked for it :-) */ ret=ssl3_get_client_certificate(s); if (ret <= 0) goto end; dtls1_stop_timer(s); s->init_num=0; s->state=SSL3_ST_SR_KEY_EXCH_A; } break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: ret=ssl3_get_client_key_exchange(s); if (ret <= 0) goto end; dtls1_stop_timer(s); s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst1), &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst2), &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: s->d1->change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; dtls1_stop_timer(s); s->state=SSL3_ST_SR_FINISHED_A; s->init_num=0; break; case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; dtls1_stop_timer(s); if (s->hit) s->state=SSL_ST_OK; #ifndef OPENSSL_NO_TLSEXT else if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; #endif else s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: ret=dtls1_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret=ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_KEY_EXCH_A; s->init_num=0; break; #endif case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; goto end; } ret=dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FINISHED_A; s->init_num=0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret= -1; goto end; } dtls1_reset_seq_numbers(s, SSL3_CC_WRITE); break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: ret=dtls1_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; else s->s3->tmp.next_state=SSL_ST_OK; s->init_num=0; break; case SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); #if 0 BUF_MEM_free(s->init_buf); s->init_buf=NULL; #endif /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num=0; if (s->new_session == 2) /* skipped if we just sent a HelloRequest */ { /* actually not necessarily a 'new' session unless * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=dtls1_accept; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; /* break; */ default: SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ }
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; unsigned char *ret = p; /* don't add extensions for SSLv3 unless doing secure renegotiation */ if (s->client_version == SSL3_VERSION && !s->s3->send_connection_binding) return p; ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ if (s->tlsext_hostname != NULL) { /* Add TLS extension servername to the Client Hello message */ unsigned long size_str; long lenmax; /* check for enough space. 4 for the servername type and entension length 2 for servernamelist length 1 for the hostname type 2 for hostname length + hostname length */ if ((lenmax = limit - ret - 9) < 0 || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL; /* extension type and length */ s2n(TLSEXT_TYPE_server_name,ret); s2n(size_str+5,ret); /* length of servername list */ s2n(size_str+3,ret); /* hostname type, length and hostname */ *(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name; s2n(size_str,ret); memcpy(ret, s->tlsext_hostname, size_str); ret+=size_str; } /* Add RI if renegotiating */ if (s->new_session) { int el; if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } if((limit - p - 4 - el) < 0) return NULL; s2n(TLSEXT_TYPE_renegotiate,ret); s2n(el,ret); if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } ret += el; } if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { int ticklen; if (!s->new_session && s->session && s->session->tlsext_tick) ticklen = s->session->tlsext_ticklen; else ticklen = 0; /* Check for enough room 2 for extension type, 2 for len * rest for ticket */ if (limit - ret - 4 - ticklen < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); s2n(ticklen,ret); if (ticklen) { memcpy(ret, s->session->tlsext_tick, ticklen); ret += ticklen; } } if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && s->version != DTLS1_VERSION) { int i; long extlen, idlen, itmp; OCSP_RESPID *id; idlen = 0; for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); itmp = i2d_OCSP_RESPID(id, NULL); if (itmp <= 0) return NULL; idlen += itmp + 2; } if (s->tlsext_ocsp_exts) { extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL); if (extlen < 0) return NULL; } else extlen = 0; if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL; s2n(TLSEXT_TYPE_status_request, ret); if (extlen + idlen > 0xFFF0) return NULL; s2n(extlen + idlen + 5, ret); *(ret++) = TLSEXT_STATUSTYPE_ocsp; s2n(idlen, ret); for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { /* save position of id len */ unsigned char *q = ret; id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); /* skip over id len */ ret += 2; itmp = i2d_OCSP_RESPID(id, &ret); /* write id len */ s2n(itmp, q); } s2n(extlen, ret); if (extlen > 0) i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); } if ((extdatalen = ret-p-2)== 0) return p; s2n(extdatalen,p); return ret; }
enum ssl_session_result_t ssl_get_prev_session( SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket, const struct ssl_early_callback_ctx *ctx) { /* This is used only by servers. */ assert(ssl->server); SSL_SESSION *session = NULL; int renew_ticket = 0; /* If tickets are disabled, always behave as if no tickets are present. */ const uint8_t *ticket = NULL; size_t ticket_len = 0; const int tickets_supported = !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) && ssl->version > SSL3_VERSION && SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len); int from_cache = 0; if (tickets_supported && ticket_len > 0) { if (!tls_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len, ctx->session_id, ctx->session_id_len)) { return ssl_session_error; } } else { /* The client didn't send a ticket, so the session ID is a real ID. */ enum ssl_session_result_t lookup_ret = ssl_lookup_session( ssl, &session, ctx->session_id, ctx->session_id_len); if (lookup_ret != ssl_session_success) { return lookup_ret; } from_cache = 1; } if (session == NULL || session->sid_ctx_length != ssl->sid_ctx_length || memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) != 0) { /* The client did not offer a suitable ticket or session ID. If supported, * the new session should use a ticket. */ goto no_session; } if ((ssl->verify_mode & SSL_VERIFY_PEER) && ssl->sid_ctx_length == 0) { /* We can't be sure if this session is being used out of context, which is * especially important for SSL_VERIFY_PEER. The application should have * used SSL[_CTX]_set_session_id_context. * * For this error case, we generate an error instead of treating the event * like a cache miss (otherwise it would be easy for applications to * effectively disable the session cache by accident without anyone * noticing). */ OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); SSL_SESSION_free(session); return ssl_session_error; } if (session->timeout < (long)(time(NULL) - session->time)) { if (from_cache) { /* The session was from the cache, so remove it. */ SSL_CTX_remove_session(ssl->initial_ctx, session); } goto no_session; } *out_session = session; *out_send_ticket = renew_ticket; return ssl_session_success; no_session: *out_session = NULL; *out_send_ticket = tickets_supported; SSL_SESSION_free(session); return ssl_session_success; }
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; unsigned char *ret = p; /* don't add extensions for SSLv3, unless doing secure renegotiation */ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) return p; ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL) { if (limit - ret - 4 < 0) return NULL; s2n(TLSEXT_TYPE_server_name,ret); s2n(0,ret); } if(s->s3->send_connection_binding) { int el; if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } if((limit - p - 4 - el) < 0) return NULL; s2n(TLSEXT_TYPE_renegotiate,ret); s2n(el,ret); if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } ret += el; } if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) { if (limit - ret - 4 < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); s2n(0,ret); } if (s->tlsext_status_expected) { if ((long)(limit - ret - 4) < 0) return NULL; s2n(TLSEXT_TYPE_status_request,ret); s2n(0,ret); } if ((extdatalen = ret-p-2)== 0) return p; s2n(extdatalen,p); return ret; }
/* Since the server cache lookup is done early on in the processing of the * ClientHello, and other operations depend on the result, we need to handle * any TLS session ticket extension at the same time. * * session_id: points at the session ID in the ClientHello. This code will * read past the end of this in order to parse out the session ticket * extension, if any. * len: the length of the session ID. * limit: a pointer to the first byte after the ClientHello. * ret: (output) on return, if a ticket was decrypted, then this is set to * point to the resulting session. * * If s->internal->tls_session_secret_cb is set then we are expecting a pre-shared key * ciphersuite, in which case we have no use for session tickets and one will * never be decrypted, nor will s->internal->tlsext_ticket_expected be set to 1. * * Returns: * -1: fatal error, either from parsing or decrypting the ticket. * 0: no ticket was found (or was ignored, based on settings). * 1: a zero length extension was found, indicating that the client supports * session tickets but doesn't currently have one to offer. * 2: either s->internal->tls_session_secret_cb was set, or a ticket was offered but * couldn't be decrypted because of a non-fatal error. * 3: a ticket was successfully decrypted and *ret was set. * * Side effects: * Sets s->internal->tlsext_ticket_expected to 1 if the server will have to issue * a new session ticket to the client because the client indicated support * (and s->internal->tls_session_secret_cb is NULL) but the client either doesn't have * a session ticket or we couldn't use the one it gave us, or if * s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket. * Otherwise, s->internal->tlsext_ticket_expected is set to 0. */ int tls1_process_ticket(SSL *s, const unsigned char *session, int session_len, const unsigned char *limit, SSL_SESSION **ret) { /* Point after session ID in client hello */ CBS session_id, cookie, cipher_list, compress_algo, extensions; *ret = NULL; s->internal->tlsext_ticket_expected = 0; /* If tickets disabled behave as if no ticket present * to permit stateful resumption. */ if (SSL_get_options(s) & SSL_OP_NO_TICKET) return 0; if (!limit) return 0; if (limit < session) return -1; CBS_init(&session_id, session, limit - session); /* Skip past the session id */ if (!CBS_skip(&session_id, session_len)) return -1; /* Skip past DTLS cookie */ if (SSL_IS_DTLS(s)) { if (!CBS_get_u8_length_prefixed(&session_id, &cookie)) return -1; } /* Skip past cipher list */ if (!CBS_get_u16_length_prefixed(&session_id, &cipher_list)) return -1; /* Skip past compression algorithm list */ if (!CBS_get_u8_length_prefixed(&session_id, &compress_algo)) return -1; /* Now at start of extensions */ if (CBS_len(&session_id) == 0) return 0; if (!CBS_get_u16_length_prefixed(&session_id, &extensions)) return -1; while (CBS_len(&extensions) > 0) { CBS ext_data; uint16_t ext_type; if (!CBS_get_u16(&extensions, &ext_type) || !CBS_get_u16_length_prefixed(&extensions, &ext_data)) return -1; if (ext_type == TLSEXT_TYPE_session_ticket) { int r; if (CBS_len(&ext_data) == 0) { /* The client will accept a ticket but doesn't * currently have one. */ s->internal->tlsext_ticket_expected = 1; return 1; } if (s->internal->tls_session_secret_cb) { /* Indicate that the ticket couldn't be * decrypted rather than generating the session * from ticket now, trigger abbreviated * handshake based on external mechanism to * calculate the master secret later. */ return 2; } r = tls_decrypt_ticket(s, CBS_data(&ext_data), CBS_len(&ext_data), session, session_len, ret); switch (r) { case 2: /* ticket couldn't be decrypted */ s->internal->tlsext_ticket_expected = 1; return 2; case 3: /* ticket was decrypted */ return r; case 4: /* ticket decrypted but need to renew */ s->internal->tlsext_ticket_expected = 1; return 3; default: /* fatal error */ return -1; } } } return 0; }
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { unsigned short type; unsigned short size; unsigned short len; unsigned char *data = *p; int tlsext_servername = 0; if (data >= (d+n-2)) return 1; n2s(data,len); while(data <= (d+n-4)) { n2s(data,type); n2s(data,size); if (data+size > (d+n)) return 1; if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 1, type, data, size, s->tlsext_debug_arg); if (type == TLSEXT_TYPE_server_name) { if (s->tlsext_hostname == NULL || size > 0) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } tlsext_servername = 1; } else if (type == TLSEXT_TYPE_session_ticket) { if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || (size > 0)) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; } s->tlsext_ticket_expected = 1; } data+=size; } if (data != d+n) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit && tlsext_servername == 1) { if (s->tlsext_hostname) { if (s->session->tlsext_hostname == NULL) { s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname); if (!s->session->tlsext_hostname) { *al = SSL_AD_UNRECOGNIZED_NAME; return 0; } } else { *al = SSL_AD_DECODE_ERROR; return 0; } } } *p = data; return 1; }