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