Coverage Report

Created: 2026-09-17 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/bio/bss_dgram_pair.c
Line
Count
Source
1
/*
2
 * Copyright 2022-2026 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
#include <stdio.h>
11
#include <errno.h>
12
#include "bio_local.h"
13
#include "internal/cryptlib.h"
14
#include "internal/safe_math.h"
15
#include "internal/threads_common.h"
16
17
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
18
19
0
#define is_dgram_pair(b) (b->pair != NULL)
20
21
OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
22
23
/* ===========================================================================
24
 * Byte-wise ring buffer which supports pushing and popping blocks of multiple
25
 * bytes at a time.
26
 */
27
struct ring_buf {
28
    unsigned char *start; /* start of buffer */
29
    size_t len; /* size of buffer allocation in bytes */
30
    size_t count; /* number of bytes currently pushed */
31
    /*
32
     * These index into start. Where idx[0] == idx[1], the buffer is full
33
     * (if count is nonzero) and empty otherwise.
34
     */
35
    size_t idx[2]; /* 0: head, 1: tail */
36
};
37
38
static int ring_buf_init(struct ring_buf *r, size_t nbytes)
39
0
{
40
0
    r->start = OPENSSL_malloc(nbytes);
41
0
    if (r->start == NULL)
42
0
        return 0;
43
44
0
    r->len = nbytes;
45
0
    r->idx[0] = r->idx[1] = r->count = 0;
46
0
    return 1;
47
0
}
48
49
static void ring_buf_destroy(struct ring_buf *r)
50
0
{
51
0
    OPENSSL_free(r->start);
52
0
    r->start = NULL;
53
0
    r->len = 0;
54
0
    r->count = 0;
55
0
}
56
57
/*
58
 * Get a pointer to the next place to write data to be pushed to the ring buffer
59
 * (idx=0), or the next data to be popped from the ring buffer (idx=1). The
60
 * pointer is written to *buf and the maximum number of bytes which can be
61
 * read/written are written to *len. After writing data to the buffer, call
62
 * ring_buf_push/pop() with the number of bytes actually read/written, which
63
 * must not exceed the returned length.
64
 */
65
static void ring_buf_head_tail(struct ring_buf *r, int idx, uint8_t **buf, size_t *len)
66
0
{
67
0
    size_t max_len = r->len - r->idx[idx];
68
69
0
    if (idx == 0 && max_len > r->len - r->count)
70
0
        max_len = r->len - r->count;
71
0
    if (idx == 1 && max_len > r->count)
72
0
        max_len = r->count;
73
74
0
    *buf = (uint8_t *)r->start + r->idx[idx];
75
0
    *len = max_len;
76
0
}
77
78
0
#define ring_buf_head(r, buf, len) ring_buf_head_tail((r), 0, (buf), (len))
79
0
#define ring_buf_tail(r, buf, len) ring_buf_head_tail((r), 1, (buf), (len))
80
81
/*
82
 * Commit bytes to the ring buffer previously filled after a call to
83
 * ring_buf_head().
84
 */
85
static void ring_buf_push_pop(struct ring_buf *r, int idx, size_t num_bytes)
86
0
{
87
0
    size_t new_idx;
88
89
    /* A single push/pop op cannot wrap around, though it can reach the end.
90
     * If the caller adheres to the convention of using the length returned
91
     * by ring_buf_head/tail(), this cannot happen.
92
     */
93
0
    if (!ossl_assert(num_bytes <= r->len - r->idx[idx]))
94
0
        return;
95
96
    /*
97
     * Must not overfill the buffer, or pop more than is in the buffer either.
98
     */
99
0
    if (!ossl_assert(idx != 0 ? num_bytes <= r->count
100
0
                              : num_bytes + r->count <= r->len))
101
0
        return;
102
103
    /* Update the index. */
104
0
    new_idx = r->idx[idx] + num_bytes;
105
0
    if (new_idx == r->len)
106
0
        new_idx = 0;
107
108
0
    r->idx[idx] = new_idx;
109
0
    if (idx != 0)
110
0
        r->count -= num_bytes;
111
0
    else
112
0
        r->count += num_bytes;
113
0
}
114
115
0
#define ring_buf_push(r, num_bytes) ring_buf_push_pop((r), 0, (num_bytes))
116
0
#define ring_buf_pop(r, num_bytes) ring_buf_push_pop((r), 1, (num_bytes))
117
118
static void ring_buf_clear(struct ring_buf *r)
119
0
{
120
0
    r->idx[0] = r->idx[1] = r->count = 0;
121
0
}
122
123
static int ring_buf_resize(struct ring_buf *r, size_t nbytes)
124
0
{
125
0
    unsigned char *new_start;
126
127
0
    if (r->start == NULL)
128
0
        return ring_buf_init(r, nbytes);
129
130
0
    if (nbytes == r->len)
131
0
        return 1;
132
133
0
    if (r->count > 0 && nbytes < r->len)
134
        /* fail shrinking the ring buffer when there is any data in it */
135
0
        return 0;
136
137
0
    new_start = OPENSSL_realloc(r->start, nbytes);
138
0
    if (new_start == NULL)
139
0
        return 0;
140
141
    /* Moving tail if it is after (or equal to) head */
142
0
    if (r->count > 0) {
143
0
        if (r->idx[0] <= r->idx[1]) {
144
0
            size_t offset = nbytes - r->len;
145
146
0
            memmove(new_start + r->idx[1] + offset, new_start + r->idx[1],
147
0
                r->len - r->idx[1]);
148
0
            r->idx[1] += offset;
149
0
        }
150
0
    } else {
151
        /* just reset the head/tail because it might be pointing outside */
152
0
        r->idx[0] = r->idx[1] = 0;
153
0
    }
154
155
0
    r->start = new_start;
156
0
    r->len = nbytes;
157
158
0
    return 1;
159
0
}
160
161
/* ===========================================================================
162
 * BIO_s_dgram_pair is documented in BIO_s_dgram_pair(3).
163
 *
164
 * INTERNAL DATA STRUCTURE
165
 *
166
 * This is managed internally by using a bytewise ring buffer which supports
167
 * pushing and popping spans of multiple bytes at once. The ring buffer stores
168
 * internal packets which look like this:
169
 *
170
 *   struct dgram_hdr hdr;
171
 *   uint8_t data[];
172
 *
173
 * The header contains the length of the data and metadata such as
174
 * source/destination addresses.
175
 *
176
 * The datagram pair BIO is designed to support both traditional
177
 * BIO_read/BIO_write (likely to be used by applications) as well as
178
 * BIO_recvmmsg/BIO_sendmmsg.
179
 */
180
struct bio_dgram_pair_st;
181
static int dgram_pair_write(BIO *bio, const char *buf, int sz_);
182
static int dgram_pair_read(BIO *bio, char *buf, int sz_);
183
static int dgram_mem_read(BIO *bio, char *buf, int sz_);
184
static long dgram_pair_ctrl(BIO *bio, int cmd, long num, void *ptr);
185
static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr);
186
static int dgram_pair_init(BIO *bio);
187
static int dgram_mem_init(BIO *bio);
188
static int dgram_pair_free(BIO *bio);
189
static int dgram_pair_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride,
190
    size_t num_msg, uint64_t flags,
191
    size_t *num_processed);
192
static int dgram_pair_recvmmsg(BIO *b, BIO_MSG *msg, size_t stride,
193
    size_t num_msg, uint64_t flags,
194
    size_t *num_processed);
195
196
static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1);
197
static size_t dgram_pair_read_inner(struct ring_buf *rbufptr, uint8_t *buf,
198
    size_t sz);
