OLD | NEW |
| (Empty) |
1 /* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ | |
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 */ | |
55 | |
56 /* Special method for a BIO where the other endpoint is also a BIO | |
57 * of this kind, handled by the same thread (i.e. the "peer" is actually | |
58 * ourselves, wearing a different hat). | |
59 * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces | |
60 * for which no specific BIO method is available. | |
61 * See ssl/ssltest.c for some hints on how this can be used. */ | |
62 | |
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 */ | |
71 #ifndef BIO_PAIR_DEBUG | |
72 # ifndef NDEBUG | |
73 # define NDEBUG | |
74 # endif | |
75 #endif | |
76 | |
77 #include <assert.h> | |
78 #include <limits.h> | |
79 #include <stdlib.h> | |
80 #include <string.h> | |
81 | |
82 #include <openssl/bio.h> | |
83 #include <openssl/err.h> | |
84 #include <openssl/crypto.h> | |
85 | |
86 #include "e_os.h" | |
87 | |
88 /* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ | |
89 #if defined(OPENSSL_SYS_VXWORKS) | |
90 # undef SSIZE_MAX | |
91 #endif | |
92 #ifndef SSIZE_MAX | |
93 # define SSIZE_MAX INT_MAX | |
94 #endif | |
95 | |
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); | |
99 static int bio_write(BIO *bio, const char *buf, int num); | |
100 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); | |
101 static int bio_puts(BIO *bio, const char *str); | |
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, | |
116 bio_free, | |
117 NULL /* no bio_callback_ctrl */ | |
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. | |
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. */ | |
131 | |
132 /* This is for what we write (i.e. reading uses peer's struct): */ | |
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 */ | |
136 size_t size; | |
137 char *buf; /* "size" elements (if != NULL) */ | |
138 | |
139 size_t request; /* valid iff peer != NULL; 0 if len != 0, | |
140 * otherwise set by peer to number of bytes | |
141 * it (unsuccessfully) tried to read, | |
142 * never more than buffer space (size-len) warrants. */ | |
143 }; | |
144 | |
145 static int bio_new(BIO *bio) | |
146 { | |
147 struct bio_bio_st *b; | |
148 | |
149 b = OPENSSL_malloc(sizeof *b); | |
150 if (b == NULL) | |
151 return 0; | |
152 | |
153 b->peer = NULL; | |
154 b->size = 17*1024; /* enough for one TLS record (just a default) */ | |
155 b->buf = NULL; | |
156 | |
157 bio->ptr = b; | |
158 return 1; | |
159 } | |
160 | |
161 | |
162 static int bio_free(BIO *bio) | |
163 { | |
164 struct bio_bio_st *b; | |
165 | |
166 if (bio == NULL) | |
167 return 0; | |
168 b = bio->ptr; | |
169 | |
170 assert(b != NULL); | |
171 | |
172 if (b->peer) | |
173 bio_destroy_pair(bio); | |
174 | |
175 if (b->buf != NULL) | |
176 { | |
177 OPENSSL_free(b->buf); | |
178 } | |
179 | |
180 OPENSSL_free(b); | |
181 | |
182 return 1; | |
183 } | |
184 | |
185 | |
186 | |
187 static int bio_read(BIO *bio, char *buf, int size_) | |
188 { | |
189 size_t size = size_; | |
190 size_t rest; | |
191 struct bio_bio_st *b, *peer_b; | |
192 | |
193 BIO_clear_retry_flags(bio); | |
194 | |
195 if (!bio->init) | |
196 return 0; | |
197 | |
198 b = bio->ptr; | |
199 assert(b != NULL); | |
200 assert(b->peer != NULL); | |
201 peer_b = b->peer->ptr; | |
202 assert(peer_b != NULL); | |
203 assert(peer_b->buf != NULL); | |
204 | |
205 peer_b->request = 0; /* will be set in "retry_read" situation */ | |
206 | |
207 if (buf == NULL || size == 0) | |
208 return 0; | |
209 | |
210 if (peer_b->len == 0) | |
211 { | |
212 if (peer_b->closed) | |
213 return 0; /* writer has closed, and no data is left */ | |
214 else | |
215 { | |
216 BIO_set_retry_read(bio); /* buffer is empty */ | |
217 if (size <= peer_b->size) | |
218 peer_b->request = size; | |
219 else | |
220 /* don't ask for more than the peer can | |
221 * deliver in one write */ | |
222 peer_b->request = peer_b->size; | |
223 return -1; | |
224 } | |
225 } | |
226 | |
227 /* we can read */ | |
228 if (peer_b->len < size) | |
229 size = peer_b->len; | |
230 | |
231 /* now read "size" bytes */ | |
232 | |
233 rest = size; | |
234 | |
235 assert(rest > 0); | |
236 do /* one or two iterations */ | |
237 { | |
238 size_t chunk; | |
239 | |
240 assert(rest <= peer_b->len); | |
241 if (peer_b->offset + rest <= peer_b->size) | |
242 chunk = rest; | |
243 else | |
244 /* wrap around ring buffer */ | |
245 chunk = peer_b->size - peer_b->offset; | |
246 assert(peer_b->offset + chunk <= peer_b->size); | |
247 | |
248 memcpy(buf, peer_b->buf + peer_b->offset, chunk); | |
249 | |
250 peer_b->len -= chunk; | |
251 if (peer_b->len) | |
252 { | |
253 peer_b->offset += chunk; | |
254 assert(peer_b->offset <= peer_b->size); | |
255 if (peer_b->offset == peer_b->size) | |
256 peer_b->offset = 0; | |
257 buf += chunk; | |
258 } | |
259 else | |
260 { | |
261 /* buffer now empty, no need to advance "buf" */ | |
262 assert(chunk == rest); | |
263 peer_b->offset = 0; | |
264 } | |
265 rest -= chunk; | |
266 } | |
267 while (rest); | |
268 | |
269 return size; | |
270 } | |
271 | |
272 /* non-copying interface: provide pointer to available data in buffer | |
273 * bio_nread0: return number of available bytes | |
274 * bio_nread: also advance index | |
275 * (example usage: bio_nread0(), read from buffer, bio_nread() | |
276 * or just bio_nread(), read from buffer) | |
277 */ | |
278 /* WARNING: The non-copying interface is largely untested as of yet | |
279 * and may contain bugs. */ | |
280 static ossl_ssize_t bio_nread0(BIO *bio, char **buf) | |
281 { | |
282 struct bio_bio_st *b, *peer_b; | |
283 ossl_ssize_t num; | |
284 | |
285 BIO_clear_retry_flags(bio); | |
286 | |
287 if (!bio->init) | |
288 return 0; | |
289 | |
290 b = bio->ptr; | |
291 assert(b != NULL); | |
292 assert(b->peer != NULL); | |
293 peer_b = b->peer->ptr; | |
294 assert(peer_b != NULL); | |
295 assert(peer_b->buf != NULL); | |
296 | |
297 peer_b->request = 0; | |
298 | |
299 if (peer_b->len == 0) | |
300 { | |
301 char dummy; | |
302 | |
303 /* avoid code duplication -- nothing available for reading */ | |
304 return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ | |
305 } | |
306 | |
307 num = peer_b->len; | |
308 if (peer_b->size < peer_b->offset + num) | |
309 /* no ring buffer wrap-around for non-copying interface */ | |
310 num = peer_b->size - peer_b->offset; | |
311 assert(num > 0); | |
312 | |
313 if (buf != NULL) | |
314 *buf = peer_b->buf + peer_b->offset; | |
315 return num; | |
316 } | |
317 | |
318 static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) | |
319 { | |
320 struct bio_bio_st *b, *peer_b; | |
321 ossl_ssize_t num, available; | |
322 | |
323 if (num_ > SSIZE_MAX) | |
324 num = SSIZE_MAX; | |
325 else | |
326 num = (ossl_ssize_t)num_; | |
327 | |
328 available = bio_nread0(bio, buf); | |
329 if (num > available) | |
330 num = available; | |
331 if (num <= 0) | |
332 return num; | |
333 | |
334 b = bio->ptr; | |
335 peer_b = b->peer->ptr; | |
336 | |
337 peer_b->len -= num; | |
338 if (peer_b->len) | |
339 { | |
340 peer_b->offset += num; | |
341 assert(peer_b->offset <= peer_b->size); | |
342 if (peer_b->offset == peer_b->size) | |
343 peer_b->offset = 0; | |
344 } | |
345 else | |
346 peer_b->offset = 0; | |
347 | |
348 return num; | |
349 } | |
350 | |
351 | |
352 static int bio_write(BIO *bio, const char *buf, int num_) | |
353 { | |
354 size_t num = num_; | |
355 size_t rest; | |
356 struct bio_bio_st *b; | |
357 | |
358 BIO_clear_retry_flags(bio); | |
359 | |
360 if (!bio->init || buf == NULL || num == 0) | |
361 return 0; | |
362 | |
363 b = bio->ptr; | |
364 assert(b != NULL); | |
365 assert(b->peer != NULL); | |
366 assert(b->buf != NULL); | |
367 | |
368 b->request = 0; | |
369 if (b->closed) | |
370 { | |
371 /* we already closed */ | |
372 BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); | |
373 return -1; | |
374 } | |
375 | |
376 assert(b->len <= b->size); | |
377 | |
378 if (b->len == b->size) | |
379 { | |
380 BIO_set_retry_write(bio); /* buffer is full */ | |
381 return -1; | |
382 } | |
383 | |
384 /* we can write */ | |
385 if (num > b->size - b->len) | |
386 num = b->size - b->len; | |
387 | |
388 /* now write "num" bytes */ | |
389 | |
390 rest = num; | |
391 | |
392 assert(rest > 0); | |
393 do /* one or two iterations */ | |
394 { | |
395 size_t write_offset; | |
396 size_t chunk; | |
397 | |
398 assert(b->len + rest <= b->size); | |
399 | |
400 write_offset = b->offset + b->len; | |
401 if (write_offset >= b->size) | |
402 write_offset -= b->size; | |
403 /* b->buf[write_offset] is the first byte we can write to. */ | |
404 | |
405 if (write_offset + rest <= b->size) | |
406 chunk = rest; | |
407 else | |
408 /* wrap around ring buffer */ | |
409 chunk = b->size - write_offset; | |
410 | |
411 memcpy(b->buf + write_offset, buf, chunk); | |
412 | |
413 b->len += chunk; | |
414 | |
415 assert(b->len <= b->size); | |
416 | |
417 rest -= chunk; | |
418 buf += chunk; | |
419 } | |
420 while (rest); | |
421 | |
422 return num; | |
423 } | |
424 | |
425 /* non-copying interface: provide pointer to region to write to | |
426 * bio_nwrite0: check how much space is available | |
427 * bio_nwrite: also increase length | |
428 * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() | |
429 * or just bio_nwrite(), write to buffer) | |
430 */ | |
431 static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) | |
432 { | |
433 struct bio_bio_st *b; | |
434 size_t num; | |
435 size_t write_offset; | |
436 | |
437 BIO_clear_retry_flags(bio); | |
438 | |
439 if (!bio->init) | |
440 return 0; | |
441 | |
442 b = bio->ptr; | |
443 assert(b != NULL); | |
444 assert(b->peer != NULL); | |
445 assert(b->buf != NULL); | |
446 | |
447 b->request = 0; | |
448 if (b->closed) | |
449 { | |
450 BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); | |
451 return -1; | |
452 } | |
453 | |
454 assert(b->len <= b->size); | |
455 | |
456 if (b->len == b->size) | |
457 { | |
458 BIO_set_retry_write(bio); | |
459 return -1; | |
460 } | |
461 | |
462 num = b->size - b->len; | |
463 write_offset = b->offset + b->len; | |
464 if (write_offset >= b->size) | |
465 write_offset -= b->size; | |
466 if (write_offset + num > b->size) | |
467 /* no ring buffer wrap-around for non-copying interface | |
468 * (to fulfil the promise by BIO_ctrl_get_write_guarantee, | |
469 * BIO_nwrite may have to be called twice) */ | |
470 num = b->size - write_offset; | |
471 | |
472 if (buf != NULL) | |
473 *buf = b->buf + write_offset; | |
474 assert(write_offset + num <= b->size); | |
475 | |
476 return num; | |
477 } | |
478 | |
479 static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) | |
480 { | |
481 struct bio_bio_st *b; | |
482 ossl_ssize_t num, space; | |
483 | |
484 if (num_ > SSIZE_MAX) | |
485 num = SSIZE_MAX; | |
486 else | |
487 num = (ossl_ssize_t)num_; | |
488 | |
489 space = bio_nwrite0(bio, buf); | |
490 if (num > space) | |
491 num = space; | |
492 if (num <= 0) | |
493 return num; | |
494 b = bio->ptr; | |
495 assert(b != NULL); | |
496 b->len += num; | |
497 assert(b->len <= b->size); | |
498 | |
499 return num; | |
500 } | |
501 | |
502 | |
503 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) | |
504 { | |
505 long ret; | |
506 struct bio_bio_st *b = bio->ptr; | |
507 | |
508 assert(b != NULL); | |
509 | |
510 switch (cmd) | |
511 { | |
512 /* specific CTRL codes */ | |
513 | |
514 case BIO_C_SET_WRITE_BUF_SIZE: | |
515 if (b->peer) | |
516 { | |
517 BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); | |
518 ret = 0; | |
519 } | |
520 else if (num == 0) | |
521 { | |
522 BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); | |
523 ret = 0; | |
524 } | |
525 else | |
526 { | |
527 size_t new_size = num; | |
528 | |
529 if (b->size != new_size) | |
530 { | |
531 if (b->buf) | |
532 { | |
533 OPENSSL_free(b->buf); | |
534 b->buf = NULL; | |
535 } | |
536 b->size = new_size; | |
537 } | |
538 ret = 1; | |
539 } | |
540 break; | |
541 | |
542 case BIO_C_GET_WRITE_BUF_SIZE: | |
543 ret = (long) b->size; | |
544 break; | |
545 | |
546 case BIO_C_MAKE_BIO_PAIR: | |
547 { | |
548 BIO *other_bio = ptr; | |
549 | |
550 if (bio_make_pair(bio, other_bio)) | |
551 ret = 1; | |
552 else | |
553 ret = 0; | |
554 } | |
555 break; | |
556 | |
557 case BIO_C_DESTROY_BIO_PAIR: | |
558 /* Affects both BIOs in the pair -- call just once! | |
559 * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ | |
560 bio_destroy_pair(bio); | |
561 ret = 1; | |
562 break; | |
563 | |
564 case BIO_C_GET_WRITE_GUARANTEE: | |
565 /* How many bytes can the caller feed to the next write | |
566 * without having to keep any? */ | |
567 if (b->peer == NULL || b->closed) | |
568 ret = 0; | |
569 else | |
570 ret = (long) b->size - b->len; | |
571 break; | |
572 | |
573 case BIO_C_GET_READ_REQUEST: | |
574 /* If the peer unsuccessfully tried to read, how many bytes | |
575 * were requested? (As with BIO_CTRL_PENDING, that number | |
576 * can usually be treated as boolean.) */ | |
577 ret = (long) b->request; | |
578 break; | |
579 | |
580 case BIO_C_RESET_READ_REQUEST: | |
581 /* Reset request. (Can be useful after read attempts | |
582 * at the other side that are meant to be non-blocking, | |
583 * e.g. when probing SSL_read to see if any data is | |
584 * available.) */ | |
585 b->request = 0; | |
586 ret = 1; | |
587 break; | |
588 | |
589 case BIO_C_SHUTDOWN_WR: | |
590 /* similar to shutdown(..., SHUT_WR) */ | |
591 b->closed = 1; | |
592 ret = 1; | |
593 break; | |
594 | |
595 case BIO_C_NREAD0: | |
596 /* prepare for non-copying read */ | |
597 ret = (long) bio_nread0(bio, ptr); | |
598 break; | |
599 | |
600 case BIO_C_NREAD: | |
601 /* non-copying read */ | |
602 ret = (long) bio_nread(bio, ptr, (size_t) num); | |
603 break; | |
604 | |
605 case BIO_C_NWRITE0: | |
606 /* prepare for non-copying write */ | |
607 ret = (long) bio_nwrite0(bio, ptr); | |
608 break; | |
609 | |
610 case BIO_C_NWRITE: | |
611 /* non-copying write */ | |
612 ret = (long) bio_nwrite(bio, ptr, (size_t) num); | |
613 break; | |
614 | |
615 | |
616 /* standard CTRL codes follow */ | |
617 | |
618 case BIO_CTRL_RESET: | |
619 if (b->buf != NULL) | |
620 { | |
621 b->len = 0; | |
622 b->offset = 0; | |
623 } | |
624 ret = 0; | |
625 break; | |
626 | |
627 case BIO_CTRL_GET_CLOSE: | |
628 ret = bio->shutdown; | |
629 break; | |
630 | |
631 case BIO_CTRL_SET_CLOSE: | |
632 bio->shutdown = (int) num; | |
633 ret = 1; | |
634 break; | |
635 | |
636 case BIO_CTRL_PENDING: | |
637 if (b->peer != NULL) | |
638 { | |
639 struct bio_bio_st *peer_b = b->peer->ptr; | |
640 | |
641 ret = (long) peer_b->len; | |
642 } | |
643 else | |
644 ret = 0; | |
645 break; | |
646 | |
647 case BIO_CTRL_WPENDING: | |
648 if (b->buf != NULL) | |
649 ret = (long) b->len; | |
650 else | |
651 ret = 0; | |
652 break; | |
653 | |
654 case BIO_CTRL_DUP: | |
655 /* See BIO_dup_chain for circumstances we have to expect. */ | |
656 { | |
657 BIO *other_bio = ptr; | |
658 struct bio_bio_st *other_b; | |
659 | |
660 assert(other_bio != NULL); | |
661 other_b = other_bio->ptr; | |
662 assert(other_b != NULL); | |
663 | |
664 assert(other_b->buf == NULL); /* other_bio is always fresh */ | |
665 | |
666 other_b->size = b->size; | |
667 } | |
668 | |
669 ret = 1; | |
670 break; | |
671 | |
672 case BIO_CTRL_FLUSH: | |
673 ret = 1; | |
674 break; | |
675 | |
676 case BIO_CTRL_EOF: | |
677 { | |
678 BIO *other_bio = ptr; | |
679 | |
680 if (other_bio) | |
681 { | |
682 struct bio_bio_st *other_b = other_bio->ptr; | |
683 | |
684 assert(other_b != NULL); | |
685 ret = other_b->len == 0 && other_b->closed; | |
686 } | |
687 else | |
688 ret = 1; | |
689 } | |
690 break; | |
691 | |
692 default: | |
693 ret = 0; | |
694 } | |
695 return ret; | |
696 } | |
697 | |
698 static int bio_puts(BIO *bio, const char *str) | |
699 { | |
700 return bio_write(bio, str, strlen(str)); | |
701 } | |
702 | |
703 | |
704 static int bio_make_pair(BIO *bio1, BIO *bio2) | |
705 { | |
706 struct bio_bio_st *b1, *b2; | |
707 | |
708 assert(bio1 != NULL); | |
709 assert(bio2 != NULL); | |
710 | |
711 b1 = bio1->ptr; | |
712 b2 = bio2->ptr; | |
713 | |
714 if (b1->peer != NULL || b2->peer != NULL) | |
715 { | |
716 BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); | |
717 return 0; | |
718 } | |
719 | |
720 if (b1->buf == NULL) | |
721 { | |
722 b1->buf = OPENSSL_malloc(b1->size); | |
723 if (b1->buf == NULL) | |
724 { | |
725 BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); | |
726 return 0; | |
727 } | |
728 b1->len = 0; | |
729 b1->offset = 0; | |
730 } | |
731 | |
732 if (b2->buf == NULL) | |
733 { | |
734 b2->buf = OPENSSL_malloc(b2->size); | |
735 if (b2->buf == NULL) | |
736 { | |
737 BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); | |
738 return 0; | |
739 } | |
740 b2->len = 0; | |
741 b2->offset = 0; | |
742 } | |
743 | |
744 b1->peer = bio2; | |
745 b1->closed = 0; | |
746 b1->request = 0; | |
747 b2->peer = bio1; | |
748 b2->closed = 0; | |
749 b2->request = 0; | |
750 | |
751 bio1->init = 1; | |
752 bio2->init = 1; | |
753 | |
754 return 1; | |
755 } | |
756 | |
757 static void bio_destroy_pair(BIO *bio) | |
758 { | |
759 struct bio_bio_st *b = bio->ptr; | |
760 | |
761 if (b != NULL) | |
762 { | |
763 BIO *peer_bio = b->peer; | |
764 | |
765 if (peer_bio != NULL) | |
766 { | |
767 struct bio_bio_st *peer_b = peer_bio->ptr; | |
768 | |
769 assert(peer_b != NULL); | |
770 assert(peer_b->peer == bio); | |
771 | |
772 peer_b->peer = NULL; | |
773 peer_bio->init = 0; | |
774 assert(peer_b->buf != NULL); | |
775 peer_b->len = 0; | |
776 peer_b->offset = 0; | |
777 | |
778 b->peer = NULL; | |
779 bio->init = 0; | |
780 assert(b->buf != NULL); | |
781 b->len = 0; | |
782 b->offset = 0; | |
783 } | |
784 } | |
785 } | |
786 | |
787 | |
788 /* Exported convenience functions */ | |
789 int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, | |
790 BIO **bio2_p, size_t writebuf2) | |
791 { | |
792 BIO *bio1 = NULL, *bio2 = NULL; | |
793 long r; | |
794 int ret = 0; | |
795 | |
796 bio1 = BIO_new(BIO_s_bio()); | |
797 if (bio1 == NULL) | |
798 goto err; | |
799 bio2 = BIO_new(BIO_s_bio()); | |
800 if (bio2 == NULL) | |
801 goto err; | |
802 | |
803 if (writebuf1) | |
804 { | |
805 r = BIO_set_write_buf_size(bio1, writebuf1); | |
806 if (!r) | |
807 goto err; | |
808 } | |
809 if (writebuf2) | |
810 { | |
811 r = BIO_set_write_buf_size(bio2, writebuf2); | |
812 if (!r) | |
813 goto err; | |
814 } | |
815 | |
816 r = BIO_make_bio_pair(bio1, bio2); | |
817 if (!r) | |
818 goto err; | |
819 ret = 1; | |
820 | |
821 err: | |
822 if (ret == 0) | |
823 { | |
824 if (bio1) | |
825 { | |
826 BIO_free(bio1); | |
827 bio1 = NULL; | |
828 } | |
829 if (bio2) | |
830 { | |
831 BIO_free(bio2); | |
832 bio2 = NULL; | |
833 } | |
834 } | |
835 | |
836 *bio1_p = bio1; | |
837 *bio2_p = bio2; | |
838 return ret; | |
839 } | |
840 | |
841 size_t BIO_ctrl_get_write_guarantee(BIO *bio) | |
842 { | |
843 return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); | |
844 } | |
845 | |
846 size_t BIO_ctrl_get_read_request(BIO *bio) | |
847 { | |
848 return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); | |
849 } | |
850 | |
851 int BIO_ctrl_reset_read_request(BIO *bio) | |
852 { | |
853 return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); | |
854 } | |
855 | |
856 | |
857 /* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now | |
858 * (conceivably some other BIOs could allow non-copying reads and writes too.) | |
859 */ | |
860 int BIO_nread0(BIO *bio, char **buf) | |
861 { | |
862 long ret; | |
863 | |
864 if (!bio->init) | |
865 { | |
866 BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); | |
867 return -2; | |
868 } | |
869 | |
870 ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); | |
871 if (ret > INT_MAX) | |
872 return INT_MAX; | |
873 else | |
874 return (int) ret; | |
875 } | |
876 | |
877 int BIO_nread(BIO *bio, char **buf, int num) | |
878 { | |
879 int ret; | |
880 | |
881 if (!bio->init) | |
882 { | |
883 BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); | |
884 return -2; | |
885 } | |
886 | |
887 ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); | |
888 if (ret > 0) | |
889 bio->num_read += ret; | |
890 return ret; | |
891 } | |
892 | |
893 int BIO_nwrite0(BIO *bio, char **buf) | |
894 { | |
895 long ret; | |
896 | |
897 if (!bio->init) | |
898 { | |
899 BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); | |
900 return -2; | |
901 } | |
902 | |
903 ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); | |
904 if (ret > INT_MAX) | |
905 return INT_MAX; | |
906 else | |
907 return (int) ret; | |
908 } | |
909 | |
910 int BIO_nwrite(BIO *bio, char **buf, int num) | |
911 { | |
912 int ret; | |
913 | |
914 if (!bio->init) | |
915 { | |
916 BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); | |
917 return -2; | |
918 } | |
919 | |
920 ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); | |
921 if (ret > 0) | |
922 bio->num_write += ret; | |
923 return ret; | |
924 } | |
OLD | NEW |