static SSL_METHOD *dtls1_get_client_method(int ver)
{
- if (ver == DTLS1_VERSION)
+ if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
return(DTLSv1_client_method());
else
return(NULL);
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
- if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00))
+ if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
+ (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
{
SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
ret = -1;
/* don't push the buffering BIO quite yet */
- ssl3_init_finished_mac(s);
-
s->state=SSL3_ST_CW_CLNT_HELLO_A;
s->ctx->stats.sess_connect++;
s->init_num=0;
+ /* mark client_random uninitialized */
+ memset(s->s3->client_random,0,sizeof(s->s3->client_random));
break;
case SSL3_ST_CW_CLNT_HELLO_A:
case SSL3_ST_CW_CLNT_HELLO_B:
s->shutdown=0;
+
+ /* every DTLS ClientHello resets Finished MAC */
+ ssl3_init_finished_mac(s);
+
+ dtls1_start_timer(s);
ret=dtls1_client_hello(s);
if (ret <= 0) goto end;
if (ret <= 0) goto end;
else
{
+ dtls1_stop_timer(s);
if (s->hit)
s->state=SSL3_ST_CR_FINISHED_A;
else
ret = dtls1_get_hello_verify(s);
if ( ret <= 0)
goto end;
+ dtls1_stop_timer(s);
if ( s->d1->send_cookie) /* start again, with a cookie */
s->state=SSL3_ST_CW_CLNT_HELLO_A;
else
case SSL3_ST_CW_CERT_B:
case SSL3_ST_CW_CERT_C:
case SSL3_ST_CW_CERT_D:
+ dtls1_start_timer(s);
ret=dtls1_send_client_certificate(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_KEY_EXCH_A;
case SSL3_ST_CW_KEY_EXCH_A:
case SSL3_ST_CW_KEY_EXCH_B:
+ dtls1_start_timer(s);
ret=dtls1_send_client_key_exchange(s);
if (ret <= 0) goto end;
l=s->s3->tmp.new_cipher->algorithms;
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
+ dtls1_start_timer(s);
ret=dtls1_send_client_verify(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_CHANGE_A;
case SSL3_ST_CW_CHANGE_A:
case SSL3_ST_CW_CHANGE_B:
+ dtls1_start_timer(s);
ret=dtls1_send_change_cipher_spec(s,
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
case SSL3_ST_CW_FINISHED_A:
case SSL3_ST_CW_FINISHED_B:
+ dtls1_start_timer(s);
ret=dtls1_send_finished(s,
SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
s->method->ssl3_enc->client_finished_label,
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
}
s->init_num=0;
+
break;
case SSL3_ST_CR_FINISHED_A:
ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
SSL3_ST_CR_FINISHED_B);
if (ret <= 0) goto end;
+ dtls1_stop_timer(s);
if (s->hit)
s->state=SSL3_ST_CW_CHANGE_A;
/* done with handshaking */
s->d1->handshake_read_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
goto end;
/* break; */
/* else use the pre-loaded session */
p=s->s3->client_random;
- Time=(unsigned long)time(NULL); /* Time */
- l2n(Time,p);
- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+ /* if client_random is initialized, reuse it, we are
+ * required to use same upon reply to HelloVerify */
+ for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ;
+ if (i==sizeof(s->s3->client_random))
+ {
+ Time=(unsigned long)time(NULL); /* Time */
+ l2n(Time,p);
+ RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4);
+ }
/* Do the message type and length last */
d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
s->session->master_key_length=sizeof tmp_buf;
q=p;
- /* Fix buf for TLS and beyond */
+ /* Fix buf for TLS and [incidentally] DTLS */
if (s->version > SSL3_VERSION)
p+=2;
n=RSA_public_encrypt(sizeof tmp_buf,
goto err;
}
- /* Fix buf for TLS and beyond */
+ /* Fix buf for TLS and [incidentally] DTLS */
if (s->version > SSL3_VERSION)
{
s2n(n,q);
* ssl->rwstate=SSL_X509_LOOKUP; return(-1);
* We then get retied later */
i=0;
- if (s->ctx->client_cert_cb != NULL)
- i=s->ctx->client_cert_cb(s,&(x509),&(pkey));
+ i = ssl_do_client_cert_cb(s, &x509, &pkey);
if (i < 0)
{
s->rwstate=SSL_X509_LOOKUP;