199
200
0
#define BIO_MSG_N(array, n) (*(BIO_MSG *)((char *)(array) + (n) * stride))
201
202
static const BIO_METHOD dgram_pair_method = {
203
    BIO_TYPE_DGRAM_PAIR,
204
    "BIO dgram pair",
205
    bwrite_conv,
206
    dgram_pair_write,
207
    bread_conv,
208
    dgram_pair_read,
209
    NULL, /* dgram_pair_puts */
210
    NULL, /* dgram_pair_gets */
211
    dgram_pair_ctrl,
212
    dgram_pair_init,
213
    dgram_pair_free,
214
    NULL, /* dgram_pair_callback_ctrl */
215
    dgram_pair_sendmmsg,
216
    dgram_pair_recvmmsg,
217
};
218
219
static const BIO_METHOD dgram_mem_method = {
220
    BIO_TYPE_DGRAM_MEM,
221
    "BIO dgram mem",
222
    bwrite_conv,
223
    dgram_pair_write,
224
    bread_conv,
225
    dgram_mem_read,
226
    NULL, /* dgram_pair_puts */
227
    NULL, /* dgram_pair_gets */
228
    dgram_mem_ctrl,
229
    dgram_mem_init,
230
    dgram_pair_free,
231
    NULL, /* dgram_pair_callback_ctrl */
232
    dgram_pair_sendmmsg,
233
    dgram_pair_recvmmsg,
234
};
235
236
const BIO_METHOD *BIO_s_dgram_pair(void)
237
0
{
238
0
    return &dgram_pair_method;
239
0
}
240
241
const BIO_METHOD *BIO_s_dgram_mem(void)
242
0
{
243
0
    return &dgram_mem_method;
244
0
}
245
246
struct dgram_hdr {
247
    size_t len; /* payload length in bytes, not including this struct */
248
    BIO_ADDR src_addr, dst_addr; /* family == 0: not present */
249
};
250
251
struct rbuf_map_st {
252
    struct bio_dgram_pair_st *self;
253
    struct ring_buf rbuf;
254
    uint32_t cap;
255
    CRYPTO_RWLOCK *lock;
256
};
257
258
/**
259
 * \defgroup peer_state Peer pairing states
260
 *
261
 * State values describing whether a peer is still associated with its
262
 * counterpart. Stored in the peer's state field and compared for
263
 * equality; the values are not a bitmask and must not be OR'd
264
 * together.
265
 *
266
 * @{
267
 */
268
269
/** Peer is associated with a live counterpart. */
270
0
#define PEER_STATE_PAIRED 0
271
272
/** Peer's counterpart has gone away; the peer is unassociated. */
273
0
#define PEER_STATE_ORPHANED 1
274
/**
275
 * \brief Shared state for a datagram BIO pair.
276
 *
277
 * Refcounted so that both ends of a pair (and any BIO holding a
278
 * reference to the peer) can keep the structure alive independently.
279
 * The object is freed when the last reference is dropped, and the peer_state
280
 * is set to PEER_STATE_ORPHANED when either side leaves the pair, either
281
 * via BIO_free() or BIO_destroy_dgram_pair()
282
 *
283
 * This structure is pointed to by each half of a BIO_dgram pair via the pair pointer
284
 * It is only allocated and assigned when a pair is formed.
285
 */
286
struct bio_dgram_peer_st {
287
    /**
288
     * Reference count. Initialised with CRYPTO_NEW_REF() and
289
     * released with CRYPTO_FREE_REF() once it reaches zero.
290
     */
291
    CRYPTO_REF_COUNT ref_cnt;
292
293
    /**
294
     * Current pairing state; one of \c PEER_STATE_PAIRED or
295
     * \c PEER_STATE_ORPHANED (see \ref peer_state).
296
     */
297
    int peer_state;
298
299
    /*
300
     * Lock for peer_state atomic ops where needed
301
     */
302
    CRYPTO_RWLOCK *peerlock;
303
304
    /**
305
     * Ring buffer mappings for the two datagram directions,
306
     * indexed one per direction.
307
     */
308
    struct rbuf_map_st map[2];
309
};
310
311
struct bio_dgram_pair_st {
312
    /* Track out pairing state */
313
    struct bio_dgram_peer_st *pair;
314
    /* Writes are directed to our own ringbuf and reads to our peer. */
315
    struct ring_buf rbuf;
316
    /* Requested size of rbuf buffer in bytes once we initialize. */
317
    size_t req_buf_len;
318
    /* Largest possible datagram size */
319
    size_t mtu;
320
    /* Capability flags. */
321
    uint32_t cap;
322
    /* The local address to use (if set) */
323
    BIO_ADDR *local_addr;
324
    /*
325
     * This lock protects updates to our rbuf. Since writes are directed to our
326
     * own rbuf, this means we use this lock for writes and our peer's lock for
327
     * reads.
328
     */
329
    CRYPTO_RWLOCK *lock;
330
    unsigned int no_trunc : 1; /* Reads fail if they would truncate */
331
    unsigned int local_addr_enable : 1; /* Can use BIO_MSG->local? */
332
    unsigned int role : 1; /* Determines lock order */
333
    unsigned int grows_on_write : 1; /* Set for BIO_s_dgram_mem only */
334
};
335
336
/*
337
 * When operating as a pair, we use the shared structure to hold our ring buffers
338
 * and locks to ensure that they remain allocated until the last half of a pair
339
 * dissolves the pair.
340
 */
341
static struct rbuf_map_st *dgram_rbuf_map_get_self(struct bio_dgram_pair_st *self)
342
0
{
343
0
    if (self->pair->map[0].self == self)
344
0
        return &self->pair->map[0];
345
0
    return &self->pair->map[1];
346
0
}
347
348
static struct rbuf_map_st *dgram_rbuf_map_get_peer(struct bio_dgram_pair_st *self)
349
0
{
350
0
    if (self->pair->map[0].self == self)
351
0
        return &self->pair->map[1];
352
0
    return &self->pair->map[0];
353
0
}
354
355
static void dgram_bio_get_self_data(struct bio_dgram_pair_st *self, struct ring_buf **rbufptr,
356
    CRYPTO_RWLOCK **lock)
357
0
{
358
0
    struct rbuf_map_st *map;
359
0
    CRYPTO_RWLOCK *mylock;
360
0
    struct ring_buf *myrbuf;
361
362
0
    if (is_dgram_pair(self)) {
363
0
        map = dgram_rbuf_map_get_self(self);
364
0
        mylock = map->lock;
365
0
        myrbuf = &map->rbuf;
366
0
    } else {
367
0
        mylock = self->lock;
368
0
        myrbuf = &self->rbuf;
369
0
    }
370
0
    if (lock != NULL)
371
0
        *lock = mylock;
372
0
    if (rbufptr != NULL)
373
0
        *rbufptr = myrbuf;
374
0
}
375
376
static void dgram_bio_get_peer_data(struct bio_dgram_pair_st *self, struct ring_buf **rbufptr,
377
    CRYPTO_RWLOCK **lock, uint32_t *caps, struct bio_dgram_pair_st **peer)
