1295016Sjkim/* crypto/bio/bss_bio.c  */
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
10280304Sjkim *    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
56280304Sjkim/*
57280304Sjkim * Special method for a BIO where the other endpoint is also a BIO of this
58280304Sjkim * kind, handled by the same thread (i.e. the "peer" is actually ourselves,
59280304Sjkim * wearing a different hat). Such "BIO pairs" are mainly for using the SSL
60280304Sjkim * library with I/O interfaces for which no specific BIO method is available.
61280304Sjkim * See ssl/ssltest.c for some hints on how this can be used.
62280304Sjkim */
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
107280304Sjkimstatic BIO_METHOD methods_biop = {
108280304Sjkim    BIO_TYPE_BIO,
109280304Sjkim    "BIO pair",
110280304Sjkim    bio_write,
111280304Sjkim    bio_read,
112280304Sjkim    bio_puts,
113280304Sjkim    NULL /* no bio_gets */ ,
114280304Sjkim    bio_ctrl,
115280304Sjkim    bio_new,
116280304Sjkim    bio_free,
117280304Sjkim    NULL                        /* no bio_callback_ctrl */
11855714Skris};
11955714Skris
12055714SkrisBIO_METHOD *BIO_s_bio(void)
12155714Skris{
122280304Sjkim    return &methods_biop;
123280304Sjkim}
12455714Skris
125280304Sjkimstruct bio_bio_st {
126280304Sjkim    BIO *peer;                  /* NULL if buf == NULL. If peer != NULL, then
127280304Sjkim                                 * peer->ptr is also a bio_bio_st, and its
128280304Sjkim                                 * "peer" member points back to us. peer !=
129280304Sjkim                                 * NULL iff init != 0 in the BIO. */
130280304Sjkim    /* This is for what we write (i.e. reading uses peer's struct): */
131280304Sjkim    int closed;                 /* valid iff peer != NULL */
132280304Sjkim    size_t len;                 /* valid iff buf != NULL; 0 if peer == NULL */
133280304Sjkim    size_t offset;              /* valid iff buf != NULL; 0 if len == 0 */
134280304Sjkim    size_t size;
135280304Sjkim    char *buf;                  /* "size" elements (if != NULL) */
136280304Sjkim    size_t request;             /* valid iff peer != NULL; 0 if len != 0,
137280304Sjkim                                 * otherwise set by peer to number of bytes
138280304Sjkim                                 * it (unsuccessfully) tried to read, never
139280304Sjkim                                 * more than buffer space (size-len)
140280304Sjkim                                 * warrants. */
14155714Skris};
14255714Skris
14355714Skrisstatic int bio_new(BIO *bio)
144280304Sjkim{
145280304Sjkim    struct bio_bio_st *b;
14655714Skris
147280304Sjkim    b = OPENSSL_malloc(sizeof *b);
148280304Sjkim    if (b == NULL)
149280304Sjkim        return 0;
15055714Skris
151280304Sjkim    b->peer = NULL;
152280304Sjkim    /* enough for one TLS record (just a default) */
153280304Sjkim    b->size = 17 * 1024;
154280304Sjkim    b->buf = NULL;
15555714Skris
156280304Sjkim    bio->ptr = b;
157280304Sjkim    return 1;
158280304Sjkim}
15955714Skris
16055714Skrisstatic int bio_free(BIO *bio)
161280304Sjkim{
162280304Sjkim    struct bio_bio_st *b;
16355714Skris
164280304Sjkim    if (bio == NULL)
165280304Sjkim        return 0;
166280304Sjkim    b = bio->ptr;
16755714Skris
168280304Sjkim    assert(b != NULL);
16955714Skris
170280304Sjkim    if (b->peer)
171280304Sjkim        bio_destroy_pair(bio);
17255714Skris
173280304Sjkim    if (b->buf != NULL) {
174280304Sjkim        OPENSSL_free(b->buf);
175280304Sjkim    }
17655714Skris
177280304Sjkim    OPENSSL_free(b);
17855714Skris
179280304Sjkim    return 1;
180280304Sjkim}
18155714Skris
18255714Skrisstatic int bio_read(BIO *bio, char *buf, int size_)
183280304Sjkim{
184280304Sjkim    size_t size = size_;
185280304Sjkim    size_t rest;
186280304Sjkim    struct bio_bio_st *b, *peer_b;
18755714Skris
188280304Sjkim    BIO_clear_retry_flags(bio);
18955714Skris
190280304Sjkim    if (!bio->init)
191280304Sjkim        return 0;
19255714Skris
193280304Sjkim    b = bio->ptr;
194280304Sjkim    assert(b != NULL);
195280304Sjkim    assert(b->peer != NULL);
196280304Sjkim    peer_b = b->peer->ptr;
197280304Sjkim    assert(peer_b != NULL);
198280304Sjkim    assert(peer_b->buf != NULL);
19955714Skris
200280304Sjkim    peer_b->request = 0;        /* will be set in "retry_read" situation */
20155714Skris
202280304Sjkim    if (buf == NULL || size == 0)
203280304Sjkim        return 0;
20455714Skris
205280304Sjkim    if (peer_b->len == 0) {
206280304Sjkim        if (peer_b->closed)
207280304Sjkim            return 0;           /* writer has closed, and no data is left */
208280304Sjkim        else {
209280304Sjkim            BIO_set_retry_read(bio); /* buffer is empty */
210280304Sjkim            if (size <= peer_b->size)
211280304Sjkim                peer_b->request = size;
212280304Sjkim            else
213280304Sjkim                /*
214280304Sjkim                 * don't ask for more than the peer can deliver in one write
215280304Sjkim                 */
216280304Sjkim                peer_b->request = peer_b->size;
217280304Sjkim            return -1;
218280304Sjkim        }
219280304Sjkim    }
22055714Skris
221280304Sjkim    /* we can read */
222280304Sjkim    if (peer_b->len < size)
223280304Sjkim        size = peer_b->len;
22455714Skris
225280304Sjkim    /* now read "size" bytes */
22655714Skris
227280304Sjkim    rest = size;
228280304Sjkim
229280304Sjkim    assert(rest > 0);
230280304Sjkim    do {                        /* one or two iterations */
231280304Sjkim        size_t chunk;
232280304Sjkim
233280304Sjkim        assert(rest <= peer_b->len);
234280304Sjkim        if (peer_b->offset + rest <= peer_b->size)
235280304Sjkim            chunk = rest;
236280304Sjkim        else
237280304Sjkim            /* wrap around ring buffer */
238280304Sjkim            chunk = peer_b->size - peer_b->offset;
239280304Sjkim        assert(peer_b->offset + chunk <= peer_b->size);
240280304Sjkim
241280304Sjkim        memcpy(buf, peer_b->buf + peer_b->offset, chunk);
242280304Sjkim
243280304Sjkim        peer_b->len -= chunk;
244280304Sjkim        if (peer_b->len) {
245280304Sjkim            peer_b->offset += chunk;
246280304Sjkim            assert(peer_b->offset <= peer_b->size);
247280304Sjkim            if (peer_b->offset == peer_b->size)
248280304Sjkim                peer_b->offset = 0;
249280304Sjkim            buf += chunk;
250280304Sjkim        } else {
251280304Sjkim            /* buffer now empty, no need to advance "buf" */
252280304Sjkim            assert(chunk == rest);
253280304Sjkim            peer_b->offset = 0;
254280304Sjkim        }
255280304Sjkim        rest -= chunk;
256280304Sjkim    }
257280304Sjkim    while (rest);
258280304Sjkim
259280304Sjkim    return size;
260280304Sjkim}
261280304Sjkim
262280304Sjkim/*-
263280304Sjkim * 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 */
269280304Sjkim/*
270280304Sjkim * WARNING: The non-copying interface is largely untested as of yet and may
271280304Sjkim * contain bugs.
272280304Sjkim */
273238405Sjkimstatic ossl_ssize_t bio_nread0(BIO *bio, char **buf)
274280304Sjkim{
275280304Sjkim    struct bio_bio_st *b, *peer_b;
276280304Sjkim    ossl_ssize_t num;
27759191Skris
278280304Sjkim    BIO_clear_retry_flags(bio);
27959191Skris
280280304Sjkim    if (!bio->init)
281280304Sjkim        return 0;
28259191Skris
283280304Sjkim    b = bio->ptr;
284280304Sjkim    assert(b != NULL);
285280304Sjkim    assert(b->peer != NULL);
286280304Sjkim    peer_b = b->peer->ptr;
287280304Sjkim    assert(peer_b != NULL);
288280304Sjkim    assert(peer_b->buf != NULL);
28959191Skris
290280304Sjkim    peer_b->request = 0;
291280304Sjkim
292280304Sjkim    if (peer_b->len == 0) {
293280304Sjkim        char dummy;
294280304Sjkim
295280304Sjkim        /* avoid code duplication -- nothing available for reading */
296280304Sjkim        return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
297280304Sjkim    }
298280304Sjkim
299280304Sjkim    num = peer_b->len;
300280304Sjkim    if (peer_b->size < peer_b->offset + num)
301280304Sjkim        /* no ring buffer wrap-around for non-copying interface */
302280304Sjkim        num = peer_b->size - peer_b->offset;
303280304Sjkim    assert(num > 0);
304280304Sjkim
305280304Sjkim    if (buf != NULL)
306280304Sjkim        *buf = peer_b->buf + peer_b->offset;
307280304Sjkim    return num;
308280304Sjkim}
309280304Sjkim
310238405Sjkimstatic ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_)
311280304Sjkim{
312280304Sjkim    struct bio_bio_st *b, *peer_b;
313280304Sjkim    ossl_ssize_t num, available;
31459191Skris
315280304Sjkim    if (num_ > SSIZE_MAX)
316280304Sjkim        num = SSIZE_MAX;
317280304Sjkim    else
318280304Sjkim        num = (ossl_ssize_t) num_;
31959191Skris
320280304Sjkim    available = bio_nread0(bio, buf);
321280304Sjkim    if (num > available)
322280304Sjkim        num = available;
323280304Sjkim    if (num <= 0)
324280304Sjkim        return num;
32559191Skris
326280304Sjkim    b = bio->ptr;
327280304Sjkim    peer_b = b->peer->ptr;
32859191Skris
329280304Sjkim    peer_b->len -= num;
330280304Sjkim    if (peer_b->len) {
331280304Sjkim        peer_b->offset += num;
332280304Sjkim        assert(peer_b->offset <= peer_b->size);
333280304Sjkim        if (peer_b->offset == peer_b->size)
334280304Sjkim            peer_b->offset = 0;
335280304Sjkim    } else
336280304Sjkim        peer_b->offset = 0;
33759191Skris
338280304Sjkim    return num;
339280304Sjkim}
34059191Skris
34168651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_)
342280304Sjkim{
343280304Sjkim    size_t num = num_;
344280304Sjkim    size_t rest;
345280304Sjkim    struct bio_bio_st *b;
34655714Skris
347280304Sjkim    BIO_clear_retry_flags(bio);
34855714Skris
349280304Sjkim    if (!bio->init || buf == NULL || num == 0)
350280304Sjkim        return 0;
35155714Skris
352280304Sjkim    b = bio->ptr;
353280304Sjkim    assert(b != NULL);
354280304Sjkim    assert(b->peer != NULL);
355280304Sjkim    assert(b->buf != NULL);
35655714Skris
357280304Sjkim    b->request = 0;
358280304Sjkim    if (b->closed) {
359280304Sjkim        /* we already closed */
360280304Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);
361280304Sjkim        return -1;
362280304Sjkim    }
36355714Skris
364280304Sjkim    assert(b->len <= b->size);
36555714Skris
366280304Sjkim    if (b->len == b->size) {
367280304Sjkim        BIO_set_retry_write(bio); /* buffer is full */
368280304Sjkim        return -1;
369280304Sjkim    }
37055714Skris
371280304Sjkim    /* we can write */
372280304Sjkim    if (num > b->size - b->len)
373280304Sjkim        num = b->size - b->len;
37455714Skris
375280304Sjkim    /* now write "num" bytes */
37655714Skris
377280304Sjkim    rest = num;
37855714Skris
379280304Sjkim    assert(rest > 0);
380280304Sjkim    do {                        /* one or two iterations */
381280304Sjkim        size_t write_offset;
382280304Sjkim        size_t chunk;
38355714Skris
384280304Sjkim        assert(b->len + rest <= b->size);
38555714Skris
386280304Sjkim        write_offset = b->offset + b->len;
387280304Sjkim        if (write_offset >= b->size)
388280304Sjkim            write_offset -= b->size;
389280304Sjkim        /* b->buf[write_offset] is the first byte we can write to. */
39055714Skris
391280304Sjkim        if (write_offset + rest <= b->size)
392280304Sjkim            chunk = rest;
393280304Sjkim        else
394280304Sjkim            /* wrap around ring buffer */
395280304Sjkim            chunk = b->size - write_offset;
39655714Skris
397280304Sjkim        memcpy(b->buf + write_offset, buf, chunk);
398280304Sjkim
399280304Sjkim        b->len += chunk;
400280304Sjkim
401280304Sjkim        assert(b->len <= b->size);
402280304Sjkim
403280304Sjkim        rest -= chunk;
404280304Sjkim        buf += chunk;
405280304Sjkim    }
406280304Sjkim    while (rest);
407280304Sjkim
408280304Sjkim    return num;
409280304Sjkim}
410280304Sjkim
411280304Sjkim/*-
412280304Sjkim * 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 */
418238405Sjkimstatic ossl_ssize_t bio_nwrite0(BIO *bio, char **buf)
419280304Sjkim{
420280304Sjkim    struct bio_bio_st *b;
421280304Sjkim    size_t num;
422280304Sjkim    size_t write_offset;
42355714Skris
424280304Sjkim    BIO_clear_retry_flags(bio);
42559191Skris
426280304Sjkim    if (!bio->init)
427280304Sjkim        return 0;
42859191Skris
429280304Sjkim    b = bio->ptr;
430280304Sjkim    assert(b != NULL);
431280304Sjkim    assert(b->peer != NULL);
432280304Sjkim    assert(b->buf != NULL);
43359191Skris
434280304Sjkim    b->request = 0;
435280304Sjkim    if (b->closed) {
436280304Sjkim        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);
437280304Sjkim        return -1;
438280304Sjkim    }
43959191Skris
440280304Sjkim    assert(b->len <= b->size);
44159191Skris
442280304Sjkim    if (b->len == b->size) {
443280304Sjkim        BIO_set_retry_write(bio);
444280304Sjkim        return -1;
445280304Sjkim    }
44659191Skris
447280304Sjkim    num = b->size - b->len;
448280304Sjkim    write_offset = b->offset + b->len;
449280304Sjkim    if (write_offset >= b->size)
450280304Sjkim        write_offset -= b->size;
451280304Sjkim    if (write_offset + num > b->size)
452280304Sjkim        /*
453280304Sjkim         * no ring buffer wrap-around for non-copying interface (to fulfil
454280304Sjkim         * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have
455280304Sjkim         * to be called twice)
456280304Sjkim         */
457280304Sjkim        num = b->size - write_offset;
45859191Skris
459280304Sjkim    if (buf != NULL)
460280304Sjkim        *buf = b->buf + write_offset;
461280304Sjkim    assert(write_offset + num <= b->size);
46259191Skris
463280304Sjkim    return num;
464280304Sjkim}
46559191Skris
466238405Sjkimstatic ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_)
467280304Sjkim{
468280304Sjkim    struct bio_bio_st *b;
469280304Sjkim    ossl_ssize_t num, space;
47059191Skris
471280304Sjkim    if (num_ > SSIZE_MAX)
472280304Sjkim        num = SSIZE_MAX;
473280304Sjkim    else
474280304Sjkim        num = (ossl_ssize_t) num_;
47559191Skris
476280304Sjkim    space = bio_nwrite0(bio, buf);
477280304Sjkim    if (num > space)
478280304Sjkim        num = space;
479280304Sjkim    if (num <= 0)
480280304Sjkim        return num;
481280304Sjkim    b = bio->ptr;
482280304Sjkim    assert(b != NULL);
483280304Sjkim    b->len += num;
484280304Sjkim    assert(b->len <= b->size);
48559191Skris
486280304Sjkim    return num;
487280304Sjkim}
48859191Skris
48955714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
490280304Sjkim{
491280304Sjkim    long ret;
492280304Sjkim    struct bio_bio_st *b = bio->ptr;
49355714Skris
494280304Sjkim    assert(b != NULL);
49555714Skris
496280304Sjkim    switch (cmd) {
497280304Sjkim        /* specific CTRL codes */
49855714Skris
499280304Sjkim    case BIO_C_SET_WRITE_BUF_SIZE:
500280304Sjkim        if (b->peer) {
501280304Sjkim            BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
502280304Sjkim            ret = 0;
503280304Sjkim        } else if (num == 0) {
504280304Sjkim            BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
505280304Sjkim            ret = 0;
506280304Sjkim        } else {
507280304Sjkim            size_t new_size = num;
50855714Skris
509280304Sjkim            if (b->size != new_size) {
510280304Sjkim                if (b->buf) {
511280304Sjkim                    OPENSSL_free(b->buf);
512280304Sjkim                    b->buf = NULL;
513280304Sjkim                }
514280304Sjkim                b->size = new_size;
515280304Sjkim            }
516280304Sjkim            ret = 1;
517280304Sjkim        }
518280304Sjkim        break;
51955714Skris
520280304Sjkim    case BIO_C_GET_WRITE_BUF_SIZE:
521280304Sjkim        ret = (long)b->size;
522280304Sjkim        break;
52355714Skris
524280304Sjkim    case BIO_C_MAKE_BIO_PAIR:
525280304Sjkim        {
526280304Sjkim            BIO *other_bio = ptr;
52755714Skris
528280304Sjkim            if (bio_make_pair(bio, other_bio))
529280304Sjkim                ret = 1;
530280304Sjkim            else
531280304Sjkim                ret = 0;
532280304Sjkim        }
533280304Sjkim        break;
53455714Skris
535280304Sjkim    case BIO_C_DESTROY_BIO_PAIR:
536280304Sjkim        /*
537280304Sjkim         * Affects both BIOs in the pair -- call just once! Or let
538280304Sjkim         * BIO_free(bio1); BIO_free(bio2); do the job.
539280304Sjkim         */
540280304Sjkim        bio_destroy_pair(bio);
541280304Sjkim        ret = 1;
542280304Sjkim        break;
54359191Skris
544280304Sjkim    case BIO_C_GET_WRITE_GUARANTEE:
545280304Sjkim        /*
546280304Sjkim         * How many bytes can the caller feed to the next write without
547280304Sjkim         * having to keep any?
548280304Sjkim         */
549280304Sjkim        if (b->peer == NULL || b->closed)
550280304Sjkim            ret = 0;
551280304Sjkim        else
552280304Sjkim            ret = (long)b->size - b->len;
553280304Sjkim        break;
55455714Skris
555280304Sjkim    case BIO_C_GET_READ_REQUEST:
556280304Sjkim        /*
557280304Sjkim         * If the peer unsuccessfully tried to read, how many bytes were
558280304Sjkim         * requested? (As with BIO_CTRL_PENDING, that number can usually be
559280304Sjkim         * treated as boolean.)
560280304Sjkim         */
561280304Sjkim        ret = (long)b->request;
562280304Sjkim        break;
56355714Skris
564280304Sjkim    case BIO_C_RESET_READ_REQUEST:
565280304Sjkim        /*
566280304Sjkim         * Reset request.  (Can be useful after read attempts at the other
567280304Sjkim         * side that are meant to be non-blocking, e.g. when probing SSL_read
568280304Sjkim         * to see if any data is available.)
569280304Sjkim         */
570280304Sjkim        b->request = 0;
571280304Sjkim        ret = 1;
572280304Sjkim        break;
57359191Skris
574280304Sjkim    case BIO_C_SHUTDOWN_WR:
575280304Sjkim        /* similar to shutdown(..., SHUT_WR) */
576280304Sjkim        b->closed = 1;
577280304Sjkim        ret = 1;
578280304Sjkim        break;
57955714Skris
580280304Sjkim    case BIO_C_NREAD0:
581280304Sjkim        /* prepare for non-copying read */
582280304Sjkim        ret = (long)bio_nread0(bio, ptr);
583280304Sjkim        break;
58455714Skris
585280304Sjkim    case BIO_C_NREAD:
586280304Sjkim        /* non-copying read */
587280304Sjkim        ret = (long)bio_nread(bio, ptr, (size_t)num);
588280304Sjkim        break;
58955714Skris
590280304Sjkim    case BIO_C_NWRITE0:
591280304Sjkim        /* prepare for non-copying write */
592280304Sjkim        ret = (long)bio_nwrite0(bio, ptr);
593280304Sjkim        break;
59455714Skris
595280304Sjkim    case BIO_C_NWRITE:
596280304Sjkim        /* non-copying write */
597280304Sjkim        ret = (long)bio_nwrite(bio, ptr, (size_t)num);
598280304Sjkim        break;
59955714Skris
600280304Sjkim        /* standard CTRL codes follow */
60155714Skris
602280304Sjkim    case BIO_CTRL_RESET:
603280304Sjkim        if (b->buf != NULL) {
604280304Sjkim            b->len = 0;
605280304Sjkim            b->offset = 0;
606280304Sjkim        }
607280304Sjkim        ret = 0;
608280304Sjkim        break;
60955714Skris
610280304Sjkim    case BIO_CTRL_GET_CLOSE:
611280304Sjkim        ret = bio->shutdown;
612280304Sjkim        break;
61355714Skris
614280304Sjkim    case BIO_CTRL_SET_CLOSE:
615280304Sjkim        bio->shutdown = (int)num;
616280304Sjkim        ret = 1;
617280304Sjkim        break;
61855714Skris
619280304Sjkim    case BIO_CTRL_PENDING:
620280304Sjkim        if (b->peer != NULL) {
621280304Sjkim            struct bio_bio_st *peer_b = b->peer->ptr;
62255714Skris
623280304Sjkim            ret = (long)peer_b->len;
624280304Sjkim        } else
625280304Sjkim            ret = 0;
626280304Sjkim        break;
62755714Skris
628280304Sjkim    case BIO_CTRL_WPENDING:
629280304Sjkim        if (b->buf != NULL)
630280304Sjkim            ret = (long)b->len;
631280304Sjkim        else
632280304Sjkim            ret = 0;
633280304Sjkim        break;
63455714Skris
635280304Sjkim    case BIO_CTRL_DUP:
636280304Sjkim        /* See BIO_dup_chain for circumstances we have to expect. */
637280304Sjkim        {
638280304Sjkim            BIO *other_bio = ptr;
639280304Sjkim            struct bio_bio_st *other_b;
640280304Sjkim
641280304Sjkim            assert(other_bio != NULL);
642280304Sjkim            other_b = other_bio->ptr;
643280304Sjkim            assert(other_b != NULL);
644280304Sjkim
645280304Sjkim            assert(other_b->buf == NULL); /* other_bio is always fresh */
646280304Sjkim
647280304Sjkim            other_b->size = b->size;
648280304Sjkim        }
649280304Sjkim
650280304Sjkim        ret = 1;
651280304Sjkim        break;
652280304Sjkim
653280304Sjkim    case BIO_CTRL_FLUSH:
654280304Sjkim        ret = 1;
655280304Sjkim        break;
656280304Sjkim
657280304Sjkim    case BIO_CTRL_EOF:
658280304Sjkim        {
659280304Sjkim            BIO *other_bio = ptr;
660280304Sjkim
661280304Sjkim            if (other_bio) {
662280304Sjkim                struct bio_bio_st *other_b = other_bio->ptr;
663280304Sjkim
664280304Sjkim                assert(other_b != NULL);
665280304Sjkim                ret = other_b->len == 0 && other_b->closed;
666280304Sjkim            } else
667280304Sjkim                ret = 1;
668280304Sjkim        }
669280304Sjkim        break;
670280304Sjkim
671280304Sjkim    default:
672280304Sjkim        ret = 0;
673280304Sjkim    }
674280304Sjkim    return ret;
675280304Sjkim}
676280304Sjkim
67768651Skrisstatic int bio_puts(BIO *bio, const char *str)
678280304Sjkim{
679280304Sjkim    return bio_write(bio, str, strlen(str));
680280304Sjkim}
68155714Skris
68255714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2)
683280304Sjkim{
684280304Sjkim    struct bio_bio_st *b1, *b2;
68555714Skris
686280304Sjkim    assert(bio1 != NULL);
687280304Sjkim    assert(bio2 != NULL);
68855714Skris
689280304Sjkim    b1 = bio1->ptr;
690280304Sjkim    b2 = bio2->ptr;
69155714Skris
692280304Sjkim    if (b1->peer != NULL || b2->peer != NULL) {
693280304Sjkim        BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
694280304Sjkim        return 0;
695280304Sjkim    }
69655714Skris
697280304Sjkim    if (b1->buf == NULL) {
698280304Sjkim        b1->buf = OPENSSL_malloc(b1->size);
699280304Sjkim        if (b1->buf == NULL) {
700280304Sjkim            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
701280304Sjkim            return 0;
702280304Sjkim        }
703280304Sjkim        b1->len = 0;
704280304Sjkim        b1->offset = 0;
705280304Sjkim    }
70655714Skris
707280304Sjkim    if (b2->buf == NULL) {
708280304Sjkim        b2->buf = OPENSSL_malloc(b2->size);
709280304Sjkim        if (b2->buf == NULL) {
710280304Sjkim            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
711280304Sjkim            return 0;
712280304Sjkim        }
713280304Sjkim        b2->len = 0;
714280304Sjkim        b2->offset = 0;
715280304Sjkim    }
716280304Sjkim
717280304Sjkim    b1->peer = bio2;
718280304Sjkim    b1->closed = 0;
719280304Sjkim    b1->request = 0;
720280304Sjkim    b2->peer = bio1;
721280304Sjkim    b2->closed = 0;
722280304Sjkim    b2->request = 0;
723280304Sjkim
724280304Sjkim    bio1->init = 1;
725280304Sjkim    bio2->init = 1;
726280304Sjkim
727280304Sjkim    return 1;
728280304Sjkim}
729280304Sjkim
73055714Skrisstatic void bio_destroy_pair(BIO *bio)
731280304Sjkim{
732280304Sjkim    struct bio_bio_st *b = bio->ptr;
73355714Skris
734280304Sjkim    if (b != NULL) {
735280304Sjkim        BIO *peer_bio = b->peer;
73655714Skris
737280304Sjkim        if (peer_bio != NULL) {
738280304Sjkim            struct bio_bio_st *peer_b = peer_bio->ptr;
73955714Skris
740280304Sjkim            assert(peer_b != NULL);
741280304Sjkim            assert(peer_b->peer == bio);
74255714Skris
743280304Sjkim            peer_b->peer = NULL;
744280304Sjkim            peer_bio->init = 0;
745280304Sjkim            assert(peer_b->buf != NULL);
746280304Sjkim            peer_b->len = 0;
747280304Sjkim            peer_b->offset = 0;
74855714Skris
749280304Sjkim            b->peer = NULL;
750280304Sjkim            bio->init = 0;
751280304Sjkim            assert(b->buf != NULL);
752280304Sjkim            b->len = 0;
753280304Sjkim            b->offset = 0;
754280304Sjkim        }
755280304Sjkim    }
756280304Sjkim}
757280304Sjkim
75855714Skris/* Exported convenience functions */
75955714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
760280304Sjkim                     BIO **bio2_p, size_t writebuf2)
761280304Sjkim{
762280304Sjkim    BIO *bio1 = NULL, *bio2 = NULL;
763280304Sjkim    long r;
764280304Sjkim    int ret = 0;
76555714Skris
766280304Sjkim    bio1 = BIO_new(BIO_s_bio());
767280304Sjkim    if (bio1 == NULL)
768280304Sjkim        goto err;
769280304Sjkim    bio2 = BIO_new(BIO_s_bio());
770280304Sjkim    if (bio2 == NULL)
771280304Sjkim        goto err;
77255714Skris
773280304Sjkim    if (writebuf1) {
774280304Sjkim        r = BIO_set_write_buf_size(bio1, writebuf1);
775280304Sjkim        if (!r)
776280304Sjkim            goto err;
777280304Sjkim    }
778280304Sjkim    if (writebuf2) {
779280304Sjkim        r = BIO_set_write_buf_size(bio2, writebuf2);
780280304Sjkim        if (!r)
781280304Sjkim            goto err;
782280304Sjkim    }
78355714Skris
784280304Sjkim    r = BIO_make_bio_pair(bio1, bio2);
785280304Sjkim    if (!r)
786280304Sjkim        goto err;
787280304Sjkim    ret = 1;
78855714Skris
78955714Skris err:
790280304Sjkim    if (ret == 0) {
791280304Sjkim        if (bio1) {
792280304Sjkim            BIO_free(bio1);
793280304Sjkim            bio1 = NULL;
794280304Sjkim        }
795280304Sjkim        if (bio2) {
796280304Sjkim            BIO_free(bio2);
797280304Sjkim            bio2 = NULL;
798280304Sjkim        }
799280304Sjkim    }
80055714Skris
801280304Sjkim    *bio1_p = bio1;
802280304Sjkim    *bio2_p = bio2;
803280304Sjkim    return ret;
804280304Sjkim}
80555714Skris
80655714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio)
807280304Sjkim{
808280304Sjkim    return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
809280304Sjkim}
81055714Skris
81155714Skrissize_t BIO_ctrl_get_read_request(BIO *bio)
812280304Sjkim{
813280304Sjkim    return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
814280304Sjkim}
81559191Skris
81659191Skrisint BIO_ctrl_reset_read_request(BIO *bio)
817280304Sjkim{
818280304Sjkim    return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
819280304Sjkim}
82059191Skris
821280304Sjkim/*
822280304Sjkim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
823280304Sjkim * (conceivably some other BIOs could allow non-copying reads and writes
824280304Sjkim * too.)
82559191Skris */
82659191Skrisint BIO_nread0(BIO *bio, char **buf)
827280304Sjkim{
828280304Sjkim    long ret;
82959191Skris
830280304Sjkim    if (!bio->init) {
831280304Sjkim        BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
832280304Sjkim        return -2;
833280304Sjkim    }
83459191Skris
835280304Sjkim    ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
836280304Sjkim    if (ret > INT_MAX)
837280304Sjkim        return INT_MAX;
838280304Sjkim    else
839280304Sjkim        return (int)ret;
840280304Sjkim}
84159191Skris
84259191Skrisint BIO_nread(BIO *bio, char **buf, int num)
843280304Sjkim{
844280304Sjkim    int ret;
84559191Skris
846280304Sjkim    if (!bio->init) {
847280304Sjkim        BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
848280304Sjkim        return -2;
849280304Sjkim    }
85059191Skris
851280304Sjkim    ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
852280304Sjkim    if (ret > 0)
853280304Sjkim        bio->num_read += ret;
854280304Sjkim    return ret;
855280304Sjkim}
85659191Skris
85759191Skrisint BIO_nwrite0(BIO *bio, char **buf)
858280304Sjkim{
859280304Sjkim    long ret;
86059191Skris
861280304Sjkim    if (!bio->init) {
862280304Sjkim        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
863280304Sjkim        return -2;
864280304Sjkim    }
86559191Skris
866280304Sjkim    ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
867280304Sjkim    if (ret > INT_MAX)
868280304Sjkim        return INT_MAX;
869280304Sjkim    else
870280304Sjkim        return (int)ret;
871280304Sjkim}
87259191Skris
87359191Skrisint BIO_nwrite(BIO *bio, char **buf, int num)
874280304Sjkim{
875280304Sjkim    int ret;
87659191Skris
877280304Sjkim    if (!bio->init) {
878280304Sjkim        BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
879280304Sjkim        return -2;
880280304Sjkim    }
88159191Skris
882280304Sjkim    ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
883280304Sjkim    if (ret > 0)
884280304Sjkim        bio->num_write += ret;
885280304Sjkim    return ret;
886280304Sjkim}
887