1295009Sjkim/* 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
10280297Sjkim *    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
56280297Sjkim/*
57280297Sjkim * Special method for a BIO where the other endpoint is also a BIO of this
58280297Sjkim * kind, handled by the same thread (i.e. the "peer" is actually ourselves,
59280297Sjkim * wearing a different hat). Such "BIO pairs" are mainly for using the SSL
60280297Sjkim * library with I/O interfaces for which no specific BIO method is available.
61280297Sjkim * See ssl/ssltest.c for some hints on how this can be used.
62280297Sjkim */
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
107280297Sjkimstatic BIO_METHOD methods_biop = {
108280297Sjkim    BIO_TYPE_BIO,
109280297Sjkim    "BIO pair",
110280297Sjkim    bio_write,
111280297Sjkim    bio_read,
112280297Sjkim    bio_puts,
113280297Sjkim    NULL /* no bio_gets */ ,
114280297Sjkim    bio_ctrl,
115280297Sjkim    bio_new,
116280297Sjkim    bio_free,
117280297Sjkim    NULL                        /* no bio_callback_ctrl */
11855714Skris};
11955714Skris
12055714SkrisBIO_METHOD *BIO_s_bio(void)
12155714Skris{
122280297Sjkim    return &methods_biop;
123280297Sjkim}
12455714Skris
125280297Sjkimstruct bio_bio_st {
126280297Sjkim    BIO *peer;                  /* NULL if buf == NULL. If peer != NULL, then
127280297Sjkim                                 * peer->ptr is also a bio_bio_st, and its
128280297Sjkim                                 * "peer" member points back to us. peer !=
129280297Sjkim                                 * NULL iff init != 0 in the BIO. */
130280297Sjkim    /* This is for what we write (i.e. reading uses peer's struct): */
131280297Sjkim    int closed;                 /* valid iff peer != NULL */
132280297Sjkim    size_t len;                 /* valid iff buf != NULL; 0 if peer == NULL */
133280297Sjkim    size_t offset;              /* valid iff buf != NULL; 0 if len == 0 */
134280297Sjkim    size_t size;
135280297Sjkim    char *buf;                  /* "size" elements (if != NULL) */
136280297Sjkim    size_t request;             /* valid iff peer != NULL; 0 if len != 0,
137280297Sjkim                                 * otherwise set by peer to number of bytes
138280297Sjkim                                 * it (unsuccessfully) tried to read, never
139280297Sjkim                                 * more than buffer space (size-len)
140280297Sjkim                                 * warrants. */
14155714Skris};
14255714Skris
14355714Skrisstatic int bio_new(BIO *bio)
144280297Sjkim{
145280297Sjkim    struct bio_bio_st *b;
14655714Skris
147331638Sjkim    b = OPENSSL_malloc(sizeof(*b));
148280297Sjkim    if (b == NULL)
149280297Sjkim        return 0;
15055714Skris
151280297Sjkim    b->peer = NULL;
152306195Sjkim    b->closed = 0;
153306195Sjkim    b->len = 0;
154306195Sjkim    b->offset = 0;
155280297Sjkim    /* enough for one TLS record (just a default) */
156280297Sjkim    b->size = 17 * 1024;
157280297Sjkim    b->buf = NULL;
158306195Sjkim    b->request = 0;
15955714Skris
160280297Sjkim    bio->ptr = b;
161280297Sjkim    return 1;
162280297Sjkim}
16355714Skris
16455714Skrisstatic int bio_free(BIO *bio)
165280297Sjkim{
166280297Sjkim    struct bio_bio_st *b;
16755714Skris
168280297Sjkim    if (bio == NULL)
169280297Sjkim        return 0;
170280297Sjkim    b = bio->ptr;
17155714Skris
172280297Sjkim    assert(b != NULL);
17355714Skris
174280297Sjkim    if (b->peer)
175280297Sjkim        bio_destroy_pair(bio);
17655714Skris
177280297Sjkim    if (b->buf != NULL) {
178280297Sjkim        OPENSSL_free(b->buf);
179280297Sjkim    }
18055714Skris
181280297Sjkim    OPENSSL_free(b);
18255714Skris
183280297Sjkim    return 1;
184280297Sjkim}
18555714Skris
18655714Skrisstatic int bio_read(BIO *bio, char *buf, int size_)
187280297Sjkim{
188280297Sjkim    size_t size = size_;
189280297Sjkim    size_t rest;
190280297Sjkim    struct bio_bio_st *b, *peer_b;
19155714Skris
192280297Sjkim    BIO_clear_retry_flags(bio);
19355714Skris
194280297Sjkim    if (!bio->init)
195280297Sjkim        return 0;
19655714Skris
197280297Sjkim    b = bio->ptr;
198280297Sjkim    assert(b != NULL);
199280297Sjkim    assert(b->peer != NULL);
200280297Sjkim    peer_b = b->peer->ptr;
201280297Sjkim    assert(peer_b != NULL);
202280297Sjkim    assert(peer_b->buf != NULL);
20355714Skris
204280297Sjkim    peer_b->request = 0;        /* will be set in "retry_read" situation */
20555714Skris
206280297Sjkim    if (buf == NULL || size == 0)
207280297Sjkim        return 0;
20855714Skris
209280297Sjkim    if (peer_b->len == 0) {
210280297Sjkim        if (peer_b->closed)
211280297Sjkim            return 0;           /* writer has closed, and no data is left */
212280297Sjkim        else {
213280297Sjkim            BIO_set_retry_read(bio); /* buffer is empty */
214280297Sjkim            if (size <= peer_b->size)
215280297Sjkim                peer_b->request = size;
216280297Sjkim            else
217280297Sjkim                /*
218280297Sjkim                 * don't ask for more than the peer can deliver in one write
219280297Sjkim                 */
220280297Sjkim                peer_b->request = peer_b->size;
221280297Sjkim            return -1;
222280297Sjkim        }
223280297Sjkim    }
22455714Skris
225280297Sjkim    /* we can read */
226280297Sjkim    if (peer_b->len < size)
227280297Sjkim        size = peer_b->len;
22855714Skris
229280297Sjkim    /* now read "size" bytes */
23055714Skris
231280297Sjkim    rest = size;
232280297Sjkim
233280297Sjkim    assert(rest > 0);
234280297Sjkim    do {                        /* one or two iterations */
235280297Sjkim        size_t chunk;
236280297Sjkim
237280297Sjkim        assert(rest <= peer_b->len);
238280297Sjkim        if (peer_b->offset + rest <= peer_b->size)
239280297Sjkim            chunk = rest;
240280297Sjkim        else
241280297Sjkim            /* wrap around ring buffer */
242280297Sjkim            chunk = peer_b->size - peer_b->offset;
243280297Sjkim        assert(peer_b->offset + chunk <= peer_b->size);
244280297Sjkim
245280297Sjkim        memcpy(buf, peer_b->buf + peer_b->offset, chunk);
246280297Sjkim
247280297Sjkim        peer_b->len -= chunk;
248280297Sjkim        if (peer_b->len) {
249280297Sjkim            peer_b->offset += chunk;
250280297Sjkim            assert(peer_b->offset <= peer_b->size);
251280297Sjkim            if (peer_b->offset == peer_b->size)
252280297Sjkim                peer_b->offset = 0;
253280297Sjkim            buf += chunk;
254280297Sjkim        } else {
255280297Sjkim            /* buffer now empty, no need to advance "buf" */
256280297Sjkim            assert(chunk == rest);
257280297Sjkim            peer_b->offset = 0;
258280297Sjkim        }
259280297Sjkim        rest -= chunk;
260280297Sjkim    }
261280297Sjkim    while (rest);
262280297Sjkim
263280297Sjkim    return size;
264280297Sjkim}
265280297Sjkim
266280297Sjkim/*-
267280297Sjkim * non-copying interface: provide pointer to available data in buffer
26859191Skris *    bio_nread0:  return number of available bytes
26959191Skris *    bio_nread:   also advance index
27059191Skris * (example usage:  bio_nread0(), read from buffer, bio_nread()
27159191Skris *  or just         bio_nread(), read from buffer)
27259191Skris */
273280297Sjkim/*
274280297Sjkim * WARNING: The non-copying interface is largely untested as of yet and may
275280297Sjkim * contain bugs.
276280297Sjkim */
277238405Sjkimstatic ossl_ssize_t bio_nread0(BIO *bio, char **buf)
278280297Sjkim{
279280297Sjkim    struct bio_bio_st *b, *peer_b;
280280297Sjkim    ossl_ssize_t num;
28159191Skris
282280297Sjkim    BIO_clear_retry_flags(bio);
28359191Skris
284280297Sjkim    if (!bio->init)
285280297Sjkim        return 0;
28659191Skris
287280297Sjkim    b = bio->ptr;
288280297Sjkim    assert(b != NULL);
289280297Sjkim    assert(b->peer != NULL);
290280297Sjkim    peer_b = b->peer->ptr;
291280297Sjkim    assert(peer_b != NULL);
292280297Sjkim    assert(peer_b->buf != NULL);
29359191Skris
294280297Sjkim    peer_b->request = 0;
295280297Sjkim
296280297Sjkim    if (peer_b->len == 0) {
297280297Sjkim        char dummy;
298280297Sjkim
299280297Sjkim        /* avoid code duplication -- nothing available for reading */
300280297Sjkim        return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
301280297Sjkim    }
302280297Sjkim
303280297Sjkim    num = peer_b->len;
304280297Sjkim    if (peer_b->size < peer_b->offset + num)
305280297Sjkim        /* no ring buffer wrap-around for non-copying interface */
306280297Sjkim        num = peer_b->size - peer_b->offset;
307280297Sjkim    assert(num > 0);
308280297Sjkim
309280297Sjkim    if (buf != NULL)
310280297Sjkim        *buf = peer_b->buf + peer_b->offset;
311280297Sjkim    return num;
312280297Sjkim}
313280297Sjkim
314238405Sjkimstatic ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_)
315280297Sjkim{
316280297Sjkim    struct bio_bio_st *b, *peer_b;
317280297Sjkim    ossl_ssize_t num, available;
31859191Skris
319280297Sjkim    if (num_ > SSIZE_MAX)
320280297Sjkim        num = SSIZE_MAX;
321280297Sjkim    else
322280297Sjkim        num = (ossl_ssize_t) num_;
32359191Skris
324280297Sjkim    available = bio_nread0(bio, buf);
325280297Sjkim    if (num > available)
326280297Sjkim        num = available;
327280297Sjkim    if (num <= 0)
328280297Sjkim        return num;
32959191Skris
330280297Sjkim    b = bio->ptr;
331280297Sjkim    peer_b = b->peer->ptr;
33259191Skris
333280297Sjkim    peer_b->len -= num;
334280297Sjkim    if (peer_b->len) {
335280297Sjkim        peer_b->offset += num;
336280297Sjkim        assert(peer_b->offset <= peer_b->size);
337280297Sjkim        if (peer_b->offset == peer_b->size)
338280297Sjkim            peer_b->offset = 0;
339280297Sjkim    } else
340280297Sjkim        peer_b->offset = 0;
34159191Skris
342280297Sjkim    return num;
343280297Sjkim}
34459191Skris
34568651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_)
346280297Sjkim{
347280297Sjkim    size_t num = num_;
348280297Sjkim    size_t rest;
349280297Sjkim    struct bio_bio_st *b;
35055714Skris
351280297Sjkim    BIO_clear_retry_flags(bio);
35255714Skris
353280297Sjkim    if (!bio->init || buf == NULL || num == 0)
354280297Sjkim        return 0;
35555714Skris
356280297Sjkim    b = bio->ptr;
357280297Sjkim    assert(b != NULL);
358280297Sjkim    assert(b->peer != NULL);
359280297Sjkim    assert(b->buf != NULL);
36055714Skris
361280297Sjkim    b->request = 0;
362280297Sjkim    if (b->closed) {
363280297Sjkim        /* we already closed */
364280297Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);
365280297Sjkim        return -1;
366280297Sjkim    }
36755714Skris
368280297Sjkim    assert(b->len <= b->size);
36955714Skris
370280297Sjkim    if (b->len == b->size) {
371280297Sjkim        BIO_set_retry_write(bio); /* buffer is full */
372280297Sjkim        return -1;
373280297Sjkim    }
37455714Skris
375280297Sjkim    /* we can write */
376280297Sjkim    if (num > b->size - b->len)
377280297Sjkim        num = b->size - b->len;
37855714Skris
379280297Sjkim    /* now write "num" bytes */
38055714Skris
381280297Sjkim    rest = num;
38255714Skris
383280297Sjkim    assert(rest > 0);
384280297Sjkim    do {                        /* one or two iterations */
385280297Sjkim        size_t write_offset;
386280297Sjkim        size_t chunk;
38755714Skris
388280297Sjkim        assert(b->len + rest <= b->size);
38955714Skris
390280297Sjkim        write_offset = b->offset + b->len;
391280297Sjkim        if (write_offset >= b->size)
392280297Sjkim            write_offset -= b->size;
393280297Sjkim        /* b->buf[write_offset] is the first byte we can write to. */
39455714Skris
395280297Sjkim        if (write_offset + rest <= b->size)
396280297Sjkim            chunk = rest;
397280297Sjkim        else
398280297Sjkim            /* wrap around ring buffer */
399280297Sjkim            chunk = b->size - write_offset;
40055714Skris
401280297Sjkim        memcpy(b->buf + write_offset, buf, chunk);
402280297Sjkim
403280297Sjkim        b->len += chunk;
404280297Sjkim
405280297Sjkim        assert(b->len <= b->size);
406280297Sjkim
407280297Sjkim        rest -= chunk;
408280297Sjkim        buf += chunk;
409280297Sjkim    }
410280297Sjkim    while (rest);
411280297Sjkim
412280297Sjkim    return num;
413280297Sjkim}
414280297Sjkim
415280297Sjkim/*-
416280297Sjkim * non-copying interface: provide pointer to region to write to
41759191Skris *   bio_nwrite0:  check how much space is available
41859191Skris *   bio_nwrite:   also increase length
41959191Skris * (example usage:  bio_nwrite0(), write to buffer, bio_nwrite()
42059191Skris *  or just         bio_nwrite(), write to buffer)
42159191Skris */
422238405Sjkimstatic ossl_ssize_t bio_nwrite0(BIO *bio, char **buf)
423280297Sjkim{
424280297Sjkim    struct bio_bio_st *b;
425280297Sjkim    size_t num;
426280297Sjkim    size_t write_offset;
42755714Skris
428280297Sjkim    BIO_clear_retry_flags(bio);
42959191Skris
430280297Sjkim    if (!bio->init)
431280297Sjkim        return 0;
43259191Skris
433280297Sjkim    b = bio->ptr;
434280297Sjkim    assert(b != NULL);
435280297Sjkim    assert(b->peer != NULL);
436280297Sjkim    assert(b->buf != NULL);
43759191Skris
438280297Sjkim    b->request = 0;
439280297Sjkim    if (b->closed) {
440280297Sjkim        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);
441280297Sjkim        return -1;
442280297Sjkim    }
44359191Skris
444280297Sjkim    assert(b->len <= b->size);
44559191Skris
446280297Sjkim    if (b->len == b->size) {
447280297Sjkim        BIO_set_retry_write(bio);
448280297Sjkim        return -1;
449280297Sjkim    }
45059191Skris
451280297Sjkim    num = b->size - b->len;
452280297Sjkim    write_offset = b->offset + b->len;
453280297Sjkim    if (write_offset >= b->size)
454280297Sjkim        write_offset -= b->size;
455280297Sjkim    if (write_offset + num > b->size)
456280297Sjkim        /*
457280297Sjkim         * no ring buffer wrap-around for non-copying interface (to fulfil
458280297Sjkim         * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have
459280297Sjkim         * to be called twice)
460280297Sjkim         */
461280297Sjkim        num = b->size - write_offset;
46259191Skris
463280297Sjkim    if (buf != NULL)
464280297Sjkim        *buf = b->buf + write_offset;
465280297Sjkim    assert(write_offset + num <= b->size);
46659191Skris
467280297Sjkim    return num;
468280297Sjkim}
46959191Skris
470238405Sjkimstatic ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_)
471280297Sjkim{
472280297Sjkim    struct bio_bio_st *b;
473280297Sjkim    ossl_ssize_t num, space;
47459191Skris
475280297Sjkim    if (num_ > SSIZE_MAX)
476280297Sjkim        num = SSIZE_MAX;
477280297Sjkim    else
478280297Sjkim        num = (ossl_ssize_t) num_;
47959191Skris
480280297Sjkim    space = bio_nwrite0(bio, buf);
481280297Sjkim    if (num > space)
482280297Sjkim        num = space;
483280297Sjkim    if (num <= 0)
484280297Sjkim        return num;
485280297Sjkim    b = bio->ptr;
486280297Sjkim    assert(b != NULL);
487280297Sjkim    b->len += num;
488280297Sjkim    assert(b->len <= b->size);
48959191Skris
490280297Sjkim    return num;
491280297Sjkim}
49259191Skris
49355714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
494280297Sjkim{
495280297Sjkim    long ret;
496280297Sjkim    struct bio_bio_st *b = bio->ptr;
49755714Skris
498280297Sjkim    assert(b != NULL);
49955714Skris
500280297Sjkim    switch (cmd) {
501280297Sjkim        /* specific CTRL codes */
50255714Skris
503280297Sjkim    case BIO_C_SET_WRITE_BUF_SIZE:
504280297Sjkim        if (b->peer) {
505280297Sjkim            BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
506280297Sjkim            ret = 0;
507280297Sjkim        } else if (num == 0) {
508280297Sjkim            BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
509280297Sjkim            ret = 0;
510280297Sjkim        } else {
511280297Sjkim            size_t new_size = num;
51255714Skris
513280297Sjkim            if (b->size != new_size) {
514280297Sjkim                if (b->buf) {
515280297Sjkim                    OPENSSL_free(b->buf);
516280297Sjkim                    b->buf = NULL;
517280297Sjkim                }
518280297Sjkim                b->size = new_size;
519280297Sjkim            }
520280297Sjkim            ret = 1;
521280297Sjkim        }
522280297Sjkim        break;
52355714Skris
524280297Sjkim    case BIO_C_GET_WRITE_BUF_SIZE:
525280297Sjkim        ret = (long)b->size;
526280297Sjkim        break;
52755714Skris
528280297Sjkim    case BIO_C_MAKE_BIO_PAIR:
529280297Sjkim        {
530280297Sjkim            BIO *other_bio = ptr;
53155714Skris
532280297Sjkim            if (bio_make_pair(bio, other_bio))
533280297Sjkim                ret = 1;
534280297Sjkim            else
535280297Sjkim                ret = 0;
536280297Sjkim        }
537280297Sjkim        break;
53855714Skris
539280297Sjkim    case BIO_C_DESTROY_BIO_PAIR:
540280297Sjkim        /*
541280297Sjkim         * Affects both BIOs in the pair -- call just once! Or let
542280297Sjkim         * BIO_free(bio1); BIO_free(bio2); do the job.
543280297Sjkim         */
544280297Sjkim        bio_destroy_pair(bio);
545280297Sjkim        ret = 1;
546280297Sjkim        break;
54759191Skris
548280297Sjkim    case BIO_C_GET_WRITE_GUARANTEE:
549280297Sjkim        /*
550280297Sjkim         * How many bytes can the caller feed to the next write without
551280297Sjkim         * having to keep any?
552280297Sjkim         */
553280297Sjkim        if (b->peer == NULL || b->closed)
554280297Sjkim            ret = 0;
555280297Sjkim        else
556280297Sjkim            ret = (long)b->size - b->len;
557280297Sjkim        break;
55855714Skris
559280297Sjkim    case BIO_C_GET_READ_REQUEST:
560280297Sjkim        /*
561280297Sjkim         * If the peer unsuccessfully tried to read, how many bytes were
562280297Sjkim         * requested? (As with BIO_CTRL_PENDING, that number can usually be
563280297Sjkim         * treated as boolean.)
564280297Sjkim         */
565280297Sjkim        ret = (long)b->request;
566280297Sjkim        break;
56755714Skris
568280297Sjkim    case BIO_C_RESET_READ_REQUEST:
569280297Sjkim        /*
570280297Sjkim         * Reset request.  (Can be useful after read attempts at the other
571280297Sjkim         * side that are meant to be non-blocking, e.g. when probing SSL_read
572280297Sjkim         * to see if any data is available.)
573280297Sjkim         */
574280297Sjkim        b->request = 0;
575280297Sjkim        ret = 1;
576280297Sjkim        break;
57759191Skris
578280297Sjkim    case BIO_C_SHUTDOWN_WR:
579280297Sjkim        /* similar to shutdown(..., SHUT_WR) */
580280297Sjkim        b->closed = 1;
581280297Sjkim        ret = 1;
582280297Sjkim        break;
58355714Skris
584280297Sjkim    case BIO_C_NREAD0:
585280297Sjkim        /* prepare for non-copying read */
586280297Sjkim        ret = (long)bio_nread0(bio, ptr);
587280297Sjkim        break;
58855714Skris
589280297Sjkim    case BIO_C_NREAD:
590280297Sjkim        /* non-copying read */
591280297Sjkim        ret = (long)bio_nread(bio, ptr, (size_t)num);
592280297Sjkim        break;
59355714Skris
594280297Sjkim    case BIO_C_NWRITE0:
595280297Sjkim        /* prepare for non-copying write */
596280297Sjkim        ret = (long)bio_nwrite0(bio, ptr);
597280297Sjkim        break;
59855714Skris
599280297Sjkim    case BIO_C_NWRITE:
600280297Sjkim        /* non-copying write */
601280297Sjkim        ret = (long)bio_nwrite(bio, ptr, (size_t)num);
602280297Sjkim        break;
60355714Skris
604280297Sjkim        /* standard CTRL codes follow */
60555714Skris
606280297Sjkim    case BIO_CTRL_RESET:
607280297Sjkim        if (b->buf != NULL) {
608280297Sjkim            b->len = 0;
609280297Sjkim            b->offset = 0;
610280297Sjkim        }
611280297Sjkim        ret = 0;
612280297Sjkim        break;
61355714Skris
614280297Sjkim    case BIO_CTRL_GET_CLOSE:
615280297Sjkim        ret = bio->shutdown;
616280297Sjkim        break;
61755714Skris
618280297Sjkim    case BIO_CTRL_SET_CLOSE:
619280297Sjkim        bio->shutdown = (int)num;
620280297Sjkim        ret = 1;
621280297Sjkim        break;
62255714Skris
623280297Sjkim    case BIO_CTRL_PENDING:
624280297Sjkim        if (b->peer != NULL) {
625280297Sjkim            struct bio_bio_st *peer_b = b->peer->ptr;
62655714Skris
627280297Sjkim            ret = (long)peer_b->len;
628280297Sjkim        } else
629280297Sjkim            ret = 0;
630280297Sjkim        break;
63155714Skris
632280297Sjkim    case BIO_CTRL_WPENDING:
633280297Sjkim        if (b->buf != NULL)
634280297Sjkim            ret = (long)b->len;
635280297Sjkim        else
636280297Sjkim            ret = 0;
637280297Sjkim        break;
63855714Skris
639280297Sjkim    case BIO_CTRL_DUP:
640280297Sjkim        /* See BIO_dup_chain for circumstances we have to expect. */
641280297Sjkim        {
642280297Sjkim            BIO *other_bio = ptr;
643280297Sjkim            struct bio_bio_st *other_b;
644280297Sjkim
645280297Sjkim            assert(other_bio != NULL);
646280297Sjkim            other_b = other_bio->ptr;
647280297Sjkim            assert(other_b != NULL);
648280297Sjkim
649280297Sjkim            assert(other_b->buf == NULL); /* other_bio is always fresh */
650280297Sjkim
651280297Sjkim            other_b->size = b->size;
652280297Sjkim        }
653280297Sjkim
654280297Sjkim        ret = 1;
655280297Sjkim        break;
656280297Sjkim
657280297Sjkim    case BIO_CTRL_FLUSH:
658280297Sjkim        ret = 1;
659280297Sjkim        break;
660280297Sjkim
661280297Sjkim    case BIO_CTRL_EOF:
662306195Sjkim        if (b->peer != NULL) {
663306195Sjkim            struct bio_bio_st *peer_b = b->peer->ptr;
664280297Sjkim
665306195Sjkim            if (peer_b->len == 0 && peer_b->closed)
666280297Sjkim                ret = 1;
667306195Sjkim            else
668306195Sjkim                ret = 0;
669306195Sjkim        } else {
670306195Sjkim            ret = 1;
671280297Sjkim        }
672280297Sjkim        break;
673280297Sjkim
674280297Sjkim    default:
675280297Sjkim        ret = 0;
676280297Sjkim    }
677280297Sjkim    return ret;
678280297Sjkim}
679280297Sjkim
68068651Skrisstatic int bio_puts(BIO *bio, const char *str)
681280297Sjkim{
682280297Sjkim    return bio_write(bio, str, strlen(str));
683280297Sjkim}
68455714Skris
68555714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2)
686280297Sjkim{
687280297Sjkim    struct bio_bio_st *b1, *b2;
68855714Skris
689280297Sjkim    assert(bio1 != NULL);
690280297Sjkim    assert(bio2 != NULL);
69155714Skris
692280297Sjkim    b1 = bio1->ptr;
693280297Sjkim    b2 = bio2->ptr;
69455714Skris
695280297Sjkim    if (b1->peer != NULL || b2->peer != NULL) {
696280297Sjkim        BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
697280297Sjkim        return 0;
698280297Sjkim    }
69955714Skris
700280297Sjkim    if (b1->buf == NULL) {
701280297Sjkim        b1->buf = OPENSSL_malloc(b1->size);
702280297Sjkim        if (b1->buf == NULL) {
703280297Sjkim            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
704280297Sjkim            return 0;
705280297Sjkim        }
706280297Sjkim        b1->len = 0;
707280297Sjkim        b1->offset = 0;
708280297Sjkim    }
70955714Skris
710280297Sjkim    if (b2->buf == NULL) {
711280297Sjkim        b2->buf = OPENSSL_malloc(b2->size);
712280297Sjkim        if (b2->buf == NULL) {
713280297Sjkim            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
714280297Sjkim            return 0;
715280297Sjkim        }
716280297Sjkim        b2->len = 0;
717280297Sjkim        b2->offset = 0;
718280297Sjkim    }
719280297Sjkim
720280297Sjkim    b1->peer = bio2;
721280297Sjkim    b1->closed = 0;
722280297Sjkim    b1->request = 0;
723280297Sjkim    b2->peer = bio1;
724280297Sjkim    b2->closed = 0;
725280297Sjkim    b2->request = 0;
726280297Sjkim
727280297Sjkim    bio1->init = 1;
728280297Sjkim    bio2->init = 1;
729280297Sjkim
730280297Sjkim    return 1;
731280297Sjkim}
732280297Sjkim
73355714Skrisstatic void bio_destroy_pair(BIO *bio)
734280297Sjkim{
735280297Sjkim    struct bio_bio_st *b = bio->ptr;
73655714Skris
737280297Sjkim    if (b != NULL) {
738280297Sjkim        BIO *peer_bio = b->peer;
73955714Skris
740280297Sjkim        if (peer_bio != NULL) {
741280297Sjkim            struct bio_bio_st *peer_b = peer_bio->ptr;
74255714Skris
743280297Sjkim            assert(peer_b != NULL);
744280297Sjkim            assert(peer_b->peer == bio);
74555714Skris
746280297Sjkim            peer_b->peer = NULL;
747280297Sjkim            peer_bio->init = 0;
748280297Sjkim            assert(peer_b->buf != NULL);
749280297Sjkim            peer_b->len = 0;
750280297Sjkim            peer_b->offset = 0;
75155714Skris
752280297Sjkim            b->peer = NULL;
753280297Sjkim            bio->init = 0;
754280297Sjkim            assert(b->buf != NULL);
755280297Sjkim            b->len = 0;
756280297Sjkim            b->offset = 0;
757280297Sjkim        }
758280297Sjkim    }
759280297Sjkim}
760280297Sjkim
76155714Skris/* Exported convenience functions */
76255714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
763280297Sjkim                     BIO **bio2_p, size_t writebuf2)
764280297Sjkim{
765280297Sjkim    BIO *bio1 = NULL, *bio2 = NULL;
766280297Sjkim    long r;
767280297Sjkim    int ret = 0;
76855714Skris
769280297Sjkim    bio1 = BIO_new(BIO_s_bio());
770280297Sjkim    if (bio1 == NULL)
771280297Sjkim        goto err;
772280297Sjkim    bio2 = BIO_new(BIO_s_bio());
773280297Sjkim    if (bio2 == NULL)
774280297Sjkim        goto err;
77555714Skris
776280297Sjkim    if (writebuf1) {
777280297Sjkim        r = BIO_set_write_buf_size(bio1, writebuf1);
778280297Sjkim        if (!r)
779280297Sjkim            goto err;
780280297Sjkim    }
781280297Sjkim    if (writebuf2) {
782280297Sjkim        r = BIO_set_write_buf_size(bio2, writebuf2);
783280297Sjkim        if (!r)
784280297Sjkim            goto err;
785280297Sjkim    }
78655714Skris
787280297Sjkim    r = BIO_make_bio_pair(bio1, bio2);
788280297Sjkim    if (!r)
789280297Sjkim        goto err;
790280297Sjkim    ret = 1;
79155714Skris
79255714Skris err:
793280297Sjkim    if (ret == 0) {
794280297Sjkim        if (bio1) {
795280297Sjkim            BIO_free(bio1);
796280297Sjkim            bio1 = NULL;
797280297Sjkim        }
798280297Sjkim        if (bio2) {
799280297Sjkim            BIO_free(bio2);
800280297Sjkim            bio2 = NULL;
801280297Sjkim        }
802280297Sjkim    }
80355714Skris
804280297Sjkim    *bio1_p = bio1;
805280297Sjkim    *bio2_p = bio2;
806280297Sjkim    return ret;
807280297Sjkim}
80855714Skris
80955714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio)
810280297Sjkim{
811280297Sjkim    return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
812280297Sjkim}
81355714Skris
81455714Skrissize_t BIO_ctrl_get_read_request(BIO *bio)
815280297Sjkim{
816280297Sjkim    return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
817280297Sjkim}
81859191Skris
81959191Skrisint BIO_ctrl_reset_read_request(BIO *bio)
820280297Sjkim{
821280297Sjkim    return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
822280297Sjkim}
82359191Skris
824280297Sjkim/*
825280297Sjkim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
826280297Sjkim * (conceivably some other BIOs could allow non-copying reads and writes
827280297Sjkim * too.)
82859191Skris */
82959191Skrisint BIO_nread0(BIO *bio, char **buf)
830280297Sjkim{
831280297Sjkim    long ret;
83259191Skris
833280297Sjkim    if (!bio->init) {
834280297Sjkim        BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
835280297Sjkim        return -2;
836280297Sjkim    }
83759191Skris
838280297Sjkim    ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
839280297Sjkim    if (ret > INT_MAX)
840280297Sjkim        return INT_MAX;
841280297Sjkim    else
842280297Sjkim        return (int)ret;
843280297Sjkim}
84459191Skris
84559191Skrisint BIO_nread(BIO *bio, char **buf, int num)
846280297Sjkim{
847280297Sjkim    int ret;
84859191Skris
849280297Sjkim    if (!bio->init) {
850280297Sjkim        BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
851280297Sjkim        return -2;
852280297Sjkim    }
85359191Skris
854280297Sjkim    ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
855280297Sjkim    if (ret > 0)
856280297Sjkim        bio->num_read += ret;
857280297Sjkim    return ret;
858280297Sjkim}
85959191Skris
86059191Skrisint BIO_nwrite0(BIO *bio, char **buf)
861280297Sjkim{
862280297Sjkim    long ret;
86359191Skris
864280297Sjkim    if (!bio->init) {
865280297Sjkim        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
866280297Sjkim        return -2;
867280297Sjkim    }
86859191Skris
869280297Sjkim    ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
870280297Sjkim    if (ret > INT_MAX)
871280297Sjkim        return INT_MAX;
872280297Sjkim    else
873280297Sjkim        return (int)ret;
874280297Sjkim}
87559191Skris
87659191Skrisint BIO_nwrite(BIO *bio, char **buf, int num)
877280297Sjkim{
878280297Sjkim    int ret;
87959191Skris
880280297Sjkim    if (!bio->init) {
881280297Sjkim        BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
882280297Sjkim        return -2;
883280297Sjkim    }
88459191Skris
885280297Sjkim    ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
886280297Sjkim    if (ret > 0)
887280297Sjkim        bio->num_write += ret;
888280297Sjkim    return ret;
889280297Sjkim}
890