#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/pqueue.h>
+#include <openssl/rand.h>
/* mod 128 saturating subtract of two 64-bit values in big-endian order */
static int satsub64be(const unsigned char *v1,const unsigned char *v2)
* always aligned, but I take no chances... */
if (((size_t)v1|(size_t)v2)&0x7) break;
- l = *((long *)v1);
- l =- *((long *)v2);
+ l = *((long *)v1);
+ l -= *((long *)v2);
if (l>128) return 128;
else if (l<-128) return -128;
else return (int)l;
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
unsigned char *priority);
static int dtls1_process_record(SSL *s);
-#if PQ_64BIT_IS_INTEGER
-static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT *num);
-#endif
static void dtls1_clear_timeouts(SSL *s);
/* copy buffered record into SSL structure */
memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
- ssl3_setup_buffers(s);
+ if (!ssl3_setup_buffers(s))
+ {
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ return(0);
+ }
return(1);
}
if (!clear)
{
- mac_size=EVP_MD_size(s->read_hash);
+ mac_size=EVP_MD_CTX_size(s->read_hash);
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
{
SSL3_RECORD *rr;
SSL_SESSION *sess;
unsigned char *p;
- short version;
+ unsigned short version;
DTLS1_BITMAP *bitmap;
unsigned int is_next_epoch;
n2s(p,rr->length);
/* Lets check version */
- if (s->first_packet)
- {
- s->first_packet=0;
- }
- else
+ if (!s->first_packet)
{
if (version != s->version)
{
dest = s->d1->alert_fragment;
dest_len = &s->d1->alert_fragment_len;
}
- else /* else it's a CCS message */
- OPENSSL_assert(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC);
+ /* else it's a CCS message, or it's wrong */
+ else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
+ {
+ /* Not certain if this is the right error handling */
+ al=SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
if (dest_maxlen > 0)
}
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 ( (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);
+
+ goto start;
}
/* Unexpected handshake message (Client Hello, or protocol violation) */
if ( (sess == NULL) ||
(s->enc_write_ctx == NULL) ||
- (s->write_hash == NULL))
+ (EVP_MD_CTX_md(s->write_hash) == NULL))
clear=1;
if (clear)
mac_size=0;
else
- mac_size=EVP_MD_size(s->write_hash);
+ mac_size=EVP_MD_CTX_size(s->write_hash);
/* DTLS implements explicit IV, so no need for empty fragments */
#if 0
/* 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 */
*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);
#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)
}
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)
memset(seq, 0x00, seq_bytes);
}
-#if PQ_64BIT_IS_INTEGER
-static PQ_64BIT
-bytes_to_long_long(unsigned char *bytes, PQ_64BIT *num)
- {
- PQ_64BIT _num;
-
- _num = (((PQ_64BIT)bytes[0]) << 56) |
- (((PQ_64BIT)bytes[1]) << 48) |
- (((PQ_64BIT)bytes[2]) << 40) |
- (((PQ_64BIT)bytes[3]) << 32) |
- (((PQ_64BIT)bytes[4]) << 24) |
- (((PQ_64BIT)bytes[5]) << 16) |
- (((PQ_64BIT)bytes[6]) << 8) |
- (((PQ_64BIT)bytes[7]) );
-
- *num = _num ;
- return _num;
- }
-#endif
-
static void
dtls1_clear_timeouts(SSL *s)