xref: /third_party/openssl/crypto/bio/bss_bio.c (revision e1051a39)
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
28static int bio_new(BIO *bio);
29static int bio_free(BIO *bio);
30static int bio_read(BIO *bio, char *buf, int size);
31static int bio_write(BIO *bio, const char *buf, int num);
32static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr);
33static int bio_puts(BIO *bio, const char *str);
34
35static int bio_make_pair(BIO *bio1, BIO *bio2);
36static void bio_destroy_pair(BIO *bio);
37
38static 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
53const BIO_METHOD *BIO_s_bio(void)
54{
55    return &methods_biop;
56}
57
58struct 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
76static 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
90static 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
109static 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 */
200static 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
237static 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
268static 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 */
345static 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
393static 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
416static 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
601static int bio_puts(BIO *bio, const char *str)
602{
603    return bio_write(bio, str, strlen(str));
604}
605
606static 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
654static 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 */
683int 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
726size_t BIO_ctrl_get_write_guarantee(BIO *bio)
727{
728    return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
729}
730
731size_t BIO_ctrl_get_read_request(BIO *bio)
732{
733    return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
734}
735
736int 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 */
746int 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
762int 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
777int 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
793int 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