Commit d102d9df authored by Matt Caswell's avatar Matt Caswell
Browse files

Implement write pipeline support in libssl



Use the new pipeline cipher capability to encrypt multiple records being
written out all in one go. Two new SSL/SSL_CTX parameters can be used to
control how this works: max_pipelines and split_send_fragment.

max_pipelines defines the maximum number of pipelines that can ever be used
in one go for a single connection. It must always be less than or equal to
SSL_MAX_PIPELINES (currently defined to be 32). By default only one
pipeline will be used (i.e. normal non-parallel operation).

split_send_fragment defines how data is split up into pipelines. The number
of pipelines used will be determined by the amount of data provided to the
SSL_write call divided by split_send_fragment. For example if
split_send_fragment is set to 2000 and max_pipelines is 4 then:
SSL_write called with 0-2000 bytes == 1 pipeline used
SSL_write called with 2001-4000 bytes == 2 pipelines used
SSL_write called with 4001-6000 bytes == 3 pipelines used
SSL_write_called with 6001+ bytes == 4 pipelines used

split_send_fragment must always be less than or equal to max_send_fragment.
By default it is set to be equal to max_send_fragment. This will mean that
the same number of records will always be created as would have been
created in the non-parallel case, although the data will be apportioned
differently. In the parallel case data will be spread equally between the
pipelines.

