Coverage Report

Created: 2025-04-22 06:18

/src/openssl/crypto/bio/bss_bio.c
Line
Count
Source (jump to first uncovered line)
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
53
const BIO_METHOD *BIO_s_bio(void)
54
0
{
55
0
    return &methods_biop;
56
0
}
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
76
static int bio_new(BIO *bio)
77
0
{
78
0
    struct bio_bio_st *b = OPENSSL_zalloc(sizeof(*b));
79
80
0
    if (b == NULL)
81
0
        return 0;
82
83
    /* enough for one TLS record (just a default) */
84
0
    b->size = 17 * 1024;
85
86
0
    bio->ptr = b;
87
0
    return 1;
88
0
}
89
90
static int bio_free(BIO *bio)
91
0
{
92
0
    struct bio_bio_st *b;
93
94
0
    if (bio == NULL)
95
0
        return 0;
96
0
    b = bio->ptr;
97
98
0
    assert(b != NULL);
99
100
0
    if (b->peer)
101
0
        bio_destroy_pair(bio);
102
103
0
    OPENSSL_free(b->buf);
104
0
    OPENSSL_free(b);
105
106
0
    return 1;
107
0
}
108
109
static int bio_read(BIO *bio, char *buf, int size_)
110
0
{
111
0
    size_t size = size_;
112
0
    size_t rest;
113
0
    struct bio_bio_st *b, *peer_b;
114
115
0
    BIO_clear_retry_flags(bio);
116
117
0
    if (!bio->init)
118
0
        return 0;
119
120
0
    b = bio->ptr;
121
0
    assert(b != NULL);
122
0
    assert(b->peer != NULL);
123
0
    peer_b = b->peer->ptr;
124
0
    assert(peer_b != NULL);
125
0
    assert(peer_b->buf != NULL);
126
127
0
    peer_b->request = 0;        /* will be set in "retry_read" situation */
128
129
0
    if (buf == NULL || size == 0)
130
0
        return 0;
131
132
0
    if (peer_b->len == 0) {
133
0
        if (peer_b->closed)
134
0
            return 0;           /* writer has closed, and no data is left */
135
0
        else {
136
0
            BIO_set_retry_read(bio); /* buffer is empty */
137
0
            if (size <= peer_b->size)
138
0
                peer_b->request = size;
139
0
            else
140
                /*
141
                 * don't ask for more than the peer can deliver in one write
142
                 */
143
0
                peer_b->request = peer_b->size;
144
0
            return -1;
145
0
        }
146
0
    }
147
148
    /* we can read */
149
0
    if (peer_b->len < size)
150
0
        size = peer_b->len;
151
152
    /* now read "size" bytes */
153
154
0
    rest = size;
155
156
0
    assert(rest > 0);
157
0
    do {                        /* one or two iterations */
158
0
        size_t chunk;
159
160
0
        assert(rest <= peer_b->len);
161
0
        if (peer_b->offset + rest <= peer_b->size)
162
0
            chunk = rest;
163
0
        else
164
            /* wrap around ring buffer */
165
0
            chunk = peer_b->size - peer_b->offset;
166
0
        assert(peer_b->offset + chunk <= peer_b->size);
167
168
0
        memcpy(buf, peer_b->buf + peer_b->offset, chunk);
169
170
0
        peer_b->len -= chunk;
171
0
        if (peer_b->len) {
172
0
            peer_b->offset += chunk;
173
0
            assert(peer_b->offset <= peer_b->size);
174
0
            if (peer_b->offset == peer_b->size)
175
0
                peer_b->offset = 0;
176
0
            buf += chunk;
177
0
        } else {
178
            /* buffer now empty, no need to advance "buf" */
179
0
            assert(chunk == rest);
180
0
            peer_b->offset = 0;
181
0
        }
182
0
        rest -= chunk;
183
0
    }
184
0
    while (rest);
185
186
0
    return size;
187
0
}
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
 */
