1 /*
2 * Copyright 1999-2021 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 "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 ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
625 return 0;
626 }
627 b1->len = 0;
628 b1->offset = 0;
629 }
630
631 if (b2->buf == NULL) {
632 b2->buf = OPENSSL_malloc(b2->size);
633 if (b2->buf == NULL) {
634 ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
635 return 0;
636 }
637 b2->len = 0;
638 b2->offset = 0;
639 }
640
641 b1->peer = bio2;
642 b1->closed = 0;
643 b1->request = 0;
644 b2->peer = bio1;
645 b2->closed = 0;
646 b2->request = 0;
647
648 bio1->init = 1;
649 bio2->init = 1;
650
651 return 1;
652 }
653
bio_destroy_pair(BIO * bio)654 static void bio_destroy_pair(BIO *bio)
655 {
656 struct bio_bio_st *b = bio->ptr;
657
658 if (b != NULL) {
659 BIO *peer_bio = b->peer;
660
661 if (peer_bio != NULL) {
662 struct bio_bio_st *peer_b = peer_bio->ptr;
663
664 assert(peer_b != NULL);
665 assert(peer_b->peer == bio);
666
667 peer_b->peer = NULL;
668 peer_bio->init = 0;
669 assert(peer_b->buf != NULL);
670 peer_b->len = 0;
671 peer_b->offset = 0;
672
673 b->peer = NULL;
674 bio->init = 0;
675 assert(b->buf != NULL);
676 b->len = 0;
677 b->offset = 0;
678 }
679 }
680 }
681
682 /* Exported convenience functions */
BIO_new_bio_pair(BIO ** bio1_p,size_t writebuf1,BIO ** bio2_p,size_t writebuf2)683 int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
684 BIO **bio2_p, size_t writebuf2)
685 {
686 BIO *bio1 = NULL, *bio2 = NULL;
687 long r;
688 int ret = 0;
689
690 bio1 = BIO_new(BIO_s_bio());
691 if (bio1 == NULL)
692 goto err;
693 bio2 = BIO_new(BIO_s_bio());
694 if (bio2 == NULL)
695 goto err;
696
697 if (writebuf1) {
698 r = BIO_set_write_buf_size(bio1, writebuf1);
699 if (!r)
700 goto err;
701 }
702 if (writebuf2) {
703 r = BIO_set_write_buf_size(bio2, writebuf2);
704 if (!r)
705 goto err;
706 }
707
708 r = BIO_make_bio_pair(bio1, bio2);
709 if (!r)
710 goto err;
711 ret = 1;
712
713 err:
714 if (ret == 0) {
715 BIO_free(bio1);
716 bio1 = NULL;
717 BIO_free(bio2);
718 bio2 = NULL;
719 }
720
721 *bio1_p = bio1;
722 *bio2_p = bio2;
723 return ret;
724 }
725
BIO_ctrl_get_write_guarantee(BIO * bio)726 size_t BIO_ctrl_get_write_guarantee(BIO *bio)
727 {
728 return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
729 }
730
BIO_ctrl_get_read_request(BIO * bio)731 size_t BIO_ctrl_get_read_request(BIO *bio)
732 {
733 return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
734 }
735
BIO_ctrl_reset_read_request(BIO * bio)736 int BIO_ctrl_reset_read_request(BIO *bio)
737 {
738 return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
739 }
740
741 /*
742 * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
743 * (conceivably some other BIOs could allow non-copying reads and writes
744 * too.)
745 */
BIO_nread0(BIO * bio,char ** buf)746 int BIO_nread0(BIO *bio, char **buf)
747 {
748 long ret;
749
750 if (!bio->init) {
751 ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
752 return -2;
753 }
754
755 ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
756 if (ret > INT_MAX)
757 return INT_MAX;
758 else
759 return (int)ret;
760 }
761
BIO_nread(BIO * bio,char ** buf,int num)762 int BIO_nread(BIO *bio, char **buf, int num)
763 {
764 int ret;
765
766 if (!bio->init) {
767 ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
768 return -2;
769 }
770
771 ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
772 if (ret > 0)
773 bio->num_read += ret;
774 return ret;
775 }
776
BIO_nwrite0(BIO * bio,char ** buf)777 int BIO_nwrite0(BIO *bio, char **buf)
778 {
779 long ret;
780
781 if (!bio->init) {
782 ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
783 return -2;
784 }
785
786 ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
787 if (ret > INT_MAX)
788 return INT_MAX;
789 else
790 return (int)ret;
791 }
792
BIO_nwrite(BIO * bio,char ** buf,int num)793 int BIO_nwrite(BIO *bio, char **buf, int num)
794 {
795 int ret;
796
797 if (!bio->init) {
798 ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
799 return -2;
800 }
801
802 ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
803 if (ret > 0)
804 bio->num_write += ret;
805 return ret;
806 }
807