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