378
0
{
379
0
    struct rbuf_map_st *map;
380
0
    CRYPTO_RWLOCK *mylock;
381
0
    struct ring_buf *myrbuf;
382
0
    struct bio_dgram_pair_st *mypeer;
383
0
    uint32_t mycaps;
384
385
0
    if (is_dgram_pair(self)) {
386
0
        map = dgram_rbuf_map_get_peer(self);
387
0
        mylock = map->lock;
388
0
        myrbuf = &map->rbuf;
389
0
        mypeer = map->self;
390
0
        mycaps = map->cap;
391
0
    } else {
392
0
        mylock = self->lock;
393
0
        myrbuf = &self->rbuf;
394
0
        mypeer = self;
395
0
        mycaps = self->cap;
396
0
    }
397
0
    if (lock != NULL)
398
0
        *lock = mylock;
399
0
    if (rbufptr != NULL)
400
0
        *rbufptr = myrbuf;
401
0
    if (peer != NULL)
402
0
        *peer = mypeer;
403
0
    if (caps != NULL)
404
0
        *caps = mycaps;
405
0
}
406
407
0
#define MIN_BUF_LEN (1024)
408
409
static int dgram_pair_init(BIO *bio)
410
0
{
411
0
    struct bio_dgram_pair_st *b = OPENSSL_zalloc(sizeof(*b));
412
413
0
    if (b == NULL)
414
0
        return 0;
415
416
0
    b->mtu = 1472; /* conservative default MTU */
417
    /* default buffer size */
418
0
    b->req_buf_len = 9 * (sizeof(struct dgram_hdr) + b->mtu);
419
420
0
    b->lock = CRYPTO_THREAD_lock_new();
421
0
    if (b->lock == NULL) {
422
0
        OPENSSL_free(b);
423
0
        return 0;
424
0
    }
425
426
0
    bio->ptr = b;
427
0
    return 1;
428
0
}
429
430
static int dgram_mem_init(BIO *bio)
431
0
{
432
0
    struct bio_dgram_pair_st *b;
433
434
0
    if (!dgram_pair_init(bio))
435
0
        return 0;
436
437
0
    b = bio->ptr;
438
439
0
    if (ring_buf_init(&b->rbuf, b->req_buf_len) == 0) {
440
0
        dgram_pair_free(bio);
441
0
        ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
442
0
        return 0;
443
0
    }
444
445
0
    b->grows_on_write = 1;
446
447
0
    bio->init = 1;
448
0
    return 1;
449
0
}
450
451
static int dgram_pair_free(BIO *bio)
452
0
{
453
0
    struct bio_dgram_pair_st *b;
454
455
0
    if (bio == NULL)
456
0
        return 0;
457
458
0
    b = bio->ptr;
459
0
    if (!ossl_assert(b != NULL))
460
0
        return 0;
461
462
    /* We are being freed. Disconnect any peer and destroy buffers. */
463
0
    dgram_pair_ctrl_destroy_bio_pair(bio);
464
465
0
    ring_buf_destroy(&b->rbuf);
466
0
    BIO_ADDR_free(b->local_addr);
467
0
    CRYPTO_THREAD_lock_free(b->lock);
468
0
    OPENSSL_free(b);
469
0
    return 1;
470
0
}
471
472
/* BIO_make_bio_pair (BIO_C_MAKE_BIO_PAIR) */
473
static int dgram_pair_ctrl_make_bio_pair(BIO *bio1, BIO *bio2)
474
0
{
475
0
    struct bio_dgram_pair_st *b1, *b2;
476
0
    struct bio_dgram_peer_st *pair;
477
478
    /* peer must be non-NULL. */
479
0
    if (bio1 == NULL || bio2 == NULL) {
480
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
481
0
        return 0;
482
0
    }
483
484
    /* Ensure the BIO we have been passed is actually a dgram pair BIO. */
485
0
    if (bio1->method != &dgram_pair_method || bio2->method != &dgram_pair_method) {
486
0
        ERR_raise_data(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT,
487
0
            "both BIOs must be BIO_dgram_pair");
488
0
        return 0;
489
0
    }
490
491
0
    b1 = bio1->ptr;
492
0
    b2 = bio2->ptr;
493
494
0
    if (!ossl_assert(b1 != NULL && b2 != NULL)) {
495
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
496
0
        return 0;
497
0
    }
498
499
    /*
500
     * This ctrl cannot be used to associate a BIO pair half which is already
501
     * associated.
502
     */
503
0
    if (b1->pair != NULL || b2->pair != NULL) {
504
0
        ERR_raise_data(ERR_LIB_BIO, BIO_R_IN_USE,
505
0
            "cannot associate a BIO_dgram_pair which is already in use");
506
0
        return 0;
507
0
    }
508
509
0
    if (!ossl_assert(b1->req_buf_len >= MIN_BUF_LEN
510
0
            && b2->req_buf_len >= MIN_BUF_LEN)) {
511
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
512
0
        return 0;
513
0
    }
514
515
    /*
516
     * Create a new pair structure, init it with appropriate
517
     * ring buffers and lock, and assign it to each half of the
518
     * pair.
519
     * Once this is done, each half of the pair uses the shared
520
     * ring buffers/lock available here instead of their own private copy
521
     */
522
0
    pair = OPENSSL_zalloc(sizeof(*pair));
523
0
    if (pair == NULL) {
524
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
525
0
        return 0;
526
0
    }
527
0
    if (!CRYPTO_NEW_REF(&pair->ref_cnt, 2)) {
528
0
        OPENSSL_free(pair);
529
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
530
0
        return 0;
531
0
    }
532
0
    pair->peerlock = CRYPTO_THREAD_lock_new();
533
0
    if (pair->peerlock == NULL) {
534
0
        CRYPTO_FREE_REF(&pair->ref_cnt);
535
0
        OPENSSL_free(pair->peerlock);
536
0
        OPENSSL_free(pair);
537
0
        return 0;
538
0
    }
539
540
0
    if (ring_buf_init(&pair->map[0].rbuf, b1->req_buf_len) == 0) {
541
0
        CRYPTO_FREE_REF(&pair->ref_cnt);
542
0
        CRYPTO_THREAD_lock_free(pair->peerlock);
543
0
        OPENSSL_free(pair);
544
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
545
0
        return 0;
546
0
    }
547
548
0
    if (ring_buf_init(&pair->map[1].rbuf, b2->req_buf_len) == 0) {
549
0
        CRYPTO_FREE_REF(&pair->ref_cnt);
550
0
        CRYPTO_THREAD_lock_free(pair->peerlock);
551
0
        OPENSSL_free(pair);
552
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
553
0
        return 0;
554
0
    }
555
0
    ring_buf_destroy(&b1->rbuf);
556
0
    ring_buf_destroy(&b2->rbuf);
557
0
    pair->map[0].lock = CRYPTO_THREAD_lock_new();
558
0
    pair->map[1].lock = CRYPTO_THREAD_lock_new();
559
0
    if (pair->map[0].lock == NULL || pair->map[1].lock == NULL) {
560
0
        CRYPTO_THREAD_lock_free(pair->map[0].lock);
561
0
        CRYPTO_THREAD_lock_free(pair->map[1].lock);
562
0
        CRYPTO_THREAD_lock_free(pair->peerlock);
563
0
        CRYPTO_FREE_REF(&pair->ref_cnt);
564
0
        OPENSSL_free(pair);
565
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
566
0
        return 0;
567
0
    }
568
0
    pair->map[0].self = b1;
569
0
    pair->map[1].self = b2;
570
0
    pair->map[0].cap = b1->cap;
571
0
    pair->map[1].cap = b2->cap;
572
0
    TSAN_BENIGN(pair, "publishing pair");
573
0
    b1->pair = pair;
574
0
    b2->pair = pair;
575
0
    b1->role = 0;
576
0
    b2->role = 1;
577
0
    bio1->init = 1;
578
0
    bio2->init = 1;
579
0
    return 1;
580
0
}
581
582
/* BIO_destroy_bio_pair (BIO_C_DESTROY_BIO_PAIR) */
583
static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1)
584
0
{
585
0
    struct bio_dgram_pair_st *b1 = bio1->ptr;
586
0
    int ref;
587
0
    int newval = PEER_STATE_ORPHANED;
588
589
    /* Early return if we don't have a peer. */
590
0
    if (b1->pair == NULL)
591
0
        return 1;
592
593
0
    ring_buf_destroy(&b1->rbuf);
594
0
    bio1->init = 0;
595
596
0
    if (ring_buf_init(&b1->rbuf, b1->req_buf_len) == 0)
597
0
        return 0;
598
599
    /*
600
     * Since one half of the pair is going away, we are now
601
     * orphaned
602
     */
603
0
    if (!CRYPTO_atomic_store_int(&b1->pair->peer_state, newval, b1->pair->peerlock))
604
0
        return 0;
605
606
0
    if (!CRYPTO_DOWN_REF(&b1->pair->ref_cnt, &ref))
607
0
        return 0;
608
0
    if (ref == 0) {
609
        /*
610
         * The last half of the pair is leaving, clean up the
611
         * shared data
612
         */
613
0
        CRYPTO_FREE_REF(&b1->pair->ref_cnt);
614
0
        CRYPTO_THREAD_lock_free(b1->pair->map[0].lock);
615
0
        CRYPTO_THREAD_lock_free(b1->pair->map[1].lock);
616
0
        CRYPTO_THREAD_lock_free(b1->pair->peerlock);
617
0
        ring_buf_destroy(&b1->pair->map[0].rbuf);
618
0
        ring_buf_destroy(&b1->pair->map[1].rbuf);
619
0
        OPENSSL_free(b1->pair);
620
0
    }
621
    /*
622
     * Make sure the leaving pair no longer references the shared peer data,
623
     * since it is no longer part of the pair.
624
     */
625
0
    TSAN_BENIGN(b1->pair, "b1 no longer accesses b1->pair");
626
0
    b1->pair = NULL;
627
0
    return 1;
628
0
}
629
630
/* BIO_eof (BIO_CTRL_EOF) */
631
static int dgram_pair_ctrl_eof(BIO *bio)
632
0
{
633
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb = NULL;
634
0
    int peer_state;
635
636
0
    if (!ossl_assert(b != NULL))
637
0
        return -1;
638
639
    /* If we aren't initialized, we can never read anything */
640
0
    if (!bio->init)
641
0
        return 1;
642
0
    if (!is_dgram_pair(b))
643
0
        return 0;
644
645
    /*
646
     * orphaned pairs always return EOF
647
     */
648
0
    if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
649
0
        return -1;
650
651
0
    if (peer_state == PEER_STATE_ORPHANED)
652
0
        return 1;
653
654
0
    dgram_bio_get_peer_data(b, NULL, NULL, NULL, &peerb);
655
0
    if (!ossl_assert(peerb != NULL))
656
0
        return -1;
657
658
    /*
659
     * Since we are emulating datagram semantics, never indicate EOF so long as
660
     * we have a peer.
661
     */
662
0
    return 0;
663
0
}
664
665
/* BIO_set_write_buf_size (BIO_C_SET_WRITE_BUF_SIZE) */
666
static int dgram_pair_ctrl_set_write_buf_size(BIO *bio, size_t len)
667
0
{
668
0
    struct bio_dgram_pair_st *b = bio->ptr;
669
670
    /* Changing buffer sizes is not permitted while a peer is connected. */
671
0
    if (b->pair != NULL) {
672
0
        ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
673
0
        return 0;
674
0
    }
675
676
    /* Enforce minimum size. */
677
0
    if (len < MIN_BUF_LEN)
678
0
        len = MIN_BUF_LEN;
679
680
0
    if (b->rbuf.start != NULL) {
681
0
        if (!ring_buf_resize(&b->rbuf, len))
682
0
            return 0;
683
0
    }
684
685
0
    b->req_buf_len = len;
686
0
    b->grows_on_write = 0;
687
0
    return 1;
688
0
}
689
690
/* BIO_reset (BIO_CTRL_RESET) */
691
static int dgram_pair_ctrl_reset(BIO *bio)
692
0
{
693
0
    struct bio_dgram_pair_st *b = bio->ptr;
694
695
0
    ring_buf_clear(&b->rbuf);
696
0
    return 1;
697
0
}
698
699
/* BIO_pending (BIO_CTRL_PENDING) (Threadsafe) */
700
static size_t dgram_pair_ctrl_pending(BIO *bio)
701
0
{
702
0
    size_t saved_idx, saved_count;
703
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
704
0
    struct dgram_hdr hdr;
705
0
    size_t l;
706
0
    struct ring_buf *rbufptr;
707
0
    CRYPTO_RWLOCK *lock;
708
0
    int peer_state;
709
710
    /* Safe to check; init may not change during this call */
711
0
    if (!bio->init)
712
0
        return 0;
713
0
    if (is_dgram_pair(b)) {
714
0
        if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
715
0
            return 0;
716
717
0
        if (peer_state == PEER_STATE_ORPHANED)
718
0
            return 0;
719
0
    }
720
721
0
    dgram_bio_get_peer_data(b, &rbufptr, &lock, NULL, &readb);
722
723
0
    if (CRYPTO_THREAD_write_lock(lock) == 0)
724
0
        return 0;
725
726
0
    saved_idx = rbufptr->idx[1];
727
0
    saved_count = rbufptr->count;
728
729
0
    l = dgram_pair_read_inner(rbufptr, (uint8_t *)&hdr, sizeof(hdr));
730
731
0
    rbufptr->idx[1] = saved_idx;
732
0
    rbufptr->count = saved_count;
733
734
0
    CRYPTO_THREAD_unlock(lock);
735
736
0
    if (!ossl_assert(l == 0 || l == sizeof(hdr)))
737
0
        return 0;
738
739
0
    return l > 0 ? hdr.len : 0;
740
0
}
741
742
/* BIO_get_write_guarantee (BIO_C_GET_WRITE_GUARANTEE) (Threadsafe) */
743
static size_t dgram_pair_ctrl_get_write_guarantee(BIO *bio)
744
0
{
745
0
    size_t l;
746
0
    struct bio_dgram_pair_st *b = bio->ptr;
747
0
    struct ring_buf *rbufptr;
748
0
    CRYPTO_RWLOCK *lock;
749
750
0
    dgram_bio_get_peer_data(b, &rbufptr, &lock, NULL, NULL);
751
752
0
    if (CRYPTO_THREAD_read_lock(lock) == 0)
753
0
        return 0;
754
755
0
    l = rbufptr->len - rbufptr->count;
756
0
    if (l >= sizeof(struct dgram_hdr))
757
0
        l -= sizeof(struct dgram_hdr);
758
759
    /*
760
     * If the amount of buffer space would not be enough to accommodate the
761
     * worst-case size of a datagram, report no space available.
762
     */
763
0
    if (l < b->mtu)
764
0
        l = 0;
765
766
0
    CRYPTO_THREAD_unlock(lock);
767
0
    return l;
768
0
}
769
770
/* BIO_dgram_get_local_addr_cap (BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP) */
771
static int dgram_pair_ctrl_get_local_addr_cap(BIO *bio)
772
0
{
773
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
774
0
    int peer_state;
775
0
    uint32_t caps;
776
777
0
    if (!bio->init)
778
0
        return 0;
779
780
0
    if (is_dgram_pair(b)) {
781
0
        if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
782
0
            return 0;
783
784
0
        if (peer_state == PEER_STATE_ORPHANED)
785
0
            return 0;
786
0
    }
787
788
0
    dgram_bio_get_peer_data(b, NULL, NULL, &caps, &readb);
789
790
0
    return (~caps & (BIO_DGRAM_CAP_HANDLES_SRC_ADDR | BIO_DGRAM_CAP_PROVIDES_DST_ADDR)) == 0;
791
0
}
792
793
/* BIO_dgram_get_effective_caps (BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS) */
794
static int dgram_pair_ctrl_get_effective_caps(BIO *bio)
795
0
{
796
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
797
0
    int peer_state;
798
0
    uint32_t caps;
799
800
0
    if (b->pair == NULL)
801
0
        return 0;
802
803
0
    if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
804
0
        return 0;
805
806
0
    if (peer_state == PEER_STATE_ORPHANED)
807
0
        return 0;
808
809
0
    dgram_bio_get_peer_data(b, NULL, NULL, &caps, &peerb);
810
811
0
    return caps;
812
0
}
813
814
/* BIO_dgram_get_caps (BIO_CTRL_DGRAM_GET_CAPS) */
815
static uint32_t dgram_pair_ctrl_get_caps(BIO *bio)
816
0
{
817
0
    struct bio_dgram_pair_st *b = bio->ptr;
818
819
0
    return b->cap;
820
0
}
821
822
/* BIO_dgram_set_caps (BIO_CTRL_DGRAM_SET_CAPS) */
823
static int dgram_pair_ctrl_set_caps(BIO *bio, uint32_t caps)
824
0
{
825
0
    struct bio_dgram_pair_st *b = bio->ptr;
826
0
    struct rbuf_map_st *map;
827
828
0
    b->cap = caps;
829
830
0
    if (is_dgram_pair(b)) {
831
0
        map = dgram_rbuf_map_get_self(b);
832
0
        map->cap = caps;
833
0
    }
834
0
    return 1;
835
0
}
836
837
/* BIO_dgram_get_local_addr_enable (BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE) */
838
static int dgram_pair_ctrl_get_local_addr_enable(BIO *bio)
839
0
{
840
0
    struct bio_dgram_pair_st *b = bio->ptr;
841
842
0
    return b->local_addr_enable;
843
0
}
844
845
/* BIO_dgram_set_local_addr_enable (BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE) */
846
static int dgram_pair_ctrl_set_local_addr_enable(BIO *bio, int enable)
847
0
{
848
0
    struct bio_dgram_pair_st *b = bio->ptr;
849
850
0
    if (dgram_pair_ctrl_get_local_addr_cap(bio) == 0)
851
0
        return 0;
852
853
0
    b->local_addr_enable = (enable != 0 ? 1 : 0);
854
0
    return 1;
855
0
}
856
857
/* BIO_dgram_get_mtu (BIO_CTRL_DGRAM_GET_MTU) */
858
static int dgram_pair_ctrl_get_mtu(BIO *bio)
859
0
{
860
0
    struct bio_dgram_pair_st *b = bio->ptr;
861
862
0
    return (int)b->mtu;
863
0
}
864
865
/* BIO_dgram_set_mtu (BIO_CTRL_DGRAM_SET_MTU) */
866
static int dgram_pair_ctrl_set_mtu(BIO *bio, size_t mtu)
867
0
{
868
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
869
0
    int peer_state;
870
871
0
    b->mtu = mtu;
872
873
0
    if (is_dgram_pair(b)) {
874
0
        if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
875
0
            return 0;
876
877
0
        if (peer_state == PEER_STATE_PAIRED) {
878
0
            dgram_bio_get_peer_data(b, NULL, NULL, NULL, &peerb);
879
0
            peerb->mtu = mtu;
880
0
        }
881
0
    }
882
883
0
    return 1;
884
0
}
885
886
/* BIO_dgram_set0_local_addr (BIO_CTRL_DGRAM_SET0_LOCAL_ADDR) */
887
static int dgram_pair_ctrl_set0_local_addr(BIO *bio, BIO_ADDR *addr)
888
0
{
889
0
    struct bio_dgram_pair_st *b = bio->ptr;
890
891
0
    BIO_ADDR_free(b->local_addr);
892
0
    b->local_addr = addr;
893
0
    return 1;
894
0
}
895
896
/* Partially threadsafe (some commands) */
897
static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
898
0
{
899
0
    long ret = 1;
900
0
    struct bio_dgram_pair_st *b = bio->ptr;
901
902
0
    if (!ossl_assert(b != NULL))
903
0
        return 0;
904
905
0
    switch (cmd) {
906
    /*
907
     * BIO_set_write_buf_size: Set the size of the ring buffer used for storing
908
     * datagrams. No more writes can be performed once the buffer is filled up,
909
     * until reads are performed. This cannot be used after a peer is connected.
910
     */
911
0
    case BIO_C_SET_WRITE_BUF_SIZE: /* Non-threadsafe */
912
0
        ret = (long)dgram_pair_ctrl_set_write_buf_size(bio, (size_t)num);
913
0
        break;
914
915
    /*
916
     * BIO_get_write_buf_size: Get ring buffer size.
917
     */
918
0
    case BIO_C_GET_WRITE_BUF_SIZE: /* Non-threadsafe */
919
0
        ret = (long)b->req_buf_len;
920
0
        break;
921
922
    /*
923
     * BIO_reset: Clear all data which was written to this side of the pair.
924
     */
925
0
    case BIO_CTRL_RESET: /* Non-threadsafe */
926
0
        dgram_pair_ctrl_reset(bio);
927
0
        break;
928
929
    /*
930
     * BIO_get_write_guarantee: Any BIO_write providing a buffer less than or
931
     * equal to this value is guaranteed to succeed.
932
     */
933
0
    case BIO_C_GET_WRITE_GUARANTEE: /* Threadsafe */
934
0
        ret = (long)dgram_pair_ctrl_get_write_guarantee(bio);
935
0
        break;
936
937
    /* BIO_pending: Bytes available to read. */
938
0
    case BIO_CTRL_PENDING: /* Threadsafe */
939
0
        ret = (long)dgram_pair_ctrl_pending(bio);
940
0
        break;
941
942
    /* BIO_flush: No-op. */
943
0
    case BIO_CTRL_FLUSH: /* Threadsafe */
944
0
        break;
945
946
    /* BIO_dgram_get_no_trunc */
947
0
    case BIO_CTRL_DGRAM_GET_NO_TRUNC: /* Non-threadsafe */
948
0
        ret = (long)b->no_trunc;
949
0
        break;
950
951
    /* BIO_dgram_set_no_trunc */
952
0
    case BIO_CTRL_DGRAM_SET_NO_TRUNC: /* Non-threadsafe */
953
0
        b->no_trunc = (num > 0);
954
0
        break;
955
956
    /* BIO_dgram_get_local_addr_enable */
957
0
    case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE: /* Non-threadsafe */
958
0
        *(int *)ptr = (int)dgram_pair_ctrl_get_local_addr_enable(bio);
959
0
        break;
960
961
    /* BIO_dgram_set_local_addr_enable */
962
0
    case BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE: /* Non-threadsafe */
963
0
        ret = (long)dgram_pair_ctrl_set_local_addr_enable(bio, num);
964
0
        break;
965
966
    /* BIO_dgram_get_local_addr_cap: Can local addresses be supported? */
967
0
    case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP: /* Non-threadsafe */
968
0
        ret = (long)dgram_pair_ctrl_get_local_addr_cap(bio);
969
0
        break;
970
971
    /* BIO_dgram_get_effective_caps */
972
0
    case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: /* Non-threadsafe */
973
    /* BIO_dgram_get_caps */
974
0
    case BIO_CTRL_DGRAM_GET_CAPS: /* Non-threadsafe */
975
0
        ret = (long)dgram_pair_ctrl_get_caps(bio);
976
0
        break;
977
978
    /* BIO_dgram_set_caps */
979
0
    case BIO_CTRL_DGRAM_SET_CAPS: /* Non-threadsafe */
980
0
        ret = (long)dgram_pair_ctrl_set_caps(bio, (uint32_t)num);
981
0
        break;
982
983
    /* BIO_dgram_get_mtu */
984
0
    case BIO_CTRL_DGRAM_GET_MTU: /* Non-threadsafe */
985
0
        ret = (long)dgram_pair_ctrl_get_mtu(bio);
986
0
        break;
987
988
    /* BIO_dgram_set_mtu */
989
0
    case BIO_CTRL_DGRAM_SET_MTU: /* Non-threadsafe */
990
0
        ret = (long)dgram_pair_ctrl_set_mtu(bio, (uint32_t)num);
991
0
        break;
992
993
0
    case BIO_CTRL_DGRAM_SET0_LOCAL_ADDR:
994
0
        ret = (long)dgram_pair_ctrl_set0_local_addr(bio, (BIO_ADDR *)ptr);
995
0
        break;
996
997
    /*
998
     * BIO_eof: Returns whether this half of the BIO pair is empty of data to
999
     * read.
1000
     */
1001
0
    case BIO_CTRL_EOF: /* Non-threadsafe */
1002
0
        ret = (long)dgram_pair_ctrl_eof(bio);
1003
0
        break;
1004
1005
0
    default:
1006
0
        ret = 0;
1007
0
        break;
1008
0
    }
1009
1010
0
    return ret;
1011
0
}
1012
1013
static long dgram_pair_ctrl(BIO *bio, int cmd, long num, void *ptr)
1014
0
{
1015
0
    long ret = 1;
1016
1017
0
    switch (cmd) {
1018
    /*
1019
     * BIO_make_bio_pair: this is usually used by BIO_new_dgram_pair, though it
1020
     * may be used manually after manually creating each half of a BIO pair
1021
     * using BIO_new. This only needs to be called on one of the BIOs.
1022
     */
1023
0
    case BIO_C_MAKE_BIO_PAIR: /* Non-threadsafe */
1024
0
        ret = (long)dgram_pair_ctrl_make_bio_pair(bio, (BIO *)ptr);
1025
0
        break;
1026
1027
    /*
1028
     * BIO_destroy_bio_pair: Manually disconnect two halves of a BIO pair so
1029
     * that they are no longer peers.
1030
     */
1031
0
    case BIO_C_DESTROY_BIO_PAIR: /* Non-threadsafe */
1032
0
        dgram_pair_ctrl_destroy_bio_pair(bio);
1033
0
        break;
1034
1035
    /* BIO_dgram_get_effective_caps */
1036
0
    case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: /* Non-threadsafe */
1037
0
        ret = (long)dgram_pair_ctrl_get_effective_caps(bio);
1038
0
        break;
1039
1040
0
    default:
1041
0
        ret = dgram_mem_ctrl(bio, cmd, num, ptr);
1042
0
        break;
1043
0
    }
1044
1045
0
    return ret;
1046
0
}
1047
1048
int BIO_new_bio_dgram_pair(BIO **pbio1, size_t writebuf1,
1049
    BIO **pbio2, size_t writebuf2)
