155714Skris/* crypto/bio/bss_bio.c  -*- Mode: C; c-file-style: "eay" -*- */
2120631Snectar/* ====================================================================
3120631Snectar * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
4120631Snectar *
5120631Snectar * Redistribution and use in source and binary forms, with or without
6120631Snectar * modification, are permitted provided that the following conditions
7120631Snectar * are met:
8120631Snectar *
9120631Snectar * 1. Redistributions of source code must retain the above copyright
10296465Sdelphij *    notice, this list of conditions and the following disclaimer.
11120631Snectar *
12120631Snectar * 2. Redistributions in binary form must reproduce the above copyright
13120631Snectar *    notice, this list of conditions and the following disclaimer in
14120631Snectar *    the documentation and/or other materials provided with the
15120631Snectar *    distribution.
16120631Snectar *
17120631Snectar * 3. All advertising materials mentioning features or use of this
18120631Snectar *    software must display the following acknowledgment:
19120631Snectar *    "This product includes software developed by the OpenSSL Project
20120631Snectar *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21120631Snectar *
22120631Snectar * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23120631Snectar *    endorse or promote products derived from this software without
24120631Snectar *    prior written permission. For written permission, please contact
25120631Snectar *    openssl-core@openssl.org.
26120631Snectar *
27120631Snectar * 5. Products derived from this software may not be called "OpenSSL"
28120631Snectar *    nor may "OpenSSL" appear in their names without prior written
29120631Snectar *    permission of the OpenSSL Project.
30120631Snectar *
31120631Snectar * 6. Redistributions of any form whatsoever must retain the following
32120631Snectar *    acknowledgment:
33120631Snectar *    "This product includes software developed by the OpenSSL Project
34120631Snectar *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35120631Snectar *
36120631Snectar * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37120631Snectar * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38120631Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39120631Snectar * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40120631Snectar * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41120631Snectar * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42120631Snectar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43120631Snectar * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44120631Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45120631Snectar * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46120631Snectar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47120631Snectar * OF THE POSSIBILITY OF SUCH DAMAGE.
48120631Snectar * ====================================================================
49120631Snectar *
50120631Snectar * This product includes cryptographic software written by Eric Young
51120631Snectar * (eay@cryptsoft.com).  This product includes software written by Tim
52120631Snectar * Hudson (tjh@cryptsoft.com).
53120631Snectar *
54120631Snectar */
5555714Skris
56296465Sdelphij/*
57296465Sdelphij * Special method for a BIO where the other endpoint is also a BIO of this
58296465Sdelphij * kind, handled by the same thread (i.e. the "peer" is actually ourselves,
59296465Sdelphij * wearing a different hat). Such "BIO pairs" are mainly for using the SSL
60296465Sdelphij * library with I/O interfaces for which no specific BIO method is available.
61296465Sdelphij * See ssl/ssltest.c for some hints on how this can be used.
62296465Sdelphij */
6355714Skris
64100936Snectar/* BIO_DEBUG implies BIO_PAIR_DEBUG */
65100936Snectar#ifdef BIO_DEBUG
66100936Snectar# ifndef BIO_PAIR_DEBUG
67100936Snectar#  define BIO_PAIR_DEBUG
68100936Snectar# endif
69100936Snectar#endif
70100936Snectar
71100936Snectar/* disable assert() unless BIO_PAIR_DEBUG has been defined */
7255714Skris#ifndef BIO_PAIR_DEBUG
73100936Snectar# ifndef NDEBUG
74100936Snectar#  define NDEBUG
75100936Snectar# endif
7655714Skris#endif
7755714Skris
7855714Skris#include <assert.h>
7959191Skris#include <limits.h>
8055714Skris#include <stdlib.h>
8155714Skris#include <string.h>
8255714Skris
8355714Skris#include <openssl/bio.h>
8455714Skris#include <openssl/err.h>
8555714Skris#include <openssl/crypto.h>
8655714Skris
87109998Smarkm#include "e_os.h"
88100928Snectar
89109998Smarkm/* VxWorks defines SSIZE_MAX with an empty value causing compile errors */
90109998Smarkm#if defined(OPENSSL_SYS_VXWORKS)
91100928Snectar# undef SSIZE_MAX
92109998Smarkm#endif
93109998Smarkm#ifndef SSIZE_MAX
9459191Skris# define SSIZE_MAX INT_MAX
9559191Skris#endif
9659191Skris
9755714Skrisstatic int bio_new(BIO *bio);
9855714Skrisstatic int bio_free(BIO *bio);
9955714Skrisstatic int bio_read(BIO *bio, char *buf, int size);
10068651Skrisstatic int bio_write(BIO *bio, const char *buf, int num);
10155714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr);
10268651Skrisstatic int bio_puts(BIO *bio, const char *str);
10355714Skris
10455714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2);
10555714Skrisstatic void bio_destroy_pair(BIO *bio);
10655714Skris
107296465Sdelphijstatic BIO_METHOD methods_biop = {
108296465Sdelphij    BIO_TYPE_BIO,
109296465Sdelphij    "BIO pair",
110296465Sdelphij    bio_write,
111296465Sdelphij    bio_read,
112296465Sdelphij    bio_puts,
113296465Sdelphij    NULL /* no bio_gets */ ,
114296465Sdelphij    bio_ctrl,
115296465Sdelphij    bio_new,
116296465Sdelphij    bio_free,
117296465Sdelphij    NULL                        /* no bio_callback_ctrl */
11855714Skris};
11955714Skris
12055714SkrisBIO_METHOD *BIO_s_bio(void)
12155714Skris{
122296465Sdelphij    return &methods_biop;
123296465Sdelphij}
12455714Skris
125296465Sdelphijstruct bio_bio_st {
126296465Sdelphij    BIO *peer;                  /* NULL if buf == NULL. If peer != NULL, then
127296465Sdelphij                                 * peer->ptr is also a bio_bio_st, and its
128296465Sdelphij                                 * "peer" member points back to us. peer !=
129296465Sdelphij                                 * NULL iff init != 0 in the BIO. */
130296465Sdelphij    /* This is for what we write (i.e. reading uses peer's struct): */
131296465Sdelphij    int closed;                 /* valid iff peer != NULL */
132296465Sdelphij    size_t len;                 /* valid iff buf != NULL; 0 if peer == NULL */
133296465Sdelphij    size_t offset;              /* valid iff buf != NULL; 0 if len == 0 */
134296465Sdelphij    size_t size;
135296465Sdelphij    char *buf;                  /* "size" elements (if != NULL) */
136296465Sdelphij    size_t request;             /* valid iff peer != NULL; 0 if len != 0,
137296465Sdelphij                                 * otherwise set by peer to number of bytes
138296465Sdelphij                                 * it (unsuccessfully) tried to read, never
139296465Sdelphij                                 * more than buffer space (size-len)
140296465Sdelphij                                 * warrants. */
14155714Skris};
14255714Skris
14355714Skrisstatic int bio_new(BIO *bio)
144296465Sdelphij{
145296465Sdelphij    struct bio_bio_st *b;
14655714Skris
147296465Sdelphij    b = OPENSSL_malloc(sizeof *b);
148296465Sdelphij    if (b == NULL)
149296465Sdelphij        return 0;
15055714Skris
151296465Sdelphij    b->peer = NULL;
152296465Sdelphij    /* enough for one TLS record (just a default) */
153296465Sdelphij    b->size = 17 * 1024;
154296465Sdelphij    b->buf = NULL;
15555714Skris
156296465Sdelphij    bio->ptr = b;
157296465Sdelphij    return 1;
158296465Sdelphij}
15955714Skris
16055714Skrisstatic int bio_free(BIO *bio)
161296465Sdelphij{
162296465Sdelphij    struct bio_bio_st *b;
16355714Skris
164296465Sdelphij    if (bio == NULL)
165296465Sdelphij        return 0;
166296465Sdelphij    b = bio->ptr;
16755714Skris
168296465Sdelphij    assert(b != NULL);
16955714Skris
170296465Sdelphij    if (b->peer)
171296465Sdelphij        bio_destroy_pair(bio);
17255714Skris
173296465Sdelphij    if (b->buf != NULL) {
174296465Sdelphij        OPENSSL_free(b->buf);
175296465Sdelphij    }
17655714Skris
177296465Sdelphij    OPENSSL_free(b);
17855714Skris
179296465Sdelphij    return 1;
180296465Sdelphij}
18155714Skris
18255714Skrisstatic int bio_read(BIO *bio, char *buf, int size_)
183296465Sdelphij{
184296465Sdelphij    size_t size = size_;
185296465Sdelphij    size_t rest;
186296465Sdelphij    struct bio_bio_st *b, *peer_b;
18755714Skris
188296465Sdelphij    BIO_clear_retry_flags(bio);
18955714Skris
190296465Sdelphij    if (!bio->init)
191296465Sdelphij        return 0;
19255714Skris
193296465Sdelphij    b = bio->ptr;
194296465Sdelphij    assert(b != NULL);
195296465Sdelphij    assert(b->peer != NULL);
196296465Sdelphij    peer_b = b->peer->ptr;
197296465Sdelphij    assert(peer_b != NULL);
198296465Sdelphij    assert(peer_b->buf != NULL);
19955714Skris
200296465Sdelphij    peer_b->request = 0;        /* will be set in "retry_read" situation */
20155714Skris
202296465Sdelphij    if (buf == NULL || size == 0)
203296465Sdelphij        return 0;
20455714Skris
205296465Sdelphij    if (peer_b->len == 0) {
206296465Sdelphij        if (peer_b->closed)
207296465Sdelphij            return 0;           /* writer has closed, and no data is left */
208296465Sdelphij        else {
209296465Sdelphij            BIO_set_retry_read(bio); /* buffer is empty */
210296465Sdelphij            if (size <= peer_b->size)
211296465Sdelphij                peer_b->request = size;
212296465Sdelphij            else
213296465Sdelphij                /*
214296465Sdelphij                 * don't ask for more than the peer can deliver in one write
215296465Sdelphij                 */
216296465Sdelphij                peer_b->request = peer_b->size;
217296465Sdelphij            return -1;
218296465Sdelphij        }
219296465Sdelphij    }
22055714Skris
221296465Sdelphij    /* we can read */
222296465Sdelphij    if (peer_b->len < size)
223296465Sdelphij        size = peer_b->len;
22455714Skris
225296465Sdelphij    /* now read "size" bytes */
22655714Skris
227296465Sdelphij    rest = size;
228296465Sdelphij
229296465Sdelphij    assert(rest > 0);
230296465Sdelphij    do {                        /* one or two iterations */
231296465Sdelphij        size_t chunk;
232296465Sdelphij
233296465Sdelphij        assert(rest <= peer_b->len);
234296465Sdelphij        if (peer_b->offset + rest <= peer_b->size)
235296465Sdelphij            chunk = rest;
236296465Sdelphij        else
237296465Sdelphij            /* wrap around ring buffer */
238296465Sdelphij            chunk = peer_b->size - peer_b->offset;
239296465Sdelphij        assert(peer_b->offset + chunk <= peer_b->size);
240296465Sdelphij
241296465Sdelphij        memcpy(buf, peer_b->buf + peer_b->offset, chunk);
242296465Sdelphij
243296465Sdelphij        peer_b->len -= chunk;
244296465Sdelphij        if (peer_b->len) {
245296465Sdelphij            peer_b->offset += chunk;
246296465Sdelphij            assert(peer_b->offset <= peer_b->size);
247296465Sdelphij            if (peer_b->offset == peer_b->size)
248296465Sdelphij                peer_b->offset = 0;
249296465Sdelphij            buf += chunk;
250296465Sdelphij        } else {
251296465Sdelphij            /* buffer now empty, no need to advance "buf" */
252296465Sdelphij            assert(chunk == rest);
253296465Sdelphij            peer_b->offset = 0;
254296465Sdelphij        }
255296465Sdelphij        rest -= chunk;
256296465Sdelphij    }
257296465Sdelphij    while (rest);
258296465Sdelphij
259296465Sdelphij    return size;
260296465Sdelphij}
261296465Sdelphij
262296465Sdelphij/*-
263296465Sdelphij * non-copying interface: provide pointer to available data in buffer
26459191Skris *    bio_nread0:  return number of available bytes
26559191Skris *    bio_nread:   also advance index
26659191Skris * (example usage:  bio_nread0(), read from buffer, bio_nread()
26759191Skris *  or just         bio_nread(), read from buffer)
26859191Skris */
269296465Sdelphij/*
270296465Sdelphij * WARNING: The non-copying interface is largely untested as of yet and may
271296465Sdelphij * contain bugs.
272296465Sdelphij */
27359191Skrisstatic ssize_t bio_nread0(BIO *bio, char **buf)
274296465Sdelphij{
275296465Sdelphij    struct bio_bio_st *b, *peer_b;
276296465Sdelphij    ssize_t num;
27759191Skris
278296465Sdelphij    BIO_clear_retry_flags(bio);
27959191Skris
280296465Sdelphij    if (!bio->init)
281296465Sdelphij        return 0;
28259191Skris
283296465Sdelphij    b = bio->ptr;
284296465Sdelphij    assert(b != NULL);
285296465Sdelphij    assert(b->peer != NULL);
286296465Sdelphij    peer_b = b->peer->ptr;
287296465Sdelphij    assert(peer_b != NULL);
288296465Sdelphij    assert(peer_b->buf != NULL);
28959191Skris
290296465Sdelphij    peer_b->request = 0;
291296465Sdelphij
292296465Sdelphij    if (peer_b->len == 0) {
293296465Sdelphij        char dummy;
294296465Sdelphij
295296465Sdelphij        /* avoid code duplication -- nothing available for reading */
296296465Sdelphij        return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
297296465Sdelphij    }
298296465Sdelphij
299296465Sdelphij    num = peer_b->len;
300296465Sdelphij    if (peer_b->size < peer_b->offset + num)
301296465Sdelphij        /* no ring buffer wrap-around for non-copying interface */
302296465Sdelphij        num = peer_b->size - peer_b->offset;
303296465Sdelphij    assert(num > 0);
304296465Sdelphij
305296465Sdelphij    if (buf != NULL)
306296465Sdelphij        *buf = peer_b->buf + peer_b->offset;
307296465Sdelphij    return num;
308296465Sdelphij}
309296465Sdelphij
31059191Skrisstatic ssize_t bio_nread(BIO *bio, char **buf, size_t num_)
311296465Sdelphij{
312296465Sdelphij    struct bio_bio_st *b, *peer_b;
313296465Sdelphij    ssize_t num, available;
31459191Skris
315296465Sdelphij    if (num_ > SSIZE_MAX)
316296465Sdelphij        num = SSIZE_MAX;
317296465Sdelphij    else
318296465Sdelphij        num = (ssize_t) num_;
31959191Skris
320296465Sdelphij    available = bio_nread0(bio, buf);
321296465Sdelphij    if (num > available)
322296465Sdelphij        num = available;
323296465Sdelphij    if (num <= 0)
324296465Sdelphij        return num;
32559191Skris
326296465Sdelphij    b = bio->ptr;
327296465Sdelphij    peer_b = b->peer->ptr;
32859191Skris
329296465Sdelphij    peer_b->len -= num;
330296465Sdelphij    if (peer_b->len) {
331296465Sdelphij        peer_b->offset += num;
332296465Sdelphij        assert(peer_b->offset <= peer_b->size);
333296465Sdelphij        if (peer_b->offset == peer_b->size)
334296465Sdelphij            peer_b->offset = 0;
335296465Sdelphij    } else
336296465Sdelphij        peer_b->offset = 0;
33759191Skris
338296465Sdelphij    return num;
339296465Sdelphij}
34059191Skris
34168651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_)
342296465Sdelphij{
343296465Sdelphij    size_t num = num_;
344296465Sdelphij    size_t rest;
345296465Sdelphij    struct bio_bio_st *b;
34655714Skris
347296465Sdelphij    BIO_clear_retry_flags(bio);
34855714Skris
349296465Sdelphij    if (!bio->init || buf == NULL || num == 0)
350296465Sdelphij        return 0;
35155714Skris
352296465Sdelphij    b = bio->ptr;
353296465Sdelphij    assert(b != NULL);
354296465Sdelphij    assert(b->peer != NULL);
355296465Sdelphij    assert(b->buf != NULL);
35655714Skris
357296465Sdelphij    b->request = 0;
358296465Sdelphij    if (b->closed) {
359296465Sdelphij        /* we already closed */
360296465Sdelphij        BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);
361296465Sdelphij        return -1;
362296465Sdelphij    }
36355714Skris
364296465Sdelphij    assert(b->len <= b->size);
36555714Skris
366296465Sdelphij    if (b->len == b->size) {
367296465Sdelphij        BIO_set_retry_write(bio); /* buffer is full */
368296465Sdelphij        return -1;
369296465Sdelphij    }
37055714Skris
371296465Sdelphij    /* we can write */
372296465Sdelphij    if (num > b->size - b->len)
373296465Sdelphij        num = b->size - b->len;
37455714Skris
375296465Sdelphij    /* now write "num" bytes */
37655714Skris
377296465Sdelphij    rest = num;
37855714Skris
379296465Sdelphij    assert(rest > 0);
380296465Sdelphij    do {                        /* one or two iterations */
381296465Sdelphij        size_t write_offset;
382296465Sdelphij        size_t chunk;
38355714Skris
384296465Sdelphij        assert(b->len + rest <= b->size);
38555714Skris
386296465Sdelphij        write_offset = b->offset + b->len;
387296465Sdelphij        if (write_offset >= b->size)
388296465Sdelphij            write_offset -= b->size;
389296465Sdelphij        /* b->buf[write_offset] is the first byte we can write to. */
39055714Skris
391296465Sdelphij        if (write_offset + rest <= b->size)
392296465Sdelphij            chunk = rest;
393296465Sdelphij        else
394296465Sdelphij            /* wrap around ring buffer */
395296465Sdelphij            chunk = b->size - write_offset;
39655714Skris
397296465Sdelphij        memcpy(b->buf + write_offset, buf, chunk);
398296465Sdelphij
399296465Sdelphij        b->len += chunk;
400296465Sdelphij
401296465Sdelphij        assert(b->len <= b->size);
402296465Sdelphij
403296465Sdelphij        rest -= chunk;
404296465Sdelphij        buf += chunk;
405296465Sdelphij    }
406296465Sdelphij    while (rest);
407296465Sdelphij
408296465Sdelphij    return num;
409296465Sdelphij}
410296465Sdelphij
411296465Sdelphij/*-
412296465Sdelphij * non-copying interface: provide pointer to region to write to
41359191Skris *   bio_nwrite0:  check how much space is available
41459191Skris *   bio_nwrite:   also increase length
41559191Skris * (example usage:  bio_nwrite0(), write to buffer, bio_nwrite()
41659191Skris *  or just         bio_nwrite(), write to buffer)
41759191Skris */
41859191Skrisstatic ssize_t bio_nwrite0(BIO *bio, char **buf)
419296465Sdelphij{
420296465Sdelphij    struct bio_bio_st *b;
421296465Sdelphij    size_t num;
422296465Sdelphij    size_t write_offset;
42355714Skris
424296465Sdelphij    BIO_clear_retry_flags(bio);
42559191Skris
426296465Sdelphij    if (!bio->init)
427296465Sdelphij        return 0;
42859191Skris
429296465Sdelphij    b = bio->ptr;
430296465Sdelphij    assert(b != NULL);
431296465Sdelphij    assert(b->peer != NULL);
432296465Sdelphij    assert(b->buf != NULL);
43359191Skris
434296465Sdelphij    b->request = 0;
435296465Sdelphij    if (b->closed) {
436296465Sdelphij        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);
437296465Sdelphij        return -1;
438296465Sdelphij    }
43959191Skris
440296465Sdelphij    assert(b->len <= b->size);
44159191Skris
442296465Sdelphij    if (b->len == b->size) {
443296465Sdelphij        BIO_set_retry_write(bio);
444296465Sdelphij        return -1;
445296465Sdelphij    }
44659191Skris
447296465Sdelphij    num = b->size - b->len;
448296465Sdelphij    write_offset = b->offset + b->len;
449296465Sdelphij    if (write_offset >= b->size)
450296465Sdelphij        write_offset -= b->size;
451296465Sdelphij    if (write_offset + num > b->size)
452296465Sdelphij        /*
453296465Sdelphij         * no ring buffer wrap-around for non-copying interface (to fulfil
454296465Sdelphij         * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have
455296465Sdelphij         * to be called twice)
456296465Sdelphij         */
457296465Sdelphij        num = b->size - write_offset;
45859191Skris
459296465Sdelphij    if (buf != NULL)
460296465Sdelphij        *buf = b->buf + write_offset;
461296465Sdelphij    assert(write_offset + num <= b->size);
46259191Skris
463296465Sdelphij    return num;
464296465Sdelphij}
46559191Skris
46659191Skrisstatic ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_)
467296465Sdelphij{
468296465Sdelphij    struct bio_bio_st *b;
469296465Sdelphij    ssize_t num, space;
47059191Skris
471296465Sdelphij    if (num_ > SSIZE_MAX)
472296465Sdelphij        num = SSIZE_MAX;
473296465Sdelphij    else
474296465Sdelphij        num = (ssize_t) num_;
47559191Skris
476296465Sdelphij    space = bio_nwrite0(bio, buf);
477296465Sdelphij    if (num > space)
478296465Sdelphij        num = space;
479296465Sdelphij    if (num <= 0)
480296465Sdelphij        return num;
481296465Sdelphij    b = bio->ptr;
482296465Sdelphij    assert(b != NULL);
483296465Sdelphij    b->len += num;
484296465Sdelphij    assert(b->len <= b->size);
48559191Skris
486296465Sdelphij    return num;
487296465Sdelphij}
48859191Skris
48955714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
490296465Sdelphij{
491296465Sdelphij    long ret;
492296465Sdelphij    struct bio_bio_st *b = bio->ptr;
49355714Skris
494296465Sdelphij    assert(b != NULL);
49555714Skris
496296465Sdelphij    switch (cmd) {
497296465Sdelphij        /* specific CTRL codes */
49855714Skris
499296465Sdelphij    case BIO_C_SET_WRITE_BUF_SIZE:
500296465Sdelphij        if (b->peer) {
501296465Sdelphij            BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
502296465Sdelphij            ret = 0;
503296465Sdelphij        } else if (num == 0) {
504296465Sdelphij            BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
505296465Sdelphij            ret = 0;
506296465Sdelphij        } else {
507296465Sdelphij            size_t new_size = num;
50855714Skris
509296465Sdelphij            if (b->size != new_size) {
510296465Sdelphij                if (b->buf) {
511296465Sdelphij                    OPENSSL_free(b->buf);
512296465Sdelphij                    b->buf = NULL;
513296465Sdelphij                }
514296465Sdelphij                b->size = new_size;
515296465Sdelphij            }
516296465Sdelphij            ret = 1;
517296465Sdelphij        }
518296465Sdelphij        break;
51955714Skris
520296465Sdelphij    case BIO_C_GET_WRITE_BUF_SIZE:
521296465Sdelphij        ret = (long)b->size;
522296465Sdelphij        break;
52355714Skris
524296465Sdelphij    case BIO_C_MAKE_BIO_PAIR:
525296465Sdelphij        {
526296465Sdelphij            BIO *other_bio = ptr;
52755714Skris
528296465Sdelphij            if (bio_make_pair(bio, other_bio))
529296465Sdelphij                ret = 1;
530296465Sdelphij            else
531296465Sdelphij                ret = 0;
532296465Sdelphij        }
533296465Sdelphij        break;
53455714Skris
535296465Sdelphij    case BIO_C_DESTROY_BIO_PAIR:
536296465Sdelphij        /*
537296465Sdelphij         * Affects both BIOs in the pair -- call just once! Or let
538296465Sdelphij         * BIO_free(bio1); BIO_free(bio2); do the job.
539296465Sdelphij         */
540296465Sdelphij        bio_destroy_pair(bio);
541296465Sdelphij        ret = 1;
542296465Sdelphij        break;
54359191Skris
544296465Sdelphij    case BIO_C_GET_WRITE_GUARANTEE:
545296465Sdelphij        /*
546296465Sdelphij         * How many bytes can the caller feed to the next write without
547296465Sdelphij         * having to keep any?
548296465Sdelphij         */
549296465Sdelphij        if (b->peer == NULL || b->closed)
550296465Sdelphij            ret = 0;
551296465Sdelphij        else
552296465Sdelphij            ret = (long)b->size - b->len;
553296465Sdelphij        break;
55455714Skris
555296465Sdelphij    case BIO_C_GET_READ_REQUEST:
556296465Sdelphij        /*
557296465Sdelphij         * If the peer unsuccessfully tried to read, how many bytes were
558296465Sdelphij         * requested? (As with BIO_CTRL_PENDING, that number can usually be
559296465Sdelphij         * treated as boolean.)
560296465Sdelphij         */
561296465Sdelphij        ret = (long)b->request;
562296465Sdelphij        break;
56355714Skris
564296465Sdelphij    case BIO_C_RESET_READ_REQUEST:
565296465Sdelphij        /*
566296465Sdelphij         * Reset request.  (Can be useful after read attempts at the other
567296465Sdelphij         * side that are meant to be non-blocking, e.g. when probing SSL_read
568296465Sdelphij         * to see if any data is available.)
569296465Sdelphij         */
570296465Sdelphij        b->request = 0;
571296465Sdelphij        ret = 1;
572296465Sdelphij        break;
57359191Skris
574296465Sdelphij    case BIO_C_SHUTDOWN_WR:
575296465Sdelphij        /* similar to shutdown(..., SHUT_WR) */
576296465Sdelphij        b->closed = 1;
577296465Sdelphij        ret = 1;
578296465Sdelphij        break;
57955714Skris
580296465Sdelphij    case BIO_C_NREAD0:
581296465Sdelphij        /* prepare for non-copying read */
582296465Sdelphij        ret = (long)bio_nread0(bio, ptr);
583296465Sdelphij        break;
58455714Skris
585296465Sdelphij    case BIO_C_NREAD:
586296465Sdelphij        /* non-copying read */
587296465Sdelphij        ret = (long)bio_nread(bio, ptr, (size_t)num);
588296465Sdelphij        break;
58955714Skris
590296465Sdelphij    case BIO_C_NWRITE0:
591296465Sdelphij        /* prepare for non-copying write */
592296465Sdelphij        ret = (long)bio_nwrite0(bio, ptr);
593296465Sdelphij        break;
59455714Skris
595296465Sdelphij    case BIO_C_NWRITE:
596296465Sdelphij        /* non-copying write */
597296465Sdelphij        ret = (long)bio_nwrite(bio, ptr, (size_t)num);
598296465Sdelphij        break;
59955714Skris
600296465Sdelphij        /* standard CTRL codes follow */
60155714Skris
602296465Sdelphij    case BIO_CTRL_RESET:
603296465Sdelphij        if (b->buf != NULL) {
604296465Sdelphij            b->len = 0;
605296465Sdelphij            b->offset = 0;
606296465Sdelphij        }
607296465Sdelphij        ret = 0;
608296465Sdelphij        break;
60955714Skris
610296465Sdelphij    case BIO_CTRL_GET_CLOSE:
611296465Sdelphij        ret = bio->shutdown;
612296465Sdelphij        break;
61355714Skris
614296465Sdelphij    case BIO_CTRL_SET_CLOSE:
615296465Sdelphij        bio->shutdown = (int)num;
616296465Sdelphij        ret = 1;
617296465Sdelphij        break;
61855714Skris
619296465Sdelphij    case BIO_CTRL_PENDING:
620296465Sdelphij        if (b->peer != NULL) {
621296465Sdelphij            struct bio_bio_st *peer_b = b->peer->ptr;
62255714Skris
623296465Sdelphij            ret = (long)peer_b->len;
624296465Sdelphij        } else
625296465Sdelphij            ret = 0;
626296465Sdelphij        break;
62755714Skris
628296465Sdelphij    case BIO_CTRL_WPENDING:
629296465Sdelphij        if (b->buf != NULL)
630296465Sdelphij            ret = (long)b->len;
631296465Sdelphij        else
632296465Sdelphij            ret = 0;
633296465Sdelphij        break;
63455714Skris
635296465Sdelphij    case BIO_CTRL_DUP:
636296465Sdelphij        /* See BIO_dup_chain for circumstances we have to expect. */
637296465Sdelphij        {
638296465Sdelphij            BIO *other_bio = ptr;
639296465Sdelphij            struct bio_bio_st *other_b;
640296465Sdelphij
641296465Sdelphij            assert(other_bio != NULL);
642296465Sdelphij            other_b = other_bio->ptr;
643296465Sdelphij            assert(other_b != NULL);
644296465Sdelphij
645296465Sdelphij            assert(other_b->buf == NULL); /* other_bio is always fresh */
646296465Sdelphij
647296465Sdelphij            other_b->size = b->size;
648296465Sdelphij        }
649296465Sdelphij
650296465Sdelphij        ret = 1;
651296465Sdelphij        break;
652296465Sdelphij
653296465Sdelphij    case BIO_CTRL_FLUSH:
654296465Sdelphij        ret = 1;
655296465Sdelphij        break;
656296465Sdelphij
657296465Sdelphij    case BIO_CTRL_EOF:
658296465Sdelphij        {
659296465Sdelphij            BIO *other_bio = ptr;
660296465Sdelphij
661296465Sdelphij            if (other_bio) {
662296465Sdelphij                struct bio_bio_st *other_b = other_bio->ptr;
663296465Sdelphij
664296465Sdelphij                assert(other_b != NULL);
665296465Sdelphij                ret = other_b->len == 0 && other_b->closed;
666296465Sdelphij            } else
667296465Sdelphij                ret = 1;
668296465Sdelphij        }
669296465Sdelphij        break;
670296465Sdelphij
671296465Sdelphij    default:
672296465Sdelphij        ret = 0;
673296465Sdelphij    }
674296465Sdelphij    return ret;
675296465Sdelphij}
676296465Sdelphij
67768651Skrisstatic int bio_puts(BIO *bio, const char *str)
678296465Sdelphij{
679296465Sdelphij    return bio_write(bio, str, strlen(str));
680296465Sdelphij}
68155714Skris
68255714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2)
683296465Sdelphij{
684296465Sdelphij    struct bio_bio_st *b1, *b2;
68555714Skris
686296465Sdelphij    assert(bio1 != NULL);
687296465Sdelphij    assert(bio2 != NULL);
68855714Skris
689296465Sdelphij    b1 = bio1->ptr;
690296465Sdelphij    b2 = bio2->ptr;
69155714Skris
692296465Sdelphij    if (b1->peer != NULL || b2->peer != NULL) {
693296465Sdelphij        BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
694296465Sdelphij        return 0;
695296465Sdelphij    }
69655714Skris
697296465Sdelphij    if (b1->buf == NULL) {
698296465Sdelphij        b1->buf = OPENSSL_malloc(b1->size);
699296465Sdelphij        if (b1->buf == NULL) {
700296465Sdelphij            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
701296465Sdelphij            return 0;
702296465Sdelphij        }
703296465Sdelphij        b1->len = 0;
704296465Sdelphij        b1->offset = 0;
705296465Sdelphij    }
70655714Skris
707296465Sdelphij    if (b2->buf == NULL) {
708296465Sdelphij        b2->buf = OPENSSL_malloc(b2->size);
709296465Sdelphij        if (b2->buf == NULL) {
710296465Sdelphij            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
711296465Sdelphij            return 0;
712296465Sdelphij        }
713296465Sdelphij        b2->len = 0;
714296465Sdelphij        b2->offset = 0;
715296465Sdelphij    }
716296465Sdelphij
717296465Sdelphij    b1->peer = bio2;
718296465Sdelphij    b1->closed = 0;
719296465Sdelphij    b1->request = 0;
720296465Sdelphij    b2->peer = bio1;
721296465Sdelphij    b2->closed = 0;
722296465Sdelphij    b2->request = 0;
723296465Sdelphij
724296465Sdelphij    bio1->init = 1;
725296465Sdelphij    bio2->init = 1;
726296465Sdelphij
727296465Sdelphij    return 1;
728296465Sdelphij}
729296465Sdelphij
73055714Skrisstatic void bio_destroy_pair(BIO *bio)
731296465Sdelphij{
732296465Sdelphij    struct bio_bio_st *b = bio->ptr;
73355714Skris
734296465Sdelphij    if (b != NULL) {
735296465Sdelphij        BIO *peer_bio = b->peer;
73655714Skris
737296465Sdelphij        if (peer_bio != NULL) {
738296465Sdelphij            struct bio_bio_st *peer_b = peer_bio->ptr;
73955714Skris
740296465Sdelphij            assert(peer_b != NULL);
741296465Sdelphij            assert(peer_b->peer == bio);
74255714Skris
743296465Sdelphij            peer_b->peer = NULL;
744296465Sdelphij            peer_bio->init = 0;
745296465Sdelphij            assert(peer_b->buf != NULL);
746296465Sdelphij            peer_b->len = 0;
747296465Sdelphij            peer_b->offset = 0;
74855714Skris
749296465Sdelphij            b->peer = NULL;
750296465Sdelphij            bio->init = 0;
751296465Sdelphij            assert(b->buf != NULL);
752296465Sdelphij            b->len = 0;
753296465Sdelphij            b->offset = 0;
754296465Sdelphij        }
755296465Sdelphij    }
756296465Sdelphij}
757296465Sdelphij
75855714Skris/* Exported convenience functions */
75955714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
760296465Sdelphij                     BIO **bio2_p, size_t writebuf2)
761296465Sdelphij{
762296465Sdelphij    BIO *bio1 = NULL, *bio2 = NULL;
763296465Sdelphij    long r;
764296465Sdelphij    int ret = 0;
76555714Skris
766296465Sdelphij    bio1 = BIO_new(BIO_s_bio());
767296465Sdelphij    if (bio1 == NULL)
768296465Sdelphij        goto err;
769296465Sdelphij    bio2 = BIO_new(BIO_s_bio());
770296465Sdelphij    if (bio2 == NULL)
771296465Sdelphij        goto err;
77255714Skris
773296465Sdelphij    if (writebuf1) {
774296465Sdelphij        r = BIO_set_write_buf_size(bio1, writebuf1);
775296465Sdelphij        if (!r)
776296465Sdelphij            goto err;
777296465Sdelphij    }
778296465Sdelphij    if (writebuf2) {
779296465Sdelphij        r = BIO_set_write_buf_size(bio2, writebuf2);
780296465Sdelphij        if (!r)
781296465Sdelphij            goto err;
782296465Sdelphij    }
78355714Skris
784296465Sdelphij    r = BIO_make_bio_pair(bio1, bio2);
785296465Sdelphij    if (!r)
786296465Sdelphij        goto err;
787296465Sdelphij    ret = 1;
78855714Skris
78955714Skris err:
790296465Sdelphij    if (ret == 0) {
791296465Sdelphij        if (bio1) {
792296465Sdelphij            BIO_free(bio1);
793296465Sdelphij            bio1 = NULL;
794296465Sdelphij        }
795296465Sdelphij        if (bio2) {
796296465Sdelphij            BIO_free(bio2);
797296465Sdelphij            bio2 = NULL;
798296465Sdelphij        }
799296465Sdelphij    }
80055714Skris
801296465Sdelphij    *bio1_p = bio1;
802296465Sdelphij    *bio2_p = bio2;
803296465Sdelphij    return ret;
804296465Sdelphij}
80555714Skris
80655714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio)
807296465Sdelphij{
808296465Sdelphij    return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
809296465Sdelphij}
81055714Skris
81155714Skrissize_t BIO_ctrl_get_read_request(BIO *bio)
812296465Sdelphij{
813296465Sdelphij    return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
814296465Sdelphij}
81559191Skris
81659191Skrisint BIO_ctrl_reset_read_request(BIO *bio)
817296465Sdelphij{
818296465Sdelphij    return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
819296465Sdelphij}
82059191Skris
821296465Sdelphij/*
822296465Sdelphij * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
823296465Sdelphij * (conceivably some other BIOs could allow non-copying reads and writes
824296465Sdelphij * too.)
82559191Skris */
82659191Skrisint BIO_nread0(BIO *bio, char **buf)
827296465Sdelphij{
828296465Sdelphij    long ret;
82959191Skris
830296465Sdelphij    if (!bio->init) {
831296465Sdelphij        BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
832296465Sdelphij        return -2;
833296465Sdelphij    }
83459191Skris
835296465Sdelphij    ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
836296465Sdelphij    if (ret > INT_MAX)
837296465Sdelphij        return INT_MAX;
838296465Sdelphij    else
839296465Sdelphij        return (int)ret;
840296465Sdelphij}
84159191Skris
84259191Skrisint BIO_nread(BIO *bio, char **buf, int num)
843296465Sdelphij{
844296465Sdelphij    int ret;
84559191Skris
846296465Sdelphij    if (!bio->init) {
847296465Sdelphij        BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
848296465Sdelphij        return -2;
849296465Sdelphij    }
85059191Skris
851296465Sdelphij    ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
852296465Sdelphij    if (ret > 0)
853296465Sdelphij        bio->num_read += ret;
854296465Sdelphij    return ret;
855296465Sdelphij}
85659191Skris
85759191Skrisint BIO_nwrite0(BIO *bio, char **buf)
858296465Sdelphij{
859296465Sdelphij    long ret;
86059191Skris
861296465Sdelphij    if (!bio->init) {
862296465Sdelphij        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
863296465Sdelphij        return -2;
864296465Sdelphij    }
86559191Skris
866296465Sdelphij    ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
867296465Sdelphij    if (ret > INT_MAX)
868296465Sdelphij        return INT_MAX;
869296465Sdelphij    else
870296465Sdelphij        return (int)ret;
871296465Sdelphij}
87259191Skris
87359191Skrisint BIO_nwrite(BIO *bio, char **buf, int num)
874296465Sdelphij{
875296465Sdelphij    int ret;
87659191Skris
877296465Sdelphij    if (!bio->init) {
878296465Sdelphij        BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
879296465Sdelphij        return -2;
880296465Sdelphij    }
88159191Skris
882296465Sdelphij    ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
883296465Sdelphij    if (ret > 0)
884296465Sdelphij        bio->num_write += ret;
885296465Sdelphij    return ret;
886296465Sdelphij}
887