200
static ossl_ssize_t bio_nread0(BIO *bio, char **buf)
201
0
{
202
0
    struct bio_bio_st *b, *peer_b;
203
0
    ossl_ssize_t num;
204
205
0
    BIO_clear_retry_flags(bio);
206
207
0
    if (!bio->init)
208
0
        return 0;
209
210
0
    b = bio->ptr;
211
0
    assert(b != NULL);
212
0
    assert(b->peer != NULL);
213
0
    peer_b = b->peer->ptr;
214
0
    assert(peer_b != NULL);
215
0
    assert(peer_b->buf != NULL);
216
217
0
    peer_b->request = 0;
218
219
0
    if (peer_b->len == 0) {
220
0
        char dummy;
221
222
        /* avoid code duplication -- nothing available for reading */
223
0
        return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
224
0
    }
225
226
0
    num = peer_b->len;
227
0
    if (peer_b->size < peer_b->offset + num)
228
        /* no ring buffer wrap-around for non-copying interface */
229
0
        num = peer_b->size - peer_b->offset;
230
0
    assert(num > 0);
231
232
0
    if (buf != NULL)
233
0
        *buf = peer_b->buf + peer_b->offset;
234
0
    return num;
235
0
}
236
237
static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_)
238
0
{
239
0
    struct bio_bio_st *b, *peer_b;
240
0
    ossl_ssize_t num, available;
241
242
0
    if (num_ > OSSL_SSIZE_MAX)
243
0
        num = OSSL_SSIZE_MAX;
244
0
    else
245
0
        num = (ossl_ssize_t) num_;
246
247
0
    available = bio_nread0(bio, buf);
248
0
    if (num > available)
249
0
        num = available;
250
0
    if (num <= 0)
251
0
        return num;
252
253
0
    b = bio->ptr;
254
0
    peer_b = b->peer->ptr;
255
256
0
    peer_b->len -= num;
257
0
    if (peer_b->len) {
258
0
        peer_b->offset += num;
259
0
        assert(peer_b->offset <= peer_b->size);
260
0
        if (peer_b->offset == peer_b->size)
261
0
            peer_b->offset = 0;
262
0
    } else
263
0
        peer_b->offset = 0;
264
265
0
    return num;
266
0
}
267
268
static int bio_write(BIO *bio, const char *buf, int num_)
269
0
{
270
0
    size_t num = num_;
271
0
    size_t rest;
272
0
    struct bio_bio_st *b;
273
274
0
    BIO_clear_retry_flags(bio);
275
276
0
    if (!bio->init || buf == NULL || num == 0)
277
0
        return 0;
278
279
0
    b = bio->ptr;
280
0
    assert(b != NULL);
281
0
    assert(b->peer != NULL);
282
0
    assert(b->buf != NULL);
283
284
0
    b->request = 0;
285
0
    if (b->closed) {
286
        /* we already closed */
287
0
        ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
288
0
        return -1;
289
0
    }
290
291
0
    assert(b->len <= b->size);
292
293
0
    if (b->len == b->size) {
294
0
        BIO_set_retry_write(bio); /* buffer is full */
295
0
        return -1;
296
0
    }
297
298
    /* we can write */
299
0
    if (num > b->size - b->len)
300
0
        num = b->size - b->len;
301
302
    /* now write "num" bytes */
303
304
0
    rest = num;
305
306
0
    assert(rest > 0);
307
0
    do {                        /* one or two iterations */
308
0
        size_t write_offset;
309
0
        size_t chunk;
310
311
0
        assert(b->len + rest <= b->size);
312
313
0
        write_offset = b->offset + b->len;
314
0
        if (write_offset >= b->size)
315
0
            write_offset -= b->size;
316
        /* b->buf[write_offset] is the first byte we can write to. */
317
318
0
        if (write_offset + rest <= b->size)
319
0
            chunk = rest;
320
0
        else
321
            /* wrap around ring buffer */
322
0
            chunk = b->size - write_offset;
323
324
0
        memcpy(b->buf + write_offset, buf, chunk);
325
326
0
        b->len += chunk;
327
328
0
        assert(b->len <= b->size);
329
330
0
        rest -= chunk;
331
0
        buf += chunk;
332
0
    }
333
0
    while (rest);
334
335
0
    return num;
336
0
}
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
 */
