aboutsummaryrefslogtreecommitdiffstats
path: root/ssl/d1_srvr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/d1_srvr.c')
-rw-r--r--ssl/d1_srvr.c228
1 files changed, 205 insertions, 23 deletions
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 0bbf8ae7f311..5b313664dd12 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -146,7 +146,6 @@ 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;
- long num1;
int ret= -1;
int new_state,state,skip=0;
@@ -236,17 +235,13 @@ int dtls1_accept(SSL *s)
s->state=SSL3_ST_SW_HELLO_REQ_A;
}
- if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
- s->d1->send_cookie = 1;
- else
- s->d1->send_cookie = 0;
-
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;
@@ -267,22 +262,31 @@ int dtls1_accept(SSL *s)
s->shutdown=0;
ret=ssl3_get_client_hello(s);
if (ret <= 0) goto end;
- s->new_session = 2;
+ dtls1_stop_timer(s);
- if ( s->d1->send_cookie)
+ 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;
+
+ /* If we're just listening, stop here */
+ if (s->d1->listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
+ {
+ ret = 2;
+ s->d1->listen = 0;
+ goto end;
+ }
+
break;
case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
+ dtls1_start_timer(s);
ret = dtls1_send_hello_verify_request(s);
if ( ret <= 0) goto end;
- s->d1->send_cookie = 0;
s->state=SSL3_ST_SW_FLUSH;
s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
@@ -293,11 +297,23 @@ int dtls1_accept(SSL *s)
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)
- s->state=SSL3_ST_SW_CHANGE_A;
+ {
+ 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;
@@ -308,12 +324,27 @@ int dtls1_accept(SSL *s)
/* 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;
@@ -349,6 +380,7 @@ int dtls1_accept(SSL *s)
)
)
{
+ dtls1_start_timer(s);
ret=dtls1_send_server_key_exchange(s);
if (ret <= 0) goto end;
}
@@ -385,6 +417,7 @@ int dtls1_accept(SSL *s)
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
@@ -399,6 +432,7 @@ int dtls1_accept(SSL *s)
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;
@@ -407,16 +441,13 @@ int dtls1_accept(SSL *s)
break;
case SSL3_ST_SW_FLUSH:
- /* number of bytes to be flushed */
- num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
- if (num1 > 0)
+ s->rwstate=SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0)
{
- s->rwstate=SSL_WRITING;
- num1=BIO_flush(s->wbio);
- if (num1 <= 0) { ret= -1; goto end; }
- s->rwstate=SSL_NOTHING;
+ ret= -1;
+ goto end;
}
-
+ s->rwstate=SSL_NOTHING;
s->state=s->s3->tmp.next_state;
break;
@@ -426,6 +457,7 @@ int dtls1_accept(SSL *s)
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 {
@@ -433,6 +465,7 @@ int dtls1_accept(SSL *s)
* 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;
}
@@ -442,6 +475,7 @@ int dtls1_accept(SSL *s)
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;
@@ -459,9 +493,11 @@ int dtls1_accept(SSL *s)
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;
@@ -469,16 +505,41 @@ int dtls1_accept(SSL *s)
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:
@@ -554,6 +615,7 @@ int dtls1_accept(SSL *s)
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; */
@@ -631,15 +693,13 @@ int dtls1_send_hello_verify_request(SSL *s)
*(p++) = s->version >> 8,
*(p++) = s->version & 0xFF;
- if (s->ctx->app_gen_cookie_cb != NULL &&
- s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
- &(s->d1->cookie_len)) == 0)
+ if (s->ctx->app_gen_cookie_cb == NULL ||
+ s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
+ &(s->d1->cookie_len)) == 0)
{
SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,ERR_R_INTERNAL_ERROR);
return 0;
}
- /* else the cookie is assumed to have
- * been initialized by the application */
*(p++) = (unsigned char) s->d1->cookie_len;
memcpy(p, s->d1->cookie, s->d1->cookie_len);
@@ -713,6 +773,8 @@ int dtls1_send_server_hello(SSL *s)
p+=sl;
/* put the cipher */
+ if (s->s3->tmp.new_cipher == NULL)
+ return -1;
i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p);
p+=i;
@@ -726,6 +788,14 @@ int dtls1_send_server_hello(SSL *s)
*(p++)=s->s3->tmp.new_compression->id;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+ {
+ SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+#endif
+
/* do the header */
l=(p-d);
d=buf;
@@ -1145,3 +1215,115 @@ int dtls1_send_server_certificate(SSL *s)
/* SSL3_ST_SW_CERT_B */
return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
}
+
+#ifndef OPENSSL_NO_TLSEXT
+int dtls1_send_newsession_ticket(SSL *s)
+ {
+ if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+ {
+ unsigned char *p, *senc, *macstart;
+ int len, slen;
+ unsigned int hlen, msg_len;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+ SSL_CTX *tctx = s->initial_ctx;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char key_name[16];
+
+ /* get session encoding length */
+ slen = i2d_SSL_SESSION(s->session, NULL);
+ /* Some length values are 16 bits, so forget it if session is
+ * too long
+ */
+ if (slen > 0xFF00)
+ return -1;
+ /* Grow buffer if need be: the length calculation is as
+ * follows 12 (DTLS handshake message header) +
+ * 4 (ticket lifetime hint) + 2 (ticket length) +
+ * 16 (key name) + max_iv_len (iv length) +
+ * session_length + max_enc_block_size (max encrypted session
+ * length) + max_md_size (HMAC).
+ */
+ if (!BUF_MEM_grow(s->init_buf,
+ DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH +
+ EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
+ return -1;
+ senc = OPENSSL_malloc(slen);
+ if (!senc)
+ return -1;
+ p = senc;
+ i2d_SSL_SESSION(s->session, &p);
+
+ p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]);
+ EVP_CIPHER_CTX_init(&ctx);
+ HMAC_CTX_init(&hctx);
+ /* Initialize HMAC and cipher contexts. If callback present
+ * it does all the work otherwise use generated values
+ * from parent ctx.
+ */
+ if (tctx->tlsext_ticket_key_cb)
+ {
+ if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+ &hctx, 1) < 0)
+ {
+ OPENSSL_free(senc);
+ return -1;
+ }
+ }
+ else
+ {
+ RAND_pseudo_bytes(iv, 16);
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ tctx->tlsext_tick_aes_key, iv);
+ HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+ tlsext_tick_md(), NULL);
+ memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+ }
+ l2n(s->session->tlsext_tick_lifetime_hint, p);
+ /* Skip ticket length for now */
+ p += 2;
+ /* Output key name */
+ macstart = p;
+ memcpy(p, key_name, 16);
+ p += 16;
+ /* output IV */
+ memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+ p += EVP_CIPHER_CTX_iv_length(&ctx);
+ /* Encrypt session data */
+ EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+ p += len;
+ EVP_EncryptFinal(&ctx, p, &len);
+ p += len;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ HMAC_Update(&hctx, macstart, p - macstart);
+ HMAC_Final(&hctx, p, &hlen);
+ HMAC_CTX_cleanup(&hctx);
+
+ p += hlen;
+ /* Now write out lengths: p points to end of data written */
+ /* Total length */
+ len = p - (unsigned char *)(s->init_buf->data);
+ /* Ticket length */
+ p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4;
+ s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p);
+
+ /* number of bytes to write */
+ s->init_num= len;
+ s->state=SSL3_ST_SW_SESSION_TICKET_B;
+ s->init_off=0;
+ OPENSSL_free(senc);
+
+ /* XDTLS: set message header ? */
+ msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
+ dtls1_set_message_header(s, (void *)s->init_buf->data,
+ SSL3_MT_NEWSESSION_TICKET, msg_len, 0, msg_len);
+
+ /* buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 0);
+ }
+
+ /* SSL3_ST_SW_SESSION_TICKET_B */
+ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+ }
+#endif