• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
63 struct 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 
bio_new(BIO * bio)88 static 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 
bio_destroy_pair(BIO * bio)102 static 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 
bio_free(BIO * bio)134 static 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 
bio_zero_copy_get_read_buf(struct bio_bio_st * peer_b,uint8_t ** out_read_buf,size_t * out_buf_offset)157 static 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 
BIO_zero_copy_get_read_buf(BIO * bio,uint8_t ** out_read_buf,size_t * out_buf_offset,size_t * out_available_bytes)173 int 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 
BIO_zero_copy_get_read_buf_done(BIO * bio,size_t bytes_read)220 int 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 
bio_zero_copy_get_write_buf(struct bio_bio_st * b,uint8_t ** out_write_buf,size_t * out_buf_offset)278 static 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 
BIO_zero_copy_get_write_buf(BIO * bio,uint8_t ** out_write_buf,size_t * out_buf_offset,size_t * out_available_bytes)303 int 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 
BIO_zero_copy_get_write_buf_done(BIO * bio,size_t bytes_written)354 int 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 
bio_read(BIO * bio,char * buf,int size_)405 static 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 
bio_write(BIO * bio,const char * buf,int num_)491 static 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 
bio_make_pair(BIO * bio1,BIO * bio2,size_t writebuf1_len,uint8_t * ext_writebuf1,size_t writebuf2_len,uint8_t * ext_writebuf2)567 static 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 
bio_ctrl(BIO * bio,int cmd,long num,void * ptr)641 static 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 
bio_puts(BIO * bio,const char * str)735 static int bio_puts(BIO *bio, const char *str) {
736   return bio_write(bio, str, strlen(str));
737 }
738 
739 static 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 
bio_s_bio(void)745 const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
746 
BIO_new_bio_pair(BIO ** bio1_p,size_t writebuf1,BIO ** bio2_p,size_t writebuf2)747 int 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 
BIO_new_bio_pair_external_buf(BIO ** bio1_p,size_t writebuf1_len,uint8_t * ext_writebuf1,BIO ** bio2_p,size_t writebuf2_len,uint8_t * ext_writebuf2)753 int 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 
780 err:
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 
BIO_ctrl_get_read_request(BIO * bio)793 size_t BIO_ctrl_get_read_request(BIO *bio) {
794   return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
795 }
796 
BIO_ctrl_get_write_guarantee(BIO * bio)797 size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
798   return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
799 }
800 
BIO_shutdown_wr(BIO * bio)801 int BIO_shutdown_wr(BIO *bio) {
802   return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
803 }
804