pair.c
Go to the documentation of this file.
1 /* ====================================================================
2  * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  * software must display the following acknowledgment:
18  * "This product includes software developed by the OpenSSL Project
19  * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  * endorse or promote products derived from this software without
23  * prior written permission. For written permission, please contact
24  * openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  * nor may "OpenSSL" appear in their names without prior written
28  * permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  * acknowledgment:
32  * "This product includes software developed by the OpenSSL Project
33  * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This product includes cryptographic software written by Eric Young
50  * (eay@cryptsoft.com). This product includes software written by Tim
51  * Hudson (tjh@cryptsoft.com). */
52 
53 #include <openssl/bio.h>
54 
55 #include <assert.h>
56 #include <string.h>
57 
58 #include <openssl/err.h>
59 #include <openssl/mem.h>
60 
61 #include "../internal.h"
62 
63 
64 struct bio_bio_st {
65  BIO *peer; // NULL if buf == NULL.
66  // If peer != NULL, then peer->ptr is also a bio_bio_st,
67  // and its "peer" member points back to us.
68  // peer != NULL iff init != 0 in the BIO.
69 
70  // This is for what we write (i.e. reading uses peer's struct):
71  int closed; // valid iff peer != NULL
72  size_t len; // valid iff buf != NULL; 0 if peer == NULL
73  size_t offset; // valid iff buf != NULL; 0 if len == 0
74  size_t size;
75  uint8_t *buf; // "size" elements (if != NULL)
76 
77  size_t request; // valid iff peer != NULL; 0 if len != 0,
78  // otherwise set by peer to number of bytes
79  // it (unsuccessfully) tried to read,
80  // never more than buffer space (size-len) warrants.
81 };
82 
83 static int bio_new(BIO *bio) {
84  struct bio_bio_st *b;
85 
86  b = OPENSSL_malloc(sizeof *b);
87  if (b == NULL) {
88  return 0;
89  }
90  OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
91 
92  b->size = 17 * 1024; // enough for one TLS record (just a default)
93  bio->ptr = b;
94  return 1;
95 }
96 
97 static void bio_destroy_pair(BIO *bio) {
98  struct bio_bio_st *b = bio->ptr;
99  BIO *peer_bio;
100  struct bio_bio_st *peer_b;
101 
102  if (b == NULL) {
103  return;
104  }
105 
106  peer_bio = b->peer;
107  if (peer_bio == NULL) {
108  return;
109  }
110 
111  peer_b = peer_bio->ptr;
112 
113  assert(peer_b != NULL);
114  assert(peer_b->peer == bio);
115 
116  peer_b->peer = NULL;
117  peer_bio->init = 0;
118  assert(peer_b->buf != NULL);
119  peer_b->len = 0;
120  peer_b->offset = 0;
121 
122  b->peer = NULL;
123  bio->init = 0;
124  assert(b->buf != NULL);
125  b->len = 0;
126  b->offset = 0;
127 }
128 
129 static int bio_free(BIO *bio) {
130  struct bio_bio_st *b = bio->ptr;
131 
132  assert(b != NULL);
133 
134  if (b->peer) {
135  bio_destroy_pair(bio);
136  }
137 
138  OPENSSL_free(b->buf);
139  OPENSSL_free(b);
140 
141  return 1;
142 }
143 
144 static int bio_read(BIO *bio, char *buf, int size_) {
145  size_t size = size_;
146  size_t rest;
147  struct bio_bio_st *b, *peer_b;
148 
150 
151  if (!bio->init) {
152  return 0;
153  }
154 
155  b = bio->ptr;
156  assert(b != NULL);
157  assert(b->peer != NULL);
158  peer_b = b->peer->ptr;
159  assert(peer_b != NULL);
160  assert(peer_b->buf != NULL);
161 
162  peer_b->request = 0; // will be set in "retry_read" situation
163 
164  if (buf == NULL || size == 0) {
165  return 0;
166  }
167 
168  if (peer_b->len == 0) {
169  if (peer_b->closed) {
170  return 0; // writer has closed, and no data is left
171  } else {
172  BIO_set_retry_read(bio); // buffer is empty
173  if (size <= peer_b->size) {
174  peer_b->request = size;
175  } else {
176  // don't ask for more than the peer can
177  // deliver in one write
178  peer_b->request = peer_b->size;
179  }
180  return -1;
181  }
182  }
183 
184  // we can read
185  if (peer_b->len < size) {
186  size = peer_b->len;
187  }
188 
189  // now read "size" bytes
190  rest = size;
191 
192  assert(rest > 0);
193  // one or two iterations
194  do {
195  size_t chunk;
196 
197  assert(rest <= peer_b->len);
198  if (peer_b->offset + rest <= peer_b->size) {
199  chunk = rest;
200  } else {
201  // wrap around ring buffer
202  chunk = peer_b->size - peer_b->offset;
203  }
204  assert(peer_b->offset + chunk <= peer_b->size);
205 
206  OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
207 
208  peer_b->len -= chunk;
209  if (peer_b->len) {
210  peer_b->offset += chunk;
211  assert(peer_b->offset <= peer_b->size);
212  if (peer_b->offset == peer_b->size) {
213  peer_b->offset = 0;
214  }
215  buf += chunk;
216  } else {
217  // buffer now empty, no need to advance "buf"
218  assert(chunk == rest);
219  peer_b->offset = 0;
220  }
221  rest -= chunk;
222  } while (rest);
223 
224  return size;
225 }
226 
227 static int bio_write(BIO *bio, const char *buf, int num_) {
228  size_t num = num_;
229  size_t rest;
230  struct bio_bio_st *b;
231 
233 
234  if (!bio->init || buf == NULL || num == 0) {
235  return 0;
236  }
237 
238  b = bio->ptr;
239  assert(b != NULL);
240  assert(b->peer != NULL);
241  assert(b->buf != NULL);
242 
243  b->request = 0;
244  if (b->closed) {
245  // we already closed
247  return -1;
248  }
249 
250  assert(b->len <= b->size);
251 
252  if (b->len == b->size) {
253  BIO_set_retry_write(bio); // buffer is full
254  return -1;
255  }
256 
257  // we can write
258  if (num > b->size - b->len) {
259  num = b->size - b->len;
260  }
261 
262  // now write "num" bytes
263  rest = num;
264 
265  assert(rest > 0);
266  // one or two iterations
267  do {
268  size_t write_offset;
269  size_t chunk;
270 
271  assert(b->len + rest <= b->size);
272 
273  write_offset = b->offset + b->len;
274  if (write_offset >= b->size) {
275  write_offset -= b->size;
276  }
277  // b->buf[write_offset] is the first byte we can write to.
278 
279  if (write_offset + rest <= b->size) {
280  chunk = rest;
281  } else {
282  // wrap around ring buffer
283  chunk = b->size - write_offset;
284  }
285 
286  OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
287 
288  b->len += chunk;
289 
290  assert(b->len <= b->size);
291 
292  rest -= chunk;
293  buf += chunk;
294  } while (rest);
295 
296  return num;
297 }
298 
299 static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
300  size_t writebuf2_len) {
301  struct bio_bio_st *b1, *b2;
302 
303  assert(bio1 != NULL);
304  assert(bio2 != NULL);
305 
306  b1 = bio1->ptr;
307  b2 = bio2->ptr;
308 
309  if (b1->peer != NULL || b2->peer != NULL) {
311  return 0;
312  }
313 
314  if (b1->buf == NULL) {
315  if (writebuf1_len) {
316  b1->size = writebuf1_len;
317  }
318  b1->buf = OPENSSL_malloc(b1->size);
319  if (b1->buf == NULL) {
321  return 0;
322  }
323  b1->len = 0;
324  b1->offset = 0;
325  }
326 
327  if (b2->buf == NULL) {
328  if (writebuf2_len) {
329  b2->size = writebuf2_len;
330  }
331  b2->buf = OPENSSL_malloc(b2->size);
332  if (b2->buf == NULL) {
334  return 0;
335  }
336  b2->len = 0;
337  b2->offset = 0;
338  }
339 
340  b1->peer = bio2;
341  b1->closed = 0;
342  b1->request = 0;
343  b2->peer = bio1;
344  b2->closed = 0;
345  b2->request = 0;
346 
347  bio1->init = 1;
348  bio2->init = 1;
349 
350  return 1;
351 }
352 
353 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
354  long ret;
355  struct bio_bio_st *b = bio->ptr;
356 
357  assert(b != NULL);
358 
359  switch (cmd) {
360  // specific CTRL codes
361 
363  ret = (long)b->size;
364  break;
365 
367  // How many bytes can the caller feed to the next write
368  // without having to keep any?
369  if (b->peer == NULL || b->closed) {
370  ret = 0;
371  } else {
372  ret = (long)b->size - b->len;
373  }
374  break;
375 
377  // If the peer unsuccessfully tried to read, how many bytes
378  // were requested? (As with BIO_CTRL_PENDING, that number
379  // can usually be treated as boolean.)
380  ret = (long)b->request;
381  break;
382 
384  // Reset request. (Can be useful after read attempts
385  // at the other side that are meant to be non-blocking,
386  // e.g. when probing SSL_read to see if any data is
387  // available.)
388  b->request = 0;
389  ret = 1;
390  break;
391 
392  case BIO_C_SHUTDOWN_WR:
393  // similar to shutdown(..., SHUT_WR)
394  b->closed = 1;
395  ret = 1;
396  break;
397 
398  // standard CTRL codes follow
399 
400  case BIO_CTRL_GET_CLOSE:
401  ret = bio->shutdown;
402  break;
403 
404  case BIO_CTRL_SET_CLOSE:
405  bio->shutdown = (int)num;
406  ret = 1;
407  break;
408 
409  case BIO_CTRL_PENDING:
410  if (b->peer != NULL) {
411  struct bio_bio_st *peer_b = b->peer->ptr;
412  ret = (long)peer_b->len;
413  } else {
414  ret = 0;
415  }
416  break;
417 
418  case BIO_CTRL_WPENDING:
419  ret = 0;
420  if (b->buf != NULL) {
421  ret = (long)b->len;
422  }
423  break;
424 
425  case BIO_CTRL_FLUSH:
426  ret = 1;
427  break;
428 
429  case BIO_CTRL_EOF: {
430  BIO *other_bio = ptr;
431 
432  if (other_bio) {
433  struct bio_bio_st *other_b = other_bio->ptr;
434  assert(other_b != NULL);
435  ret = other_b->len == 0 && other_b->closed;
436  } else {
437  ret = 1;
438  }
439  } break;
440 
441  default:
442  ret = 0;
443  }
444  return ret;
445 }
446 
447 
448 static const BIO_METHOD methods_biop = {
449  BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
450  NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */,
451 };
452 
453 static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
454 
455 int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
456  BIO** bio2_p, size_t writebuf2_len) {
457  BIO *bio1 = BIO_new(bio_s_bio());
458  BIO *bio2 = BIO_new(bio_s_bio());
459  if (bio1 == NULL || bio2 == NULL ||
460  !bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
461  BIO_free(bio1);
462  BIO_free(bio2);
463  *bio1_p = NULL;
464  *bio2_p = NULL;
465  return 0;
466  }
467 
468  *bio1_p = bio1;
469  *bio2_p = bio2;
470  return 1;
471 }
472 
474  return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
475 }
476 
478  return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
479 }
480 
481 int BIO_shutdown_wr(BIO *bio) {
482  return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
483 }
bio_method_st
Definition: bio.h:808
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
BIO_C_GET_WRITE_GUARANTEE
#define BIO_C_GET_WRITE_GUARANTEE
Definition: bio.h:883
BIO_CTRL_WPENDING
#define BIO_CTRL_WPENDING
Definition: bio.h:715
BIO_C_GET_WRITE_BUF_SIZE
#define BIO_C_GET_WRITE_BUF_SIZE
Definition: bio.h:882
bio_bio_st::buf
uint8_t * buf
Definition: pair.c:75
BIO_shutdown_wr
int BIO_shutdown_wr(BIO *bio)
Definition: pair.c:481
BIO_R_IN_USE
#define BIO_R_IN_USE
Definition: bio.h:924
BIO_new_bio_pair
int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1_len, BIO **bio2_p, size_t writebuf2_len)
Definition: pair.c:455
BIO_ctrl_get_write_guarantee
size_t BIO_ctrl_get_write_guarantee(BIO *bio)
Definition: pair.c:477
bio_st
Definition: bio.h:822
bio_free
static int bio_free(BIO *bio)
Definition: pair.c:129
bio_st::ptr
void * ptr
Definition: bio.h:838
BIO_set_retry_write
#define BIO_set_retry_write
Definition: boringssl_prefix_symbols.h:856
bio_bio_st::peer
BIO * peer
Definition: pair.c:65
bio_bio_st::closed
int closed
Definition: pair.c:71
OPENSSL_PUT_ERROR
#define OPENSSL_PUT_ERROR(library, reason)
Definition: err.h:423
bio_make_pair
static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len, size_t writebuf2_len)
Definition: pair.c:299
bio.h
string.h
bio_st::init
int init
Definition: bio.h:826
bio_new
static int bio_new(BIO *bio)
Definition: pair.c:83
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
bio_bio_st::len
size_t len
Definition: pair.c:72
bio_s_bio
static const BIO_METHOD * bio_s_bio(void)
Definition: pair.c:453
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
OPENSSL_memset
static void * OPENSSL_memset(void *dst, int c, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:835
BIO_CTRL_EOF
#define BIO_CTRL_EOF
Definition: bio.h:693
bio_bio_st
Definition: pair.c:64
OPENSSL_malloc
#define OPENSSL_malloc
Definition: boringssl_prefix_symbols.h:1885
b2
T::second_type b2
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:308
BIO_ctrl
#define BIO_ctrl
Definition: boringssl_prefix_symbols.h:779
OPENSSL_memcpy
static void * OPENSSL_memcpy(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:819
regen-readme.cmd
cmd
Definition: regen-readme.py:21
BIO_ctrl_get_read_request
size_t BIO_ctrl_get_read_request(BIO *bio)
Definition: pair.c:473
err.h
BIO_new
#define BIO_new
Definition: boringssl_prefix_symbols.h:814
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
BIO_R_BROKEN_PIPE
#define BIO_R_BROKEN_PIPE
Definition: bio.h:920
bio_bio_st::offset
size_t offset
Definition: pair.c:73
bio_st::shutdown
int shutdown
Definition: bio.h:831
methods_biop
static const BIO_METHOD methods_biop
Definition: pair.c:448
BIO_CTRL_GET_CLOSE
#define BIO_CTRL_GET_CLOSE
Definition: bio.h:702
b1
T::second_type b1
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:306
BIO_free
#define BIO_free
Definition: boringssl_prefix_symbols.h:787
BIO_CTRL_FLUSH
#define BIO_CTRL_FLUSH
Definition: bio.h:712
BIO_CTRL_PENDING
#define BIO_CTRL_PENDING
Definition: bio.h:709
BIO_C_GET_READ_REQUEST
#define BIO_C_GET_READ_REQUEST
Definition: bio.h:884
bio_write
static int bio_write(BIO *bio, const char *buf, int num_)
Definition: pair.c:227
size_
size_t size_
Definition: memory_allocator.cc:56
BIO_TYPE_BIO
#define BIO_TYPE_BIO
Definition: bio.h:792
BIO_CTRL_SET_CLOSE
#define BIO_CTRL_SET_CLOSE
Definition: bio.h:706
bio_ctrl
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
Definition: pair.c:353
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
bio_bio_st::request
size_t request
Definition: pair.c:77
bio_destroy_pair
static void bio_destroy_pair(BIO *bio)
Definition: pair.c:97
xds_manager.num
num
Definition: xds_manager.py:56
mem.h
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
BIO_C_SHUTDOWN_WR
#define BIO_C_SHUTDOWN_WR
Definition: bio.h:885
BIO_C_RESET_READ_REQUEST
#define BIO_C_RESET_READ_REQUEST
Definition: bio.h:890
OPENSSL_free
#define OPENSSL_free
Definition: boringssl_prefix_symbols.h:1869
BIO_set_retry_read
#define BIO_set_retry_read
Definition: boringssl_prefix_symbols.h:853
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
ERR_R_MALLOC_FAILURE
#define ERR_R_MALLOC_FAILURE
Definition: err.h:371
bio_bio_st::size
size_t size
Definition: pair.c:74
BIO_clear_retry_flags
#define BIO_clear_retry_flags
Definition: boringssl_prefix_symbols.h:777
bio_read
static int bio_read(BIO *bio, char *buf, int size_)
Definition: pair.c:144
google::protobuf.internal.decoder.long
long
Definition: bloaty/third_party/protobuf/python/google/protobuf/internal/decoder.py:89


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:49