-/* ssl/record/ssl3_record.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
};
+/*
+ * Clear the contents of an SSL3_RECORD but retain any memory allocated
+ */
void SSL3_RECORD_clear(SSL3_RECORD *r)
{
- memset(r->seq_num, 0, sizeof(r->seq_num));
+ unsigned char *comp = r->comp;
+
+ memset(r, 0, sizeof(*r));
+ r->comp = comp;
}
void SSL3_RECORD_release(SSL3_RECORD *r)
unsigned char md[EVP_MAX_MD_SIZE];
short version;
unsigned mac_size;
- size_t extra;
unsigned empty_record_count = 0;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
sess = s->session;
- if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
- extra = SSL3_RT_MAX_EXTRA;
- else
- extra = 0;
- if (extra && !s->s3->init_extra) {
- /*
- * An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER set after
- * ssl3_setup_buffers() was done
- */
- SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR);
- return -1;
- }
-
again:
/* check if we have the header */
if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
/*
* Check whether this is a regular record or an SSLv2 style record. The
- * latter is only used in an initial ClientHello for old clients.
+ * latter is only used in an initial ClientHello for old clients. We
+ * check s->read_hash and s->enc_read_ctx to ensure this does not apply
+ * during renegotiation
*/
if (s->first_packet && s->server && !s->read_hash && !s->enc_read_ctx
&& (p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) {
/* SSLv2 style record */
- if (s->msg_callback)
- s->msg_callback(0, SSL2_VERSION, 0, p + 2,
- RECORD_LAYER_get_packet_length(&s->rlayer) - 2,
- s, s->msg_callback_arg);
-
rr->type = SSL3_RT_HANDSHAKE;
rr->rec_version = SSL2_VERSION;
n2s(p, rr->length);
/* Lets check version */
- if (!s->first_packet) {
- if (version != s->version) {
- SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
- if ((s->version & 0xFF00) == (version & 0xFF00)
- && !s->enc_write_ctx && !s->write_hash)
+ if (!s->first_packet && version != s->version) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
+ if ((s->version & 0xFF00) == (version & 0xFF00)
+ && !s->enc_write_ctx && !s->write_hash) {
+ if (rr->type == SSL3_RT_ALERT) {
/*
- * Send back error using their minor version number :-)
+ * The record is using an incorrect version number, but
+ * what we've got appears to be an alert. We haven't
+ * read the body yet to check whether its a fatal or
+ * not - but chances are it is. We probably shouldn't
+ * send a fatal alert back. We'll just end.
*/
- s->version = (unsigned short)version;
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
+ goto err;
+ }
+ /*
+ * Send back error using their minor version number :-)
+ */
+ s->version = (unsigned short)version;
}
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
}
if ((version >> 8) != SSL3_VERSION_MAJOR) {
+ if (s->first_packet) {
+ /* Go back to start of packet, look at the five bytes
+ * that we have. */
+ p = RECORD_LAYER_get_packet(&s->rlayer);
+ if (strncmp((char *)p, "GET ", 4) == 0 ||
+ strncmp((char *)p, "POST ", 5) == 0 ||
+ strncmp((char *)p, "HEAD ", 5) == 0 ||
+ strncmp((char *)p, "PUT ", 4) == 0) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST);
+ goto err;
+ } else if (strncmp((char *)p, "CONNE", 5) == 0) {
+ SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_HTTPS_PROXY_REQUEST);
+ goto err;
+ }
+ }
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
goto err;
}
n = ssl3_read_n(s, i, i, 1);
if (n <= 0)
return (n); /* error or non-blocking io */
- /*
- * now n == rr->length, and
- * s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length
- * or
- * s->packet_length == SSL2_RT_HEADER_LENGTH + rr->length
- * (if SSLv2 packet)
- */
- } else {
- n = 0;
}
/* set state for later operations */
*/
/* check is not needed I believe */
- if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) {
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
goto f_err;
if (i < 0 || mac == NULL
|| CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
enc_err = -1;
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra + mac_size)
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
enc_err = -1;
}
/* r->length is now just compressed */
if (s->expand != NULL) {
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra) {
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_COMPRESSED_LENGTH_TOO_LONG);
goto f_err;
}
}
- if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) {
+ if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
goto f_err;
rec->input = rec->data;
} else {
l = rec->length;
- bs = EVP_CIPHER_block_size(ds->cipher);
+ bs = EVP_CIPHER_CTX_block_size(ds);
/* COMPRESS */
ret = 1;
} else {
l = rec->length;
- bs = EVP_CIPHER_block_size(ds->cipher);
+ bs = EVP_CIPHER_CTX_block_size(ds);
- if (EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) & EVP_CIPH_FLAG_AEAD_CIPHER) {
unsigned char buf[EVP_AEAD_TLS1_AAD_LEN], *seq;
seq = send ? RECORD_LAYER_get_write_sequence(&s->rlayer)
/* we need to add 'i' padding bytes of value j */
j = i - 1;
- if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) {
- if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
- j++;
- }
for (k = (int)l; k < (int)(l + i); k++)
rec->input[k] = j;
l += i;
}
i = EVP_Cipher(ds, rec->data, rec->input, l);
- if ((EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER)
+ if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds)) & EVP_CIPH_FLAG_CUSTOM_CIPHER)
? (i < 0)
: (i == 0))
return -1; /* AEAD can fail to verify MAC */
- if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send) {
- rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ if (send == 0) {
+ if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) {
+ rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) {
+ rec->data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ rec->input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ rec->length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ }
}
ret = 1;
{
SSL3_RECORD *rec;
unsigned char *mac_sec, *seq;
- EVP_MD_CTX md_ctx;
const EVP_MD_CTX *hash;
unsigned char *p, rec_char;
size_t md_size;
header[j++] = rec->length & 0xff;
/* Final param == is SSLv3 */
- ssl3_cbc_digest_record(hash,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, rec->orig_len,
- mac_sec, md_size, 1);
+ if (ssl3_cbc_digest_record(hash,
+ md, &md_size,
+ header, rec->input,
+ rec->length + md_size, rec->orig_len,
+ mac_sec, md_size, 1) <= 0)
+ return -1;
} else {
unsigned int md_size_u;
/* Chop the digest off the end :-) */
- EVP_MD_CTX_init(&md_ctx);
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+
+ if (md_ctx == NULL)
+ return -1;
- EVP_MD_CTX_copy_ex(&md_ctx, hash);
- EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
- EVP_DigestUpdate(&md_ctx, ssl3_pad_1, npad);
- EVP_DigestUpdate(&md_ctx, seq, 8);
rec_char = rec->type;
- EVP_DigestUpdate(&md_ctx, &rec_char, 1);
p = md;
s2n(rec->length, p);
- EVP_DigestUpdate(&md_ctx, md, 2);
- EVP_DigestUpdate(&md_ctx, rec->input, rec->length);
- EVP_DigestFinal_ex(&md_ctx, md, NULL);
-
- EVP_MD_CTX_copy_ex(&md_ctx, hash);
- EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
- EVP_DigestUpdate(&md_ctx, ssl3_pad_2, npad);
- EVP_DigestUpdate(&md_ctx, md, md_size);
- EVP_DigestFinal_ex(&md_ctx, md, &md_size_u);
+ if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
+ || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
+ || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0
+ || EVP_DigestUpdate(md_ctx, seq, 8) <= 0
+ || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0
+ || EVP_DigestUpdate(md_ctx, md, 2) <= 0
+ || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0
+ || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
+ || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
+ || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0
+ || EVP_DigestUpdate(md_ctx, md, md_size) <= 0
+ || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) {
+ EVP_MD_CTX_reset(md_ctx);
+ return -1;
+ }
md_size = md_size_u;
- EVP_MD_CTX_cleanup(&md_ctx);
+ EVP_MD_CTX_free(md_ctx);
}
ssl3_record_sequence_update(seq);
EVP_MD_CTX *hash;
size_t md_size;
int i;
- EVP_MD_CTX hmac, *mac_ctx;
+ EVP_MD_CTX *hmac = NULL, *mac_ctx;
unsigned char header[13];
int stream_mac = (send ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
if (stream_mac) {
mac_ctx = hash;
} else {
- if (!EVP_MD_CTX_copy(&hmac, hash))
+ hmac = EVP_MD_CTX_new();
+ if (hmac == NULL
+ || !EVP_MD_CTX_copy(hmac, hash))
return -1;
- mac_ctx = &hmac;
+ mac_ctx = hmac;
}
if (SSL_IS_DTLS(ssl)) {
* are hashing because that gives an attacker a timing-oracle.
*/
/* Final param == not SSLv3 */
- ssl3_cbc_digest_record(mac_ctx,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, rec->orig_len,
- ssl->s3->read_mac_secret,
- ssl->s3->read_mac_secret_size, 0);
+ if (ssl3_cbc_digest_record(mac_ctx,
+ md, &md_size,
+ header, rec->input,
+ rec->length + md_size, rec->orig_len,
+ ssl->s3->read_mac_secret,
+ ssl->s3->read_mac_secret_size, 0) <= 0) {
+ EVP_MD_CTX_free(hmac);
+ return -1;
+ }
} else {
- EVP_DigestSignUpdate(mac_ctx, header, sizeof(header));
- EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length);
- t = EVP_DigestSignFinal(mac_ctx, md, &md_size);
- OPENSSL_assert(t > 0);
+ if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
+ || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
+ EVP_MD_CTX_free(hmac);
+ return -1;
+ }
if (!send && !SSL_USE_ETM(ssl) && FIPS_mode())
tls_fips_digest_extra(ssl->enc_read_ctx,
mac_ctx, rec->input,
rec->length, rec->orig_len);
}
- if (!stream_mac)
- EVP_MD_CTX_cleanup(&hmac);
+ EVP_MD_CTX_free(hmac);
+
#ifdef TLS_DEBUG
fprintf(stderr, "seq=");
{
padding_length = rec->data[rec->length - 1];
- /*
- * NB: if compression is in operation the first packet may not be of even
- * length so the padding bug check cannot be performed. This bug
- * workaround has been around since SSLeay so hopefully it is either
- * fixed now or no buggy implementation supports compression [steve]
- */
- if ((s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) {
- /* First packet is even in size, so check */
- if ((memcmp(RECORD_LAYER_get_read_sequence(&s->rlayer),
- "\0\0\0\0\0\0\0\0", 8) == 0) &&
- !(padding_length & 1)) {
- s->s3->flags |= TLS1_FLAGS_TLS_PADDING_BUG;
- }
- if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) && padding_length > 0) {
- padding_length--;
- }
- }
-
- if (EVP_CIPHER_flags(s->enc_read_ctx->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) {
/* padding is already verified */
rec->length -= padding_length + 1;
return 1;
/* Only do replay check if no SCTP bio */
if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
#endif
- /*
- * Check whether this is a repeat, or aged record. Don't check if
- * we're listening and this message is a ClientHello. They can look
- * as if they're replayed, since they arrive from different
- * connections and would be dropped unnecessarily.
- */
- if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
- RECORD_LAYER_get_packet_length(&s->rlayer)
- > DTLS1_RT_HEADER_LENGTH &&
- RECORD_LAYER_get_packet(&s->rlayer)[DTLS1_RT_HEADER_LENGTH]
- == SSL3_MT_CLIENT_HELLO) &&
- !dtls1_record_replay_check(s, bitmap)) {
+ /* Check whether this is a repeat, or aged record. */
+ if (!dtls1_record_replay_check(s, bitmap)) {
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer); /* dump this record */
goto again; /* get another record */
/*
* If this record is from the next epoch (either HM or ALERT), and a
* handshake is currently in progress, buffer it since it cannot be
- * processed at this time. However, do not buffer anything while
- * listening.
+ * processed at this time.
*/
if (is_next_epoch) {
- if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) {
+ if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) {
if (dtls1_buffer_record
(s, &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)),
rr->seq_num) < 0)
return (1);
}
-