1/* ====================================================================
2 * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 *    software must display the following acknowledgment:
18 *    "This product includes software developed by the OpenSSL Project
19 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 *    endorse or promote products derived from this software without
23 *    prior written permission. For written permission, please contact
24 *    openssl-core@openssl.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 *    nor may "OpenSSL" appear in their names without prior written
28 *    permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 *    acknowledgment:
32 *    "This product includes software developed by the OpenSSL Project
33 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This product includes cryptographic software written by Eric Young
50 * (eay@cryptsoft.com).  This product includes software written by Tim
51 * Hudson (tjh@cryptsoft.com). */
52
53#include <openssl/bio.h>
54
55#include <assert.h>
56#include <string.h>
57
58#include <openssl/buf.h>
59#include <openssl/err.h>
60#include <openssl/mem.h>
61
62
63struct bio_bio_st {
64  BIO *peer; /* NULL if buf == NULL.
65              * If peer != NULL, then peer->ptr is also a bio_bio_st,
66              * and its "peer" member points back to us.
67              * peer != NULL iff init != 0 in the BIO. */
68
69  /* This is for what we write (i.e. reading uses peer's struct): */
70  int closed;    /* valid iff peer != NULL */
71  size_t len;    /* valid iff buf != NULL; 0 if peer == NULL */
72  size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
73  size_t size;
74  uint8_t *buf; /* "size" elements (if != NULL) */
75  char buf_externally_allocated; /* true iff buf was externally allocated. */
76
77  char zero_copy_read_lock;  /* true iff a zero copy read operation
78                              * is in progress. */
79  char zero_copy_write_lock; /* true iff a zero copy write operation
80                              * is in progress. */
81
82  size_t request; /* valid iff peer != NULL; 0 if len != 0,
83                   * otherwise set by peer to number of bytes
84                   * it (unsuccessfully) tried to read,
85                   * never more than buffer space (size-len) warrants. */
86};
87
88static int bio_new(BIO *bio) {
89  struct bio_bio_st *b;
90
91  b = OPENSSL_malloc(sizeof *b);
92  if (b == NULL) {
93    return 0;
94  }
95  memset(b, 0, sizeof(struct bio_bio_st));
96
97  b->size = 17 * 1024; /* enough for one TLS record (just a default) */
98  bio->ptr = b;
99  return 1;
100}
101
102static void bio_destroy_pair(BIO *bio) {
103  struct bio_bio_st *b = bio->ptr;
104  BIO *peer_bio;
105  struct bio_bio_st *peer_b;
106
107  if (b == NULL) {
108    return;
109  }
110
111  peer_bio = b->peer;
112  if (peer_bio == NULL) {
113    return;
114  }
115
116  peer_b = peer_bio->ptr;
117
118  assert(peer_b != NULL);
119  assert(peer_b->peer == bio);
120
121  peer_b->peer = NULL;
122  peer_bio->init = 0;
123  assert(peer_b->buf != NULL);
124  peer_b->len = 0;
125  peer_b->offset = 0;
126
127  b->peer = NULL;
128  bio->init = 0;
129  assert(b->buf != NULL);
130  b->len = 0;
131  b->offset = 0;
132}
133
134static int bio_free(BIO *bio) {
135  struct bio_bio_st *b;
136
137  if (bio == NULL) {
138    return 0;
139  }
140  b = bio->ptr;
141
142  assert(b != NULL);
143
144  if (b->peer) {
145    bio_destroy_pair(bio);
146  }
147
148  if (!b->buf_externally_allocated) {
149    OPENSSL_free(b->buf);
150  }
151
152  OPENSSL_free(b);
153
154  return 1;
155}
156
157static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
158                                         uint8_t** out_read_buf,
159                                         size_t* out_buf_offset) {
160  size_t max_available;
161  if (peer_b->len > peer_b->size - peer_b->offset) {
162    /* Only the first half of the ring buffer can be read. */
163    max_available = peer_b->size - peer_b->offset;
164  } else {
165    max_available = peer_b->len;
166  }
167
168  *out_read_buf = peer_b->buf;
169  *out_buf_offset = peer_b->offset;
170  return max_available;
171}
172
173int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
174                               size_t* out_buf_offset,
175                               size_t* out_available_bytes) {
176  struct bio_bio_st* b;
177  struct bio_bio_st* peer_b;
178  size_t max_available;
179  *out_available_bytes = 0;
180
181  BIO_clear_retry_flags(bio);
182
183  if (!bio->init) {
184    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
185    return 0;
186  }
187
188  b = bio->ptr;
189
190  if (!b || !b->peer) {
191    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
192    return 0;
193  }
194
195  peer_b = b->peer->ptr;
196  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
197    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
198    return 0;
199  }
200
201  if (peer_b->zero_copy_read_lock) {
202    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
203    return 0;
204  }
205
206  peer_b->request = 0;  /* Is not used by zero-copy API. */
207
208  max_available =
209      bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
210
211  assert(peer_b->buf != NULL);
212  if (max_available > 0) {
213    peer_b->zero_copy_read_lock = 1;
214  }
215
216  *out_available_bytes = max_available;
217  return 1;
218}
219
220int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
221  struct bio_bio_st* b;
222  struct bio_bio_st* peer_b;
223  size_t max_available;
224  size_t dummy_read_offset;
225  uint8_t* dummy_read_buf;
226
227  assert(BIO_get_retry_flags(bio) == 0);
228
229  if (!bio->init) {
230    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
231    return 0;
232  }
233
234  b = bio->ptr;
235
236  if (!b || !b->peer) {
237    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
238    return 0;
239  }
240
241  peer_b = b->peer->ptr;
242  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
243    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
244    return 0;
245  }
246
247  if (!peer_b->zero_copy_read_lock) {
248    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
249    return 0;
250  }
251
252  max_available =
253      bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
254  if (bytes_read > max_available) {
255    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
256    return 0;
257  }
258
259  assert(peer_b->len >= bytes_read);
260  peer_b->len -= bytes_read;
261  assert(peer_b->offset + bytes_read <= peer_b->size);
262
263  /* Move read offset. If zero_copy_write_lock == 1 we must advance the
264   * offset even if buffer becomes empty, to make sure
265   * write_offset = (offset + len) mod size does not change. */
266  if (peer_b->offset + bytes_read == peer_b->size ||
267      (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
268    peer_b->offset = 0;
269  } else {
270    peer_b->offset += bytes_read;
271  }
272
273  bio->num_read += bytes_read;
274  peer_b->zero_copy_read_lock = 0;
275  return 1;
276}
277
278static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
279                                          uint8_t** out_write_buf,
280                                          size_t* out_buf_offset) {
281  size_t write_offset;
282  size_t max_available;
283
284  assert(b->len <= b->size);
285
286  write_offset = b->offset + b->len;
287
288  if (write_offset >= b->size) {
289    /* Only the first half of the ring buffer can be written to. */
290    write_offset -= b->size;
291    /* write up to the start of the ring buffer. */
292    max_available = b->offset - write_offset;
293  } else {
294    /* write up to the end the buffer. */
295    max_available = b->size - write_offset;
296  }
297
298  *out_write_buf = b->buf;
299  *out_buf_offset = write_offset;
300  return max_available;
301}
302
303int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
304                                size_t* out_buf_offset,
305                                size_t* out_available_bytes) {
306  struct bio_bio_st* b;
307  struct bio_bio_st* peer_b;
308  size_t max_available;
309
310  *out_available_bytes = 0;
311  BIO_clear_retry_flags(bio);
312
313  if (!bio->init) {
314    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
315    return 0;
316  }
317
318  b = bio->ptr;
319
320  if (!b || !b->buf || !b->peer) {
321    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
322    return 0;
323  }
324  peer_b = b->peer->ptr;
325  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
326    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
327    return 0;
328  }
329
330  assert(b->buf != NULL);
331
332  if (b->zero_copy_write_lock) {
333    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
334    return 0;
335  }
336
337  b->request = 0;
338  if (b->closed) {
339    /* Bio is already closed. */
340    OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
341    return 0;
342  }
343
344  max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
345
346  if (max_available > 0) {
347    b->zero_copy_write_lock = 1;
348  }
349
350  *out_available_bytes = max_available;
351  return 1;
352}
353
354int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
355  struct bio_bio_st* b;
356  struct bio_bio_st* peer_b;
357
358  size_t rest;
359  size_t dummy_write_offset;
360  uint8_t* dummy_write_buf;
361
362  if (!bio->init) {
363    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
364    return 0;
365  }
366
367  b = bio->ptr;
368
369  if (!b || !b->buf || !b->peer) {
370    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
371    return 0;
372  }
373  peer_b = b->peer->ptr;
374  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
375    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
376    return 0;
377  }
378
379  b->request = 0;
380  if (b->closed) {
381    /* BIO is already closed. */
382    OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
383    return 0;
384  }
385
386  if (!b->zero_copy_write_lock) {
387    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
388    return 0;
389  }
390
391  rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
392
393  if (bytes_written > rest) {
394    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
395    return 0;
396  }
397
398  bio->num_write += bytes_written;
399  /* Move write offset. */
400  b->len += bytes_written;
401  b->zero_copy_write_lock = 0;
402  return 1;
403}
404
405static int bio_read(BIO *bio, char *buf, int size_) {
406  size_t size = size_;
407  size_t rest;
408  struct bio_bio_st *b, *peer_b;
409
410  BIO_clear_retry_flags(bio);
411
412  if (!bio->init) {
413    return 0;
414  }
415
416  b = bio->ptr;
417  assert(b != NULL);
418  assert(b->peer != NULL);
419  peer_b = b->peer->ptr;
420  assert(peer_b != NULL);
421  assert(peer_b->buf != NULL);
422
423  peer_b->request = 0; /* will be set in "retry_read" situation */
424
425  if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
426    return 0;
427  }
428
429  if (peer_b->len == 0) {
430    if (peer_b->closed) {
431      return 0; /* writer has closed, and no data is left */
432    } else {
433      BIO_set_retry_read(bio); /* buffer is empty */
434      if (size <= peer_b->size) {
435        peer_b->request = size;
436      } else {
437        /* don't ask for more than the peer can
438         * deliver in one write */
439        peer_b->request = peer_b->size;
440      }
441      return -1;
442    }
443  }
444
445  /* we can read */
446  if (peer_b->len < size) {
447    size = peer_b->len;
448  }
449
450  /* now read "size" bytes */
451  rest = size;
452
453  assert(rest > 0);
454  /* one or two iterations */
455  do {
456    size_t chunk;
457
458    assert(rest <= peer_b->len);
459    if (peer_b->offset + rest <= peer_b->size) {
460      chunk = rest;
461    } else {
462      /* wrap around ring buffer */
463      chunk = peer_b->size - peer_b->offset;
464    }
465    assert(peer_b->offset + chunk <= peer_b->size);
466
467    memcpy(buf, peer_b->buf + peer_b->offset, chunk);
468
469    peer_b->len -= chunk;
470    /* If zero_copy_write_lock == 1 we must advance the offset even if buffer
471     * becomes empty, to make sure write_offset = (offset + len) % size
472     * does not change. */
473    if (peer_b->len || peer_b->zero_copy_write_lock) {
474      peer_b->offset += chunk;
475      assert(peer_b->offset <= peer_b->size);
476      if (peer_b->offset == peer_b->size) {
477        peer_b->offset = 0;
478      }
479      buf += chunk;
480    } else {
481      /* buffer now empty, no need to advance "buf" */
482      assert(chunk == rest);
483      peer_b->offset = 0;
484    }
485    rest -= chunk;
486  } while (rest);
487
488  return size;
489}
490
491static int bio_write(BIO *bio, const char *buf, int num_) {
492  size_t num = num_;
493  size_t rest;
494  struct bio_bio_st *b;
495
496  BIO_clear_retry_flags(bio);
497
498  if (!bio->init || buf == NULL || num == 0) {
499    return 0;
500  }
501
502  b = bio->ptr;
503  assert(b != NULL);
504  assert(b->peer != NULL);
505  assert(b->buf != NULL);
506
507  if (b->zero_copy_write_lock) {
508    return 0;
509  }
510
511  b->request = 0;
512  if (b->closed) {
513    /* we already closed */
514    OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
515    return -1;
516  }
517
518  assert(b->len <= b->size);
519
520  if (b->len == b->size) {
521    BIO_set_retry_write(bio); /* buffer is full */
522    return -1;
523  }
524
525  /* we can write */
526  if (num > b->size - b->len) {
527    num = b->size - b->len;
528  }
529
530  /* now write "num" bytes */
531  rest = num;
532
533  assert(rest > 0);
534  /* one or two iterations */
535  do {
536    size_t write_offset;
537    size_t chunk;
538
539    assert(b->len + rest <= b->size);
540
541    write_offset = b->offset + b->len;
542    if (write_offset >= b->size) {
543      write_offset -= b->size;
544    }
545    /* b->buf[write_offset] is the first byte we can write to. */
546
547    if (write_offset + rest <= b->size) {
548      chunk = rest;
549    } else {
550      /* wrap around ring buffer */
551      chunk = b->size - write_offset;
552    }
553
554    memcpy(b->buf + write_offset, buf, chunk);
555
556    b->len += chunk;
557
558    assert(b->len <= b->size);
559
560    rest -= chunk;
561    buf += chunk;
562  } while (rest);
563
564  return num;
565}
566
567static int bio_make_pair(BIO* bio1, BIO* bio2,
568                         size_t writebuf1_len, uint8_t* ext_writebuf1,
569                         size_t writebuf2_len, uint8_t* ext_writebuf2) {
570  struct bio_bio_st *b1, *b2;
571
572  assert(bio1 != NULL);
573  assert(bio2 != NULL);
574
575  b1 = bio1->ptr;
576  b2 = bio2->ptr;
577
578  if (b1->peer != NULL || b2->peer != NULL) {
579    OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
580    return 0;
581  }
582
583  assert(b1->buf_externally_allocated == 0);
584  assert(b2->buf_externally_allocated == 0);
585
586  if (b1->buf == NULL) {
587    if (writebuf1_len) {
588      b1->size = writebuf1_len;
589    }
590    if (!ext_writebuf1) {
591      b1->buf_externally_allocated = 0;
592      b1->buf = OPENSSL_malloc(b1->size);
593      if (b1->buf == NULL) {
594        OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
595        return 0;
596      }
597    } else {
598      b1->buf = ext_writebuf1;
599      b1->buf_externally_allocated = 1;
600    }
601    b1->len = 0;
602    b1->offset = 0;
603  }
604
605  if (b2->buf == NULL) {
606    if (writebuf2_len) {
607      b2->size = writebuf2_len;
608    }
609    if (!ext_writebuf2) {
610      b2->buf_externally_allocated = 0;
611      b2->buf = OPENSSL_malloc(b2->size);
612      if (b2->buf == NULL) {
613        OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
614        return 0;
615      }
616    } else {
617      b2->buf = ext_writebuf2;
618      b2->buf_externally_allocated = 1;
619    }
620    b2->len = 0;
621    b2->offset = 0;
622  }
623
624  b1->peer = bio2;
625  b1->closed = 0;
626  b1->request = 0;
627  b1->zero_copy_read_lock = 0;
628  b1->zero_copy_write_lock = 0;
629  b2->peer = bio1;
630  b2->closed = 0;
631  b2->request = 0;
632  b2->zero_copy_read_lock = 0;
633  b2->zero_copy_write_lock = 0;
634
635  bio1->init = 1;
636  bio2->init = 1;
637
638  return 1;
639}
640
641static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
642  long ret;
643  struct bio_bio_st *b = bio->ptr;
644
645  assert(b != NULL);
646
647  switch (cmd) {
648    /* specific CTRL codes */
649
650    case BIO_C_GET_WRITE_BUF_SIZE:
651      ret = (long)b->size;
652      break;
653
654    case BIO_C_GET_WRITE_GUARANTEE:
655      /* How many bytes can the caller feed to the next write
656       * without having to keep any? */
657      if (b->peer == NULL || b->closed) {
658        ret = 0;
659      } else {
660        ret = (long)b->size - b->len;
661      }
662      break;
663
664    case BIO_C_GET_READ_REQUEST:
665      /* If the peer unsuccessfully tried to read, how many bytes
666       * were requested?  (As with BIO_CTRL_PENDING, that number
667       * can usually be treated as boolean.) */
668      ret = (long)b->request;
669      break;
670
671    case BIO_C_RESET_READ_REQUEST:
672      /* Reset request.  (Can be useful after read attempts
673       * at the other side that are meant to be non-blocking,
674       * e.g. when probing SSL_read to see if any data is
675       * available.) */
676      b->request = 0;
677      ret = 1;
678      break;
679
680    case BIO_C_SHUTDOWN_WR:
681      /* similar to shutdown(..., SHUT_WR) */
682      b->closed = 1;
683      ret = 1;
684      break;
685
686    /* standard CTRL codes follow */
687
688    case BIO_CTRL_GET_CLOSE:
689      ret = bio->shutdown;
690      break;
691
692    case BIO_CTRL_SET_CLOSE:
693      bio->shutdown = (int)num;
694      ret = 1;
695      break;
696
697    case BIO_CTRL_PENDING:
698      if (b->peer != NULL) {
699        struct bio_bio_st *peer_b = b->peer->ptr;
700        ret = (long)peer_b->len;
701      } else {
702        ret = 0;
703      }
704      break;
705
706    case BIO_CTRL_WPENDING:
707      ret = 0;
708      if (b->buf != NULL) {
709        ret = (long)b->len;
710      }
711      break;
712
713    case BIO_CTRL_FLUSH:
714      ret = 1;
715      break;
716
717    case BIO_CTRL_EOF: {
718      BIO *other_bio = ptr;
719
720      if (other_bio) {
721        struct bio_bio_st *other_b = other_bio->ptr;
722        assert(other_b != NULL);
723        ret = other_b->len == 0 && other_b->closed;
724      } else {
725        ret = 1;
726      }
727    } break;
728
729    default:
730      ret = 0;
731  }
732  return ret;
733}
734
735static int bio_puts(BIO *bio, const char *str) {
736  return bio_write(bio, str, strlen(str));
737}
738
739static const BIO_METHOD methods_biop = {
740    BIO_TYPE_BIO, "BIO pair",             bio_write, bio_read,
741    bio_puts,     NULL /* no bio_gets */, bio_ctrl,  bio_new,
742    bio_free,     NULL /* no bio_callback_ctrl */
743};
744
745const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
746
747int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
748                     BIO** bio2_p, size_t writebuf2) {
749  return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
750                                       writebuf2, NULL);
751}
752
753int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
754                                  uint8_t* ext_writebuf1,
755                                  BIO** bio2_p, size_t writebuf2_len,
756                                  uint8_t* ext_writebuf2) {
757  BIO *bio1 = NULL, *bio2 = NULL;
758  int ret = 0;
759
760  /* External buffers must have sizes greater than 0. */
761  if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
762    goto err;
763  }
764
765  bio1 = BIO_new(bio_s_bio());
766  if (bio1 == NULL) {
767    goto err;
768  }
769  bio2 = BIO_new(bio_s_bio());
770  if (bio2 == NULL) {
771    goto err;
772  }
773
774  if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
775                     ext_writebuf2)) {
776    goto err;
777  }
778  ret = 1;
779
780err:
781  if (ret == 0) {
782    BIO_free(bio1);
783    bio1 = NULL;
784    BIO_free(bio2);
785    bio2 = NULL;
786  }
787
788  *bio1_p = bio1;
789  *bio2_p = bio2;
790  return ret;
791}
792
793size_t BIO_ctrl_get_read_request(BIO *bio) {
794  return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
795}
796
797size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
798  return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
799}
800
801int BIO_shutdown_wr(BIO *bio) {
802  return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
803}
804