1050
0
{
1051
0
    int ret = 0;
1052
0
    long r;
1053
0
    BIO *bio1 = NULL, *bio2 = NULL;
1054
1055
0
    if (writebuf1 > LONG_MAX || writebuf2 > LONG_MAX)
1056
0
        goto err;
1057
1058
0
    bio1 = BIO_new(BIO_s_dgram_pair());
1059
0
    if (bio1 == NULL)
1060
0
        goto err;
1061
1062
0
    bio2 = BIO_new(BIO_s_dgram_pair());
1063
0
    if (bio2 == NULL)
1064
0
        goto err;
1065
1066
0
    if (writebuf1 > 0) {
1067
0
        r = BIO_set_write_buf_size(bio1, (long)writebuf1);
1068
0
        if (r == 0)
1069
0
            goto err;
1070
0
    }
1071
1072
0
    if (writebuf2 > 0) {
1073
0
        r = BIO_set_write_buf_size(bio2, (long)writebuf2);
1074
0
        if (r == 0)
1075
0
            goto err;
1076
0
    }
1077
1078
0
    r = BIO_make_bio_pair(bio1, bio2);
1079
0
    if (r == 0)
1080
0
        goto err;
1081
1082
0
    ret = 1;
1083
0
err:
1084
0
    if (ret == 0) {
1085
0
        BIO_free(bio1);
1086
0
        bio1 = NULL;
1087
0
        BIO_free(bio2);
1088
0
        bio2 = NULL;
1089
0
    }
1090
1091
0
    *pbio1 = bio1;
1092
0
    *pbio2 = bio2;
1093
0
    return ret;
1094
0
}
1095
1096
/* Must hold peer write lock */
1097
static size_t dgram_pair_read_inner(struct ring_buf *rbufptr, uint8_t *buf, size_t sz)
1098
0
{
1099
0
    size_t total_read = 0;
1100
1101
    /*
1102
     * We repeat pops from the ring buffer for as long as we have more
1103
     * application *buffer to fill until we fail. We may not be able to pop
1104
     * enough data to fill the buffer in one operation if the ring buffer wraps
1105
     * around, but there may still be more data available.
1106
     */
1107
0
    while (sz > 0) {
1108
0
        uint8_t *src_buf = NULL;
1109
0
        size_t src_len = 0;
1110
1111
        /*
1112
         * There are two BIO instances, each with a ringbuf. We read from the
1113
         * peer ringbuf and write to our own ringbuf.
1114
         */
1115
0
        ring_buf_tail(rbufptr, &src_buf, &src_len);
1116
0
        if (src_len == 0)
1117
0
            break;
1118
1119
0
        if (src_len > sz)
1120
0
            src_len = sz;
1121
1122
0
        if (buf != NULL)
1123
0
            memcpy(buf, src_buf, src_len);
1124
1125
0
        ring_buf_pop(rbufptr, src_len);
1126
1127
0
        if (buf != NULL)
1128
0
            buf += src_len;
1129
0
        total_read += src_len;
1130
0
        sz -= src_len;
1131
0
    }
1132
1133
0
    return total_read;
1134
0
}
1135
1136
/*
1137
 * Must hold peer write lock. Returns number of bytes processed or negated BIO
1138
 * response code.
1139
 */