345
static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf)
346
0
{
347
0
    struct bio_bio_st *b;
348
0
    size_t num;
349
0
    size_t write_offset;
350
351
0
    BIO_clear_retry_flags(bio);
352
353
0
    if (!bio->init)
354
0
        return 0;
355
356
0
    b = bio->ptr;
357
0
    assert(b != NULL);
358
0
    assert(b->peer != NULL);
359
0
    assert(b->buf != NULL);
360
361
0
    b->request = 0;
362
0
    if (b->closed) {
363
0
        ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
364
0
        return -1;
365
0
    }
366
367
0
    assert(b->len <= b->size);
368
369
0
    if (b->len == b->size) {
370
0
        BIO_set_retry_write(bio);
371
0
        return -1;
372
0
    }
373
374
0
    num = b->size - b->len;
375
0
    write_offset = b->offset + b->len;
376
0
    if (write_offset >= b->size)
377
0
        write_offset -= b->size;
378
0
    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
0
        num = b->size - write_offset;
385
386
0
    if (buf != NULL)
387
0
        *buf = b->buf + write_offset;
388
0
    assert(write_offset + num <= b->size);
389
390
0
    return num;
391
0
}
392
393
static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_)
394
0
{
395
0
    struct bio_bio_st *b;
396
0
    ossl_ssize_t num, space;
397
398
0
    if (num_ > OSSL_SSIZE_MAX)
399
0
        num = OSSL_SSIZE_MAX;
400
0
    else
401
0
        num = (ossl_ssize_t) num_;
402
403
0
    space = bio_nwrite0(bio, buf);
404
0
    if (num > space)
405
0
        num = space;
406
0
    if (num <= 0)
407
0
        return num;
408
0
    b = bio->ptr;
409
0
    assert(b != NULL);
410
0
    b->len += num;
411
0
    assert(b->len <= b->size);
412
413
0
    return num;
414
0
}
415
416
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
417
0
{
418
0
    long ret;
419
0
    struct bio_bio_st *b = bio->ptr;
420
421
0
    assert(b != NULL);
422
423
0
    switch (cmd) {
424
        /* specific CTRL codes */
425
426
0
    case BIO_C_SET_WRITE_BUF_SIZE:
427
0
        if (b->peer) {
428
0
            ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
429
0
            ret = 0;
430
0
        } else if (num == 0) {
431
0
            ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
432
0
            ret = 0;
433
0
        } else {
434
0
            size_t new_size = num;
435
436
0
            if (b->size != new_size) {
437
0
                OPENSSL_free(b->buf);
438
0
                b->buf = NULL;
439
0
                b->size = new_size;
440
0
            }
441
0
            ret = 1;
442
0
        }
443
0
        break;
444
445
0
    case BIO_C_GET_WRITE_BUF_SIZE:
446
0
        ret = (long)b->size;
447
0
        break;
448
449
0
    case BIO_C_MAKE_BIO_PAIR:
450
0
        {
451
0
            BIO *other_bio = ptr;
452
453
0
            if (bio_make_pair(bio, other_bio))
454
0
                ret = 1;
455
0
            else
456
0
                ret = 0;
457
0
        }
458
0
        break;
459
460
0
    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
0
        bio_destroy_pair(bio);
466
0
        ret = 1;
467
0
        break;
468
469
0
    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
0
        if (b->peer == NULL || b->closed)
475
0
            ret = 0;
476
0
        else
477
0
            ret = (long)b->size - b->len;
478
0
        break;
479
480
0
    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
0
        ret = (long)b->request;
487
0
        break;
488
489
0
    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
0
        b->request = 0;
496
0
        ret = 1;
497
0
        break;
498
499
0
    case BIO_C_SHUTDOWN_WR:
500
        /* similar to shutdown(..., SHUT_WR) */
501
0
        b->closed = 1;
502
0
        ret = 1;
503
0
        break;
504
505
0
    case BIO_C_NREAD0:
506
        /* prepare for non-copying read */
507
0
        ret = (long)bio_nread0(bio, ptr);
508
0
        break;
509
510
0
    case BIO_C_NREAD:
511
        /* non-copying read */
512
0
        ret = (long)bio_nread(bio, ptr, (size_t)num);
513
0
        break;
514
515
0
    case BIO_C_NWRITE0:
516
        /* prepare for non-copying write */
517
0
        ret = (long)bio_nwrite0(bio, ptr);
518
0
        break;
519
520
0
    case BIO_C_NWRITE:
521
        /* non-copying write */
522
0
        ret = (long)bio_nwrite(bio, ptr, (size_t)num);
523
0
        break;
524
525
        /* standard CTRL codes follow */
526
527
0
    case BIO_CTRL_RESET:
528
0
        if (b->buf != NULL) {
529
0
            b->len = 0;
530
0
            b->offset = 0;
531
0
        }
532
0
        ret = 0;
533
0
        break;
534
535
0
    case BIO_CTRL_GET_CLOSE:
536
0
        ret = bio->shutdown;
537
0
        break;
538
539
0
    case BIO_CTRL_SET_CLOSE:
540
0
        bio->shutdown = (int)num;
541
0
        ret = 1;
542
0
        break;
543
544
0
    case BIO_CTRL_PENDING:
545
0
        if (b->peer != NULL) {
546
0
            struct bio_bio_st *peer_b = b->peer->ptr;
547
548
0
            ret = (long)peer_b->len;
549
0
        } else
550
0
            ret = 0;
551
0
        break;
552
553
0
    case BIO_CTRL_WPENDING:
554
0
        if (b->buf != NULL)
555
0
            ret = (long)b->len;
556
0
        else
557
0
            ret = 0;
558
0
        break;
559
560
0
    case BIO_CTRL_DUP:
561
        /* See BIO_dup_chain for circumstances we have to expect. */
562
0
        {
563
0
            BIO *other_bio = ptr;
564
0
            struct bio_bio_st *other_b;
565
566
0
            assert(other_bio != NULL);
567
0
            other_b = other_bio->ptr;
568
0
            assert(other_b != NULL);
569
570
0
            assert(other_b->buf == NULL); /* other_bio is always fresh */
571
572
0
            other_b->size = b->size;
573
0
        }
574
575
0
        ret = 1;
576
0
        break;
577
578
0
    case BIO_CTRL_FLUSH:
579
0
        ret = 1;
580
0
        break;
581
582
0
    case BIO_CTRL_EOF:
583
0
        if (b->peer != NULL) {
584
0
            struct bio_bio_st *peer_b = b->peer->ptr;
585
586
0
            if (peer_b->len == 0 && peer_b->closed)
587
0
                ret = 1;
588
0
            else
589
0
                ret = 0;
590
0
        } else {
591
0
            ret = 1;
592
0
        }
593
0
        break;
594
595
0
    default:
596
0
        ret = 0;
597
0
    }
598
0
    return ret;
599
0
}
600
601
static int bio_puts(BIO *bio, const char *str)
602
0
{
603
0
    return bio_write(bio, str, strlen(str));
604
0
}
605
606
static int bio_make_pair(BIO *bio1, BIO *bio2)
607
0
{
608
0
    struct bio_bio_st *b1, *b2;
609
610
0
    assert(bio1 != NULL);
611
0
    assert(bio2 != NULL);
612
613
0
    b1 = bio1->ptr;
614
0
    b2 = bio2->ptr;
615
616
0
    if (b1->peer != NULL || b2->peer != NULL) {
617
0
        ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
618
0
        return 0;
619
0
    }
620
621
0
    if (b1->buf == NULL) {
622
0
        b1->buf = OPENSSL_malloc(b1->size);
623
0
        if (b1->buf == NULL) {
624
0
            ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
625
0
            return 0;
626
0
        }
627
0
        b1->len = 0;
628
0
        b1->offset = 0;
629
0
    }
630
631
0
    if (b2->buf == NULL) {
632
0
        b2->buf = OPENSSL_malloc(b2->size);
633
0
        if (b2->buf == NULL) {
634
0
            ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
635
0
            return 0;
636
0
        }
637
0
        b2->len = 0;
638
0
        b2->offset = 0;
639
0
    }
640
641
0
    b1->peer = bio2;
642
0
    b1->closed = 0;
643
0
    b1->request = 0;
644
0
    b2->peer = bio1;
645
0
    b2->closed = 0;
646
0
    b2->request = 0;
647
648
0
    bio1->init = 1;
649
0
    bio2->init = 1;
650
651
0
    return 1;
652
0
}
653
654
static void bio_destroy_pair(BIO *bio)
655
0
{
656
0
    struct bio_bio_st *b = bio->ptr;
657
658
0
    if (b != NULL) {
659
0
        BIO *peer_bio = b->peer;
660
661
0
        if (peer_bio != NULL) {
662
0
            struct bio_bio_st *peer_b = peer_bio->ptr;
663
664
0
            assert(peer_b != NULL);
665
0
            assert(peer_b->peer == bio);
666
667
0
            peer_b->peer = NULL;
668
0
            peer_bio->init = 0;
669
0
            assert(peer_b->buf != NULL);
670
0
            peer_b->len = 0;
671
0
            peer_b->offset = 0;
672
673
0
            b->peer = NULL;
674
0
            bio->init = 0;
675
0
            assert(b->buf != NULL);
676
0
            b->len = 0;
677
0
            b->offset = 0;
678
0
        }
679
0
    }
680
0
}
681
682
/* Exported convenience functions */
683
int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
684
                     BIO **bio2_p, size_t writebuf2)
