const EVP_CIPHER *ciph, size_t taglen,
/* TODO(RECLAYER): This probably should not be an int */
int mactype,
- const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
- BIO_ADDR *local, BIO_ADDR *peer,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
+ BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
const OSSL_PARAM *settings, const OSSL_PARAM *options,
OSSL_RECORD_LAYER **retrl,
/* TODO(RECLAYER): Remove me */
ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
key, keylen, iv, ivlen, mackey, mackeylen,
- ciph, taglen, mactype, md, comp, transport,
- local, peer, settings, options, retrl, s);
+ ciph, taglen, mactype, md, comp, prev,
+ transport, next, local, peer, settings,
+ options, retrl, s);
if (ret != OSSL_RECORD_RETURN_SUCCESS)
return ret;
# define SSL_AD_NO_ALERT -1
+static void tls_int_free(OSSL_RECORD_LAYER *rl);
+
void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
const char *fmt, ...)
{
while (left < n) {
size_t bioread = 0;
int ret;
+ BIO *bio = rl->prev != NULL ? rl->prev : rl->bio;
/*
* Now we have len+left bytes at the front of s->s3.rbuf.buf and
*/
clear_sys_error();
- if (rl->bio != NULL) {
- ret = BIO_read(rl->bio, pkt + len + left, max - left);
+ if (bio != NULL) {
+ ret = BIO_read(bio, pkt + len + left, max - left);
if (ret > 0) {
bioread = ret;
ret = OSSL_RECORD_RETURN_SUCCESS;
- } else if (BIO_should_retry(rl->bio)) {
+ } else if (BIO_should_retry(bio)) {
+ if (rl->prev != NULL) {
+ /*
+ * We were reading from the previous epoch. Now there is no
+ * more data, so swap to the actual transport BIO
+ */
+ BIO_free(rl->prev);
+ rl->prev = NULL;
+ continue;
+ }
ret = OSSL_RECORD_RETURN_RETRY;
- } else if (BIO_eof(rl->bio)) {
+ } else if (BIO_eof(bio)) {
ret = OSSL_RECORD_RETURN_EOF;
} else {
ret = OSSL_RECORD_RETURN_FATAL;
const EVP_CIPHER *ciph, size_t taglen,
/* TODO(RECLAYER): This probably should not be an int */
int mactype,
- const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
- BIO_ADDR *local, BIO_ADDR *peer,
- const OSSL_PARAM *settings, const OSSL_PARAM *options,
- OSSL_RECORD_LAYER **retrl,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
+ BIO *transport, BIO *next, BIO_ADDR *local,
+ BIO_ADDR *peer, const OSSL_PARAM *settings,
+ const OSSL_PARAM *options, OSSL_RECORD_LAYER **retrl,
/* TODO(RECLAYER): Remove me */
SSL_CONNECTION *s)
{
return OSSL_RECORD_RETURN_FATAL;
}
- if (transport != NULL && !BIO_up_ref(transport)) {
- RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
/*
* TODO(RECLAYER): Need to handle the case where the params are updated
* after the record layer has been created.
if (!tls_set1_bio(rl, transport))
goto err;
+ if (prev != NULL && !BIO_up_ref(prev))
+ goto err;
+ rl->prev = prev;
+
+ if (next != NULL && !BIO_up_ref(next))
+ goto err;
+ rl->next = next;
+
*retrl = rl;
return OSSL_RECORD_RETURN_SUCCESS;
err:
- OPENSSL_free(rl);
+ tls_int_free(rl);
return OSSL_RECORD_RETURN_FATAL;
}
const EVP_CIPHER *ciph, size_t taglen,
/* TODO(RECLAYER): This probably should not be an int */
int mactype,
- const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
- BIO_ADDR *local, BIO_ADDR *peer,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
+ BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
const OSSL_PARAM *settings, const OSSL_PARAM *options,
OSSL_RECORD_LAYER **retrl,
/* TODO(RECLAYER): Remove me */
ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
key, keylen, iv, ivlen, mackey, mackeylen,
- ciph, taglen, mactype, md, comp, transport,
- local, peer, settings, options, retrl, s);
+ ciph, taglen, mactype, md, comp, prev,
+ transport, next, local, peer, settings,
+ options, retrl, s);
if (ret != OSSL_RECORD_RETURN_SUCCESS)
return ret;
const EVP_CIPHER *ciph, size_t taglen,
/* TODO(RECLAYER): This probably should not be an int */
int mactype,
- const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
- BIO_ADDR *local, BIO_ADDR *peer,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *prev,
+ BIO *transport, BIO *next, BIO_ADDR *local, BIO_ADDR *peer,
const OSSL_PARAM *settings, const OSSL_PARAM *options,
OSSL_RECORD_LAYER **retrl,
/* TODO(RECLAYER): Remove me */
ret = tls_int_new_record_layer(libctx, propq, vers, role, direction, level,
key, keylen, iv, ivlen, mackey, mackeylen,
- ciph, taglen, mactype, md, comp, transport,
- local, peer, settings, options, retrl, s);
+ ciph, taglen, mactype, md, comp, prev,
+ transport, next, local, peer, settings,
+ options, retrl, s);
if (ret != OSSL_RECORD_RETURN_SUCCESS)
return ret;
return OSSL_RECORD_RETURN_SUCCESS;
}
-void tls_free(OSSL_RECORD_LAYER *rl)
+static void tls_int_free(OSSL_RECORD_LAYER *rl)
{
/* TODO(RECLAYER): Cleanse sensitive fields */
+ BIO_free(rl->prev);
BIO_free(rl->bio);
+ BIO_free(rl->next);
+ SSL3_BUFFER_release(&rl->rbuf);
+
+ EVP_CIPHER_CTX_free(rl->enc_read_ctx);
+ EVP_MD_CTX_free(rl->read_hash);
+ COMP_CTX_free(rl->expand);
+
OPENSSL_free(rl);
}
+int tls_free(OSSL_RECORD_LAYER *rl)
+{
+ SSL3_BUFFER *rbuf;
+ size_t left, written;
+ int ret = 1;
+
+ rbuf = &rl->rbuf;
+
+ left = SSL3_BUFFER_get_left(rbuf);
+ if (left > 0) {
+ /*
+ * This record layer is closing but we still have data left in our
+ * buffer. It must be destined for the next epoch - so push it there.
+ */
+ ret = BIO_write_ex(rl->next, rbuf->buf + rbuf->offset, left, &written);
+ }
+ tls_int_free(rl);
+
+ return ret;
+}
+
+
int tls_reset(OSSL_RECORD_LAYER *rl)
{
memset(rl, 0, sizeof(*rl));
meth = ssl_select_next_record_layer(s, level);
- if (s->rrlmethod != NULL)
- s->rrlmethod->free(s->rrl);
+ if (s->rrlmethod != NULL && !s->rrlmethod->free(s->rrl)) {
+ ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
if (meth != NULL)
s->rrlmethod = meth;
for (;;) {
int rlret;
+ BIO *prev = s->rrlnext;
+
+ s->rrlnext = BIO_new(BIO_s_mem());
+
+ if (s->rrlnext == NULL) {
+ BIO_free(prev);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
rlret = s->rrlmethod->new_record_layer(sctx->libctx, sctx->propq,
version, s->server, direction,
level, key, keylen, iv, ivlen,
mackey, mackeylen, ciph, taglen,
- mactype, md, comp, s->rbio,
- NULL, NULL, NULL, options,
- &s->rrl, s);
+ mactype, md, comp, prev, s->rbio,
+ s->rrlnext, NULL, NULL, NULL,
+ options, &s->rrl, s);
+ BIO_free(prev);
switch (rlret) {
case OSSL_RECORD_RETURN_FATAL:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_RECORD_LAYER_FAILURE);