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