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