]>
Commit | Line | Data |
---|---|---|
9e06f6f6 | 1 | /* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ |
3aa8d3a7 BM |
2 | /* ==================================================================== |
3 | * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in | |
14 | * the documentation and/or other materials provided with the | |
15 | * distribution. | |
16 | * | |
17 | * 3. All advertising materials mentioning features or use of this | |
18 | * software must display the following acknowledgment: | |
19 | * "This product includes software developed by the OpenSSL Project | |
20 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
21 | * | |
22 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
23 | * endorse or promote products derived from this software without | |
24 | * prior written permission. For written permission, please contact | |
25 | * openssl-core@openssl.org. | |
26 | * | |
27 | * 5. Products derived from this software may not be called "OpenSSL" | |
28 | * nor may "OpenSSL" appear in their names without prior written | |
29 | * permission of the OpenSSL Project. | |
30 | * | |
31 | * 6. Redistributions of any form whatsoever must retain the following | |
32 | * acknowledgment: | |
33 | * "This product includes software developed by the OpenSSL Project | |
34 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
35 | * | |
36 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
37 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
39 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
40 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
41 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
42 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
43 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
44 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
45 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
46 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
47 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
48 | * ==================================================================== | |
49 | * | |
50 | * This product includes cryptographic software written by Eric Young | |
51 | * (eay@cryptsoft.com). This product includes software written by Tim | |
52 | * Hudson (tjh@cryptsoft.com). | |
53 | * | |
54 | */ | |
9e06f6f6 | 55 | |
9e06f6f6 | 56 | /* Special method for a BIO where the other endpoint is also a BIO |
95d29597 BM |
57 | * of this kind, handled by the same thread (i.e. the "peer" is actually |
58 | * ourselves, wearing a different hat). | |
9e06f6f6 | 59 | * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces |
95d29597 BM |
60 | * for which no specific BIO method is available. |
61 | * See ssl/ssltest.c for some hints on how this can be used. */ | |
9e06f6f6 | 62 | |
60e5f36d BM |
63 | /* BIO_DEBUG implies BIO_PAIR_DEBUG */ |
64 | #ifdef BIO_DEBUG | |
65 | # ifndef BIO_PAIR_DEBUG | |
66 | # define BIO_PAIR_DEBUG | |
67 | # endif | |
68 | #endif | |
69 | ||
70 | /* disable assert() unless BIO_PAIR_DEBUG has been defined */ | |
e334d78b | 71 | #ifndef BIO_PAIR_DEBUG |
60e5f36d BM |
72 | # ifndef NDEBUG |
73 | # define NDEBUG | |
74 | # endif | |
e334d78b BM |
75 | #endif |
76 | ||
9e06f6f6 | 77 | #include <assert.h> |
c1082a90 | 78 | #include <limits.h> |
9e06f6f6 | 79 | #include <stdlib.h> |
d58d092b | 80 | #include <string.h> |
9e06f6f6 BM |
81 | |
82 | #include <openssl/bio.h> | |
83 | #include <openssl/err.h> | |
84 | #include <openssl/crypto.h> | |
85 | ||
41d2a336 | 86 | #include "e_os.h" |
3e83e686 RL |
87 | |
88 | /* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ | |
6a89a25c | 89 | #if defined(OPENSSL_SYS_VXWORKS) |
3e83e686 RL |
90 | # undef SSIZE_MAX |
91 | #endif | |
4991d07c BM |
92 | #ifndef SSIZE_MAX |
93 | # define SSIZE_MAX INT_MAX | |
94 | #endif | |
95 | ||
9e06f6f6 BM |
96 | static int bio_new(BIO *bio); |
97 | static int bio_free(BIO *bio); | |
98 | static int bio_read(BIO *bio, char *buf, int size); | |
0e1c0612 | 99 | static int bio_write(BIO *bio, const char *buf, int num); |
95d29597 | 100 | static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); |
0e1c0612 | 101 | static int bio_puts(BIO *bio, const char *str); |
9e06f6f6 BM |
102 | |
103 | static int bio_make_pair(BIO *bio1, BIO *bio2); | |
104 | static void bio_destroy_pair(BIO *bio); | |
105 | ||
106 | static BIO_METHOD methods_biop = | |
107 | { | |
108 | BIO_TYPE_BIO, | |
109 | "BIO pair", | |
110 | bio_write, | |
111 | bio_read, | |
112 | bio_puts, | |
113 | NULL /* no bio_gets */, | |
114 | bio_ctrl, | |
115 | bio_new, | |
d3442bc7 RL |
116 | bio_free, |
117 | NULL /* no bio_callback_ctrl */ | |
9e06f6f6 BM |
118 | }; |
119 | ||
120 | BIO_METHOD *BIO_s_bio(void) | |
121 | { | |
122 | return &methods_biop; | |
123 | } | |
124 | ||
125 | struct bio_bio_st | |
126 | { | |
127 | BIO *peer; /* NULL if buf == NULL. | |
c035b0c3 BM |
128 | * If peer != NULL, then peer->ptr is also a bio_bio_st, |
129 | * and its "peer" member points back to us. | |
130 | * peer != NULL iff init != 0 in the BIO. */ | |
9e06f6f6 BM |
131 | |
132 | /* This is for what we write (i.e. reading uses peer's struct): */ | |
c035b0c3 BM |
133 | int closed; /* valid iff peer != NULL */ |
134 | size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ | |
135 | size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ | |
9e06f6f6 | 136 | size_t size; |
c035b0c3 BM |
137 | char *buf; /* "size" elements (if != NULL) */ |
138 | ||
316d5cdc | 139 | size_t request; /* valid iff peer != NULL; 0 if len != 0, |
c035b0c3 | 140 | * otherwise set by peer to number of bytes |
657e60fa | 141 | * it (unsuccessfully) tried to read, |
316d5cdc | 142 | * never more than buffer space (size-len) warrants. */ |
9e06f6f6 BM |
143 | }; |
144 | ||
145 | static int bio_new(BIO *bio) | |
146 | { | |
147 | struct bio_bio_st *b; | |
148 | ||
26a3a48d | 149 | b = OPENSSL_malloc(sizeof *b); |
9e06f6f6 BM |
150 | if (b == NULL) |
151 | return 0; | |
152 | ||
153 | b->peer = NULL; | |
68d39f3c MC |
154 | /* enough for one TLS record (just a default) */ |
155 | b->size = 17*1024; | |
9e06f6f6 BM |
156 | b->buf = NULL; |
157 | ||
95d29597 | 158 | bio->ptr = b; |
9e06f6f6 BM |
159 | return 1; |
160 | } | |
161 | ||
162 | ||
163 | static int bio_free(BIO *bio) | |
164 | { | |
165 | struct bio_bio_st *b; | |
166 | ||
167 | if (bio == NULL) | |
168 | return 0; | |
169 | b = bio->ptr; | |
170 | ||
171 | assert(b != NULL); | |
172 | ||
173 | if (b->peer) | |
174 | bio_destroy_pair(bio); | |
175 | ||
176 | if (b->buf != NULL) | |
177 | { | |
26a3a48d | 178 | OPENSSL_free(b->buf); |
9e06f6f6 BM |
179 | } |
180 | ||
26a3a48d | 181 | OPENSSL_free(b); |
9e06f6f6 BM |
182 | |
183 | return 1; | |
184 | } | |
185 | ||
186 | ||
187 | ||
95d29597 | 188 | static int bio_read(BIO *bio, char *buf, int size_) |
9e06f6f6 | 189 | { |
95d29597 BM |
190 | size_t size = size_; |
191 | size_t rest; | |
192 | struct bio_bio_st *b, *peer_b; | |
193 | ||
194 | BIO_clear_retry_flags(bio); | |
195 | ||
196 | if (!bio->init) | |
197 | return 0; | |
198 | ||
199 | b = bio->ptr; | |
200 | assert(b != NULL); | |
201 | assert(b->peer != NULL); | |
202 | peer_b = b->peer->ptr; | |
203 | assert(peer_b != NULL); | |
204 | assert(peer_b->buf != NULL); | |
205 | ||
206 | peer_b->request = 0; /* will be set in "retry_read" situation */ | |
207 | ||
208 | if (buf == NULL || size == 0) | |
209 | return 0; | |
210 | ||
211 | if (peer_b->len == 0) | |
212 | { | |
213 | if (peer_b->closed) | |
214 | return 0; /* writer has closed, and no data is left */ | |
215 | else | |
216 | { | |
217 | BIO_set_retry_read(bio); /* buffer is empty */ | |
218 | if (size <= peer_b->size) | |
219 | peer_b->request = size; | |
220 | else | |
99187624 BM |
221 | /* don't ask for more than the peer can |
222 | * deliver in one write */ | |
223 | peer_b->request = peer_b->size; | |
95d29597 BM |
224 | return -1; |
225 | } | |
226 | } | |
227 | ||
228 | /* we can read */ | |
229 | if (peer_b->len < size) | |
230 | size = peer_b->len; | |
231 | ||
232 | /* now read "size" bytes */ | |
233 | ||
234 | rest = size; | |
235 | ||
236 | assert(rest > 0); | |
237 | do /* one or two iterations */ | |
238 | { | |
239 | size_t chunk; | |
240 | ||
241 | assert(rest <= peer_b->len); | |
242 | if (peer_b->offset + rest <= peer_b->size) | |
243 | chunk = rest; | |
244 | else | |
245 | /* wrap around ring buffer */ | |
246 | chunk = peer_b->size - peer_b->offset; | |
247 | assert(peer_b->offset + chunk <= peer_b->size); | |
248 | ||
249 | memcpy(buf, peer_b->buf + peer_b->offset, chunk); | |
250 | ||
251 | peer_b->len -= chunk; | |
252 | if (peer_b->len) | |
253 | { | |
254 | peer_b->offset += chunk; | |
255 | assert(peer_b->offset <= peer_b->size); | |
256 | if (peer_b->offset == peer_b->size) | |
257 | peer_b->offset = 0; | |
258 | buf += chunk; | |
259 | } | |
260 | else | |
261 | { | |
262 | /* buffer now empty, no need to advance "buf" */ | |
263 | assert(chunk == rest); | |
264 | peer_b->offset = 0; | |
265 | } | |
266 | rest -= chunk; | |
267 | } | |
268 | while (rest); | |
269 | ||
95d29597 | 270 | return size; |
9e06f6f6 BM |
271 | } |
272 | ||
1d97c843 TH |
273 | /*- |
274 | * non-copying interface: provide pointer to available data in buffer | |
c1082a90 BM |
275 | * bio_nread0: return number of available bytes |
276 | * bio_nread: also advance index | |
277 | * (example usage: bio_nread0(), read from buffer, bio_nread() | |
278 | * or just bio_nread(), read from buffer) | |
279 | */ | |
6f7af152 BM |
280 | /* WARNING: The non-copying interface is largely untested as of yet |
281 | * and may contain bugs. */ | |
eb1c48be | 282 | static ossl_ssize_t bio_nread0(BIO *bio, char **buf) |
c1082a90 BM |
283 | { |
284 | struct bio_bio_st *b, *peer_b; | |
eb1c48be | 285 | ossl_ssize_t num; |
c1082a90 BM |
286 | |
287 | BIO_clear_retry_flags(bio); | |
288 | ||
289 | if (!bio->init) | |
290 | return 0; | |
291 | ||
292 | b = bio->ptr; | |
293 | assert(b != NULL); | |
294 | assert(b->peer != NULL); | |
295 | peer_b = b->peer->ptr; | |
296 | assert(peer_b != NULL); | |
297 | assert(peer_b->buf != NULL); | |
298 | ||
299 | peer_b->request = 0; | |
300 | ||
301 | if (peer_b->len == 0) | |
302 | { | |
303 | char dummy; | |
304 | ||
305 | /* avoid code duplication -- nothing available for reading */ | |
d680ba86 | 306 | return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ |
c1082a90 BM |
307 | } |
308 | ||
309 | num = peer_b->len; | |
310 | if (peer_b->size < peer_b->offset + num) | |
311 | /* no ring buffer wrap-around for non-copying interface */ | |
312 | num = peer_b->size - peer_b->offset; | |
313 | assert(num > 0); | |
314 | ||
315 | if (buf != NULL) | |
316 | *buf = peer_b->buf + peer_b->offset; | |
317 | return num; | |
318 | } | |
319 | ||
eb1c48be | 320 | static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) |
c1082a90 BM |
321 | { |
322 | struct bio_bio_st *b, *peer_b; | |
eb1c48be | 323 | ossl_ssize_t num, available; |
4991d07c BM |
324 | |
325 | if (num_ > SSIZE_MAX) | |
e65991f9 | 326 | num = SSIZE_MAX; |
4991d07c | 327 | else |
eb1c48be | 328 | num = (ossl_ssize_t)num_; |
c1082a90 BM |
329 | |
330 | available = bio_nread0(bio, buf); | |
331 | if (num > available) | |
332 | num = available; | |
4991d07c | 333 | if (num <= 0) |
c1082a90 BM |
334 | return num; |
335 | ||
336 | b = bio->ptr; | |
337 | peer_b = b->peer->ptr; | |
338 | ||
339 | peer_b->len -= num; | |
340 | if (peer_b->len) | |
341 | { | |
342 | peer_b->offset += num; | |
343 | assert(peer_b->offset <= peer_b->size); | |
344 | if (peer_b->offset == peer_b->size) | |
345 | peer_b->offset = 0; | |
346 | } | |
347 | else | |
348 | peer_b->offset = 0; | |
349 | ||
350 | return num; | |
351 | } | |
352 | ||
353 | ||
0e1c0612 | 354 | static int bio_write(BIO *bio, const char *buf, int num_) |
9e06f6f6 | 355 | { |
95d29597 BM |
356 | size_t num = num_; |
357 | size_t rest; | |
358 | struct bio_bio_st *b; | |
359 | ||
360 | BIO_clear_retry_flags(bio); | |
361 | ||
362 | if (!bio->init || buf == NULL || num == 0) | |
363 | return 0; | |
364 | ||
365 | b = bio->ptr; | |
366 | assert(b != NULL); | |
367 | assert(b->peer != NULL); | |
368 | assert(b->buf != NULL); | |
369 | ||
370 | b->request = 0; | |
371 | if (b->closed) | |
372 | { | |
373 | /* we already closed */ | |
374 | BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); | |
375 | return -1; | |
376 | } | |
377 | ||
378 | assert(b->len <= b->size); | |
379 | ||
380 | if (b->len == b->size) | |
381 | { | |
382 | BIO_set_retry_write(bio); /* buffer is full */ | |
383 | return -1; | |
384 | } | |
385 | ||
386 | /* we can write */ | |
387 | if (num > b->size - b->len) | |
388 | num = b->size - b->len; | |
389 | ||
390 | /* now write "num" bytes */ | |
391 | ||
392 | rest = num; | |
9e06f6f6 | 393 | |
95d29597 BM |
394 | assert(rest > 0); |
395 | do /* one or two iterations */ | |
396 | { | |
397 | size_t write_offset; | |
398 | size_t chunk; | |
399 | ||
400 | assert(b->len + rest <= b->size); | |
401 | ||
402 | write_offset = b->offset + b->len; | |
403 | if (write_offset >= b->size) | |
404 | write_offset -= b->size; | |
405 | /* b->buf[write_offset] is the first byte we can write to. */ | |
406 | ||
407 | if (write_offset + rest <= b->size) | |
408 | chunk = rest; | |
409 | else | |
410 | /* wrap around ring buffer */ | |
411 | chunk = b->size - write_offset; | |
412 | ||
413 | memcpy(b->buf + write_offset, buf, chunk); | |
414 | ||
415 | b->len += chunk; | |
416 | ||
417 | assert(b->len <= b->size); | |
418 | ||
419 | rest -= chunk; | |
420 | buf += chunk; | |
421 | } | |
422 | while (rest); | |
423 | ||
424 | return num; | |
425 | } | |
426 | ||
1d97c843 TH |
427 | /*- |
428 | * non-copying interface: provide pointer to region to write to | |
c1082a90 BM |
429 | * bio_nwrite0: check how much space is available |
430 | * bio_nwrite: also increase length | |
431 | * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() | |
432 | * or just bio_nwrite(), write to buffer) | |
433 | */ | |
eb1c48be | 434 | static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) |
c1082a90 BM |
435 | { |
436 | struct bio_bio_st *b; | |
437 | size_t num; | |
438 | size_t write_offset; | |
439 | ||
440 | BIO_clear_retry_flags(bio); | |
441 | ||
442 | if (!bio->init) | |
443 | return 0; | |
444 | ||
445 | b = bio->ptr; | |
446 | assert(b != NULL); | |
447 | assert(b->peer != NULL); | |
448 | assert(b->buf != NULL); | |
449 | ||
450 | b->request = 0; | |
451 | if (b->closed) | |
452 | { | |
453 | BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); | |
454 | return -1; | |
455 | } | |
456 | ||
457 | assert(b->len <= b->size); | |
458 | ||
459 | if (b->len == b->size) | |
460 | { | |
461 | BIO_set_retry_write(bio); | |
462 | return -1; | |
463 | } | |
464 | ||
465 | num = b->size - b->len; | |
466 | write_offset = b->offset + b->len; | |
467 | if (write_offset >= b->size) | |
468 | write_offset -= b->size; | |
469 | if (write_offset + num > b->size) | |
470 | /* no ring buffer wrap-around for non-copying interface | |
f50c0497 | 471 | * (to fulfil the promise by BIO_ctrl_get_write_guarantee, |
c1082a90 BM |
472 | * BIO_nwrite may have to be called twice) */ |
473 | num = b->size - write_offset; | |
474 | ||
475 | if (buf != NULL) | |
476 | *buf = b->buf + write_offset; | |
477 | assert(write_offset + num <= b->size); | |
478 | ||
479 | return num; | |
480 | } | |
481 | ||
eb1c48be | 482 | static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) |
c1082a90 | 483 | { |
5671876d | 484 | struct bio_bio_st *b; |
eb1c48be | 485 | ossl_ssize_t num, space; |
4991d07c BM |
486 | |
487 | if (num_ > SSIZE_MAX) | |
488 | num = SSIZE_MAX; | |
489 | else | |
eb1c48be | 490 | num = (ossl_ssize_t)num_; |
c1082a90 BM |
491 | |
492 | space = bio_nwrite0(bio, buf); | |
493 | if (num > space) | |
494 | num = space; | |
4991d07c | 495 | if (num <= 0) |
c1082a90 | 496 | return num; |
5671876d BM |
497 | b = bio->ptr; |
498 | assert(b != NULL); | |
c1082a90 BM |
499 | b->len += num; |
500 | assert(b->len <= b->size); | |
501 | ||
502 | return num; | |
503 | } | |
504 | ||
95d29597 BM |
505 | |
506 | static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) | |
9e06f6f6 BM |
507 | { |
508 | long ret; | |
509 | struct bio_bio_st *b = bio->ptr; | |
510 | ||
511 | assert(b != NULL); | |
512 | ||
513 | switch (cmd) | |
514 | { | |
95d29597 BM |
515 | /* specific CTRL codes */ |
516 | ||
517 | case BIO_C_SET_WRITE_BUF_SIZE: | |
518 | if (b->peer) | |
519 | { | |
520 | BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); | |
521 | ret = 0; | |
522 | } | |
6c82fda2 BM |
523 | else if (num == 0) |
524 | { | |
525 | BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); | |
526 | ret = 0; | |
527 | } | |
95d29597 BM |
528 | else |
529 | { | |
530 | size_t new_size = num; | |
531 | ||
532 | if (b->size != new_size) | |
533 | { | |
534 | if (b->buf) | |
535 | { | |
26a3a48d | 536 | OPENSSL_free(b->buf); |
95d29597 BM |
537 | b->buf = NULL; |
538 | } | |
539 | b->size = new_size; | |
540 | } | |
541 | ret = 1; | |
542 | } | |
543 | break; | |
544 | ||
545 | case BIO_C_GET_WRITE_BUF_SIZE: | |
54fbc77d LJ |
546 | ret = (long) b->size; |
547 | break; | |
95d29597 BM |
548 | |
549 | case BIO_C_MAKE_BIO_PAIR: | |
550 | { | |
551 | BIO *other_bio = ptr; | |
552 | ||
553 | if (bio_make_pair(bio, other_bio)) | |
554 | ret = 1; | |
555 | else | |
556 | ret = 0; | |
557 | } | |
558 | break; | |
559 | ||
560 | case BIO_C_DESTROY_BIO_PAIR: | |
3aa8d3a7 | 561 | /* Affects both BIOs in the pair -- call just once! |
95d29597 BM |
562 | * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ |
563 | bio_destroy_pair(bio); | |
564 | ret = 1; | |
565 | break; | |
566 | ||
567 | case BIO_C_GET_WRITE_GUARANTEE: | |
568 | /* How many bytes can the caller feed to the next write | |
657e60fa | 569 | * without having to keep any? */ |
95d29597 BM |
570 | if (b->peer == NULL || b->closed) |
571 | ret = 0; | |
572 | else | |
573 | ret = (long) b->size - b->len; | |
574 | break; | |
575 | ||
576 | case BIO_C_GET_READ_REQUEST: | |
657e60fa | 577 | /* If the peer unsuccessfully tried to read, how many bytes |
95d29597 BM |
578 | * were requested? (As with BIO_CTRL_PENDING, that number |
579 | * can usually be treated as boolean.) */ | |
580 | ret = (long) b->request; | |
581 | break; | |
582 | ||
e405b8d1 BM |
583 | case BIO_C_RESET_READ_REQUEST: |
584 | /* Reset request. (Can be useful after read attempts | |
585 | * at the other side that are meant to be non-blocking, | |
586 | * e.g. when probing SSL_read to see if any data is | |
587 | * available.) */ | |
588 | b->request = 0; | |
589 | ret = 1; | |
590 | break; | |
591 | ||
95d29597 BM |
592 | case BIO_C_SHUTDOWN_WR: |
593 | /* similar to shutdown(..., SHUT_WR) */ | |
594 | b->closed = 1; | |
595 | ret = 1; | |
596 | break; | |
597 | ||
4991d07c BM |
598 | case BIO_C_NREAD0: |
599 | /* prepare for non-copying read */ | |
600 | ret = (long) bio_nread0(bio, ptr); | |
601 | break; | |
602 | ||
c1082a90 BM |
603 | case BIO_C_NREAD: |
604 | /* non-copying read */ | |
605 | ret = (long) bio_nread(bio, ptr, (size_t) num); | |
606 | break; | |
607 | ||
608 | case BIO_C_NWRITE0: | |
609 | /* prepare for non-copying write */ | |
610 | ret = (long) bio_nwrite0(bio, ptr); | |
611 | break; | |
612 | ||
613 | case BIO_C_NWRITE: | |
614 | /* non-copying write */ | |
615 | ret = (long) bio_nwrite(bio, ptr, (size_t) num); | |
616 | break; | |
617 | ||
95d29597 BM |
618 | |
619 | /* standard CTRL codes follow */ | |
9e06f6f6 BM |
620 | |
621 | case BIO_CTRL_RESET: | |
622 | if (b->buf != NULL) | |
623 | { | |
624 | b->len = 0; | |
625 | b->offset = 0; | |
626 | } | |
627 | ret = 0; | |
628 | break; | |
629 | ||
630 | case BIO_CTRL_GET_CLOSE: | |
631 | ret = bio->shutdown; | |
632 | break; | |
633 | ||
634 | case BIO_CTRL_SET_CLOSE: | |
635 | bio->shutdown = (int) num; | |
636 | ret = 1; | |
637 | break; | |
638 | ||
639 | case BIO_CTRL_PENDING: | |
640 | if (b->peer != NULL) | |
641 | { | |
7eea36bb | 642 | struct bio_bio_st *peer_b = b->peer->ptr; |
9e06f6f6 BM |
643 | |
644 | ret = (long) peer_b->len; | |
645 | } | |
646 | else | |
647 | ret = 0; | |
648 | break; | |
649 | ||
650 | case BIO_CTRL_WPENDING: | |
651 | if (b->buf != NULL) | |
652 | ret = (long) b->len; | |
653 | else | |
654 | ret = 0; | |
655 | break; | |
656 | ||
657 | case BIO_CTRL_DUP: | |
95d29597 BM |
658 | /* See BIO_dup_chain for circumstances we have to expect. */ |
659 | { | |
660 | BIO *other_bio = ptr; | |
661 | struct bio_bio_st *other_b; | |
662 | ||
663 | assert(other_bio != NULL); | |
664 | other_b = other_bio->ptr; | |
665 | assert(other_b != NULL); | |
666 | ||
667 | assert(other_b->buf == NULL); /* other_bio is always fresh */ | |
668 | ||
669 | other_b->size = b->size; | |
670 | } | |
671 | ||
c035b0c3 BM |
672 | ret = 1; |
673 | break; | |
9e06f6f6 BM |
674 | |
675 | case BIO_CTRL_FLUSH: | |
676 | ret = 1; | |
677 | break; | |
678 | ||
95d29597 BM |
679 | case BIO_CTRL_EOF: |
680 | { | |
681 | BIO *other_bio = ptr; | |
682 | ||
683 | if (other_bio) | |
684 | { | |
685 | struct bio_bio_st *other_b = other_bio->ptr; | |
686 | ||
687 | assert(other_b != NULL); | |
688 | ret = other_b->len == 0 && other_b->closed; | |
689 | } | |
690 | else | |
691 | ret = 1; | |
692 | } | |
693 | break; | |
694 | ||
9e06f6f6 BM |
695 | default: |
696 | ret = 0; | |
697 | } | |
698 | return ret; | |
699 | } | |
700 | ||
0e1c0612 | 701 | static int bio_puts(BIO *bio, const char *str) |
9e06f6f6 BM |
702 | { |
703 | return bio_write(bio, str, strlen(str)); | |
704 | } | |
705 | ||
9e06f6f6 BM |
706 | |
707 | static int bio_make_pair(BIO *bio1, BIO *bio2) | |
708 | { | |
709 | struct bio_bio_st *b1, *b2; | |
710 | ||
711 | assert(bio1 != NULL); | |
712 | assert(bio2 != NULL); | |
713 | ||
714 | b1 = bio1->ptr; | |
715 | b2 = bio2->ptr; | |
716 | ||
717 | if (b1->peer != NULL || b2->peer != NULL) | |
718 | { | |
719 | BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); | |
720 | return 0; | |
721 | } | |
722 | ||
1aad3392 | 723 | if (b1->buf == NULL) |
9e06f6f6 | 724 | { |
26a3a48d | 725 | b1->buf = OPENSSL_malloc(b1->size); |
9e06f6f6 BM |
726 | if (b1->buf == NULL) |
727 | { | |
728 | BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); | |
729 | return 0; | |
730 | } | |
731 | b1->len = 0; | |
732 | b1->offset = 0; | |
733 | } | |
734 | ||
1aad3392 | 735 | if (b2->buf == NULL) |
9e06f6f6 | 736 | { |
26a3a48d | 737 | b2->buf = OPENSSL_malloc(b2->size); |
9e06f6f6 BM |
738 | if (b2->buf == NULL) |
739 | { | |
740 | BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); | |
741 | return 0; | |
742 | } | |
743 | b2->len = 0; | |
744 | b2->offset = 0; | |
745 | } | |
746 | ||
747 | b1->peer = bio2; | |
c035b0c3 BM |
748 | b1->closed = 0; |
749 | b1->request = 0; | |
9e06f6f6 | 750 | b2->peer = bio1; |
c035b0c3 BM |
751 | b2->closed = 0; |
752 | b2->request = 0; | |
9e06f6f6 | 753 | |
3928b6bf BM |
754 | bio1->init = 1; |
755 | bio2->init = 1; | |
756 | ||
9e06f6f6 BM |
757 | return 1; |
758 | } | |
759 | ||
760 | static void bio_destroy_pair(BIO *bio) | |
761 | { | |
762 | struct bio_bio_st *b = bio->ptr; | |
763 | ||
764 | if (b != NULL) | |
765 | { | |
766 | BIO *peer_bio = b->peer; | |
767 | ||
768 | if (peer_bio != NULL) | |
769 | { | |
770 | struct bio_bio_st *peer_b = peer_bio->ptr; | |
771 | ||
772 | assert(peer_b != NULL); | |
773 | assert(peer_b->peer == bio); | |
774 | ||
775 | peer_b->peer = NULL; | |
776 | peer_bio->init = 0; | |
777 | assert(peer_b->buf != NULL); | |
778 | peer_b->len = 0; | |
779 | peer_b->offset = 0; | |
780 | ||
781 | b->peer = NULL; | |
782 | bio->init = 0; | |
783 | assert(b->buf != NULL); | |
784 | b->len = 0; | |
785 | b->offset = 0; | |
786 | } | |
787 | } | |
788 | } | |
95d29597 BM |
789 | |
790 | ||
791 | /* Exported convenience functions */ | |
792 | int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, | |
793 | BIO **bio2_p, size_t writebuf2) | |
794 | { | |
795 | BIO *bio1 = NULL, *bio2 = NULL; | |
796 | long r; | |
797 | int ret = 0; | |
798 | ||
799 | bio1 = BIO_new(BIO_s_bio()); | |
800 | if (bio1 == NULL) | |
801 | goto err; | |
802 | bio2 = BIO_new(BIO_s_bio()); | |
803 | if (bio2 == NULL) | |
804 | goto err; | |
805 | ||
806 | if (writebuf1) | |
807 | { | |
808 | r = BIO_set_write_buf_size(bio1, writebuf1); | |
809 | if (!r) | |
810 | goto err; | |
811 | } | |
812 | if (writebuf2) | |
813 | { | |
814 | r = BIO_set_write_buf_size(bio2, writebuf2); | |
815 | if (!r) | |
816 | goto err; | |
817 | } | |
818 | ||
819 | r = BIO_make_bio_pair(bio1, bio2); | |
820 | if (!r) | |
821 | goto err; | |
822 | ret = 1; | |
823 | ||
824 | err: | |
825 | if (ret == 0) | |
826 | { | |
827 | if (bio1) | |
828 | { | |
829 | BIO_free(bio1); | |
830 | bio1 = NULL; | |
831 | } | |
832 | if (bio2) | |
833 | { | |
834 | BIO_free(bio2); | |
835 | bio2 = NULL; | |
836 | } | |
837 | } | |
838 | ||
839 | *bio1_p = bio1; | |
840 | *bio2_p = bio2; | |
841 | return ret; | |
842 | } | |
843 | ||
844 | size_t BIO_ctrl_get_write_guarantee(BIO *bio) | |
99187624 | 845 | { |
95d29597 BM |
846 | return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); |
847 | } | |
848 | ||
2de62540 | 849 | size_t BIO_ctrl_get_read_request(BIO *bio) |
99187624 | 850 | { |
95d29597 BM |
851 | return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); |
852 | } | |
c1082a90 | 853 | |
e405b8d1 BM |
854 | int BIO_ctrl_reset_read_request(BIO *bio) |
855 | { | |
856 | return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); | |
857 | } | |
858 | ||
c1082a90 | 859 | |
657e60fa | 860 | /* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now |
c1082a90 BM |
861 | * (conceivably some other BIOs could allow non-copying reads and writes too.) |
862 | */ | |
863 | int BIO_nread0(BIO *bio, char **buf) | |
864 | { | |
865 | long ret; | |
866 | ||
867 | if (!bio->init) | |
868 | { | |
869 | BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); | |
870 | return -2; | |
871 | } | |
872 | ||
873 | ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); | |
874 | if (ret > INT_MAX) | |
875 | return INT_MAX; | |
876 | else | |
877 | return (int) ret; | |
878 | } | |
879 | ||
880 | int BIO_nread(BIO *bio, char **buf, int num) | |
881 | { | |
882 | int ret; | |
883 | ||
884 | if (!bio->init) | |
885 | { | |
886 | BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); | |
887 | return -2; | |
888 | } | |
889 | ||
890 | ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); | |
891 | if (ret > 0) | |
892 | bio->num_read += ret; | |
893 | return ret; | |
894 | } | |
895 | ||
896 | int BIO_nwrite0(BIO *bio, char **buf) | |
897 | { | |
898 | long ret; | |
899 | ||
900 | if (!bio->init) | |
901 | { | |
902 | BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); | |
903 | return -2; | |
904 | } | |
905 | ||
906 | ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); | |
907 | if (ret > INT_MAX) | |
908 | return INT_MAX; | |
909 | else | |
910 | return (int) ret; | |
911 | } | |
912 | ||
913 | int BIO_nwrite(BIO *bio, char **buf, int num) | |
914 | { | |
915 | int ret; | |
916 | ||
917 | if (!bio->init) | |
918 | { | |
919 | BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); | |
920 | return -2; | |
921 | } | |
922 | ||
923 | ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); | |
924 | if (ret > 0) | |
44390fad | 925 | bio->num_write += ret; |
c1082a90 BM |
926 | return ret; |
927 | } |