bss_bio.c revision 295009
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
147280297Sjkim    b = OPENSSL_malloc(sizeof *b);
148280297Sjkim    if (b == NULL)
149280297Sjkim        return 0;
15055714Skris
151280297Sjkim    b->peer = NULL;
152280297Sjkim    /* enough for one TLS record (just a default) */
153280297Sjkim    b->size = 17 * 1024;
154280297Sjkim    b->buf = NULL;
15555714Skris
156280297Sjkim    bio->ptr = b;
157280297Sjkim    return 1;
158280297Sjkim}
15955714Skris
16055714Skrisstatic int bio_free(BIO *bio)
161280297Sjkim{
162280297Sjkim    struct bio_bio_st *b;
16355714Skris
164280297Sjkim    if (bio == NULL)
165280297Sjkim        return 0;
166280297Sjkim    b = bio->ptr;
16755714Skris
168280297Sjkim    assert(b != NULL);
16955714Skris
170280297Sjkim    if (b->peer)
171280297Sjkim        bio_destroy_pair(bio);
17255714Skris
173280297Sjkim    if (b->buf != NULL) {
174280297Sjkim        OPENSSL_free(b->buf);
175280297Sjkim    }
17655714Skris
177280297Sjkim    OPENSSL_free(b);
17855714Skris
179280297Sjkim    return 1;
180280297Sjkim}
18155714Skris
18255714Skrisstatic int bio_read(BIO *bio, char *buf, int size_)
183280297Sjkim{
184280297Sjkim    size_t size = size_;
185280297Sjkim    size_t rest;
186280297Sjkim    struct bio_bio_st *b, *peer_b;
18755714Skris
188280297Sjkim    BIO_clear_retry_flags(bio);
18955714Skris
190280297Sjkim    if (!bio->init)
191280297Sjkim        return 0;
19255714Skris
193280297Sjkim    b = bio->ptr;
194280297Sjkim    assert(b != NULL);
195280297Sjkim    assert(b->peer != NULL);
196280297Sjkim    peer_b = b->peer->ptr;
197280297Sjkim    assert(peer_b != NULL);
198280297Sjkim    assert(peer_b->buf != NULL);
19955714Skris
200280297Sjkim    peer_b->request = 0;        /* will be set in "retry_read" situation */
20155714Skris
202280297Sjkim    if (buf == NULL || size == 0)
203280297Sjkim        return 0;
20455714Skris
205280297Sjkim    if (peer_b->len == 0) {
206280297Sjkim        if (peer_b->closed)
207280297Sjkim            return 0;           /* writer has closed, and no data is left */
208280297Sjkim        else {
209280297Sjkim            BIO_set_retry_read(bio); /* buffer is empty */
210280297Sjkim            if (size <= peer_b->size)
211280297Sjkim                peer_b->request = size;
212280297Sjkim            else
213280297Sjkim                /*
214280297Sjkim                 * don't ask for more than the peer can deliver in one write
215280297Sjkim                 */
216280297Sjkim                peer_b->request = peer_b->size;
217280297Sjkim            return -1;
218280297Sjkim        }
219280297Sjkim    }
22055714Skris
221280297Sjkim    /* we can read */
222280297Sjkim    if (peer_b->len < size)
223280297Sjkim        size = peer_b->len;
22455714Skris
225280297Sjkim    /* now read "size" bytes */
22655714Skris
227280297Sjkim    rest = size;
228280297Sjkim
229280297Sjkim    assert(rest > 0);
230280297Sjkim    do {                        /* one or two iterations */
231280297Sjkim        size_t chunk;
232280297Sjkim
233280297Sjkim        assert(rest <= peer_b->len);
234280297Sjkim        if (peer_b->offset + rest <= peer_b->size)
235280297Sjkim            chunk = rest;
236280297Sjkim        else
237280297Sjkim            /* wrap around ring buffer */
238280297Sjkim            chunk = peer_b->size - peer_b->offset;
239280297Sjkim        assert(peer_b->offset + chunk <= peer_b->size);
240280297Sjkim
241280297Sjkim        memcpy(buf, peer_b->buf + peer_b->offset, chunk);
242280297Sjkim
243280297Sjkim        peer_b->len -= chunk;
244280297Sjkim        if (peer_b->len) {
245280297Sjkim            peer_b->offset += chunk;
246280297Sjkim            assert(peer_b->offset <= peer_b->size);
247280297Sjkim            if (peer_b->offset == peer_b->size)
248280297Sjkim                peer_b->offset = 0;
249280297Sjkim            buf += chunk;
250280297Sjkim        } else {
251280297Sjkim            /* buffer now empty, no need to advance "buf" */
252280297Sjkim            assert(chunk == rest);
253280297Sjkim            peer_b->offset = 0;
254280297Sjkim        }
255280297Sjkim        rest -= chunk;
256280297Sjkim    }
257280297Sjkim    while (rest);
258280297Sjkim
259280297Sjkim    return size;
260280297Sjkim}
261280297Sjkim
262280297Sjkim/*-
263280297Sjkim * 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 */
269280297Sjkim/*
270280297Sjkim * WARNING: The non-copying interface is largely untested as of yet and may
271280297Sjkim * contain bugs.
272280297Sjkim */
273238405Sjkimstatic ossl_ssize_t bio_nread0(BIO *bio, char **buf)
274280297Sjkim{
275280297Sjkim    struct bio_bio_st *b, *peer_b;
276280297Sjkim    ossl_ssize_t num;
27759191Skris
278280297Sjkim    BIO_clear_retry_flags(bio);
27959191Skris
280280297Sjkim    if (!bio->init)
281280297Sjkim        return 0;
28259191Skris
283280297Sjkim    b = bio->ptr;
284280297Sjkim    assert(b != NULL);
285280297Sjkim    assert(b->peer != NULL);
286280297Sjkim    peer_b = b->peer->ptr;
287280297Sjkim    assert(peer_b != NULL);
288280297Sjkim    assert(peer_b->buf != NULL);
28959191Skris
290280297Sjkim    peer_b->request = 0;
291280297Sjkim
292280297Sjkim    if (peer_b->len == 0) {
293280297Sjkim        char dummy;
294280297Sjkim
295280297Sjkim        /* avoid code duplication -- nothing available for reading */
296280297Sjkim        return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
297280297Sjkim    }
298280297Sjkim
299280297Sjkim    num = peer_b->len;
300280297Sjkim    if (peer_b->size < peer_b->offset + num)
301280297Sjkim        /* no ring buffer wrap-around for non-copying interface */
302280297Sjkim        num = peer_b->size - peer_b->offset;
303280297Sjkim    assert(num > 0);
304280297Sjkim
305280297Sjkim    if (buf != NULL)
306280297Sjkim        *buf = peer_b->buf + peer_b->offset;
307280297Sjkim    return num;
308280297Sjkim}
309280297Sjkim
310238405Sjkimstatic ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_)
311280297Sjkim{
312280297Sjkim    struct bio_bio_st *b, *peer_b;
313280297Sjkim    ossl_ssize_t num, available;
31459191Skris
315280297Sjkim    if (num_ > SSIZE_MAX)
316280297Sjkim        num = SSIZE_MAX;
317280297Sjkim    else
318280297Sjkim        num = (ossl_ssize_t) num_;
31959191Skris
320280297Sjkim    available = bio_nread0(bio, buf);
321280297Sjkim    if (num > available)
322280297Sjkim        num = available;
323280297Sjkim    if (num <= 0)
324280297Sjkim        return num;
32559191Skris
326280297Sjkim    b = bio->ptr;
327280297Sjkim    peer_b = b->peer->ptr;
32859191Skris
329280297Sjkim    peer_b->len -= num;
330280297Sjkim    if (peer_b->len) {
331280297Sjkim        peer_b->offset += num;
332280297Sjkim        assert(peer_b->offset <= peer_b->size);
333280297Sjkim        if (peer_b->offset == peer_b->size)
334280297Sjkim            peer_b->offset = 0;
335280297Sjkim    } else
336280297Sjkim        peer_b->offset = 0;
33759191Skris
338280297Sjkim    return num;
339280297Sjkim}
34059191Skris
34168651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_)
342280297Sjkim{
343280297Sjkim    size_t num = num_;
344280297Sjkim    size_t rest;
345280297Sjkim    struct bio_bio_st *b;
34655714Skris
347280297Sjkim    BIO_clear_retry_flags(bio);
34855714Skris
349280297Sjkim    if (!bio->init || buf == NULL || num == 0)
350280297Sjkim        return 0;
35155714Skris
352280297Sjkim    b = bio->ptr;
353280297Sjkim    assert(b != NULL);
354280297Sjkim    assert(b->peer != NULL);
355280297Sjkim    assert(b->buf != NULL);
35655714Skris
357280297Sjkim    b->request = 0;
358280297Sjkim    if (b->closed) {
359280297Sjkim        /* we already closed */
360280297Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);
361280297Sjkim        return -1;
362280297Sjkim    }
36355714Skris
364280297Sjkim    assert(b->len <= b->size);
36555714Skris
366280297Sjkim    if (b->len == b->size) {
367280297Sjkim        BIO_set_retry_write(bio); /* buffer is full */
368280297Sjkim        return -1;
369280297Sjkim    }
37055714Skris
371280297Sjkim    /* we can write */
372280297Sjkim    if (num > b->size - b->len)
373280297Sjkim        num = b->size - b->len;
37455714Skris
375280297Sjkim    /* now write "num" bytes */
37655714Skris
377280297Sjkim    rest = num;
37855714Skris
379280297Sjkim    assert(rest > 0);
380280297Sjkim    do {                        /* one or two iterations */
381280297Sjkim        size_t write_offset;
382280297Sjkim        size_t chunk;
38355714Skris
384280297Sjkim        assert(b->len + rest <= b->size);
38555714Skris
386280297Sjkim        write_offset = b->offset + b->len;
387280297Sjkim        if (write_offset >= b->size)
388280297Sjkim            write_offset -= b->size;
389280297Sjkim        /* b->buf[write_offset] is the first byte we can write to. */
39055714Skris
391280297Sjkim        if (write_offset + rest <= b->size)
392280297Sjkim            chunk = rest;
393280297Sjkim        else
394280297Sjkim            /* wrap around ring buffer */
395280297Sjkim            chunk = b->size - write_offset;
39655714Skris
397280297Sjkim        memcpy(b->buf + write_offset, buf, chunk);
398280297Sjkim
399280297Sjkim        b->len += chunk;
400280297Sjkim
401280297Sjkim        assert(b->len <= b->size);
402280297Sjkim
403280297Sjkim        rest -= chunk;
404280297Sjkim        buf += chunk;
405280297Sjkim    }
406280297Sjkim    while (rest);
407280297Sjkim
408280297Sjkim    return num;
409280297Sjkim}
410280297Sjkim
411280297Sjkim/*-
412280297Sjkim * 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)
419280297Sjkim{
420280297Sjkim    struct bio_bio_st *b;
421280297Sjkim    size_t num;
422280297Sjkim    size_t write_offset;
42355714Skris
424280297Sjkim    BIO_clear_retry_flags(bio);
42559191Skris
426280297Sjkim    if (!bio->init)
427280297Sjkim        return 0;
42859191Skris
429280297Sjkim    b = bio->ptr;
430280297Sjkim    assert(b != NULL);
431280297Sjkim    assert(b->peer != NULL);
432280297Sjkim    assert(b->buf != NULL);
43359191Skris
434280297Sjkim    b->request = 0;
435280297Sjkim    if (b->closed) {
436280297Sjkim        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);
437280297Sjkim        return -1;
438280297Sjkim    }
43959191Skris
440280297Sjkim    assert(b->len <= b->size);
44159191Skris
442280297Sjkim    if (b->len == b->size) {
443280297Sjkim        BIO_set_retry_write(bio);
444280297Sjkim        return -1;
445280297Sjkim    }
44659191Skris
447280297Sjkim    num = b->size - b->len;
448280297Sjkim    write_offset = b->offset + b->len;
449280297Sjkim    if (write_offset >= b->size)
450280297Sjkim        write_offset -= b->size;
451280297Sjkim    if (write_offset + num > b->size)
452280297Sjkim        /*
453280297Sjkim         * no ring buffer wrap-around for non-copying interface (to fulfil
454280297Sjkim         * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have
455280297Sjkim         * to be called twice)
456280297Sjkim         */
457280297Sjkim        num = b->size - write_offset;
45859191Skris
459280297Sjkim    if (buf != NULL)
460280297Sjkim        *buf = b->buf + write_offset;
461280297Sjkim    assert(write_offset + num <= b->size);
46259191Skris
463280297Sjkim    return num;
464280297Sjkim}
46559191Skris
466238405Sjkimstatic ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_)
467280297Sjkim{
468280297Sjkim    struct bio_bio_st *b;
469280297Sjkim    ossl_ssize_t num, space;
47059191Skris
471280297Sjkim    if (num_ > SSIZE_MAX)
472280297Sjkim        num = SSIZE_MAX;
473280297Sjkim    else
474280297Sjkim        num = (ossl_ssize_t) num_;
47559191Skris
476280297Sjkim    space = bio_nwrite0(bio, buf);
477280297Sjkim    if (num > space)
478280297Sjkim        num = space;
479280297Sjkim    if (num <= 0)
480280297Sjkim        return num;
481280297Sjkim    b = bio->ptr;
482280297Sjkim    assert(b != NULL);
483280297Sjkim    b->len += num;
484280297Sjkim    assert(b->len <= b->size);
48559191Skris
486280297Sjkim    return num;
487280297Sjkim}
48859191Skris
48955714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
490280297Sjkim{
491280297Sjkim    long ret;
492280297Sjkim    struct bio_bio_st *b = bio->ptr;
49355714Skris
494280297Sjkim    assert(b != NULL);
49555714Skris
496280297Sjkim    switch (cmd) {
497280297Sjkim        /* specific CTRL codes */
49855714Skris
499280297Sjkim    case BIO_C_SET_WRITE_BUF_SIZE:
500280297Sjkim        if (b->peer) {
501280297Sjkim            BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
502280297Sjkim            ret = 0;
503280297Sjkim        } else if (num == 0) {
504280297Sjkim            BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
505280297Sjkim            ret = 0;
506280297Sjkim        } else {
507280297Sjkim            size_t new_size = num;
50855714Skris
509280297Sjkim            if (b->size != new_size) {
510280297Sjkim                if (b->buf) {
511280297Sjkim                    OPENSSL_free(b->buf);
512280297Sjkim                    b->buf = NULL;
513280297Sjkim                }
514280297Sjkim                b->size = new_size;
515280297Sjkim            }
516280297Sjkim            ret = 1;
517280297Sjkim        }
518280297Sjkim        break;
51955714Skris
520280297Sjkim    case BIO_C_GET_WRITE_BUF_SIZE:
521280297Sjkim        ret = (long)b->size;
522280297Sjkim        break;
52355714Skris
524280297Sjkim    case BIO_C_MAKE_BIO_PAIR:
525280297Sjkim        {
526280297Sjkim            BIO *other_bio = ptr;
52755714Skris
528280297Sjkim            if (bio_make_pair(bio, other_bio))
529280297Sjkim                ret = 1;
530280297Sjkim            else
531280297Sjkim                ret = 0;
532280297Sjkim        }
533280297Sjkim        break;
53455714Skris
535280297Sjkim    case BIO_C_DESTROY_BIO_PAIR:
536280297Sjkim        /*
537280297Sjkim         * Affects both BIOs in the pair -- call just once! Or let
538280297Sjkim         * BIO_free(bio1); BIO_free(bio2); do the job.
539280297Sjkim         */
540280297Sjkim        bio_destroy_pair(bio);
541280297Sjkim        ret = 1;
542280297Sjkim        break;
54359191Skris
544280297Sjkim    case BIO_C_GET_WRITE_GUARANTEE:
545280297Sjkim        /*
546280297Sjkim         * How many bytes can the caller feed to the next write without
547280297Sjkim         * having to keep any?
548280297Sjkim         */
549280297Sjkim        if (b->peer == NULL || b->closed)
550280297Sjkim            ret = 0;
551280297Sjkim        else
552280297Sjkim            ret = (long)b->size - b->len;
553280297Sjkim        break;
55455714Skris
555280297Sjkim    case BIO_C_GET_READ_REQUEST:
556280297Sjkim        /*
557280297Sjkim         * If the peer unsuccessfully tried to read, how many bytes were
558280297Sjkim         * requested? (As with BIO_CTRL_PENDING, that number can usually be
559280297Sjkim         * treated as boolean.)
560280297Sjkim         */
561280297Sjkim        ret = (long)b->request;
562280297Sjkim        break;
56355714Skris
564280297Sjkim    case BIO_C_RESET_READ_REQUEST:
565280297Sjkim        /*
566280297Sjkim         * Reset request.  (Can be useful after read attempts at the other
567280297Sjkim         * side that are meant to be non-blocking, e.g. when probing SSL_read
568280297Sjkim         * to see if any data is available.)
569280297Sjkim         */
570280297Sjkim        b->request = 0;
571280297Sjkim        ret = 1;
572280297Sjkim        break;
57359191Skris
574280297Sjkim    case BIO_C_SHUTDOWN_WR:
575280297Sjkim        /* similar to shutdown(..., SHUT_WR) */
576280297Sjkim        b->closed = 1;
577280297Sjkim        ret = 1;
578280297Sjkim        break;
57955714Skris
580280297Sjkim    case BIO_C_NREAD0:
581280297Sjkim        /* prepare for non-copying read */
582280297Sjkim        ret = (long)bio_nread0(bio, ptr);
583280297Sjkim        break;
58455714Skris
585280297Sjkim    case BIO_C_NREAD:
586280297Sjkim        /* non-copying read */
587280297Sjkim        ret = (long)bio_nread(bio, ptr, (size_t)num);
588280297Sjkim        break;
58955714Skris
590280297Sjkim    case BIO_C_NWRITE0:
591280297Sjkim        /* prepare for non-copying write */
592280297Sjkim        ret = (long)bio_nwrite0(bio, ptr);
593280297Sjkim        break;
59455714Skris
595280297Sjkim    case BIO_C_NWRITE:
596280297Sjkim        /* non-copying write */
597280297Sjkim        ret = (long)bio_nwrite(bio, ptr, (size_t)num);
598280297Sjkim        break;
59955714Skris
600280297Sjkim        /* standard CTRL codes follow */
60155714Skris
602280297Sjkim    case BIO_CTRL_RESET:
603280297Sjkim        if (b->buf != NULL) {
604280297Sjkim            b->len = 0;
605280297Sjkim            b->offset = 0;
606280297Sjkim        }
607280297Sjkim        ret = 0;
608280297Sjkim        break;
60955714Skris
610280297Sjkim    case BIO_CTRL_GET_CLOSE:
611280297Sjkim        ret = bio->shutdown;
612280297Sjkim        break;
61355714Skris
614280297Sjkim    case BIO_CTRL_SET_CLOSE:
615280297Sjkim        bio->shutdown = (int)num;
616280297Sjkim        ret = 1;
617280297Sjkim        break;
61855714Skris
619280297Sjkim    case BIO_CTRL_PENDING:
620280297Sjkim        if (b->peer != NULL) {
621280297Sjkim            struct bio_bio_st *peer_b = b->peer->ptr;
62255714Skris
623280297Sjkim            ret = (long)peer_b->len;
624280297Sjkim        } else
625280297Sjkim            ret = 0;
626280297Sjkim        break;
62755714Skris
628280297Sjkim    case BIO_CTRL_WPENDING:
629280297Sjkim        if (b->buf != NULL)
630280297Sjkim            ret = (long)b->len;
631280297Sjkim        else
632280297Sjkim            ret = 0;
633280297Sjkim        break;
63455714Skris
635280297Sjkim    case BIO_CTRL_DUP:
636280297Sjkim        /* See BIO_dup_chain for circumstances we have to expect. */
637280297Sjkim        {
638280297Sjkim            BIO *other_bio = ptr;
639280297Sjkim            struct bio_bio_st *other_b;
640280297Sjkim
641280297Sjkim            assert(other_bio != NULL);
642280297Sjkim            other_b = other_bio->ptr;
643280297Sjkim            assert(other_b != NULL);
644280297Sjkim
645280297Sjkim            assert(other_b->buf == NULL); /* other_bio is always fresh */
646280297Sjkim
647280297Sjkim            other_b->size = b->size;
648280297Sjkim        }
649280297Sjkim
650280297Sjkim        ret = 1;
651280297Sjkim        break;
652280297Sjkim
653280297Sjkim    case BIO_CTRL_FLUSH:
654280297Sjkim        ret = 1;
655280297Sjkim        break;
656280297Sjkim
657280297Sjkim    case BIO_CTRL_EOF:
658280297Sjkim        {
659280297Sjkim            BIO *other_bio = ptr;
660280297Sjkim
661280297Sjkim            if (other_bio) {
662280297Sjkim                struct bio_bio_st *other_b = other_bio->ptr;
663280297Sjkim
664280297Sjkim                assert(other_b != NULL);
665280297Sjkim                ret = other_b->len == 0 && other_b->closed;
666280297Sjkim            } else
667280297Sjkim                ret = 1;
668280297Sjkim        }
669280297Sjkim        break;
670280297Sjkim
671280297Sjkim    default:
672280297Sjkim        ret = 0;
673280297Sjkim    }
674280297Sjkim    return ret;
675280297Sjkim}
676280297Sjkim
67768651Skrisstatic int bio_puts(BIO *bio, const char *str)
678280297Sjkim{
679280297Sjkim    return bio_write(bio, str, strlen(str));
680280297Sjkim}
68155714Skris
68255714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2)
683280297Sjkim{
684280297Sjkim    struct bio_bio_st *b1, *b2;
68555714Skris
686280297Sjkim    assert(bio1 != NULL);
687280297Sjkim    assert(bio2 != NULL);
68855714Skris
689280297Sjkim    b1 = bio1->ptr;
690280297Sjkim    b2 = bio2->ptr;
69155714Skris
692280297Sjkim    if (b1->peer != NULL || b2->peer != NULL) {
693280297Sjkim        BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
694280297Sjkim        return 0;
695280297Sjkim    }
69655714Skris
697280297Sjkim    if (b1->buf == NULL) {
698280297Sjkim        b1->buf = OPENSSL_malloc(b1->size);
699280297Sjkim        if (b1->buf == NULL) {
700280297Sjkim            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
701280297Sjkim            return 0;
702280297Sjkim        }
703280297Sjkim        b1->len = 0;
704280297Sjkim        b1->offset = 0;
705280297Sjkim    }
70655714Skris
707280297Sjkim    if (b2->buf == NULL) {
708280297Sjkim        b2->buf = OPENSSL_malloc(b2->size);
709280297Sjkim        if (b2->buf == NULL) {
710280297Sjkim            BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
711280297Sjkim            return 0;
712280297Sjkim        }
713280297Sjkim        b2->len = 0;
714280297Sjkim        b2->offset = 0;
715280297Sjkim    }
716280297Sjkim
717280297Sjkim    b1->peer = bio2;
718280297Sjkim    b1->closed = 0;
719280297Sjkim    b1->request = 0;
720280297Sjkim    b2->peer = bio1;
721280297Sjkim    b2->closed = 0;
722280297Sjkim    b2->request = 0;
723280297Sjkim
724280297Sjkim    bio1->init = 1;
725280297Sjkim    bio2->init = 1;
726280297Sjkim
727280297Sjkim    return 1;
728280297Sjkim}
729280297Sjkim
73055714Skrisstatic void bio_destroy_pair(BIO *bio)
731280297Sjkim{
732280297Sjkim    struct bio_bio_st *b = bio->ptr;
73355714Skris
734280297Sjkim    if (b != NULL) {
735280297Sjkim        BIO *peer_bio = b->peer;
73655714Skris
737280297Sjkim        if (peer_bio != NULL) {
738280297Sjkim            struct bio_bio_st *peer_b = peer_bio->ptr;
73955714Skris
740280297Sjkim            assert(peer_b != NULL);
741280297Sjkim            assert(peer_b->peer == bio);
74255714Skris
743280297Sjkim            peer_b->peer = NULL;
744280297Sjkim            peer_bio->init = 0;
745280297Sjkim            assert(peer_b->buf != NULL);
746280297Sjkim            peer_b->len = 0;
747280297Sjkim            peer_b->offset = 0;
74855714Skris
749280297Sjkim            b->peer = NULL;
750280297Sjkim            bio->init = 0;
751280297Sjkim            assert(b->buf != NULL);
752280297Sjkim            b->len = 0;
753280297Sjkim            b->offset = 0;
754280297Sjkim        }
755280297Sjkim    }
756280297Sjkim}
757280297Sjkim
75855714Skris/* Exported convenience functions */
75955714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
760280297Sjkim                     BIO **bio2_p, size_t writebuf2)
761280297Sjkim{
762280297Sjkim    BIO *bio1 = NULL, *bio2 = NULL;
763280297Sjkim    long r;
764280297Sjkim    int ret = 0;
76555714Skris
766280297Sjkim    bio1 = BIO_new(BIO_s_bio());
767280297Sjkim    if (bio1 == NULL)
768280297Sjkim        goto err;
769280297Sjkim    bio2 = BIO_new(BIO_s_bio());
770280297Sjkim    if (bio2 == NULL)
771280297Sjkim        goto err;
77255714Skris
773280297Sjkim    if (writebuf1) {
774280297Sjkim        r = BIO_set_write_buf_size(bio1, writebuf1);
775280297Sjkim        if (!r)
776280297Sjkim            goto err;
777280297Sjkim    }
778280297Sjkim    if (writebuf2) {
779280297Sjkim        r = BIO_set_write_buf_size(bio2, writebuf2);
780280297Sjkim        if (!r)
781280297Sjkim            goto err;
782280297Sjkim    }
78355714Skris
784280297Sjkim    r = BIO_make_bio_pair(bio1, bio2);
785280297Sjkim    if (!r)
786280297Sjkim        goto err;
787280297Sjkim    ret = 1;
78855714Skris
78955714Skris err:
790280297Sjkim    if (ret == 0) {
791280297Sjkim        if (bio1) {
792280297Sjkim            BIO_free(bio1);
793280297Sjkim            bio1 = NULL;
794280297Sjkim        }
795280297Sjkim        if (bio2) {
796280297Sjkim            BIO_free(bio2);
797280297Sjkim            bio2 = NULL;
798280297Sjkim        }
799280297Sjkim    }
80055714Skris
801280297Sjkim    *bio1_p = bio1;
802280297Sjkim    *bio2_p = bio2;
803280297Sjkim    return ret;
804280297Sjkim}
80555714Skris
80655714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio)
807280297Sjkim{
808280297Sjkim    return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
809280297Sjkim}
81055714Skris
81155714Skrissize_t BIO_ctrl_get_read_request(BIO *bio)
812280297Sjkim{
813280297Sjkim    return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
814280297Sjkim}
81559191Skris
81659191Skrisint BIO_ctrl_reset_read_request(BIO *bio)
817280297Sjkim{
818280297Sjkim    return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
819280297Sjkim}
82059191Skris
821280297Sjkim/*
822280297Sjkim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
823280297Sjkim * (conceivably some other BIOs could allow non-copying reads and writes
824280297Sjkim * too.)
82559191Skris */
82659191Skrisint BIO_nread0(BIO *bio, char **buf)
827280297Sjkim{
828280297Sjkim    long ret;
82959191Skris
830280297Sjkim    if (!bio->init) {
831280297Sjkim        BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
832280297Sjkim        return -2;
833280297Sjkim    }
83459191Skris
835280297Sjkim    ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
836280297Sjkim    if (ret > INT_MAX)
837280297Sjkim        return INT_MAX;
838280297Sjkim    else
839280297Sjkim        return (int)ret;
840280297Sjkim}
84159191Skris
84259191Skrisint BIO_nread(BIO *bio, char **buf, int num)
843280297Sjkim{
844280297Sjkim    int ret;
84559191Skris
846280297Sjkim    if (!bio->init) {
847280297Sjkim        BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
848280297Sjkim        return -2;
849280297Sjkim    }
85059191Skris
851280297Sjkim    ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
852280297Sjkim    if (ret > 0)
853280297Sjkim        bio->num_read += ret;
854280297Sjkim    return ret;
855280297Sjkim}
85659191Skris
85759191Skrisint BIO_nwrite0(BIO *bio, char **buf)
858280297Sjkim{
859280297Sjkim    long ret;
86059191Skris
861280297Sjkim    if (!bio->init) {
862280297Sjkim        BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
863280297Sjkim        return -2;
864280297Sjkim    }
86559191Skris
866280297Sjkim    ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
867280297Sjkim    if (ret > INT_MAX)
868280297Sjkim        return INT_MAX;
869280297Sjkim    else
870280297Sjkim        return (int)ret;
871280297Sjkim}
87259191Skris
87359191Skrisint BIO_nwrite(BIO *bio, char **buf, int num)
874280297Sjkim{
875280297Sjkim    int ret;
87659191Skris
877280297Sjkim    if (!bio->init) {
878280297Sjkim        BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
879280297Sjkim        return -2;
880280297Sjkim    }
88159191Skris
882280297Sjkim    ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
883280297Sjkim    if (ret > 0)
884280297Sjkim        bio->num_write += ret;
885280297Sjkim    return ret;
886280297Sjkim}
887