summaryrefslogtreecommitdiffstats
path: root/ssl/s3_clnt.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2013-03-11 15:34:28 +0000
committerDr. Stephen Henson <steve@openssl.org>2013-09-18 13:46:02 +0100
commit741c9959f621a383055816cb3db37a61fee889e5 (patch)
treee2f34100481b3e36c1c240e5fbd84fe837aa5a26 /ssl/s3_clnt.c
parent7c23127fde8fe94af914961eb7702caa7f256a05 (diff)
DTLS revision.
Revise DTLS code. There was a *lot* of code duplication in the DTLS code that generates records. This makes it harder to maintain and sometimes a TLS update is omitted by accident from the DTLS code. Specifically almost all of the record generation functions have code like this: some_pointer = buffer + HANDSHAKE_HEADER_LENGTH; ... Record creation stuff ... set_handshake_header(ssl, SSL_MT_SOMETHING, message_len); ... write_handshake_message(ssl); Where the "Record creation stuff" is identical between SSL/TLS and DTLS or in some cases has very minor differences. By adding a few fields to SSL3_ENC to include the header length, some flags and function pointers for handshake header setting and handshake writing the code can cope with both cases. (cherry picked from commit 173e72e64c6a07ae97660c322396b66215009f33)
Diffstat (limited to 'ssl/s3_clnt.c')
-rw-r--r--ssl/s3_clnt.c90
1 files changed, 52 insertions, 38 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 61b0cdc204..88384bf5da 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -697,13 +697,34 @@ int ssl3_client_hello(SSL *s)
/* else use the pre-loaded session */
p=s->s3->client_random;
- Time=(unsigned long)time(NULL); /* Time */
- l2n(Time,p);
- if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
- goto err;
+
+ /* for DTLS if client_random is initialized, reuse it, we are
+ * required to use same upon reply to HelloVerify */
+ if (SSL_IS_DTLS(s))
+ {
+ size_t idx;
+ i = 1;
+ for (idx=0; idx < sizeof(s->s3->client_random); idx++)
+ {
+ if (p[idx])
+ {
+ i = 0;
+ break;
+ }
+ }
+ }
+ else
+ i = 1;
+
+ if (i)
+ {
+ Time=(unsigned long)time(NULL); /* Time */
+ l2n(Time,p);
+ RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4);
+ }
/* Do the message type and length last */
- d=p= &(buf[4]);
+ d=p= ssl_handshake_start(s);
/* version indicates the negotiated version: for example from
* an SSLv2/v3 compatible client hello). The client_version
@@ -764,6 +785,19 @@ int ssl3_client_hello(SSL *s)
p+=i;
}
+ /* cookie stuff for DTLS */
+ if (SSL_IS_DTLS(s))
+ {
+ if ( s->d1->cookie_len > sizeof(s->d1->cookie))
+ {
+ SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ *(p++) = s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+ }
+
/* Ciphers supported */
i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
if (i == 0)
@@ -816,19 +850,13 @@ int ssl3_client_hello(SSL *s)
}
#endif
- l=(p-d);
- d=buf;
- *(d++)=SSL3_MT_CLIENT_HELLO;
- l2n3(l,d);
-
+ l= p-d;
+ ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l);
s->state=SSL3_ST_CW_CLNT_HELLO_B;
- /* number of bytes to write */
- s->init_num=p-buf;
- s->init_off=0;
}
/* SSL3_ST_CW_CLNT_HELLO_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
err:
return(-1);
}
@@ -2261,7 +2289,7 @@ int ssl3_get_server_done(SSL *s)
int ssl3_send_client_key_exchange(SSL *s)
{
- unsigned char *p,*d;
+ unsigned char *p;
int n;
unsigned long alg_k;
#ifndef OPENSSL_NO_RSA
@@ -2282,8 +2310,7 @@ int ssl3_send_client_key_exchange(SSL *s)
if (s->state == SSL3_ST_CW_KEY_EXCH_A)
{
- d=(unsigned char *)s->init_buf->data;
- p= &(d[4]);
+ p = ssl_handshake_start(s);
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
@@ -2984,18 +3011,13 @@ int ssl3_send_client_key_exchange(SSL *s)
ERR_R_INTERNAL_ERROR);
goto err;
}
-
- *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE;
- l2n3(n,d);
+ ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
s->state=SSL3_ST_CW_KEY_EXCH_B;
- /* number of bytes to write */
- s->init_num=n+4;
- s->init_off=0;
}
/* SSL3_ST_CW_KEY_EXCH_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
err:
#ifndef OPENSSL_NO_ECDH
BN_CTX_free(bn_ctx);
@@ -3009,7 +3031,7 @@ err:
int ssl3_send_client_verify(SSL *s)
{
- unsigned char *p,*d;
+ unsigned char *p;
unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx=NULL;
@@ -3022,8 +3044,7 @@ int ssl3_send_client_verify(SSL *s)
if (s->state == SSL3_ST_CW_CERT_VRFY_A)
{
- d=(unsigned char *)s->init_buf->data;
- p= &(d[4]);
+ p= ssl_handshake_start(s);
pkey=s->cert->key->privatekey;
/* Create context from key and test if sha1 is allowed as digest */
pctx = EVP_PKEY_CTX_new(pkey,NULL);
@@ -3149,16 +3170,12 @@ int ssl3_send_client_verify(SSL *s)
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
goto err;
}
- *(d++)=SSL3_MT_CERTIFICATE_VERIFY;
- l2n3(n,d);
-
+ ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
s->state=SSL3_ST_CW_CERT_VRFY_B;
- s->init_num=(int)n+4;
- s->init_off=0;
}
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx);
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
err:
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx);
@@ -3215,7 +3232,6 @@ int ssl3_send_client_certificate(SSL *s)
X509 *x509=NULL;
EVP_PKEY *pkey=NULL;
int i;
- unsigned long l;
if (s->state == SSL3_ST_CW_CERT_A)
{
@@ -3284,13 +3300,11 @@ int ssl3_send_client_certificate(SSL *s)
if (s->state == SSL3_ST_CW_CERT_C)
{
s->state=SSL3_ST_CW_CERT_D;
- l=ssl3_output_cert_chain(s,
+ ssl3_output_cert_chain(s,
(s->s3->tmp.cert_req == 2)?NULL:s->cert->key);
- s->init_num=(int)l;
- s->init_off=0;
}
/* SSL3_ST_CW_CERT_D */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
}
#define has_bits(i,m) (((i)&(m)) == (m))