1140
static ossl_ssize_t dgram_pair_read_actual(BIO *bio, char *buf, size_t sz,
1141
    BIO_ADDR *local, BIO_ADDR *peer,
1142
    int is_multi)
1143
0
{
1144
0
    size_t l, trunc = 0, saved_idx, saved_count;
1145
0
    struct bio_dgram_pair_st *b = bio->ptr;
1146
0
    struct dgram_hdr hdr;
1147
0
    struct ring_buf *rbufptr;
1148
1149
0
    if (!is_multi)
1150
0
        BIO_clear_retry_flags(bio);
1151
1152
0
    if (!bio->init)
1153
0
        return -BIO_R_UNINITIALIZED;
1154
1155
0
    if (!ossl_assert(b != NULL))
1156
0
        return -BIO_R_TRANSFER_ERROR;
1157
1158
0
    dgram_bio_get_peer_data(b, &rbufptr, NULL, NULL, NULL);
1159
1160
0
    if (!ossl_assert(rbufptr->start != NULL))
1161
0
        return -BIO_R_TRANSFER_ERROR;
1162
1163
0
    if (sz > 0 && buf == NULL)
1164
0
        return -BIO_R_INVALID_ARGUMENT;
1165
1166
    /* If the caller wants to know the local address, it must be enabled */
1167
0
    if (local != NULL && b->local_addr_enable == 0)
1168
0
        return -BIO_R_LOCAL_ADDR_NOT_AVAILABLE;
1169
1170
    /* Read the header. */
1171
0
    saved_idx = rbufptr->idx[1];
1172
0
    saved_count = rbufptr->count;
1173
0
    l = dgram_pair_read_inner(rbufptr, (uint8_t *)&hdr, sizeof(hdr));
1174
0
    if (l == 0) {
1175
        /* Buffer was empty. */
1176
0
        if (!is_multi)
1177
0
            BIO_set_retry_read(bio);
1178
0
        return -BIO_R_NON_FATAL;
1179
0
    }
1180
1181
0
    if (!ossl_assert(l == sizeof(hdr)))
1182
        /*
1183
         * This should not be possible as headers (and their following payloads)
1184
         * should always be written atomically.
1185
         */
1186
0
        return -BIO_R_BROKEN_PIPE;
1187
1188
0
    if (sz > hdr.len) {
1189
0
        sz = hdr.len;
1190
0
    } else if (sz < hdr.len) {
1191
        /* Truncation is occurring. */
1192
0
        trunc = hdr.len - sz;
1193
0
        if (b->no_trunc) {
1194
            /* Restore original state. */
1195
0
            rbufptr->idx[1] = saved_idx;
1196
0
            rbufptr->count = saved_count;
1197
0
            return -BIO_R_NON_FATAL;
1198
0
        }
1199
0
    }
1200
1201
0
    l = dgram_pair_read_inner(rbufptr, (uint8_t *)buf, sz);
1202
0
    if (!ossl_assert(l == sz))
1203
        /* We were somehow not able to read the entire datagram. */
1204
0
        return -BIO_R_TRANSFER_ERROR;
1205
1206
    /*
1207
     * If the datagram was truncated due to an inadequate buffer, discard the
1208
     * remainder.
1209
     */
1210
0
    if (trunc > 0 && !ossl_assert(dgram_pair_read_inner(rbufptr, NULL, trunc) == trunc))
1211
        /* We were somehow not able to read/skip the entire datagram. */
1212
0
        return -BIO_R_TRANSFER_ERROR;
1213
1214
0
    if (local != NULL)
1215
0
        *local = hdr.dst_addr;
1216
0
    if (peer != NULL)
1217
0
        *peer = hdr.src_addr;
1218
1219
0
    return (ossl_ssize_t)l;
1220
0
}
1221
1222
/* Threadsafe */
1223
static int dgram_pair_lock_both_write(struct bio_dgram_pair_st *a,
1224
    struct bio_dgram_pair_st *b)