685
0
{
686
0
    BIO *bio1 = NULL, *bio2 = NULL;
687
0
    long r;
688
0
    int ret = 0;
689
690
0
    bio1 = BIO_new(BIO_s_bio());
691
0
    if (bio1 == NULL)
692
0
        goto err;
693
0
    bio2 = BIO_new(BIO_s_bio());
694
0
    if (bio2 == NULL)
695
0
        goto err;
696
697
0
    if (writebuf1) {
698
0
        r = BIO_set_write_buf_size(bio1, writebuf1);
699
0
        if (!r)
700
0
            goto err;
701
0
    }
702
0
    if (writebuf2) {
703
0
        r = BIO_set_write_buf_size(bio2, writebuf2);
704
0
        if (!r)
705
0
            goto err;
706
0
    }
707
708
0
    r = BIO_make_bio_pair(bio1, bio2);
709
0
    if (!r)
710
0
        goto err;
711
0
    ret = 1;
712
713
0
 err:
714
0
    if (ret == 0) {
715
0
        BIO_free(bio1);
716
0
        bio1 = NULL;
717
0
        BIO_free(bio2);
718
0
        bio2 = NULL;
719
0
    }
720
721
0
    *bio1_p = bio1;
722
0
    *bio2_p = bio2;
723
0
    return ret;
724
0
}
725
726
size_t BIO_ctrl_get_write_guarantee(BIO *bio)
727
0
{
728
0
    return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
729
0
}
730
731
size_t BIO_ctrl_get_read_request(BIO *bio)
732
0
{
733
0
    return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
734
0
}
735
736
int BIO_ctrl_reset_read_request(BIO *bio)
737
0
{
738
0
    return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
739
0
}
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
 */