Reviewed-by: default avatarTim Hudson <tjh@openssl.org>
parent 98ee7543
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -181,6 +181,9 @@ extern "C" {
# define SSL_MAX_KEY_ARG_LENGTH                  8
# define SSL_MAX_MASTER_KEY_LENGTH               48

/* The maximum number of encrypt/decrypt pipelines we can support */
# define SSL_MAX_PIPELINES  32

/* text strings for the ciphers */

/* These are used to specify which ciphers to use and not to use */
@@ -1233,6 +1236,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_CTRL_GET_EXTMS_SUPPORT              122
# define SSL_CTRL_SET_MIN_PROTO_VERSION          123
# define SSL_CTRL_SET_MAX_PROTO_VERSION          124
# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT        125
# define SSL_CTRL_SET_MAX_PIPELINES              126
# define SSL_CERT_SET_FIRST                      1
# define SSL_CERT_SET_NEXT                       2
# define SSL_CERT_SET_SERVER                     3
@@ -1794,6 +1799,14 @@ __owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_set_max_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_split_send_fragment(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_set_split_send_fragment(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_max_pipelines(ctx,m) \
        SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_max_pipelines(ssl,m) \
        SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)

     /* NB: the keylength is only applicable when is_export is true */
# ifndef OPENSSL_NO_DH
@@ -2193,6 +2206,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_TLS1_CHANGE_CIPHER_STATE                   209
# define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS            341
# define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT              274
# define SSL_F_TLS1_ENC                                   401
# define SSL_F_TLS1_EXPORT_KEYING_MATERIAL                314
# define SSL_F_TLS1_GET_CURVELIST                         338
# define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT            275
@@ -2412,6 +2426,7 @@ void ERR_load_SSL_strings(void);
# define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE          199
# define SSL_R_PEM_NAME_BAD_PREFIX                        391
# define SSL_R_PEM_NAME_TOO_SHORT                         392
# define SSL_R_PIPELINE_FAILURE                           406
# define SSL_R_PRE_MAC_LENGTH_TOO_LONG                    205
# define SSL_R_PROTOCOL_IS_SHUTDOWN                       207
# define SSL_R_PSK_IDENTITY_NOT_FOUND                     223
+4 −4
Original line number Diff line number Diff line
@@ -1039,7 +1039,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
    SSL3_BUFFER *wb;
    SSL_SESSION *sess;

    wb = &s->rlayer.wbuf;
    wb = &s->rlayer.wbuf[0];

    /*
     * first check if there is a SSL3_BUFFER still being written out.  This
@@ -1128,7 +1128,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,

    /* first we compress */
    if (s->compress != NULL) {
        if (!ssl3_do_compress(s)) {
        if (!ssl3_do_compress(s, wr)) {
            SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_COMPRESSION_FAILURE);
            goto err;
        }
@@ -1145,7 +1145,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     */

    if (mac_size != 0) {
        if (s->method->ssl3_enc->mac(s,
        if (s->method->ssl3_enc->mac(s, wr,
                &(p[SSL3_RECORD_get_length(wr) + eivlen]), 1) < 0)
            goto err;
        SSL3_RECORD_add_length(wr, mac_size);
@@ -1158,7 +1158,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
    if (eivlen)
        SSL3_RECORD_add_length(wr, eivlen);

    if (s->method->ssl3_enc->enc(s, 1) < 1)
    if (s->method->ssl3_enc->enc(s, wr, 1, 1) < 1)
        goto err;

    /* record length after mac and block padding */
+216 −113
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ void RECORD_LAYER_init(RECORD_LAYER *rl, SSL *s)

void RECORD_LAYER_clear(RECORD_LAYER *rl)
{
    unsigned int pipes;

    rl->rstate = SSL_ST_READ_HEADER;

    /* Do I need to clear read_ahead? As far as I can tell read_ahead did not
@@ -161,7 +163,9 @@ void RECORD_LAYER_clear(RECORD_LAYER *rl)
    rl->wpend_buf = NULL;

    SSL3_BUFFER_clear(&rl->rbuf);
    SSL3_BUFFER_clear(&rl->wbuf);
    for(pipes = 0; pipes < rl->numwpipes; pipes++)
        SSL3_BUFFER_clear(&rl->wbuf[pipes]);
    rl->numwpipes = 0;
    SSL3_RECORD_clear(&rl->rrec);
    SSL3_RECORD_clear(&rl->wrec);

@@ -176,7 +180,7 @@ void RECORD_LAYER_release(RECORD_LAYER *rl)
{
    if (SSL3_BUFFER_is_initialised(&rl->rbuf))
        ssl3_release_read_buffer(rl->s);
    if (SSL3_BUFFER_is_initialised(&rl->wbuf))
    if (rl->numwpipes > 0)
        ssl3_release_write_buffer(rl->s);
    SSL3_RECORD_release(&rl->rrec);
}
@@ -188,7 +192,8 @@ int RECORD_LAYER_read_pending(RECORD_LAYER *rl)

int RECORD_LAYER_write_pending(RECORD_LAYER *rl)
{
    return SSL3_BUFFER_get_left(&rl->wbuf) != 0;
    return (rl->numwpipes > 0)
            && SSL3_BUFFER_get_left(&rl->wbuf[rl->numwpipes-1]) != 0;
}

int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len)
@@ -433,10 +438,10 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
    int tot;
    unsigned int n, nw;
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
    unsigned int max_send_fragment;
    unsigned int max_send_fragment, split_send_fragment, maxpipes;
    unsigned int u_len = (unsigned int)len;
#endif
    SSL3_BUFFER *wb = &s->rlayer.wbuf;
    SSL3_BUFFER *wb = &s->rlayer.wbuf[0];
    int i;

    if (len < 0) {
@@ -622,13 +627,70 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
    }

    n = (len - tot);

    split_send_fragment = s->split_send_fragment;
    /*
     * If max_pipelines is 0 then this means "undefined" and we default to
     * 1 pipeline. Similaraly if the cipher does not support pipelined
     * processing then we also only use 1 pipeline, or if we're not using
     * explicit IVs
     */
    maxpipes = s->max_pipelines;
    if (maxpipes > SSL_MAX_PIPELINES) {
        /*
         * We should have prevented this when we set max_pipelines so we
         * shouldn't get here
        */
        SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
        return -1;
    }
    if (maxpipes == 0
            || s->enc_write_ctx == NULL
            || !(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx))
                 & EVP_CIPH_FLAG_PIPELINE)
            || !SSL_USE_EXPLICIT_IV(s))
        maxpipes = 1;
    if (s->max_send_fragment == 0 || split_send_fragment > s->max_send_fragment
            || split_send_fragment == 0) {
        /*
         * We should have prevented this when we set the split and max send
         * fragments so we shouldn't get here
        */
        SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
        return -1;
    }

    for (;;) {
        if (n > s->max_send_fragment)
            nw = s->max_send_fragment;
        unsigned int pipelens[SSL_MAX_PIPELINES], tmppipelen, remain;
        unsigned int numpipes, j;

        if (n == 0)
            numpipes = 1;
        else
            nw = n;
            numpipes = ((n - 1) / split_send_fragment) + 1;
        if (numpipes > maxpipes)
            numpipes = maxpipes;

        if (n / numpipes >= s->max_send_fragment) {
            /*
             * We have enough data to completely fill all available
             * pipelines
             */
            for (j = 0; j < numpipes; j++) {
                pipelens[j] = s->max_send_fragment;
            }
        } else {
            /* We can partially fill all available pipelines */
            tmppipelen = n / numpipes;
            remain = n % numpipes;
            for (j = 0; j < numpipes; j++) {
                pipelens[j] = tmppipelen;
                if (j < remain)
                    pipelens[j]++;
            }
        }

        i = do_ssl3_write(s, type, &(buf[tot]), nw, 0);
        i = do_ssl3_write(s, type, &(buf[tot]), pipelens, numpipes, 0);
        if (i <= 0) {
            /* XXX should we ssl3_release_write_buffer if i<0? */
            s->rlayer.wnum = tot;
@@ -657,23 +719,28 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
}

int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
                  unsigned int len, int create_empty_fragment)
                  unsigned int *pipelens, unsigned int numpipes,
                  int create_empty_fragment)
{
    unsigned char *p, *plen;
    unsigned char *outbuf[SSL_MAX_PIPELINES], *plen[SSL_MAX_PIPELINES];
    SSL3_RECORD wr[SSL_MAX_PIPELINES];
    int i, mac_size, clear = 0;
    int prefix_len = 0;
    int eivlen;
    size_t align = 0;
    SSL3_RECORD *wr;
    SSL3_BUFFER *wb = &s->rlayer.wbuf;
    SSL3_BUFFER *wb;
    SSL_SESSION *sess;
    unsigned int totlen = 0;
    unsigned int j;

    for (j = 0; j < numpipes; j++)
        totlen += pipelens[j];
    /*
     * first check if there is a SSL3_BUFFER still being written out.  This
     * will happen with non blocking IO
     */
    if (SSL3_BUFFER_get_left(wb) != 0)
        return (ssl3_write_pending(s, type, buf, len));
    if (RECORD_LAYER_write_pending(&s->rlayer))
        return (ssl3_write_pending(s, type, buf, totlen));

    /* If we have an alert to send, lets send it */
    if (s->s3->alert_dispatch) {
@@ -683,14 +750,13 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        /* if it went, fall through and send more stuff */
    }

    if (!SSL3_BUFFER_is_initialised(wb))
        if (!ssl3_setup_write_buffer(s))
    if (s->rlayer.numwpipes < numpipes)
        if (!ssl3_setup_write_buffer(s, numpipes))
            return -1;

    if (len == 0 && !create_empty_fragment)
    if (totlen == 0 && !create_empty_fragment)
        return 0;

    wr = &s->rlayer.wrec;
    sess = s->session;

    if ((sess == NULL) ||
@@ -720,7 +786,9 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
             * 'prefix_len' bytes are sent out later together with the actual
             * payload)
             */
            prefix_len = do_ssl3_write(s, type, buf, 0, 1);
            unsigned int tmppipelen = 0;

            prefix_len = do_ssl3_write(s, type, buf, &tmppipelen, 1, 1);
            if (prefix_len <= 0)
                goto err;

@@ -737,6 +805,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
    }

    if (create_empty_fragment) {
        wb = &s->rlayer.wbuf[0];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
        /*
         * extra fragment would be couple of cipher blocks, which would be
@@ -746,38 +815,24 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        align = (size_t)SSL3_BUFFER_get_buf(wb) + 2 * SSL3_RT_HEADER_LENGTH;
        align = (0-align) & (SSL3_ALIGN_PAYLOAD - 1);
#endif
        p = SSL3_BUFFER_get_buf(wb) + align;
        outbuf[0] = SSL3_BUFFER_get_buf(wb) + align;
        SSL3_BUFFER_set_offset(wb, align);
    } else if (prefix_len) {
        p = SSL3_BUFFER_get_buf(wb) + SSL3_BUFFER_get_offset(wb) + prefix_len;
        wb = &s->rlayer.wbuf[0];
        outbuf[0] = SSL3_BUFFER_get_buf(wb) + SSL3_BUFFER_get_offset(wb)
                    + prefix_len;
    } else {
        for (j=0; j < numpipes; j++) {
            wb = &s->rlayer.wbuf[j];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
            align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
        align = (0-align) & (SSL3_ALIGN_PAYLOAD - 1);
            align = (-align) & (SSL3_ALIGN_PAYLOAD - 1);
#endif
        p = SSL3_BUFFER_get_buf(wb) + align;
            outbuf[j] = SSL3_BUFFER_get_buf(wb) + align;
            SSL3_BUFFER_set_offset(wb, align);
        }
    }

    /* write the header */

    *(p++) = type & 0xff;
    SSL3_RECORD_set_type(wr, type);

    *(p++) = (s->version >> 8);
    /*
     * Some servers hang if iniatial client hello is larger than 256 bytes
     * and record version number > TLS 1.0
     */
    if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO
        && !s->renegotiate && TLS1_get_version(s) > TLS1_VERSION)
        *(p++) = 0x1;
    else
        *(p++) = s->version & 0xff;

    /* field where we are to write out packet length */
    plen = p;
    p += 2;
    /* Explicit IV length, block ciphers appropriate version flag */
    if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) {
        int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
@@ -796,11 +851,35 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
    } else
        eivlen = 0;

    /* lets setup the record stuff. */
    SSL3_RECORD_set_data(wr, p + eivlen);
    SSL3_RECORD_set_length(wr, (int)len);
    SSL3_RECORD_set_input(wr, (unsigned char *)buf);

    totlen = 0;
    /* Clear our SSL3_RECORD structures */
    memset(wr, 0, sizeof wr);
    for (j=0; j < numpipes; j++) {
        /* write the header */
        *(outbuf[j]++) = type & 0xff;
        SSL3_RECORD_set_type(&wr[j], type);

        *(outbuf[j]++) = (s->version >> 8);
        /*
         * Some servers hang if iniatial client hello is larger than 256 bytes
         * and record version number > TLS 1.0
         */
        if (SSL_get_state(s) == TLS_ST_CW_CLNT_HELLO
            && !s->renegotiate && TLS1_get_version(s) > TLS1_VERSION)
            *(outbuf[j]++) = 0x1;
        else
            *(outbuf[j]++) = s->version & 0xff;

        /* field where we are to write out packet length */
        plen[j] = outbuf[j];
        outbuf[j] += 2;

        /* lets setup the record stuff. */
        SSL3_RECORD_set_data(&wr[j], outbuf[j] + eivlen);
        SSL3_RECORD_set_length(&wr[j], (int)pipelens[j]);
        SSL3_RECORD_set_input(&wr[j], (unsigned char *)&buf[totlen]);
        totlen += pipelens[j];

        /*
         * we now 'read' from wr->input, wr->length bytes into wr->data
@@ -808,13 +887,13 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,

        /* first we compress */
        if (s->compress != NULL) {
        if (!ssl3_do_compress(s)) {
            if (!ssl3_do_compress(s, &wr[j])) {
                SSLerr(SSL_F_DO_SSL3_WRITE, SSL_R_COMPRESSION_FAILURE);
                goto err;
            }
        } else {
        memcpy(wr->data, wr->input, wr->length);
        SSL3_RECORD_reset_input(wr);
            memcpy(wr[j].data, wr[j].input, wr[j].length);
            SSL3_RECORD_reset_input(&wr[j]);
        }

        /*
@@ -824,66 +903,80 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
         */

        if (!SSL_USE_ETM(s) && mac_size != 0) {
        if (s->method->ssl3_enc->mac(s, &(p[wr->length + eivlen]), 1) < 0)
            if (s->method->ssl3_enc->mac(s, &wr[j],
                    &(outbuf[j][wr[j].length + eivlen]), 1) < 0)
                goto err;
        SSL3_RECORD_add_length(wr, mac_size);
            SSL3_RECORD_add_length(&wr[j], mac_size);
        }

    SSL3_RECORD_set_data(wr, p);
    SSL3_RECORD_reset_input(wr);

        SSL3_RECORD_set_data(&wr[j], outbuf[j]);
        SSL3_RECORD_reset_input(&wr[j]);

        if (eivlen) {
            /*
             * if (RAND_pseudo_bytes(p, eivlen) <= 0) goto err;
             */
        SSL3_RECORD_add_length(wr, eivlen);
            SSL3_RECORD_add_length(&wr[j], eivlen);
        }
    }

    if (s->method->ssl3_enc->enc(s, 1) < 1)
    if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1)
        goto err;

    for (j=0; j < numpipes; j++) {
        if (SSL_USE_ETM(s) && mac_size != 0) {
        if (s->method->ssl3_enc->mac(s, p + wr->length, 1) < 0)
            if (s->method->ssl3_enc->mac(s, &wr[j],
                                         outbuf[j] + wr[j].length, 1) < 0)
                goto err;
        SSL3_RECORD_add_length(wr, mac_size);
            SSL3_RECORD_add_length(&wr[j], mac_size);
        }

        /* record length after mac and block padding */
    s2n(SSL3_RECORD_get_length(wr), plen);
        s2n(SSL3_RECORD_get_length(&wr[j]), plen[j]);

        if (s->msg_callback)
        s->msg_callback(1, 0, SSL3_RT_HEADER, plen - 5, 5, s,
            s->msg_callback(1, 0, SSL3_RT_HEADER, plen[j] - 5, 5, s,
                            s->msg_callback_arg);

        /*
         * we should now have wr->data pointing to the encrypted data, which is
         * wr->length long
         */
    SSL3_RECORD_set_type(wr, type);  /* not needed but helps for debugging */
    SSL3_RECORD_add_length(wr, SSL3_RT_HEADER_LENGTH);
        SSL3_RECORD_set_type(&wr[j], type);  /* not needed but helps for debugging */
        SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);

        if (create_empty_fragment) {
            /*
             * we are in a recursive call; just return the length, don't write
             * out anything here
             */
            if (j > 0) {
                /* We should never be pipelining an empty fragment!! */
                SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
                goto err;
            }
            return SSL3_RECORD_get_length(wr);
        }

        /* now let's set up wb */
    SSL3_BUFFER_set_left(wb, prefix_len + SSL3_RECORD_get_length(wr));
        SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
            prefix_len + SSL3_RECORD_get_length(&wr[j]));
    }



    /*
     * memorize arguments so that ssl3_write_pending can detect bad write
     * retries later
     */
    s->rlayer.wpend_tot = len;
    s->rlayer.wpend_tot = totlen;
    s->rlayer.wpend_buf = buf;
    s->rlayer.wpend_type = type;
    s->rlayer.wpend_ret = len;
    s->rlayer.wpend_ret = totlen;

    /* we now just need to write the buffer */
    return ssl3_write_pending(s, type, buf, len);
    return ssl3_write_pending(s, type, buf, totlen);
 err:
    return -1;
}
@@ -893,7 +986,8 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                       unsigned int len)
{
    int i;
    SSL3_BUFFER *wb = &s->rlayer.wbuf;
    SSL3_BUFFER *wb = s->rlayer.wbuf;
    unsigned int currbuf = 0;

/* XXXX */
    if ((s->rlayer.wpend_tot > (int)len)
@@ -905,19 +999,28 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
    }

    for (;;) {
        /* Loop until we find a buffer we haven't written out yet */
        if (SSL3_BUFFER_get_left(&wb[currbuf]) == 0
                && currbuf < s->rlayer.numwpipes - 1) {
            currbuf++;
            continue;
        }
        clear_sys_error();
        if (s->wbio != NULL) {
            s->rwstate = SSL_WRITING;
            i = BIO_write(s->wbio,
                (char *)&(SSL3_BUFFER_get_buf(wb)[SSL3_BUFFER_get_offset(wb)]),
                (unsigned int)SSL3_BUFFER_get_left(wb));
                (char *)&(SSL3_BUFFER_get_buf(&wb[currbuf])[
                                SSL3_BUFFER_get_offset(&wb[currbuf])]),
                (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf]));
        } else {
            SSLerr(SSL_F_SSL3_WRITE_PENDING, SSL_R_BIO_NOT_SET);
            i = -1;
        }
        if (i == SSL3_BUFFER_get_left(wb)) {
            SSL3_BUFFER_set_left(wb, 0);
            SSL3_BUFFER_add_offset(wb, i);
        if (i == SSL3_BUFFER_get_left(&wb[currbuf])) {
            SSL3_BUFFER_set_left(&wb[currbuf], 0);
            SSL3_BUFFER_add_offset(&wb[currbuf], i);
            if (currbuf + 1 < s->rlayer.numwpipes)
                continue;
            s->rwstate = SSL_NOTHING;
            return (s->rlayer.wpend_ret);
        } else if (i <= 0) {
@@ -926,12 +1029,12 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                 * For DTLS, just drop it. That's kind of the whole point in
                 * using a datagram service
                 */
                SSL3_BUFFER_set_left(wb, 0);
                SSL3_BUFFER_set_left(&wb[currbuf], 0);
            }
            return (i);
        }
        SSL3_BUFFER_add_offset(wb, i);
        SSL3_BUFFER_add_left(wb, -i);
        SSL3_BUFFER_add_offset(&wb[currbuf], i);
        SSL3_BUFFER_add_left(&wb[currbuf], -i);
    }
}