1225
0
{
1226
0
    struct bio_dgram_pair_st *x, *y;
1227
1228
0
    if (is_dgram_pair(b)) {
1229
0
        if (CRYPTO_THREAD_write_lock(b->pair->map[0].lock) == 0)
1230
0
            return 0;
1231
0
        if (CRYPTO_THREAD_write_lock(b->pair->map[1].lock) == 0) {
1232
0
            CRYPTO_THREAD_unlock(b->pair->map[0].lock);
1233
0
            return 0;
1234
0
        }
1235
0
    } else {
1236
0
        x = (a->role == 1) ? a : b;
1237
0
        y = (a->role == 1) ? b : a;
1238
1239
0
        if (!ossl_assert(a->role != b->role))
1240
0
            return 0;
1241
1242
0
        if (!ossl_assert(a != b && x != y))
1243
0
            return 0;
1244
1245
0
        if (CRYPTO_THREAD_write_lock(x->lock) == 0)
1246
0
            return 0;
1247
1248
0
        if (CRYPTO_THREAD_write_lock(y->lock) == 0) {
1249
0
            CRYPTO_THREAD_unlock(x->lock);
1250
0
            return 0;
1251
0
        }
1252
0
    }
1253
1254
0
    return 1;
1255
0
}
1256
1257
static void dgram_pair_unlock_both(struct bio_dgram_pair_st *a,
1258
    struct bio_dgram_pair_st *b)