746
int BIO_nread0(BIO *bio, char **buf)
747
0
{
748
0
    long ret;
749
750
0
    if (!bio->init) {
751
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
752
0
        return -2;
753
0
    }
754
755
0
    ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
756
0
    if (ret > INT_MAX)
757
0
        return INT_MAX;
758
0
    else
759
0
        return (int)ret;
760
0
}
761
762
int BIO_nread(BIO *bio, char **buf, int num)
763
0
{
764
0
    int ret;
765
766
0
    if (!bio->init) {
767
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
768
0
        return -2;
769
0
    }
770
771
0
    ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
772
0
    if (ret > 0)
773
0
        bio->num_read += ret;
774
0
    return ret;
775
0
}
776
777
int BIO_nwrite0(BIO *bio, char **buf)
778
0
{
779
0
    long ret;
780
781
0
    if (!bio->init) {
782
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
783
0
        return -2;
784
0
    }
785
786
0
    ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
787
0
    if (ret > INT_MAX)
788
0
        return INT_MAX;
789
0
    else
790
0
        return (int)ret;
791
0
}
792
793
int BIO_nwrite(BIO *bio, char **buf, int num)
794
0
{
795
0
    int ret;
796
797
0
    if (!bio->init) {
798
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
799
0
        return -2;
800
0
    }
801
802
0
    ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
803
0
    if (ret > 0)
804
0
        bio->num_write += ret;
805
0
    return ret;
806
0
}