diff options
Diffstat (limited to 'ssl/d1_pkt.c')
-rw-r--r-- | ssl/d1_pkt.c | 117 |
1 files changed, 68 insertions, 49 deletions
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index 8270419a8dcea..b2765ba8019ff 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -120,6 +120,7 @@ #include <openssl/evp.h> #include <openssl/buffer.h> #include <openssl/pqueue.h> +#include <openssl/rand.h> static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, int len, int peek); @@ -486,9 +487,9 @@ int dtls1_get_record(SSL *s) SSL3_RECORD *rr; SSL_SESSION *sess; unsigned char *p; - short version; + unsigned short version; DTLS1_BITMAP *bitmap; - unsigned int is_next_epoch; + unsigned int is_next_epoch; rr= &(s->s3->rrec); sess=s->session; @@ -524,7 +525,7 @@ again: ssl_minor= *(p++); version=(ssl_major<<8)|ssl_minor; - /* sequence number is 64 bits, with top 2 bytes = epoch */ + /* sequence number is 64 bits, with top 2 bytes = epoch */ n2s(p,rr->epoch); memcpy(&(s->s3->read_sequence[2]), p, 6); @@ -535,7 +536,7 @@ again: /* Lets check version */ if (!s->first_packet) { - if (version != s->version) + if (version != s->version && version != DTLS1_BAD_VER) { SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); /* Send back error using their @@ -546,7 +547,8 @@ again: } } - if ((version & 0xff00) != (DTLS1_VERSION & 0xff00)) + if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) && + (version & 0xff00) != (DTLS1_BAD_VER & 0xff00)) { SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); goto err; @@ -559,6 +561,7 @@ again: goto f_err; } + s->client_version = version; /* now s->rstate == SSL_ST_READ_BODY */ } @@ -808,6 +811,14 @@ start: * may be fragmented--don't always expect dest_maxlen bytes */ if ( rr->length < dest_maxlen) { +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE + /* + * for normal alerts rr->length is 2, while + * dest_maxlen is 7 if we were to handle this + * non-existing alert... + */ + FIX ME +#endif s->rstate=SSL_ST_READ_HEADER; rr->length = 0; goto start; @@ -973,47 +984,40 @@ start: } if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) - { - struct ccs_header_st ccs_hdr; + { + struct ccs_header_st ccs_hdr; dtls1_get_ccs_header(rr->data, &ccs_hdr); - if ( ccs_hdr.seq == s->d1->handshake_read_seq) - { - /* 'Change Cipher Spec' is just a single byte, so we know - * exactly what the record payload has to look like */ - /* XDTLS: check that epoch is consistent */ - if ( (rr->length != DTLS1_CCS_HEADER_LENGTH) || - (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) - { - i=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto err; - } - - rr->length=0; - - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, - rr->data, 1, s, s->msg_callback_arg); - - s->s3->change_cipher_spec=1; - if (!ssl3_do_change_cipher_spec(s)) - goto err; - - /* do this whenever CCS is processed */ - dtls1_reset_seq_numbers(s, SSL3_CC_READ); - - /* handshake read seq is reset upon handshake completion */ - s->d1->handshake_read_seq++; - - goto start; - } - else + /* 'Change Cipher Spec' is just a single byte, so we know + * exactly what the record payload has to look like */ + /* XDTLS: check that epoch is consistent */ + if ( (s->client_version == DTLS1_BAD_VER && rr->length != 3) || + (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) || + (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) { - rr->length = 0; - goto start; + i=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); + goto err; } + + rr->length=0; + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, + rr->data, 1, s, s->msg_callback_arg); + + s->s3->change_cipher_spec=1; + if (!ssl3_do_change_cipher_spec(s)) + goto err; + + /* do this whenever CCS is processed */ + dtls1_reset_seq_numbers(s, SSL3_CC_READ); + + if (s->client_version == DTLS1_BAD_VER) + s->d1->handshake_read_seq++; + + goto start; } /* Unexpected handshake message (Client Hello, or protocol violation) */ @@ -1255,7 +1259,7 @@ int dtls1_write_bytes(SSL *s, int type, const void *buf_, int len) else s->s3->wnum += i; - return tot + i; + return i; } int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment) @@ -1341,8 +1345,12 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, *(p++)=type&0xff; wr->type=type; - *(p++)=(s->version>>8); - *(p++)=s->version&0xff; + if (s->client_version == DTLS1_BAD_VER) + *(p++) = DTLS1_BAD_VER>>8, + *(p++) = DTLS1_BAD_VER&0xff; + else + *(p++)=(s->version>>8), + *(p++)=s->version&0xff; /* field where we are to write out packet epoch, seq num and len */ pseq=p; @@ -1397,8 +1405,14 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, /* ssl3_enc can only have an error on read */ - wr->length += bs; /* bs != 0 in case of CBC. The enc fn provides - * the randomness */ + if (bs) /* bs != 0 in case of CBC */ + { + RAND_pseudo_bytes(p,bs); + /* master IV and last CBC residue stand for + * the rest of randomness */ + wr->length += bs; + } + s->method->ssl3_enc->enc(s,1); /* record length after mac and block padding */ @@ -1570,7 +1584,7 @@ int dtls1_dispatch_alert(SSL *s) { int i,j; void (*cb)(const SSL *ssl,int type,int val)=NULL; - unsigned char buf[2 + 2 + 3]; /* alert level + alert desc + message seq +frag_off */ + unsigned char buf[DTLS1_AL_HEADER_LENGTH]; unsigned char *ptr = &buf[0]; s->s3->alert_dispatch=0; @@ -1579,6 +1593,7 @@ int dtls1_dispatch_alert(SSL *s) *ptr++ = s->s3->send_alert[0]; *ptr++ = s->s3->send_alert[1]; +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) { s2n(s->d1->handshake_read_seq, ptr); @@ -1594,6 +1609,7 @@ int dtls1_dispatch_alert(SSL *s) #endif l2n3(s->d1->r_msg_hdr.frag_off, ptr); } +#endif i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0); if (i <= 0) @@ -1603,8 +1619,11 @@ int dtls1_dispatch_alert(SSL *s) } else { - if ( s->s3->send_alert[0] == SSL3_AL_FATAL || - s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) + if (s->s3->send_alert[0] == SSL3_AL_FATAL +#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE + || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +#endif + ) (void)BIO_flush(s->wbio); if (s->msg_callback) |