1259
0
{
1260
0
    if (is_dgram_pair(b)) {
1261
0
        CRYPTO_THREAD_unlock(b->pair->map[0].lock);
1262
0
        CRYPTO_THREAD_unlock(b->pair->map[1].lock);
1263
0
    } else {
1264
0
        CRYPTO_THREAD_unlock(a->lock);
1265
0
        CRYPTO_THREAD_unlock(b->lock);
1266
0
    }
1267
0
}
1268
1269
/* Threadsafe */
1270
static int dgram_pair_read(BIO *bio, char *buf, int sz_)
1271
0
{
1272
0
    int ret;
1273
0
    ossl_ssize_t l;
1274
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
1275
0
    int peer_state;
1276
1277
0
    if (sz_ < 0) {
1278
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1279
0
        return -1;
1280
0
    }
1281
1282
0
    if (b->pair == NULL) {
1283
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
1284
0
        return -1;
1285
0
    }
1286
1287
0
    if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
1288
0
        return -1;
1289
1290
0
    if (peer_state == PEER_STATE_ORPHANED) {
1291
0
        ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1292
0
        return -1;
1293
0
    }
1294
1295
0
    dgram_bio_get_peer_data(b, NULL, NULL, NULL, &peerb);
1296
1297
    /*
1298
     * For BIO_read we have to acquire both locks because we touch the retry
1299
     * flags on the local bio. (This is avoided in the recvmmsg case as it does
1300
     * not touch the retry flags.)
1301
     */
1302
0
    if (dgram_pair_lock_both_write(peerb, b) == 0) {
1303
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1304
0
        return -1;
1305
0
    }
1306
1307
0
    l = dgram_pair_read_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1308
0
    if (l < 0) {
1309
0
        if (l != -BIO_R_NON_FATAL)
1310
0
            ERR_raise(ERR_LIB_BIO, (int)-l);
1311
0
        ret = -1;
1312
0
    } else {
1313
0
        ret = (int)l;
1314
0
    }
1315
1316
0
    dgram_pair_unlock_both(peerb, b);
1317
0
    return ret;
1318
0
}
1319
1320
/* Threadsafe */
1321
static int dgram_pair_recvmmsg(BIO *bio, BIO_MSG *msg,
1322
    size_t stride, size_t num_msg,
1323
    uint64_t flags,
1324
    size_t *num_processed)
1325
0
{
1326
0
    int ret;
1327
0
    ossl_ssize_t l;
1328
0
    BIO_MSG *m;
1329
0
    size_t i;
1330
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
1331
0
    CRYPTO_RWLOCK *lock;
1332
0
    int peer_state;
1333
1334
0
    if (num_msg == 0) {
1335
0
        *num_processed = 0;
1336
0
        return 1;
1337
0
    }
1338
1339
0
    if (!bio->init) {
1340
0
        ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1341
0
        *num_processed = 0;
1342
0
        return 0;
1343
0
    }
1344
1345
0
    if (is_dgram_pair(b)) {
1346
0
        if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock)) {
1347
0
            *num_processed = 0;
1348
0
            return 0;
1349
0
        }
1350
1351
0
        if (peer_state == PEER_STATE_ORPHANED) {
1352
0
            *num_processed = 0;
1353
0
            ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1354
0
            return 0;
1355
0
        }
1356
0
    }
1357
1358
0
    dgram_bio_get_peer_data(b, NULL, &lock, NULL, &readb);
1359
0
    if (CRYPTO_THREAD_write_lock(lock) == 0) {
1360
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1361
0
        *num_processed = 0;
1362
0
        return 0;
1363
0
    }
1364
1365
0
    for (i = 0; i < num_msg; ++i) {
1366
0
        m = &BIO_MSG_N(msg, i);
1367
0
        l = dgram_pair_read_actual(bio, m->data, m->data_len,
1368
0
            m->local, m->peer, 1);
1369
0
        if (l < 0) {
1370
0
            *num_processed = i;
1371
0
            if (i > 0) {
1372
0
                ret = 1;
1373
0
            } else {
1374
0
                ERR_raise(ERR_LIB_BIO, (int)-l);
1375
0
                ret = 0;
1376
0
            }
1377
0
            goto out;
1378
0
        }
1379
1380
0
        m->data_len = l;
1381
0
        m->flags = 0;
1382
0
    }
1383
1384
0
    *num_processed = i;
1385
0
    ret = 1;
1386
0
out:
1387
0
    CRYPTO_THREAD_unlock(lock);
1388
0
    return ret;
1389
0
}
1390
1391
/* Threadsafe */
1392
static int dgram_mem_read(BIO *bio, char *buf, int sz_)
1393
0
{
1394
0
    int ret;
1395
0
    ossl_ssize_t l;
1396
0
    struct bio_dgram_pair_st *b = bio->ptr;
1397
1398
0
    if (sz_ < 0) {
1399
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1400
0
        return -1;
1401
0
    }
1402
1403
0
    if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1404
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1405
0
        return -1;
1406
0
    }
1407
1408
0
    l = dgram_pair_read_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1409
0
    if (l < 0) {
1410
0
        if (l != -BIO_R_NON_FATAL)
1411
0
            ERR_raise(ERR_LIB_BIO, (int)-l);
1412
0
        ret = -1;
1413
0
    } else {
1414
0
        ret = (int)l;
1415
0
    }
1416
1417
0
    CRYPTO_THREAD_unlock(b->lock);
1418
0
    return ret;
1419
0
}
1420
1421
/*
1422
 * Calculate the array growth based on the target size.
1423
 *
1424
 * The growth factor is a rational number and is defined by a numerator
1425
 * and a denominator.  According to Andrew Koenig in his paper "Why Are
1426
 * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
1427
 * than the golden ratio (1.618...).
1428
 *
1429
 * We use an expansion factor of 8 / 5 = 1.6
1430
 */
1431
static const size_t max_rbuf_size = SIZE_MAX / 2; /* unlimited in practice */
1432
static ossl_inline size_t compute_rbuf_growth(size_t target, size_t current)
1433
0
{
1434
0
    int err = 0;
1435
1436
0
    while (current < target) {
1437
0
        if (current >= max_rbuf_size)
1438
0
            return 0;
1439
1440
0
        current = safe_muldiv_size_t(current, 8, 5, &err);
1441
0
        if (err)
1442
0
            return 0;
1443
0
        if (current >= max_rbuf_size)
1444
0
            current = max_rbuf_size;
1445
0
    }
1446
0
    return current;
1447
0
}
1448
1449
/* Must hold local write lock */
1450
static size_t dgram_pair_write_inner(struct bio_dgram_pair_st *b,
1451
    const uint8_t *buf, size_t sz)
