|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/dtls1.h.dtls-fixes openssl-fips-0.9.8f-dev/ssl/dtls1.h
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/dtls1.h.dtls-fixes 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/dtls1.h 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -67,9 +67,8 @@
|
|
|
5820f5 |
extern "C" {
|
|
|
5820f5 |
#endif
|
|
|
5820f5 |
|
|
|
5820f5 |
-#define DTLS1_VERSION 0x0100
|
|
|
5820f5 |
-#define DTLS1_VERSION_MAJOR 0x01
|
|
|
5820f5 |
-#define DTLS1_VERSION_MINOR 0x00
|
|
|
5820f5 |
+#define DTLS1_VERSION 0xFEFF
|
|
|
5820f5 |
+#define DTLS1_BAD_VER 0x0100
|
|
|
5820f5 |
|
|
|
5820f5 |
#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
|
|
|
5820f5 |
|
|
|
5820f5 |
@@ -83,7 +82,7 @@ extern "C" {
|
|
|
5820f5 |
#define DTLS1_HM_BAD_FRAGMENT -2
|
|
|
5820f5 |
#define DTLS1_HM_FRAGMENT_RETRY -3
|
|
|
5820f5 |
|
|
|
5820f5 |
-#define DTLS1_CCS_HEADER_LENGTH 3
|
|
|
5820f5 |
+#define DTLS1_CCS_HEADER_LENGTH 1
|
|
|
5820f5 |
|
|
|
5820f5 |
#define DTLS1_AL_HEADER_LENGTH 7
|
|
|
5820f5 |
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_lib.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_lib.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/d1_lib.c.dtls-fixes 2007-01-21 17:07:25.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_lib.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -188,3 +188,23 @@ void dtls1_clear(SSL *s)
|
|
|
5820f5 |
ssl3_clear(s);
|
|
|
5820f5 |
s->version=DTLS1_VERSION;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+/*
|
|
|
5820f5 |
+ * As it's impossible to use stream ciphers in "datagram" mode, this
|
|
|
5820f5 |
+ * simple filter is designed to disengage them in DTLS. Unfortunately
|
|
|
5820f5 |
+ * there is no universal way to identify stream SSL_CIPHER, so we have
|
|
|
5820f5 |
+ * to explicitly list their SSL_* codes. Currently RC4 is the only one
|
|
|
5820f5 |
+ * available, but if new ones emerge, they will have to be added...
|
|
|
5820f5 |
+ */
|
|
|
5820f5 |
+SSL_CIPHER *dtls1_get_cipher(unsigned int u)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ SSL_CIPHER *ciph = ssl3_get_cipher(u);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (ciph != NULL)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4)
|
|
|
5820f5 |
+ return NULL;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ return ciph;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_srvr.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_srvr.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/d1_srvr.c.dtls-fixes 2007-09-19 02:02:49.000000000 +0200
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_srvr.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -285,6 +285,10 @@ int dtls1_accept(SSL *s)
|
|
|
5820f5 |
s->d1->send_cookie = 0;
|
|
|
5820f5 |
s->state=SSL3_ST_SW_FLUSH;
|
|
|
5820f5 |
s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ /* HelloVerifyRequests resets Finished MAC */
|
|
|
5820f5 |
+ if (s->client_version != DTLS1_BAD_VER)
|
|
|
5820f5 |
+ ssl3_init_finished_mac(s);
|
|
|
5820f5 |
break;
|
|
|
5820f5 |
|
|
|
5820f5 |
case SSL3_ST_SW_SRVR_HELLO_A:
|
|
|
5820f5 |
@@ -620,10 +624,13 @@ int dtls1_send_hello_verify_request(SSL
|
|
|
5820f5 |
buf = (unsigned char *)s->init_buf->data;
|
|
|
5820f5 |
|
|
|
5820f5 |
msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
|
|
|
5820f5 |
- *(p++) = s->version >> 8;
|
|
|
5820f5 |
- *(p++) = s->version & 0xFF;
|
|
|
5820f5 |
+ if (s->client_version == DTLS1_BAD_VER)
|
|
|
5820f5 |
+ *(p++) = DTLS1_BAD_VER>>8,
|
|
|
5820f5 |
+ *(p++) = DTLS1_BAD_VER&0xff;
|
|
|
5820f5 |
+ else
|
|
|
5820f5 |
+ *(p++) = s->version >> 8,
|
|
|
5820f5 |
+ *(p++) = s->version & 0xFF;
|
|
|
5820f5 |
|
|
|
5820f5 |
- *(p++) = (unsigned char) s->d1->cookie_len;
|
|
|
5820f5 |
if ( s->ctx->app_gen_cookie_cb != NULL &&
|
|
|
5820f5 |
s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
|
|
|
5820f5 |
&(s->d1->cookie_len)) == 0)
|
|
|
5820f5 |
@@ -634,6 +641,7 @@ int dtls1_send_hello_verify_request(SSL
|
|
|
5820f5 |
/* else the cookie is assumed to have
|
|
|
5820f5 |
* been initialized by the application */
|
|
|
5820f5 |
|
|
|
5820f5 |
+ *(p++) = (unsigned char) s->d1->cookie_len;
|
|
|
5820f5 |
memcpy(p, s->d1->cookie, s->d1->cookie_len);
|
|
|
5820f5 |
p += s->d1->cookie_len;
|
|
|
5820f5 |
msg_len = p - msg;
|
|
|
5820f5 |
@@ -672,8 +680,12 @@ int dtls1_send_server_hello(SSL *s)
|
|
|
5820f5 |
/* Do the message type and length last */
|
|
|
5820f5 |
d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
|
|
|
5820f5 |
|
|
|
5820f5 |
- *(p++)=s->version>>8;
|
|
|
5820f5 |
- *(p++)=s->version&0xff;
|
|
|
5820f5 |
+ if (s->client_version == DTLS1_BAD_VER)
|
|
|
5820f5 |
+ *(p++)=DTLS1_BAD_VER>>8,
|
|
|
5820f5 |
+ *(p++)=DTLS1_BAD_VER&0xff;
|
|
|
5820f5 |
+ else
|
|
|
5820f5 |
+ *(p++)=s->version>>8,
|
|
|
5820f5 |
+ *(p++)=s->version&0xff;
|
|
|
5820f5 |
|
|
|
5820f5 |
/* Random stuff */
|
|
|
5820f5 |
memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/s3_srvr.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/s3_srvr.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/s3_srvr.c.dtls-fixes 2007-03-22 01:39:14.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/s3_srvr.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -699,7 +699,8 @@ int ssl3_get_client_hello(SSL *s)
|
|
|
5820f5 |
s->client_version=(((int)p[0])<<8)|(int)p[1];
|
|
|
5820f5 |
p+=2;
|
|
|
5820f5 |
|
|
|
5820f5 |
- if (s->client_version < s->version)
|
|
|
5820f5 |
+ if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
|
|
|
5820f5 |
+ (s->version != DTLS1_VERSION && s->client_version < s->version))
|
|
|
5820f5 |
{
|
|
|
5820f5 |
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
|
|
|
5820f5 |
if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
|
|
|
5820f5 |
@@ -750,7 +751,7 @@ int ssl3_get_client_hello(SSL *s)
|
|
|
5820f5 |
|
|
|
5820f5 |
p+=j;
|
|
|
5820f5 |
|
|
|
5820f5 |
- if (SSL_version(s) == DTLS1_VERSION)
|
|
|
5820f5 |
+ if (s->version == DTLS1_VERSION)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
/* cookie stuff */
|
|
|
5820f5 |
cookie_len = *(p++);
|
|
|
5820f5 |
@@ -1713,8 +1714,9 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
|
5820f5 |
rsa=pkey->pkey.rsa;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* TLS */
|
|
|
5820f5 |
- if (s->version > SSL3_VERSION)
|
|
|
5820f5 |
+ /* TLS and [incidentally] DTLS, including pre-0.9.8f */
|
|
|
5820f5 |
+ if (s->version > SSL3_VERSION &&
|
|
|
5820f5 |
+ s->client_version != DTLS1_BAD_VER)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
n2s(p,i);
|
|
|
5820f5 |
if (n != i+2)
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/ssl_locl.h.dtls-fixes openssl-fips-0.9.8f-dev/ssl/ssl_locl.h
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/ssl_locl.h.dtls-fixes 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/ssl_locl.h 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -680,7 +680,7 @@ SSL_METHOD *func_name(void) \
|
|
|
5820f5 |
ssl3_put_cipher_by_char, \
|
|
|
5820f5 |
ssl3_pending, \
|
|
|
5820f5 |
ssl3_num_ciphers, \
|
|
|
5820f5 |
- ssl3_get_cipher, \
|
|
|
5820f5 |
+ dtls1_get_cipher, \
|
|
|
5820f5 |
s_get_meth, \
|
|
|
5820f5 |
dtls1_default_timeout, \
|
|
|
5820f5 |
&DTLSv1_enc_data, \
|
|
|
5820f5 |
@@ -845,6 +845,8 @@ void dtls1_get_message_header(unsigned c
|
|
|
5820f5 |
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
|
|
|
5820f5 |
void dtls1_reset_seq_numbers(SSL *s, int rw);
|
|
|
5820f5 |
long dtls1_default_timeout(void);
|
|
|
5820f5 |
+SSL_CIPHER *dtls1_get_cipher(unsigned int u);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
|
|
|
5820f5 |
|
|
|
5820f5 |
/* some client-only functions */
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/t1_enc.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/t1_enc.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/t1_enc.c.dtls-fixes 2007-03-22 01:39:15.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/t1_enc.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -740,15 +740,35 @@ int tls1_mac(SSL *ssl, unsigned char *md
|
|
|
5820f5 |
md_size=EVP_MD_size(hash);
|
|
|
5820f5 |
|
|
|
5820f5 |
buf[0]=rec->type;
|
|
|
5820f5 |
- buf[1]=TLS1_VERSION_MAJOR;
|
|
|
5820f5 |
- buf[2]=TLS1_VERSION_MINOR;
|
|
|
5820f5 |
+ if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ buf[1]=TLS1_VERSION_MAJOR;
|
|
|
5820f5 |
+ buf[2]=TLS1_VERSION_MINOR;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+ else {
|
|
|
5820f5 |
+ buf[1]=(unsigned char)(ssl->version>>8);
|
|
|
5820f5 |
+ buf[2]=(unsigned char)(ssl->version);
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
buf[3]=rec->length>>8;
|
|
|
5820f5 |
buf[4]=rec->length&0xff;
|
|
|
5820f5 |
|
|
|
5820f5 |
/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
|
|
|
5820f5 |
HMAC_CTX_init(&hmac);
|
|
|
5820f5 |
HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);
|
|
|
5820f5 |
- HMAC_Update(&hmac,seq,8);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ unsigned char dtlsseq[8],*p=dtlsseq;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
|
|
|
5820f5 |
+ memcpy (p,&seq[2],6);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ HMAC_Update(&hmac,dtlsseq,8);
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+ else
|
|
|
5820f5 |
+ HMAC_Update(&hmac,seq,8);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
HMAC_Update(&hmac,buf,5);
|
|
|
5820f5 |
HMAC_Update(&hmac,rec->input,rec->length);
|
|
|
5820f5 |
HMAC_Final(&hmac,md,&md_size);
|
|
|
5820f5 |
@@ -765,8 +785,8 @@ printf("rec=");
|
|
|
5820f5 |
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
|
|
|
5820f5 |
#endif
|
|
|
5820f5 |
|
|
|
5820f5 |
- if ( SSL_version(ssl) != DTLS1_VERSION)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
+ if ( SSL_version(ssl) != DTLS1_VERSION)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
for (i=7; i>=0; i--)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
++seq[i];
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/ssl.h.dtls-fixes openssl-fips-0.9.8f-dev/ssl/ssl.h
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/ssl.h.dtls-fixes 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/ssl.h 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -1554,6 +1554,7 @@ void ERR_load_SSL_strings(void);
|
|
|
5820f5 |
#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253
|
|
|
5820f5 |
#define SSL_F_DTLS1_GET_RECORD 254
|
|
|
5820f5 |
#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
|
|
|
5820f5 |
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277
|
|
|
5820f5 |
#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
|
|
|
5820f5 |
#define SSL_F_DTLS1_PROCESS_RECORD 257
|
|
|
5820f5 |
#define SSL_F_DTLS1_READ_BYTES 258
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_pkt.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_pkt.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/d1_pkt.c.dtls-fixes 2006-11-29 15:45:13.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_pkt.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -120,6 +120,7 @@
|
|
|
5820f5 |
#include <openssl/evp.h>
|
|
|
5820f5 |
#include <openssl/buffer.h>
|
|
|
5820f5 |
#include <openssl/pqueue.h>
|
|
|
5820f5 |
+#include <openssl/rand.h>
|
|
|
5820f5 |
|
|
|
5820f5 |
static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
|
|
|
5820f5 |
int len, int peek);
|
|
|
5820f5 |
@@ -486,9 +487,9 @@ int dtls1_get_record(SSL *s)
|
|
|
5820f5 |
SSL3_RECORD *rr;
|
|
|
5820f5 |
SSL_SESSION *sess;
|
|
|
5820f5 |
unsigned char *p;
|
|
|
5820f5 |
- short version;
|
|
|
5820f5 |
+ unsigned short version;
|
|
|
5820f5 |
DTLS1_BITMAP *bitmap;
|
|
|
5820f5 |
- unsigned int is_next_epoch;
|
|
|
5820f5 |
+ unsigned int is_next_epoch;
|
|
|
5820f5 |
|
|
|
5820f5 |
rr= &(s->s3->rrec);
|
|
|
5820f5 |
sess=s->session;
|
|
|
5820f5 |
@@ -524,7 +525,7 @@ again:
|
|
|
5820f5 |
ssl_minor= *(p++);
|
|
|
5820f5 |
version=(ssl_major<<8)|ssl_minor;
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* sequence number is 64 bits, with top 2 bytes = epoch */
|
|
|
5820f5 |
+ /* sequence number is 64 bits, with top 2 bytes = epoch */
|
|
|
5820f5 |
n2s(p,rr->epoch);
|
|
|
5820f5 |
|
|
|
5820f5 |
memcpy(&(s->s3->read_sequence[2]), p, 6);
|
|
|
5820f5 |
@@ -535,7 +536,7 @@ again:
|
|
|
5820f5 |
/* Lets check version */
|
|
|
5820f5 |
if (!s->first_packet)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- if (version != s->version)
|
|
|
5820f5 |
+ if (version != s->version && version != DTLS1_BAD_VER)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
|
|
|
5820f5 |
/* Send back error using their
|
|
|
5820f5 |
@@ -546,7 +547,8 @@ again:
|
|
|
5820f5 |
}
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
- if ((version & 0xff00) != (DTLS1_VERSION & 0xff00))
|
|
|
5820f5 |
+ if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
|
|
|
5820f5 |
+ (version & 0xff00) != (DTLS1_BAD_VER & 0xff00))
|
|
|
5820f5 |
{
|
|
|
5820f5 |
SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
|
|
|
5820f5 |
goto err;
|
|
|
5820f5 |
@@ -559,6 +561,7 @@ again:
|
|
|
5820f5 |
goto f_err;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
+ s->client_version = version;
|
|
|
5820f5 |
/* now s->rstate == SSL_ST_READ_BODY */
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
@@ -973,47 +976,40 @@ start:
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- struct ccs_header_st ccs_hdr;
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ struct ccs_header_st ccs_hdr;
|
|
|
5820f5 |
|
|
|
5820f5 |
dtls1_get_ccs_header(rr->data, &ccs_hdr);
|
|
|
5820f5 |
|
|
|
5820f5 |
- if ( ccs_hdr.seq == s->d1->handshake_read_seq)
|
|
|
5820f5 |
+ /* 'Change Cipher Spec' is just a single byte, so we know
|
|
|
5820f5 |
+ * exactly what the record payload has to look like */
|
|
|
5820f5 |
+ /* XDTLS: check that epoch is consistent */
|
|
|
5820f5 |
+ if ( (s->client_version == DTLS1_BAD_VER && rr->length != 3) ||
|
|
|
5820f5 |
+ (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) ||
|
|
|
5820f5 |
+ (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- /* 'Change Cipher Spec' is just a single byte, so we know
|
|
|
5820f5 |
- * exactly what the record payload has to look like */
|
|
|
5820f5 |
- /* XDTLS: check that epoch is consistent */
|
|
|
5820f5 |
- if ( (rr->length != DTLS1_CCS_HEADER_LENGTH) ||
|
|
|
5820f5 |
- (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- i=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- rr->length=0;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- if (s->msg_callback)
|
|
|
5820f5 |
- s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
|
|
|
5820f5 |
- rr->data, 1, s, s->msg_callback_arg);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- s->s3->change_cipher_spec=1;
|
|
|
5820f5 |
- if (!ssl3_do_change_cipher_spec(s))
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* do this whenever CCS is processed */
|
|
|
5820f5 |
- dtls1_reset_seq_numbers(s, SSL3_CC_READ);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* handshake read seq is reset upon handshake completion */
|
|
|
5820f5 |
- s->d1->handshake_read_seq++;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- goto start;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- else
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- rr->length = 0;
|
|
|
5820f5 |
- goto start;
|
|
|
5820f5 |
+ i=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
+ SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ rr->length=0;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (s->msg_callback)
|
|
|
5820f5 |
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
|
|
|
5820f5 |
+ rr->data, 1, s, s->msg_callback_arg);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ s->s3->change_cipher_spec=1;
|
|
|
5820f5 |
+ if (!ssl3_do_change_cipher_spec(s))
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ /* do this whenever CCS is processed */
|
|
|
5820f5 |
+ dtls1_reset_seq_numbers(s, SSL3_CC_READ);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (s->client_version == DTLS1_BAD_VER)
|
|
|
5820f5 |
+ s->d1->handshake_read_seq++;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ goto start;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
/* Unexpected handshake message (Client Hello, or protocol violation) */
|
|
|
5820f5 |
@@ -1341,8 +1337,12 @@ int do_dtls1_write(SSL *s, int type, con
|
|
|
5820f5 |
*(p++)=type&0xff;
|
|
|
5820f5 |
wr->type=type;
|
|
|
5820f5 |
|
|
|
5820f5 |
- *(p++)=(s->version>>8);
|
|
|
5820f5 |
- *(p++)=s->version&0xff;
|
|
|
5820f5 |
+ if (s->client_version == DTLS1_BAD_VER)
|
|
|
5820f5 |
+ *(p++) = DTLS1_BAD_VER>>8,
|
|
|
5820f5 |
+ *(p++) = DTLS1_BAD_VER&0xff;
|
|
|
5820f5 |
+ else
|
|
|
5820f5 |
+ *(p++)=(s->version>>8),
|
|
|
5820f5 |
+ *(p++)=s->version&0xff;
|
|
|
5820f5 |
|
|
|
5820f5 |
/* field where we are to write out packet epoch, seq num and len */
|
|
|
5820f5 |
pseq=p;
|
|
|
5820f5 |
@@ -1397,8 +1397,14 @@ int do_dtls1_write(SSL *s, int type, con
|
|
|
5820f5 |
|
|
|
5820f5 |
|
|
|
5820f5 |
/* ssl3_enc can only have an error on read */
|
|
|
5820f5 |
- wr->length += bs; /* bs != 0 in case of CBC. The enc fn provides
|
|
|
5820f5 |
- * the randomness */
|
|
|
5820f5 |
+ if (bs) /* bs != 0 in case of CBC */
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ RAND_pseudo_bytes(p,bs);
|
|
|
5820f5 |
+ /* master IV and last CBC residue stand for
|
|
|
5820f5 |
+ * the rest of randomness */
|
|
|
5820f5 |
+ wr->length += bs;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
s->method->ssl3_enc->enc(s,1);
|
|
|
5820f5 |
|
|
|
5820f5 |
/* record length after mac and block padding */
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/ssl_err.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/ssl_err.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/ssl_err.c.dtls-fixes 2006-11-21 21:14:46.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/ssl_err.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -87,6 +87,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
|
|
|
5820f5 |
{ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT), "DTLS1_GET_MESSAGE_FRAGMENT"},
|
|
|
5820f5 |
{ERR_FUNC(SSL_F_DTLS1_GET_RECORD), "DTLS1_GET_RECORD"},
|
|
|
5820f5 |
{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"},
|
|
|
5820f5 |
+{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"},
|
|
|
5820f5 |
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE), "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
|
|
|
5820f5 |
{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
|
|
|
5820f5 |
{ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "DTLS1_READ_BYTES"},
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/s3_clnt.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/s3_clnt.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/s3_clnt.c.dtls-fixes 2007-03-22 01:39:14.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/s3_clnt.c 2008-07-15 21:08:43.000000000 +0200
|
|
|
5820f5 |
@@ -1847,6 +1847,13 @@ int ssl3_send_client_key_exchange(SSL *s
|
|
|
5820f5 |
{
|
|
|
5820f5 |
DH *dh_srvr,*dh_clnt;
|
|
|
5820f5 |
|
|
|
5820f5 |
+ if (s->session->sess_cert == NULL)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
|
|
|
5820f5 |
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
if (s->session->sess_cert->peer_dh_tmp != NULL)
|
|
|
5820f5 |
dh_srvr=s->session->sess_cert->peer_dh_tmp;
|
|
|
5820f5 |
else
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_both.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_both.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/d1_both.c.dtls-fixes 2007-06-22 14:17:52.000000000 +0200
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_both.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -138,38 +138,40 @@ static void dtls1_set_message_header_int
|
|
|
5820f5 |
unsigned long frag_len);
|
|
|
5820f5 |
static int dtls1_retransmit_buffered_messages(SSL *s);
|
|
|
5820f5 |
static long dtls1_get_message_fragment(SSL *s, int st1, int stn,
|
|
|
5820f5 |
- long max, int *ok);
|
|
|
5820f5 |
-static void dtls1_process_handshake_fragment(SSL *s, int frag_len);
|
|
|
5820f5 |
+ long max, int *ok);
|
|
|
5820f5 |
|
|
|
5820f5 |
static hm_fragment *
|
|
|
5820f5 |
dtls1_hm_fragment_new(unsigned long frag_len)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- hm_fragment *frag = NULL;
|
|
|
5820f5 |
- unsigned char *buf = NULL;
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ hm_fragment *frag = NULL;
|
|
|
5820f5 |
+ unsigned char *buf = NULL;
|
|
|
5820f5 |
|
|
|
5820f5 |
- frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
|
|
|
5820f5 |
- if ( frag == NULL)
|
|
|
5820f5 |
- return NULL;
|
|
|
5820f5 |
+ frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
|
|
|
5820f5 |
+ if ( frag == NULL)
|
|
|
5820f5 |
+ return NULL;
|
|
|
5820f5 |
|
|
|
5820f5 |
- buf = (unsigned char *)OPENSSL_malloc(frag_len
|
|
|
5820f5 |
- + DTLS1_HM_HEADER_LENGTH);
|
|
|
5820f5 |
- if ( buf == NULL)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- OPENSSL_free(frag);
|
|
|
5820f5 |
- return NULL;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- frag->fragment = buf;
|
|
|
5820f5 |
+ if (frag_len)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ buf = (unsigned char *)OPENSSL_malloc(frag_len);
|
|
|
5820f5 |
+ if ( buf == NULL)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ OPENSSL_free(frag);
|
|
|
5820f5 |
+ return NULL;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
- return frag;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+ /* zero length fragment gets zero frag->fragment */
|
|
|
5820f5 |
+ frag->fragment = buf;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ return frag;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
static void
|
|
|
5820f5 |
dtls1_hm_fragment_free(hm_fragment *frag)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- OPENSSL_free(frag->fragment);
|
|
|
5820f5 |
- OPENSSL_free(frag);
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ if (frag->fragment) OPENSSL_free(frag->fragment);
|
|
|
5820f5 |
+ OPENSSL_free(frag);
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
|
|
|
5820f5 |
int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
@@ -180,7 +182,7 @@ int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
|
|
|
5820f5 |
/* AHA! Figure out the MTU, and stick to the right size */
|
|
|
5820f5 |
if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
s->d1->mtu =
|
|
|
5820f5 |
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
|
|
|
5820f5 |
|
|
|
5820f5 |
@@ -207,7 +209,7 @@ int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
mtu = curr_mtu;
|
|
|
5820f5 |
else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0)
|
|
|
5820f5 |
return ret;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+
|
|
|
5820f5 |
if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
ret = BIO_flush(SSL_get_wbio(s));
|
|
|
5820f5 |
@@ -254,11 +256,11 @@ int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
s->init_off -= DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
s->init_num += DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* write atleast DTLS1_HM_HEADER_LENGTH bytes */
|
|
|
5820f5 |
+ /* write atleast DTLS1_HM_HEADER_LENGTH bytes */
|
|
|
5820f5 |
if ( len <= DTLS1_HM_HEADER_LENGTH)
|
|
|
5820f5 |
len += DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+
|
|
|
5820f5 |
dtls1_fix_message_header(s, frag_off,
|
|
|
5820f5 |
len - DTLS1_HM_HEADER_LENGTH);
|
|
|
5820f5 |
|
|
|
5820f5 |
@@ -286,18 +288,40 @@ int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
}
|
|
|
5820f5 |
else
|
|
|
5820f5 |
{
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+
|
|
|
5820f5 |
/* bad if this assert fails, only part of the handshake
|
|
|
5820f5 |
* message got sent. but why would this happen? */
|
|
|
5820f5 |
- OPENSSL_assert(len == (unsigned int)ret);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+ OPENSSL_assert(len == (unsigned int)ret);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
/* should not be done for 'Hello Request's, but in that case
|
|
|
5820f5 |
* we'll ignore the result anyway */
|
|
|
5820f5 |
- ssl3_finish_mac(s,
|
|
|
5820f5 |
- (unsigned char *)&s->init_buf->data[s->init_off +
|
|
|
5820f5 |
- DTLS1_HM_HEADER_LENGTH], ret - DTLS1_HM_HEADER_LENGTH);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+ unsigned char *p = &s->init_buf->data[s->init_off];
|
|
|
5820f5 |
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
|
|
|
5820f5 |
+ int len;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (frag_off == 0 && s->client_version != DTLS1_BAD_VER)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ /* reconstruct message header is if it
|
|
|
5820f5 |
+ * is being sent in single fragment */
|
|
|
5820f5 |
+ *p++ = msg_hdr->type;
|
|
|
5820f5 |
+ l2n3(msg_hdr->msg_len,p);
|
|
|
5820f5 |
+ s2n (msg_hdr->seq,p);
|
|
|
5820f5 |
+ l2n3(0,p);
|
|
|
5820f5 |
+ l2n3(msg_hdr->msg_len,p);
|
|
|
5820f5 |
+ p -= DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+ len = ret;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+ else
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ p += DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+ len = ret - DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ ssl3_finish_mac(s, p, len);
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
if (ret == s->init_num)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
if (s->msg_callback)
|
|
|
5820f5 |
@@ -307,7 +331,7 @@ int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
|
|
|
5820f5 |
s->init_off = 0; /* done writing this message */
|
|
|
5820f5 |
s->init_num = 0;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+
|
|
|
5820f5 |
return(1);
|
|
|
5820f5 |
}
|
|
|
5820f5 |
s->init_off+=ret;
|
|
|
5820f5 |
@@ -327,6 +351,7 @@ int dtls1_do_write(SSL *s, int type)
|
|
|
5820f5 |
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
int i, al;
|
|
|
5820f5 |
+ struct hm_header_st *msg_hdr;
|
|
|
5820f5 |
|
|
|
5820f5 |
/* s3->tmp is used to store messages that are unexpected, caused
|
|
|
5820f5 |
* by the absence of an optional handshake message */
|
|
|
5820f5 |
@@ -344,25 +369,56 @@ long dtls1_get_message(SSL *s, int st1,
|
|
|
5820f5 |
s->init_num = (int)s->s3->tmp.message_size;
|
|
|
5820f5 |
return s->init_num;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ msg_hdr = &s->d1->r_msg_hdr;
|
|
|
5820f5 |
do
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- if ( s->d1->r_msg_hdr.frag_off == 0)
|
|
|
5820f5 |
+ if ( msg_hdr->frag_off == 0)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
/* s->d1->r_message_header.msg_len = 0; */
|
|
|
5820f5 |
- memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
|
|
|
5820f5 |
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
i = dtls1_get_message_fragment(s, st1, stn, max, ok);
|
|
|
5820f5 |
if ( i == DTLS1_HM_BAD_FRAGMENT ||
|
|
|
5820f5 |
- i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */
|
|
|
5820f5 |
+ i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */
|
|
|
5820f5 |
continue;
|
|
|
5820f5 |
else if ( i <= 0 && !*ok)
|
|
|
5820f5 |
return i;
|
|
|
5820f5 |
|
|
|
5820f5 |
- if (s->d1->r_msg_hdr.msg_len == (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
|
|
|
5820f5 |
+ /* Note that s->init_sum is used as a counter summing
|
|
|
5820f5 |
+ * up fragments' lengths: as soon as they sum up to
|
|
|
5820f5 |
+ * handshake packet length, we assume we have got all
|
|
|
5820f5 |
+ * the fragments. Overlapping fragments would cause
|
|
|
5820f5 |
+ * premature termination, so we don't expect overlaps.
|
|
|
5820f5 |
+ * Well, handling overlaps would require something more
|
|
|
5820f5 |
+ * drastic. Indeed, as it is now there is no way to
|
|
|
5820f5 |
+ * tell if out-of-order fragment from the middle was
|
|
|
5820f5 |
+ * the last. '>=' is the best/least we can do to control
|
|
|
5820f5 |
+ * the potential damage caused by malformed overlaps. */
|
|
|
5820f5 |
+ if ((unsigned int)s->init_num >= msg_hdr->msg_len)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
|
|
|
5820f5 |
+ unsigned char *p = s->init_buf->data;
|
|
|
5820f5 |
+ unsigned long msg_len = msg_hdr->msg_len;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ /* reconstruct message header as if it was
|
|
|
5820f5 |
+ * sent in single fragment */
|
|
|
5820f5 |
+ *(p++) = msg_hdr->type;
|
|
|
5820f5 |
+ l2n3(msg_len,p);
|
|
|
5820f5 |
+ s2n (msg_hdr->seq,p);
|
|
|
5820f5 |
+ l2n3(0,p);
|
|
|
5820f5 |
+ l2n3(msg_len,p);
|
|
|
5820f5 |
+ if (s->client_version != DTLS1_BAD_VER)
|
|
|
5820f5 |
+ p -= DTLS1_HM_HEADER_LENGTH,
|
|
|
5820f5 |
+ msg_len += DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ ssl3_finish_mac(s, p, msg_len);
|
|
|
5820f5 |
+ if (s->msg_callback)
|
|
|
5820f5 |
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
+ p, msg_len,
|
|
|
5820f5 |
+ s, s->msg_callback_arg);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
|
|
|
5820f5 |
|
|
|
5820f5 |
s->d1->handshake_read_seq++;
|
|
|
5820f5 |
/* we just read a handshake message from the other side:
|
|
|
5820f5 |
@@ -379,11 +435,11 @@ long dtls1_get_message(SSL *s, int st1,
|
|
|
5820f5 |
* first data segment, but is there a better way? */
|
|
|
5820f5 |
dtls1_clear_record_buffer(s);
|
|
|
5820f5 |
|
|
|
5820f5 |
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
- return s->init_num - DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+ return s->init_num;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
else
|
|
|
5820f5 |
- s->d1->r_msg_hdr.frag_off = i;
|
|
|
5820f5 |
+ msg_hdr->frag_off = i;
|
|
|
5820f5 |
} while(1) ;
|
|
|
5820f5 |
|
|
|
5820f5 |
f_err:
|
|
|
5820f5 |
@@ -393,161 +449,183 @@ f_err:
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
|
|
|
5820f5 |
-static int
|
|
|
5820f5 |
-dtls1_retrieve_buffered_fragment(SSL *s, unsigned long *copied)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- /* (0) check whether the desired fragment is available
|
|
|
5820f5 |
- * if so:
|
|
|
5820f5 |
- * (1) copy over the fragment to s->init_buf->data[]
|
|
|
5820f5 |
- * (2) update s->init_num
|
|
|
5820f5 |
- */
|
|
|
5820f5 |
- pitem *item;
|
|
|
5820f5 |
- hm_fragment *frag;
|
|
|
5820f5 |
- unsigned long overlap;
|
|
|
5820f5 |
- unsigned char *p;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- item = pqueue_peek(s->d1->buffered_messages);
|
|
|
5820f5 |
- if ( item == NULL)
|
|
|
5820f5 |
- return 0;
|
|
|
5820f5 |
+static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ size_t frag_off,frag_len,msg_len;
|
|
|
5820f5 |
|
|
|
5820f5 |
- frag = (hm_fragment *)item->data;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- if ( s->d1->handshake_read_seq == frag->msg_header.seq &&
|
|
|
5820f5 |
- frag->msg_header.frag_off <= (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- pqueue_pop(s->d1->buffered_messages);
|
|
|
5820f5 |
- overlap = s->init_num - DTLS1_HM_HEADER_LENGTH
|
|
|
5820f5 |
- - frag->msg_header.frag_off;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- p = frag->fragment;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- memcpy(&s->init_buf->data[s->init_num],
|
|
|
5820f5 |
- p + DTLS1_HM_HEADER_LENGTH + overlap,
|
|
|
5820f5 |
- frag->msg_header.frag_len - overlap);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- OPENSSL_free(frag->fragment);
|
|
|
5820f5 |
- OPENSSL_free(frag);
|
|
|
5820f5 |
- pitem_free(item);
|
|
|
5820f5 |
+ msg_len = msg_hdr->msg_len;
|
|
|
5820f5 |
+ frag_off = msg_hdr->frag_off;
|
|
|
5820f5 |
+ frag_len = msg_hdr->frag_len;
|
|
|
5820f5 |
|
|
|
5820f5 |
- *copied = frag->msg_header.frag_len - overlap;
|
|
|
5820f5 |
- return *copied;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- else
|
|
|
5820f5 |
- return 0;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+ /* sanity checking */
|
|
|
5820f5 |
+ if ( (frag_off+frag_len) > msg_len)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
+ return SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
+ if ( (frag_off+frag_len) > (unsigned long)max)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
+ return SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
-static int
|
|
|
5820f5 |
-dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr)
|
|
|
5820f5 |
-{
|
|
|
5820f5 |
- hm_fragment *frag = NULL;
|
|
|
5820f5 |
- pitem *item = NULL;
|
|
|
5820f5 |
- PQ_64BIT seq64;
|
|
|
5820f5 |
+ if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ /* msg_len is limited to 2^24, but is effectively checked
|
|
|
5820f5 |
+ * against max above */
|
|
|
5820f5 |
+ if (!BUF_MEM_grow_clean(s->init_buf,(int)msg_len+DTLS1_HM_HEADER_LENGTH))
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
|
|
|
5820f5 |
+ return SSL_AD_INTERNAL_ERROR;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
- frag = dtls1_hm_fragment_new(msg_hdr->frag_len);
|
|
|
5820f5 |
- if ( frag == NULL)
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
+ s->s3->tmp.message_size = msg_len;
|
|
|
5820f5 |
+ s->d1->r_msg_hdr.msg_len = msg_len;
|
|
|
5820f5 |
+ s->s3->tmp.message_type = msg_hdr->type;
|
|
|
5820f5 |
+ s->d1->r_msg_hdr.type = msg_hdr->type;
|
|
|
5820f5 |
+ s->d1->r_msg_hdr.seq = msg_hdr->seq;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+ else if (msg_len != s->d1->r_msg_hdr.msg_len)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ /* They must be playing with us! BTW, failure to enforce
|
|
|
5820f5 |
+ * upper limit would open possibility for buffer overrun. */
|
|
|
5820f5 |
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
+ return SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
- memcpy(frag->fragment, &(s->init_buf->data[s->init_num]),
|
|
|
5820f5 |
- msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH);
|
|
|
5820f5 |
+ return 0; /* no error */
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
- memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
|
|
|
5820f5 |
|
|
|
5820f5 |
- pq_64bit_init(&seq64);
|
|
|
5820f5 |
- pq_64bit_assign_word(&seq64, msg_hdr->seq);
|
|
|
5820f5 |
+static int
|
|
|
5820f5 |
+dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ /* (0) check whether the desired fragment is available
|
|
|
5820f5 |
+ * if so:
|
|
|
5820f5 |
+ * (1) copy over the fragment to s->init_buf->data[]
|
|
|
5820f5 |
+ * (2) update s->init_num
|
|
|
5820f5 |
+ */
|
|
|
5820f5 |
+ pitem *item;
|
|
|
5820f5 |
+ hm_fragment *frag;
|
|
|
5820f5 |
+ int al;
|
|
|
5820f5 |
|
|
|
5820f5 |
- item = pitem_new(seq64, frag);
|
|
|
5820f5 |
- if ( item == NULL)
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
+ *ok = 0;
|
|
|
5820f5 |
+ item = pqueue_peek(s->d1->buffered_messages);
|
|
|
5820f5 |
+ if ( item == NULL)
|
|
|
5820f5 |
+ return 0;
|
|
|
5820f5 |
|
|
|
5820f5 |
- pq_64bit_free(&seq64);
|
|
|
5820f5 |
+ frag = (hm_fragment *)item->data;
|
|
|
5820f5 |
|
|
|
5820f5 |
- pqueue_insert(s->d1->buffered_messages, item);
|
|
|
5820f5 |
- return 1;
|
|
|
5820f5 |
+ if ( s->d1->handshake_read_seq == frag->msg_header.seq)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ pqueue_pop(s->d1->buffered_messages);
|
|
|
5820f5 |
|
|
|
5820f5 |
-err:
|
|
|
5820f5 |
- if ( frag != NULL) dtls1_hm_fragment_free(frag);
|
|
|
5820f5 |
- if ( item != NULL) OPENSSL_free(item);
|
|
|
5820f5 |
- return 0;
|
|
|
5820f5 |
-}
|
|
|
5820f5 |
+ al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
|
|
|
5820f5 |
|
|
|
5820f5 |
+ if (al==0) /* no alert */
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ unsigned char *p = s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+ memcpy(&p[frag->msg_header.frag_off],
|
|
|
5820f5 |
+ frag->fragment,frag->msg_header.frag_len);
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
-static void
|
|
|
5820f5 |
-dtls1_process_handshake_fragment(SSL *s, int frag_len)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- unsigned char *p;
|
|
|
5820f5 |
+ dtls1_hm_fragment_free(frag);
|
|
|
5820f5 |
+ pitem_free(item);
|
|
|
5820f5 |
|
|
|
5820f5 |
- p = (unsigned char *)s->init_buf->data;
|
|
|
5820f5 |
+ if (al==0)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ *ok = 1;
|
|
|
5820f5 |
+ return frag->msg_header.frag_len;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
- ssl3_finish_mac(s, &p[s->init_num - frag_len], frag_len);
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
|
|
|
5820f5 |
+ s->init_num = 0;
|
|
|
5820f5 |
+ *ok = 0;
|
|
|
5820f5 |
+ return -1;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+ else
|
|
|
5820f5 |
+ return 0;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
|
|
|
5820f5 |
static int
|
|
|
5820f5 |
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st *msg_hdr, int *ok)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- int i;
|
|
|
5820f5 |
- unsigned char *p;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* make sure there's enough room to read this fragment */
|
|
|
5820f5 |
- if ( (int)msg_hdr->frag_len && !BUF_MEM_grow_clean(s->init_buf,
|
|
|
5820f5 |
- (int)msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH + s->init_num))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE,ERR_R_BUF_LIB);
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
|
|
|
5820f5 |
+{
|
|
|
5820f5 |
+ int i=-1;
|
|
|
5820f5 |
+ hm_fragment *frag = NULL;
|
|
|
5820f5 |
+ pitem *item = NULL;
|
|
|
5820f5 |
+ PQ_64BIT seq64;
|
|
|
5820f5 |
+ unsigned long frag_len = msg_hdr->frag_len;
|
|
|
5820f5 |
|
|
|
5820f5 |
- p = (unsigned char *)s->init_buf->data;
|
|
|
5820f5 |
+ if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* read the body of the fragment (header has already been read */
|
|
|
5820f5 |
- if ( msg_hdr->frag_len > 0)
|
|
|
5820f5 |
+ if (msg_hdr->seq <= s->d1->handshake_read_seq)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
- &p[s->init_num],
|
|
|
5820f5 |
- msg_hdr->frag_len,0);
|
|
|
5820f5 |
- if (i <= 0)
|
|
|
5820f5 |
+ unsigned char devnull [256];
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ while (frag_len)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- *ok = 0;
|
|
|
5820f5 |
- return i;
|
|
|
5820f5 |
+ i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
+ devnull,
|
|
|
5820f5 |
+ frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
|
|
|
5820f5 |
+ if (i<=0) goto err;
|
|
|
5820f5 |
+ frag_len -= i;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
- if ( msg_hdr->seq > s->d1->handshake_read_seq)
|
|
|
5820f5 |
- dtls1_buffer_handshake_fragment(s, msg_hdr);
|
|
|
5820f5 |
- else
|
|
|
5820f5 |
- OPENSSL_assert(msg_hdr->seq < s->d1->handshake_read_seq);
|
|
|
5820f5 |
+ frag = dtls1_hm_fragment_new(frag_len);
|
|
|
5820f5 |
+ if ( frag == NULL)
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (frag_len)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ /* read the body of the fragment (header has already been read */
|
|
|
5820f5 |
+ i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
+ frag->fragment,frag_len,0);
|
|
|
5820f5 |
+ if (i<=0 || i!=frag_len)
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ pq_64bit_init(&seq64);
|
|
|
5820f5 |
+ pq_64bit_assign_word(&seq64, msg_hdr->seq);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ item = pitem_new(seq64, frag);
|
|
|
5820f5 |
+ pq_64bit_free(&seq64);
|
|
|
5820f5 |
+ if ( item == NULL)
|
|
|
5820f5 |
+ goto err;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ pqueue_insert(s->d1->buffered_messages, item);
|
|
|
5820f5 |
+ return DTLS1_HM_FRAGMENT_RETRY;
|
|
|
5820f5 |
|
|
|
5820f5 |
- return DTLS1_HM_FRAGMENT_RETRY;
|
|
|
5820f5 |
err:
|
|
|
5820f5 |
- *ok = 0;
|
|
|
5820f5 |
- return -1;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+ if ( frag != NULL) dtls1_hm_fragment_free(frag);
|
|
|
5820f5 |
+ if ( item != NULL) OPENSSL_free(item);
|
|
|
5820f5 |
+ *ok = 0;
|
|
|
5820f5 |
+ return i;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
|
|
|
5820f5 |
static long
|
|
|
5820f5 |
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- unsigned char *p;
|
|
|
5820f5 |
+ unsigned char wire[DTLS1_HM_HEADER_LENGTH];
|
|
|
5820f5 |
unsigned long l, frag_off, frag_len;
|
|
|
5820f5 |
int i,al;
|
|
|
5820f5 |
struct hm_header_st msg_hdr;
|
|
|
5820f5 |
- unsigned long overlap;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* see if we have the required fragment already */
|
|
|
5820f5 |
- if (dtls1_retrieve_buffered_fragment(s, &l))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- /* compute MAC, remove fragment headers */
|
|
|
5820f5 |
- dtls1_process_handshake_fragment(s, l);
|
|
|
5820f5 |
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
- s->state = stn;
|
|
|
5820f5 |
- return 1;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* get a handshake fragment from the record layer */
|
|
|
5820f5 |
- p = (unsigned char *)s->init_buf->data;
|
|
|
5820f5 |
+ /* see if we have the required fragment already */
|
|
|
5820f5 |
+ if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ if (*ok) s->init_num += frag_len;
|
|
|
5820f5 |
+ return frag_len;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* read handshake message header */
|
|
|
5820f5 |
- i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],
|
|
|
5820f5 |
+ /* read handshake message header */
|
|
|
5820f5 |
+ i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
|
|
|
5820f5 |
DTLS1_HM_HEADER_LENGTH, 0);
|
|
|
5820f5 |
if (i <= 0) /* nbio, or an error */
|
|
|
5820f5 |
{
|
|
|
5820f5 |
@@ -555,130 +633,61 @@ dtls1_get_message_fragment(SSL *s, int s
|
|
|
5820f5 |
*ok = 0;
|
|
|
5820f5 |
return i;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
-
|
|
|
5820f5 |
OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);
|
|
|
5820f5 |
|
|
|
5820f5 |
- p += s->init_num;
|
|
|
5820f5 |
- /* parse the message fragment header */
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- dtls1_get_message_header(p, &msg_hdr);
|
|
|
5820f5 |
+ /* parse the message fragment header */
|
|
|
5820f5 |
+ dtls1_get_message_header(wire, &msg_hdr);
|
|
|
5820f5 |
|
|
|
5820f5 |
- /*
|
|
|
5820f5 |
- * if this is a future (or stale) message it gets buffered
|
|
|
5820f5 |
- * (or dropped)--no further processing at this time
|
|
|
5820f5 |
- */
|
|
|
5820f5 |
- if ( msg_hdr.seq != s->d1->handshake_read_seq)
|
|
|
5820f5 |
- return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
|
|
|
5820f5 |
+ /*
|
|
|
5820f5 |
+ * if this is a future (or stale) message it gets buffered
|
|
|
5820f5 |
+ * (or dropped)--no further processing at this time
|
|
|
5820f5 |
+ */
|
|
|
5820f5 |
+ if ( msg_hdr.seq != s->d1->handshake_read_seq)
|
|
|
5820f5 |
+ return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
|
|
|
5820f5 |
|
|
|
5820f5 |
- l = msg_hdr.msg_len;
|
|
|
5820f5 |
- frag_off = msg_hdr.frag_off;
|
|
|
5820f5 |
+ l = msg_hdr.msg_len;
|
|
|
5820f5 |
+ frag_off = msg_hdr.frag_off;
|
|
|
5820f5 |
frag_len = msg_hdr.frag_len;
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* sanity checking */
|
|
|
5820f5 |
- if ( frag_off + frag_len > l)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- al=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
- goto f_err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
|
|
|
5820f5 |
- p[0] == SSL3_MT_HELLO_REQUEST)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- /* The server may always send 'Hello Request' messages --
|
|
|
5820f5 |
- * we are doing a handshake anyway now, so ignore them
|
|
|
5820f5 |
- * if their format is correct. Does not count for
|
|
|
5820f5 |
- * 'Finished' MAC. */
|
|
|
5820f5 |
- if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- if (s->msg_callback)
|
|
|
5820f5 |
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
- p, DTLS1_HM_HEADER_LENGTH, s,
|
|
|
5820f5 |
- s->msg_callback_arg);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- s->init_num = 0;
|
|
|
5820f5 |
- return dtls1_get_message_fragment(s, st1, stn,
|
|
|
5820f5 |
- max, ok);
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- else /* Incorrectly formated Hello request */
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- al=SSL_AD_UNEXPECTED_MESSAGE;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
|
|
|
5820f5 |
- goto f_err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* XDTLS: do a sanity check on the fragment */
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- s->init_num += i;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
|
|
|
5820f5 |
+ wire[0] == SSL3_MT_HELLO_REQUEST)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- /* BUF_MEM_grow takes an 'int' parameter */
|
|
|
5820f5 |
- if (l > (INT_MAX-DTLS1_HM_HEADER_LENGTH))
|
|
|
5820f5 |
+ /* The server may always send 'Hello Request' messages --
|
|
|
5820f5 |
+ * we are doing a handshake anyway now, so ignore them
|
|
|
5820f5 |
+ * if their format is correct. Does not count for
|
|
|
5820f5 |
+ * 'Finished' MAC. */
|
|
|
5820f5 |
+ if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- al=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
- goto f_err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l
|
|
|
5820f5 |
- + DTLS1_HM_HEADER_LENGTH))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
+ if (s->msg_callback)
|
|
|
5820f5 |
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
+ wire, DTLS1_HM_HEADER_LENGTH, s,
|
|
|
5820f5 |
+ s->msg_callback_arg);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ s->init_num = 0;
|
|
|
5820f5 |
+ return dtls1_get_message_fragment(s, st1, stn,
|
|
|
5820f5 |
+ max, ok);
|
|
|
5820f5 |
}
|
|
|
5820f5 |
- /* Only do this test when we're reading the expected message.
|
|
|
5820f5 |
- * Stale messages will be dropped and future messages will be buffered */
|
|
|
5820f5 |
- if ( l > (unsigned long)max)
|
|
|
5820f5 |
+ else /* Incorrectly formated Hello request */
|
|
|
5820f5 |
{
|
|
|
5820f5 |
- al=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
+ al=SSL_AD_UNEXPECTED_MESSAGE;
|
|
|
5820f5 |
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
|
|
|
5820f5 |
goto f_err;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- s->s3->tmp.message_size=l;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
- if ( frag_len > (unsigned long)max)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- al=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
- goto f_err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- if ( frag_len + s->init_num > (INT_MAX - DTLS1_HM_HEADER_LENGTH))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- al=SSL_AD_ILLEGAL_PARAMETER;
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
|
|
5820f5 |
- goto f_err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- if ( frag_len & !BUF_MEM_grow_clean(s->init_buf, (int)frag_len
|
|
|
5820f5 |
- + DTLS1_HM_HEADER_LENGTH + s->init_num))
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
|
|
|
5820f5 |
- goto err;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- if ( s->d1->r_msg_hdr.frag_off == 0)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- s->s3->tmp.message_type = msg_hdr.type;
|
|
|
5820f5 |
- s->d1->r_msg_hdr.type = msg_hdr.type;
|
|
|
5820f5 |
- s->d1->r_msg_hdr.msg_len = l;
|
|
|
5820f5 |
- /* s->d1->r_msg_hdr.seq = seq_num; */
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
+ if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
|
|
|
5820f5 |
+ goto f_err;
|
|
|
5820f5 |
|
|
|
5820f5 |
/* XDTLS: ressurect this when restart is in place */
|
|
|
5820f5 |
s->state=stn;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* next state (stn) */
|
|
|
5820f5 |
- p = (unsigned char *)s->init_buf->data;
|
|
|
5820f5 |
|
|
|
5820f5 |
if ( frag_len > 0)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
+ unsigned char *p=s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
|
|
|
5820f5 |
- &p[s->init_num],
|
|
|
5820f5 |
- frag_len,0);
|
|
|
5820f5 |
- /* XDTLS: fix this--message fragments cannot span multiple packets */
|
|
|
5820f5 |
+ &p[frag_off],frag_len,0);
|
|
|
5820f5 |
+ /* XDTLS: fix this--message fragments cannot span multiple packets */
|
|
|
5820f5 |
if (i <= 0)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
s->rwstate=SSL_READING;
|
|
|
5820f5 |
@@ -689,70 +698,23 @@ dtls1_get_message_fragment(SSL *s, int s
|
|
|
5820f5 |
else
|
|
|
5820f5 |
i = 0;
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* XDTLS: an incorrectly formatted fragment should cause the
|
|
|
5820f5 |
- * handshake to fail */
|
|
|
5820f5 |
+ /* XDTLS: an incorrectly formatted fragment should cause the
|
|
|
5820f5 |
+ * handshake to fail */
|
|
|
5820f5 |
OPENSSL_assert(i == (int)frag_len);
|
|
|
5820f5 |
|
|
|
5820f5 |
-#if 0
|
|
|
5820f5 |
- /* Successfully read a fragment.
|
|
|
5820f5 |
- * It may be (1) out of order, or
|
|
|
5820f5 |
- * (2) it's a repeat, in which case we dump it
|
|
|
5820f5 |
- * (3) the one we are expecting next (maybe with overlap)
|
|
|
5820f5 |
- * If it is next one, it may overlap with previously read bytes
|
|
|
5820f5 |
- */
|
|
|
5820f5 |
+ *ok = 1;
|
|
|
5820f5 |
|
|
|
5820f5 |
- /* case (1): buffer the future fragment
|
|
|
5820f5 |
- * (we can treat fragments from a future message the same
|
|
|
5820f5 |
- * as future fragments from the message being currently read, since
|
|
|
5820f5 |
- * they are sematically simply out of order.
|
|
|
5820f5 |
- */
|
|
|
5820f5 |
- if ( msg_hdr.seq > s->d1->handshake_read_seq ||
|
|
|
5820f5 |
- frag_off > s->init_num - DTLS1_HM_HEADER_LENGTH)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- dtls1_buffer_handshake_fragment(s, &msg_hdr);
|
|
|
5820f5 |
- return DTLS1_HM_FRAGMENT_RETRY;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* case (2): drop the entire fragment, and try again */
|
|
|
5820f5 |
- if ( msg_hdr.seq < s->d1->handshake_read_seq ||
|
|
|
5820f5 |
- frag_off + frag_len < s->init_num - DTLS1_HM_HEADER_LENGTH)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- s->init_num -= DTLS1_HM_HEADER_LENGTH;
|
|
|
5820f5 |
- return DTLS1_HM_FRAGMENT_RETRY;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
-#endif
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* case (3): received a immediately useful fragment. Determine the
|
|
|
5820f5 |
- * possible overlap and copy the fragment.
|
|
|
5820f5 |
- */
|
|
|
5820f5 |
- overlap = (s->init_num - DTLS1_HM_HEADER_LENGTH) - frag_off;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- /* retain the header for the first fragment */
|
|
|
5820f5 |
- if ( s->init_num > DTLS1_HM_HEADER_LENGTH)
|
|
|
5820f5 |
- {
|
|
|
5820f5 |
- memmove(&(s->init_buf->data[s->init_num]),
|
|
|
5820f5 |
- &(s->init_buf->data[s->init_num + DTLS1_HM_HEADER_LENGTH + overlap]),
|
|
|
5820f5 |
- frag_len - overlap);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- s->init_num += frag_len - overlap;
|
|
|
5820f5 |
- }
|
|
|
5820f5 |
- else
|
|
|
5820f5 |
- s->init_num += frag_len;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- dtls1_process_handshake_fragment(s, frag_len - overlap);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- if (s->msg_callback)
|
|
|
5820f5 |
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
|
|
|
5820f5 |
- (size_t)s->init_num, s,
|
|
|
5820f5 |
- s->msg_callback_arg);
|
|
|
5820f5 |
- *ok=1;
|
|
|
5820f5 |
-
|
|
|
5820f5 |
- return s->init_num;
|
|
|
5820f5 |
+ /* Note that s->init_num is *not* used as current offset in
|
|
|
5820f5 |
+ * s->init_buf->data, but as a counter summing up fragments'
|
|
|
5820f5 |
+ * lengths: as soon as they sum up to handshake packet
|
|
|
5820f5 |
+ * length, we assume we have got all the fragments. */
|
|
|
5820f5 |
+ s->init_num += frag_len;
|
|
|
5820f5 |
+ return frag_len;
|
|
|
5820f5 |
|
|
|
5820f5 |
f_err:
|
|
|
5820f5 |
ssl3_send_alert(s,SSL3_AL_FATAL,al);
|
|
|
5820f5 |
- s->init_num = 0;
|
|
|
5820f5 |
-err:
|
|
|
5820f5 |
+ s->init_num = 0;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
*ok=0;
|
|
|
5820f5 |
return(-1);
|
|
|
5820f5 |
}
|
|
|
5820f5 |
@@ -790,7 +752,7 @@ int dtls1_send_finished(SSL *s, int a, i
|
|
|
5820f5 |
|
|
|
5820f5 |
/* buffer the message to handle re-xmits */
|
|
|
5820f5 |
dtls1_buffer_message(s, 0);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
+
|
|
|
5820f5 |
s->state=b;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
|
|
|
5820f5 |
@@ -815,10 +777,15 @@ int dtls1_send_change_cipher_spec(SSL *s
|
|
|
5820f5 |
p=(unsigned char *)s->init_buf->data;
|
|
|
5820f5 |
*p++=SSL3_MT_CCS;
|
|
|
5820f5 |
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
|
|
|
5820f5 |
- s->d1->next_handshake_write_seq++;
|
|
|
5820f5 |
- s2n(s->d1->handshake_write_seq,p);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
s->init_num=DTLS1_CCS_HEADER_LENGTH;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ if (s->client_version == DTLS1_BAD_VER)
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ s->d1->next_handshake_write_seq++;
|
|
|
5820f5 |
+ s2n(s->d1->handshake_write_seq,p);
|
|
|
5820f5 |
+ s->init_num+=2;
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
+
|
|
|
5820f5 |
s->init_off=0;
|
|
|
5820f5 |
|
|
|
5820f5 |
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
|
|
|
5820f5 |
@@ -1044,6 +1011,7 @@ dtls1_buffer_message(SSL *s, int is_ccs)
|
|
|
5820f5 |
pitem *item;
|
|
|
5820f5 |
hm_fragment *frag;
|
|
|
5820f5 |
PQ_64BIT seq64;
|
|
|
5820f5 |
+ unsigned int epoch = s->d1->w_epoch;
|
|
|
5820f5 |
|
|
|
5820f5 |
/* this function is called immediately after a message has
|
|
|
5820f5 |
* been serialized */
|
|
|
5820f5 |
@@ -1056,7 +1024,8 @@ dtls1_buffer_message(SSL *s, int is_ccs)
|
|
|
5820f5 |
if ( is_ccs)
|
|
|
5820f5 |
{
|
|
|
5820f5 |
OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
|
|
|
5820f5 |
- DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num);
|
|
|
5820f5 |
+ DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
|
|
|
5820f5 |
+ epoch++;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
else
|
|
|
5820f5 |
{
|
|
|
5820f5 |
@@ -1072,7 +1041,7 @@ dtls1_buffer_message(SSL *s, int is_ccs)
|
|
|
5820f5 |
frag->msg_header.is_ccs = is_ccs;
|
|
|
5820f5 |
|
|
|
5820f5 |
pq_64bit_init(&seq64);
|
|
|
5820f5 |
- pq_64bit_assign_word(&seq64, frag->msg_header.seq);
|
|
|
5820f5 |
+ pq_64bit_assign_word(&seq64, epoch<<16 | frag->msg_header.seq);
|
|
|
5820f5 |
|
|
|
5820f5 |
item = pitem_new(seq64, frag);
|
|
|
5820f5 |
pq_64bit_free(&seq64);
|
|
|
5820f5 |
@@ -1259,5 +1228,4 @@ dtls1_get_ccs_header(unsigned char *data
|
|
|
5820f5 |
memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
|
|
|
5820f5 |
|
|
|
5820f5 |
ccs_hdr->type = *(data++);
|
|
|
5820f5 |
- n2s(data, ccs_hdr->seq);
|
|
|
5820f5 |
}
|
|
|
5820f5 |
diff -up openssl-fips-0.9.8f-dev/ssl/d1_clnt.c.dtls-fixes openssl-fips-0.9.8f-dev/ssl/d1_clnt.c
|
|
|
5820f5 |
--- openssl-fips-0.9.8f-dev/ssl/d1_clnt.c.dtls-fixes 2005-12-05 18:32:19.000000000 +0100
|
|
|
5820f5 |
+++ openssl-fips-0.9.8f-dev/ssl/d1_clnt.c 2008-07-15 21:01:29.000000000 +0200
|
|
|
5820f5 |
@@ -214,17 +214,21 @@ int dtls1_connect(SSL *s)
|
|
|
5820f5 |
|
|
|
5820f5 |
/* don't push the buffering BIO quite yet */
|
|
|
5820f5 |
|
|
|
5820f5 |
- ssl3_init_finished_mac(s);
|
|
|
5820f5 |
-
|
|
|
5820f5 |
s->state=SSL3_ST_CW_CLNT_HELLO_A;
|
|
|
5820f5 |
s->ctx->stats.sess_connect++;
|
|
|
5820f5 |
s->init_num=0;
|
|
|
5820f5 |
+ /* mark client_random uninitialized */
|
|
|
5820f5 |
+ memset(s->s3->client_random,0,sizeof(s->s3->client_random));
|
|
|
5820f5 |
break;
|
|
|
5820f5 |
|
|
|
5820f5 |
case SSL3_ST_CW_CLNT_HELLO_A:
|
|
|
5820f5 |
case SSL3_ST_CW_CLNT_HELLO_B:
|
|
|
5820f5 |
|
|
|
5820f5 |
s->shutdown=0;
|
|
|
5820f5 |
+
|
|
|
5820f5 |
+ /* every DTLS ClientHello resets Finished MAC */
|
|
|
5820f5 |
+ ssl3_init_finished_mac(s);
|
|
|
5820f5 |
+
|
|
|
5820f5 |
ret=dtls1_client_hello(s);
|
|
|
5820f5 |
if (ret <= 0) goto end;
|
|
|
5820f5 |
|
|
|
5820f5 |
@@ -422,6 +426,9 @@ int dtls1_connect(SSL *s)
|
|
|
5820f5 |
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
|
|
|
5820f5 |
}
|
|
|
5820f5 |
s->init_num=0;
|
|
|
5820f5 |
+ /* mark client_random uninitialized */
|
|
|
5820f5 |
+ memset (s->s3->client_random,0,sizeof(s->s3->client_random));
|
|
|
5820f5 |
+
|
|
|
5820f5 |
break;
|
|
|
5820f5 |
|
|
|
5820f5 |
case SSL3_ST_CR_FINISHED_A:
|
|
|
5820f5 |
@@ -544,9 +551,15 @@ int dtls1_client_hello(SSL *s)
|
|
|
5820f5 |
/* else use the pre-loaded session */
|
|
|
5820f5 |
|
|
|
5820f5 |
p=s->s3->client_random;
|
|
|
5820f5 |
- Time=(unsigned long)time(NULL); /* Time */
|
|
|
5820f5 |
- l2n(Time,p);
|
|
|
5820f5 |
- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
|
|
|
5820f5 |
+ /* if client_random is initialized, reuse it, we are
|
|
|
5820f5 |
+ * required to use same upon reply to HelloVerify */
|
|
|
5820f5 |
+ for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ;
|
|
|
5820f5 |
+ if (i==sizeof(s->s3->client_random))
|
|
|
5820f5 |
+ {
|
|
|
5820f5 |
+ Time=(unsigned long)time(NULL); /* Time */
|
|
|
5820f5 |
+ l2n(Time,p);
|
|
|
5820f5 |
+ RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4);
|
|
|
5820f5 |
+ }
|
|
|
5820f5 |
|
|
|
5820f5 |
/* Do the message type and length last */
|
|
|
5820f5 |
d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
|