+11 −6
Original line number Diff line number Diff line
@@ -252,10 +252,12 @@ typedef struct record_layer_st {
    int read_ahead;
    /* where we are when reading */
    int rstate;

    unsigned int numwpipes;
    /* read IO goes into here */
    SSL3_BUFFER rbuf;
    /* write IO goes into here */
    SSL3_BUFFER wbuf;
    SSL3_BUFFER wbuf[SSL_MAX_PIPELINES];
    /* each decoded record goes in here */
    SSL3_RECORD rrec;
    /* goes out from here */
@@ -326,16 +328,19 @@ unsigned int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl);
__owur int ssl3_pending(const SSL *s);
__owur int ssl3_write_bytes(SSL *s, int type, const void *buf, int len);
__owur int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
                         unsigned int len, int create_empty_fragment);
                         unsigned int *pipelens, unsigned int numpipes,
                         int create_empty_fragment);
__owur int ssl3_read_bytes(SSL *s, int type, int *recvd_type,
                           unsigned char *buf, int len, int peek);
__owur int ssl3_setup_buffers(SSL *s);
__owur int ssl3_enc(SSL *s, int send_data);
__owur int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data);
__owur int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, unsigned int numpipes,
                    int send);
__owur int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
__owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                       unsigned int len);
__owur int tls1_enc(SSL *s, int snd);
__owur int tls1_mac(SSL *ssl, unsigned char *md, int snd);
__owur int tls1_enc(SSL *s, SSL3_RECORD *recs, unsigned int numpipes,
                    int send);
__owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send);
int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl);
void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl);
+3 −3
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@
/* Functions/macros provided by the RECORD_LAYER component */

#define RECORD_LAYER_get_rbuf(rl)               (&(rl)->rbuf)
#define RECORD_LAYER_get_wbuf(rl)               (&(rl)->wbuf)
#define RECORD_LAYER_get_wbuf(rl)               ((rl)->wbuf)
#define RECORD_LAYER_get_rrec(rl)               (&(rl)->rrec)
#define RECORD_LAYER_get_wrec(rl)               (&(rl)->wrec)
#define RECORD_LAYER_set_packet(rl, p)          ((rl)->packet = (p))
@@ -165,7 +165,7 @@ void SSL3_BUFFER_clear(SSL3_BUFFER *b);
void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n);
void SSL3_BUFFER_release(SSL3_BUFFER *b);
__owur int ssl3_setup_read_buffer(SSL *s);
__owur int ssl3_setup_write_buffer(SSL *s);
__owur int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes);
int ssl3_release_read_buffer(SSL *s);
int ssl3_release_write_buffer(SSL *s);

@@ -194,7 +194,7 @@ void SSL3_RECORD_release(SSL3_RECORD *r);
int SSL3_RECORD_setup(SSL3_RECORD *r);
void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
int ssl3_get_record(SSL *s);
__owur int ssl3_do_compress(SSL *ssl);
__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
__owur int ssl3_do_uncompress(SSL *ssl);
void ssl3_cbc_copy_mac(unsigned char *out,
                       const SSL3_RECORD *rec, unsigned md_size);
Loading