1452
0
{
1453
0
    size_t total_written = 0;
1454
0
    struct ring_buf *rbufptr;
1455
1456
0
    dgram_bio_get_self_data(b, &rbufptr, NULL);
1457
1458
    /*
1459
     * We repeat pushes to the ring buffer for as long as we have data until we
1460
     * fail. We may not be able to push in one operation if the ring buffer
1461
     * wraps around, but there may still be more room for data.
1462
     */
1463
0
    while (sz > 0) {
1464
0
        size_t dst_len;
1465
0
        uint8_t *dst_buf;
1466
1467
        /*
1468
         * There are two BIO instances, each with a ringbuf. We write to our own
1469
         * ringbuf and read from the peer ringbuf.
1470
         */
1471
0
        ring_buf_head(rbufptr, &dst_buf, &dst_len);
1472
0
        if (dst_len == 0) {
1473
0
            size_t new_len;
1474
1475
0
            if (!b->grows_on_write) /* resize only if size not set explicitly */
1476
0
                break;
1477
            /* increase the size */
1478
0
            new_len = compute_rbuf_growth(b->req_buf_len + sz, b->req_buf_len);
1479
0
            if (new_len == 0 || !ring_buf_resize(rbufptr, new_len))
1480
0
                break;
1481
0
            b->req_buf_len = new_len;
1482
0
        }
1483
1484
0
        if (dst_len > sz)
1485
0
            dst_len = sz;
1486
1487
0
        memcpy(dst_buf, buf, dst_len);
1488
0
        ring_buf_push(rbufptr, dst_len);
1489
1490
0
        buf += dst_len;
1491
0
        sz -= dst_len;
1492
0
        total_written += dst_len;
1493
0
    }
1494
1495
0
    return total_written;
1496
0
}
1497
1498
/*
1499
 * Must hold local write lock. Returns number of bytes processed or negated BIO
1500
 * response code.
1501
 */
1502
static ossl_ssize_t dgram_pair_write_actual(BIO *bio, const char *buf, size_t sz,
1503
    const BIO_ADDR *local, const BIO_ADDR *peer,
1504
    int is_multi)
1505
0
{
1506
0
    static const BIO_ADDR zero_addr;
1507
0
    size_t saved_idx, saved_count;
1508
0
    struct bio_dgram_pair_st *b = bio->ptr;
1509
0
    struct dgram_hdr hdr = { 0 };
1510
0
    struct ring_buf *rbufptr;
1511
0
    int peer_state;
1512
0
    uint32_t caps;
1513
1514
0
    if (!is_multi)
1515
0
        BIO_clear_retry_flags(bio);
1516
1517
0
    if (!bio->init)
1518
0
        return -BIO_R_UNINITIALIZED;
1519
1520
0
    if (is_dgram_pair(b)) {
1521
0
        if (!CRYPTO_atomic_load_int(&b->pair->peer_state, &peer_state, b->pair->peerlock))
1522
0
            return -BIO_R_UNINITIALIZED;
1523
0
        if (peer_state == PEER_STATE_ORPHANED)
1524
0
            return -BIO_R_BROKEN_PIPE;
1525
0
    }
1526
1527
0
    dgram_bio_get_self_data(b, &rbufptr, NULL);
1528
1529
0
    if (!ossl_assert(b != NULL && rbufptr->start != NULL))
1530
0
        return -BIO_R_TRANSFER_ERROR;
1531
1532
0
    if (sz > 0 && buf == NULL)
1533
0
        return -BIO_R_INVALID_ARGUMENT;
1534
1535
0
    if (local != NULL && b->local_addr_enable == 0)
1536
0
        return -BIO_R_LOCAL_ADDR_NOT_AVAILABLE;
1537
1538
0
    dgram_bio_get_peer_data(b, NULL, NULL, &caps, NULL);
1539
1540
0
    if (peer != NULL && (caps & BIO_DGRAM_CAP_HANDLES_DST_ADDR) == 0)
1541
0
        return -BIO_R_PEER_ADDR_NOT_AVAILABLE;
1542
1543
0
    hdr.len = sz;
1544
0
    hdr.dst_addr = (peer != NULL ? *peer : zero_addr);
1545
0
    if (local == NULL)
1546
0
        local = b->local_addr;
1547
0
    hdr.src_addr = (local != NULL ? *local : zero_addr);
1548
1549
0
    saved_idx = rbufptr->idx[0];
1550
0
    saved_count = rbufptr->count;
1551
0
    if (dgram_pair_write_inner(b, (const uint8_t *)&hdr, sizeof(hdr)) != sizeof(hdr)
1552
0
        || dgram_pair_write_inner(b, (const uint8_t *)buf, sz) != sz) {
1553
        /*
1554
         * We were not able to push the header and the entirety of the payload
1555
         * onto the ring buffer, so abort and roll back the ring buffer state.
1556
         */
1557
0
        rbufptr->idx[0] = saved_idx;
1558
0
        rbufptr->count = saved_count;
1559
0
        if (!is_multi)
1560
0
            BIO_set_retry_write(bio);
1561
0
        return -BIO_R_NON_FATAL;
1562
0
    }
1563
1564
0
    return sz;
1565
0
}
1566
1567
/* Threadsafe */
1568
static int dgram_pair_write(BIO *bio, const char *buf, int sz_)
1569
0
{
1570
0
    int ret;
1571
0
    ossl_ssize_t l;
1572
0
    struct bio_dgram_pair_st *b = bio->ptr;
1573
0
    CRYPTO_RWLOCK *lock;
1574
1575
0
    if (sz_ < 0) {
1576
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1577
0
        return -1;
1578
0
    }
1579
1580
0
    dgram_bio_get_self_data(b, NULL, &lock);
1581
1582
0
    if (CRYPTO_THREAD_write_lock(lock) == 0) {
1583
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1584
0
        return -1;
1585
0
    }
1586
1587
0
    l = dgram_pair_write_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1588
0
    if (l < 0) {
1589
0
        ERR_raise(ERR_LIB_BIO, (int)-l);
1590
0
        ret = -1;
1591
0
    } else {
1592
0
        ret = (int)l;
1593
0
    }
1594
1595
0
    CRYPTO_THREAD_unlock(lock);
1596
0
    return ret;
1597
0
}
1598
1599
/* Threadsafe */
1600
static int dgram_pair_sendmmsg(BIO *bio, BIO_MSG *msg,
1601
    size_t stride, size_t num_msg,
1602
    uint64_t flags, size_t *num_processed)
1603
0
{
1604
0
    ossl_ssize_t l;
1605
0
    BIO_MSG *m;
1606
0
    size_t i;
1607
0
    struct bio_dgram_pair_st *b = bio->ptr;
1608
0
    int ret = 0;
1609
0
    CRYPTO_RWLOCK *lock;
1610
1611
0
    if (num_msg == 0) {
1612
0
        *num_processed = 0;
1613
0
        return 1;
1614
0
    }
1615
1616
0
    dgram_bio_get_self_data(b, NULL, &lock);
1617
1618
0
    if (CRYPTO_THREAD_write_lock(lock) == 0) {
1619
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1620
0
        *num_processed = 0;
1621
0
        return 0;
1622
0
    }
1623
1624
0
    for (i = 0; i < num_msg; ++i) {
1625
0
        m = &BIO_MSG_N(msg, i);
1626
0
        l = dgram_pair_write_actual(bio, m->data, m->data_len,
1627
0
            m->local, m->peer, 1);
1628
0
        if (l < 0) {
1629
0
            *num_processed = i;
1630
0
            if (i > 0) {
1631
0
                ret = 1;
1632
0
            } else {
1633
0
                ERR_raise(ERR_LIB_BIO, (int)-l);
1634
0
            }
1635
0
            goto out;
1636
0
        }
1637
1638
0
        m->flags = 0;
1639
0
    }
1640
1641
0
    *num_processed = i;
1642
0
    ret = 1;
1643
0
out:
1644
0
    CRYPTO_THREAD_unlock(lock);
1645
0
    return ret;
1646
0
}
1647
1648
#endif