]>
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; | |
154 | b->size = 17*1024; /* enough for one TLS record (just a default) */ | |
155 | b->buf = NULL; | |
156 | ||
95d29597 | 157 | bio->ptr = b; |
9e06f6f6 BM |
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 | { | |
26a3a48d | 177 | OPENSSL_free(b->buf); |
9e06f6f6 BM |
178 | } |
179 | ||
26a3a48d | 180 | OPENSSL_free(b); |
9e06f6f6 BM |
181 | |
182 | return 1; | |
183 | } | |
184 | ||
185 | ||
186 | ||
95d29597 | 187 | static int bio_read(BIO *bio, char *buf, int size_) |
9e06f6f6 | 188 | { |
95d29597 BM |
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 | |
99187624 BM |
220 | /* don't ask for more than the peer can |
221 | * deliver in one write */ | |
222 | peer_b->request = peer_b->size; | |
95d29597 BM |
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 | ||
95d29597 | 269 | return size; |
9e06f6f6 BM |
270 | } |
271 | ||
3e9a08ec TH |
272 | /*- |
273 | * non-copying interface: provide pointer to available data in buffer | |
c1082a90 BM |
274 | * bio_nread0: return number of available bytes |
275 | * bio_nread: also advance index | |
276 | * (example usage: bio_nread0(), read from buffer, bio_nread() | |
277 | * or just bio_nread(), read from buffer) | |
278 | */ | |
6f7af152 BM |
279 | /* WARNING: The non-copying interface is largely untested as of yet |
280 | * and may contain bugs. */ | |
cb70355d | 281 | static ossl_ssize_t bio_nread0(BIO *bio, char **buf) |
c1082a90 BM |
282 | { |
283 | struct bio_bio_st *b, *peer_b; | |
cb70355d | 284 | ossl_ssize_t num; |
c1082a90 BM |
285 | |
286 | BIO_clear_retry_flags(bio); | |
287 | ||
288 | if (!bio->init) | |
289 | return 0; | |
290 | ||
291 | b = bio->ptr; | |
292 | assert(b != NULL); | |
293 | assert(b->peer != NULL); | |
294 | peer_b = b->peer->ptr; | |
295 | assert(peer_b != NULL); | |
296 | assert(peer_b->buf != NULL); | |
297 | ||
298 | peer_b->request = 0; | |
299 | ||
300 | if (peer_b->len == 0) | |
301 | { | |
302 | char dummy; | |
303 | ||
304 | /* avoid code duplication -- nothing available for reading */ | |
d680ba86 | 305 | return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ |
c1082a90 BM |
306 | } |
307 | ||
308 | num = peer_b->len; | |
309 | if (peer_b->size < peer_b->offset + num) | |
310 | /* no ring buffer wrap-around for non-copying interface */ | |
311 | num = peer_b->size - peer_b->offset; | |
312 | assert(num > 0); | |
313 | ||
314 | if (buf != NULL) | |
315 | *buf = peer_b->buf + peer_b->offset; | |
316 | return num; | |
317 | } | |
318 | ||
cb70355d | 319 | static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) |
c1082a90 BM |
320 | { |
321 | struct bio_bio_st *b, *peer_b; | |
cb70355d | 322 | ossl_ssize_t num, available; |
4991d07c BM |
323 | |
324 | if (num_ > SSIZE_MAX) | |
e65991f9 | 325 | num = SSIZE_MAX; |
4991d07c | 326 | else |
cb70355d | 327 | num = (ossl_ssize_t)num_; |
c1082a90 BM |
328 | |
329 | available = bio_nread0(bio, buf); | |
330 | if (num > available) | |
331 | num = available; | |
4991d07c | 332 | if (num <= 0) |
c1082a90 BM |
333 | return num; |
334 | ||
335 | b = bio->ptr; | |
336 | peer_b = b->peer->ptr; | |
337 | ||
338 | peer_b->len -= num; | |
339 | if (peer_b->len) | |
340 | { | |
341 | peer_b->offset += num; | |
342 | assert(peer_b->offset <= peer_b->size); | |
343 | if (peer_b->offset == peer_b->size) | |
344 | peer_b->offset = 0; | |
345 | } | |
346 | else | |
347 | peer_b->offset = 0; | |
348 | ||
349 | return num; | |
350 | } | |
351 | ||
352 | ||
0e1c0612 | 353 | static int bio_write(BIO *bio, const char *buf, int num_) |
9e06f6f6 | 354 | { |
95d29597 BM |
355 | size_t num = num_; |
356 | size_t rest; | |
357 | struct bio_bio_st *b; | |
358 | ||
359 | BIO_clear_retry_flags(bio); | |
360 | ||
361 | if (!bio->init || buf == NULL || num == 0) | |
362 | return 0; | |
363 | ||
364 | b = bio->ptr; | |
365 | assert(b != NULL); | |
366 | assert(b->peer != NULL); | |
367 | assert(b->buf != NULL); | |
368 | ||
369 | b->request = 0; | |
370 | if (b->closed) | |
371 | { | |
372 | /* we already closed */ | |
373 | BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); | |
374 | return -1; | |
375 | } | |
376 | ||
377 | assert(b->len <= b->size); | |
378 | ||
379 | if (b->len == b->size) | |
380 | { | |
381 | BIO_set_retry_write(bio); /* buffer is full */ | |
382 | return -1; | |
383 | } | |
384 | ||
385 | /* we can write */ | |
386 | if (num > b->size - b->len) | |
387 | num = b->size - b->len; | |
388 | ||
389 | /* now write "num" bytes */ | |
390 | ||
391 | rest = num; | |
9e06f6f6 | 392 | |
95d29597 BM |
393 | assert(rest > 0); |
394 | do /* one or two iterations */ | |
395 | { | |
396 | size_t write_offset; | |
397 | size_t chunk; | |
398 | ||
399 | assert(b->len + rest <= b->size); | |
400 | ||
401 | write_offset = b->offset + b->len; | |
402 | if (write_offset >= b->size) | |
403 | write_offset -= b->size; | |
404 | /* b->buf[write_offset] is the first byte we can write to. */ | |
405 | ||
406 | if (write_offset + rest <= b->size) | |
407 | chunk = rest; | |
408 | else | |
409 | /* wrap around ring buffer */ | |
410 | chunk = b->size - write_offset; | |
411 | ||
412 | memcpy(b->buf + write_offset, buf, chunk); | |
413 | ||
414 | b->len += chunk; | |
415 | ||
416 | assert(b->len <= b->size); | |
417 | ||
418 | rest -= chunk; | |
419 | buf += chunk; | |
420 | } | |
421 | while (rest); | |
422 | ||
423 | return num; | |
424 | } | |
425 | ||
3e9a08ec TH |
426 | /*- |
427 | * non-copying interface: provide pointer to region to write to | |
c1082a90 BM |
428 | * bio_nwrite0: check how much space is available |
429 | * bio_nwrite: also increase length | |
430 | * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() | |
431 | * or just bio_nwrite(), write to buffer) | |
432 | */ | |
cb70355d | 433 | static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) |
c1082a90 BM |
434 | { |
435 | struct bio_bio_st *b; | |
436 | size_t num; | |
437 | size_t write_offset; | |
438 | ||
439 | BIO_clear_retry_flags(bio); | |
440 | ||
441 | if (!bio->init) | |
442 | return 0; | |
443 | ||
444 | b = bio->ptr; | |
445 | assert(b != NULL); | |
446 | assert(b->peer != NULL); | |
447 | assert(b->buf != NULL); | |
448 | ||
449 | b->request = 0; | |
450 | if (b->closed) | |
451 | { | |
452 | BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); | |
453 | return -1; | |
454 | } | |
455 | ||
456 | assert(b->len <= b->size); | |
457 | ||
458 | if (b->len == b->size) | |
459 | { | |
460 | BIO_set_retry_write(bio); | |
461 | return -1; | |
462 | } | |
463 | ||
464 | num = b->size - b->len; | |
465 | write_offset = b->offset + b->len; | |
466 | if (write_offset >= b->size) | |
467 | write_offset -= b->size; | |
468 | if (write_offset + num > b->size) | |
469 | /* no ring buffer wrap-around for non-copying interface | |
f50c0497 | 470 | * (to fulfil the promise by BIO_ctrl_get_write_guarantee, |
c1082a90 BM |
471 | * BIO_nwrite may have to be called twice) */ |
472 | num = b->size - write_offset; | |
473 | ||
474 | if (buf != NULL) | |
475 | *buf = b->buf + write_offset; | |
476 | assert(write_offset + num <= b->size); | |
477 | ||
478 | return num; | |
479 | } | |
480 | ||
cb70355d | 481 | static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) |
c1082a90 | 482 | { |
5671876d | 483 | struct bio_bio_st *b; |
cb70355d | 484 | ossl_ssize_t num, space; |
4991d07c BM |
485 | |
486 | if (num_ > SSIZE_MAX) | |
487 | num = SSIZE_MAX; | |
488 | else | |
cb70355d | 489 | num = (ossl_ssize_t)num_; |
c1082a90 BM |
490 | |
491 | space = bio_nwrite0(bio, buf); | |
492 | if (num > space) | |
493 | num = space; | |
4991d07c | 494 | if (num <= 0) |
c1082a90 | 495 | return num; |
5671876d BM |
496 | b = bio->ptr; |
497 | assert(b != NULL); | |
c1082a90 BM |
498 | b->len += num; |
499 | assert(b->len <= b->size); | |
500 | ||
501 | return num; | |
502 | } | |
503 | ||
95d29597 BM |
504 | |
505 | static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) | |
9e06f6f6 BM |
506 | { |
507 | long ret; | |
508 | struct bio_bio_st *b = bio->ptr; | |
509 | ||
510 | assert(b != NULL); | |
511 | ||
512 | switch (cmd) | |
513 | { | |
95d29597 BM |
514 | /* specific CTRL codes */ |
515 | ||
516 | case BIO_C_SET_WRITE_BUF_SIZE: | |
517 | if (b->peer) | |
518 | { | |
519 | BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); | |
520 | ret = 0; | |
521 | } | |
6c82fda2 BM |
522 | else if (num == 0) |
523 | { | |
524 | BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); | |
525 | ret = 0; | |
526 | } | |
95d29597 BM |
527 | else |
528 | { | |
529 | size_t new_size = num; | |
530 | ||
531 | if (b->size != new_size) | |
532 | { | |
533 | if (b->buf) | |
534 | { | |
26a3a48d | 535 | OPENSSL_free(b->buf); |
95d29597 BM |
536 | b->buf = NULL; |
537 | } | |
538 | b->size = new_size; | |
539 | } | |
540 | ret = 1; | |
541 | } | |
542 | break; | |
543 | ||
544 | case BIO_C_GET_WRITE_BUF_SIZE: | |
54fbc77d LJ |
545 | ret = (long) b->size; |
546 | break; | |
95d29597 BM |
547 | |
548 | case BIO_C_MAKE_BIO_PAIR: | |
549 | { | |
550 | BIO *other_bio = ptr; | |
551 | ||
552 | if (bio_make_pair(bio, other_bio)) | |
553 | ret = 1; | |
554 | else | |
555 | ret = 0; | |
556 | } | |
557 | break; | |
558 | ||
559 | case BIO_C_DESTROY_BIO_PAIR: | |
3aa8d3a7 | 560 | /* Affects both BIOs in the pair -- call just once! |
95d29597 BM |
561 | * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ |
562 | bio_destroy_pair(bio); | |
563 | ret = 1; | |
564 | break; | |
565 | ||
566 | case BIO_C_GET_WRITE_GUARANTEE: | |
567 | /* How many bytes can the caller feed to the next write | |
657e60fa | 568 | * without having to keep any? */ |
95d29597 BM |
569 | if (b->peer == NULL || b->closed) |
570 | ret = 0; | |
571 | else | |
572 | ret = (long) b->size - b->len; | |
573 | break; | |
574 | ||
575 | case BIO_C_GET_READ_REQUEST: | |
657e60fa | 576 | /* If the peer unsuccessfully tried to read, how many bytes |
95d29597 BM |
577 | * were requested? (As with BIO_CTRL_PENDING, that number |
578 | * can usually be treated as boolean.) */ | |
579 | ret = (long) b->request; | |
580 | break; | |
581 | ||
e405b8d1 BM |
582 | case BIO_C_RESET_READ_REQUEST: |
583 | /* Reset request. (Can be useful after read attempts | |
584 | * at the other side that are meant to be non-blocking, | |
585 | * e.g. when probing SSL_read to see if any data is | |
586 | * available.) */ | |
587 | b->request = 0; | |
588 | ret = 1; | |
589 | break; | |
590 | ||
95d29597 BM |
591 | case BIO_C_SHUTDOWN_WR: |
592 | /* similar to shutdown(..., SHUT_WR) */ | |
593 | b->closed = 1; | |
594 | ret = 1; | |
595 | break; | |
596 | ||
4991d07c BM |
597 | case BIO_C_NREAD0: |
598 | /* prepare for non-copying read */ | |
599 | ret = (long) bio_nread0(bio, ptr); | |
600 | break; | |
601 | ||
c1082a90 BM |
602 | case BIO_C_NREAD: |
603 | /* non-copying read */ | |
604 | ret = (long) bio_nread(bio, ptr, (size_t) num); | |
605 | break; | |
606 | ||
607 | case BIO_C_NWRITE0: | |
608 | /* prepare for non-copying write */ | |
609 | ret = (long) bio_nwrite0(bio, ptr); | |
610 | break; | |
611 | ||
612 | case BIO_C_NWRITE: | |
613 | /* non-copying write */ | |
614 | ret = (long) bio_nwrite(bio, ptr, (size_t) num); | |
615 | break; | |
616 | ||
95d29597 BM |
617 | |
618 | /* standard CTRL codes follow */ | |
9e06f6f6 BM |
619 | |
620 | case BIO_CTRL_RESET: | |
621 | if (b->buf != NULL) | |
622 | { | |
623 | b->len = 0; | |
624 | b->offset = 0; | |
625 | } | |
626 | ret = 0; | |
627 | break; | |
628 | ||
629 | case BIO_CTRL_GET_CLOSE: | |
630 | ret = bio->shutdown; | |
631 | break; | |
632 | ||
633 | case BIO_CTRL_SET_CLOSE: | |
634 | bio->shutdown = (int) num; | |
635 | ret = 1; | |
636 | break; | |
637 | ||
638 | case BIO_CTRL_PENDING: | |
639 | if (b->peer != NULL) | |
640 | { | |
7eea36bb | 641 | struct bio_bio_st *peer_b = b->peer->ptr; |
9e06f6f6 BM |
642 | |
643 | ret = (long) peer_b->len; | |
644 | } | |
645 | else | |
646 | ret = 0; | |
647 | break; | |
648 | ||
649 | case BIO_CTRL_WPENDING: | |
650 | if (b->buf != NULL) | |
651 | ret = (long) b->len; | |
652 | else | |
653 | ret = 0; | |
654 | break; | |
655 | ||
656 | case BIO_CTRL_DUP: | |
95d29597 BM |
657 | /* See BIO_dup_chain for circumstances we have to expect. */ |
658 | { | |
659 | BIO *other_bio = ptr; | |
660 | struct bio_bio_st *other_b; | |
661 | ||
662 | assert(other_bio != NULL); | |
663 | other_b = other_bio->ptr; | |
664 | assert(other_b != NULL); | |
665 | ||
666 | assert(other_b->buf == NULL); /* other_bio is always fresh */ | |
667 | ||
668 | other_b->size = b->size; | |
669 | } | |
670 | ||
c035b0c3 BM |
671 | ret = 1; |
672 | break; | |
9e06f6f6 BM |
673 | |
674 | case BIO_CTRL_FLUSH: | |
675 | ret = 1; | |
676 | break; | |
677 | ||
95d29597 BM |
678 | case BIO_CTRL_EOF: |
679 | { | |
680 | BIO *other_bio = ptr; | |
681 | ||
682 | if (other_bio) | |
683 | { | |
684 | struct bio_bio_st *other_b = other_bio->ptr; | |
685 | ||
686 | assert(other_b != NULL); | |
687 | ret = other_b->len == 0 && other_b->closed; | |
688 | } | |
689 | else | |
690 | ret = 1; | |
691 | } | |
692 | break; | |
693 | ||
9e06f6f6 BM |
694 | default: |
695 | ret = 0; | |
696 | } | |
697 | return ret; | |
698 | } | |
699 | ||
0e1c0612 | 700 | static int bio_puts(BIO *bio, const char *str) |
9e06f6f6 BM |
701 | { |
702 | return bio_write(bio, str, strlen(str)); | |
703 | } | |
704 | ||
9e06f6f6 BM |
705 | |
706 | static int bio_make_pair(BIO *bio1, BIO *bio2) | |
707 | { | |
708 | struct bio_bio_st *b1, *b2; | |
709 | ||
710 | assert(bio1 != NULL); | |
711 | assert(bio2 != NULL); | |
712 | ||
713 | b1 = bio1->ptr; | |
714 | b2 = bio2->ptr; | |
715 | ||
716 | if (b1->peer != NULL || b2->peer != NULL) | |
717 | { | |
718 | BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); | |
719 | return 0; | |
720 | } | |
721 | ||
1aad3392 | 722 | if (b1->buf == NULL) |
9e06f6f6 | 723 | { |
26a3a48d | 724 | b1->buf = OPENSSL_malloc(b1->size); |
9e06f6f6 BM |
725 | if (b1->buf == NULL) |
726 | { | |
727 | BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); | |
728 | return 0; | |
729 | } | |
730 | b1->len = 0; | |
731 | b1->offset = 0; | |
732 | } | |
733 | ||
1aad3392 | 734 | if (b2->buf == NULL) |
9e06f6f6 | 735 | { |
26a3a48d | 736 | b2->buf = OPENSSL_malloc(b2->size); |
9e06f6f6 BM |
737 | if (b2->buf == NULL) |
738 | { | |
739 | BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); | |
740 | return 0; | |
741 | } | |
742 | b2->len = 0; | |
743 | b2->offset = 0; | |
744 | } | |
745 | ||
746 | b1->peer = bio2; | |
c035b0c3 BM |
747 | b1->closed = 0; |
748 | b1->request = 0; | |
9e06f6f6 | 749 | b2->peer = bio1; |
c035b0c3 BM |
750 | b2->closed = 0; |
751 | b2->request = 0; | |
9e06f6f6 | 752 | |
3928b6bf BM |
753 | bio1->init = 1; |
754 | bio2->init = 1; | |
755 | ||
9e06f6f6 BM |
756 | return 1; |
757 | } | |
758 | ||
759 | static void bio_destroy_pair(BIO *bio) | |
760 | { | |
761 | struct bio_bio_st *b = bio->ptr; | |
762 | ||
763 | if (b != NULL) | |
764 | { | |
765 | BIO *peer_bio = b->peer; | |
766 | ||
767 | if (peer_bio != NULL) | |
768 | { | |
769 | struct bio_bio_st *peer_b = peer_bio->ptr; | |
770 | ||
771 | assert(peer_b != NULL); | |
772 | assert(peer_b->peer == bio); | |
773 | ||
774 | peer_b->peer = NULL; | |
775 | peer_bio->init = 0; | |
776 | assert(peer_b->buf != NULL); | |
777 | peer_b->len = 0; | |
778 | peer_b->offset = 0; | |
779 | ||
780 | b->peer = NULL; | |
781 | bio->init = 0; | |
782 | assert(b->buf != NULL); | |
783 | b->len = 0; | |
784 | b->offset = 0; | |
785 | } | |
786 | } | |
787 | } | |
95d29597 BM |
788 | |
789 | ||
790 | /* Exported convenience functions */ | |
791 | int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, | |
792 | BIO **bio2_p, size_t writebuf2) | |
793 | { | |
794 | BIO *bio1 = NULL, *bio2 = NULL; | |
795 | long r; | |
796 | int ret = 0; | |
797 | ||
798 | bio1 = BIO_new(BIO_s_bio()); | |
799 | if (bio1 == NULL) | |
800 | goto err; | |
801 | bio2 = BIO_new(BIO_s_bio()); | |
802 | if (bio2 == NULL) | |
803 | goto err; | |
804 | ||
805 | if (writebuf1) | |
806 | { | |
807 | r = BIO_set_write_buf_size(bio1, writebuf1); | |
808 | if (!r) | |
809 | goto err; | |
810 | } | |
811 | if (writebuf2) | |
812 | { | |
813 | r = BIO_set_write_buf_size(bio2, writebuf2); | |
814 | if (!r) | |
815 | goto err; | |
816 | } | |
817 | ||
818 | r = BIO_make_bio_pair(bio1, bio2); | |
819 | if (!r) | |
820 | goto err; | |
821 | ret = 1; | |
822 | ||
823 | err: | |
824 | if (ret == 0) | |
825 | { | |
826 | if (bio1) | |
827 | { | |
828 | BIO_free(bio1); | |
829 | bio1 = NULL; | |
830 | } | |
831 | if (bio2) | |
832 | { | |
833 | BIO_free(bio2); | |
834 | bio2 = NULL; | |
835 | } | |
836 | } | |
837 | ||
838 | *bio1_p = bio1; | |
839 | *bio2_p = bio2; | |
840 | return ret; | |
841 | } | |
842 | ||
843 | size_t BIO_ctrl_get_write_guarantee(BIO *bio) | |
99187624 | 844 | { |
95d29597 BM |
845 | return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); |
846 | } | |
847 | ||
2de62540 | 848 | size_t BIO_ctrl_get_read_request(BIO *bio) |
99187624 | 849 | { |
95d29597 BM |
850 | return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); |
851 | } | |
c1082a90 | 852 | |
e405b8d1 BM |
853 | int BIO_ctrl_reset_read_request(BIO *bio) |
854 | { | |
855 | return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); | |
856 | } | |
857 | ||
c1082a90 | 858 | |
657e60fa | 859 | /* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now |
c1082a90 BM |
860 | * (conceivably some other BIOs could allow non-copying reads and writes too.) |
861 | */ | |
862 | int BIO_nread0(BIO *bio, char **buf) | |
863 | { | |
864 | long ret; | |
865 | ||
866 | if (!bio->init) | |
867 | { | |
868 | BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); | |
869 | return -2; | |
870 | } | |
871 | ||
872 | ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); | |
873 | if (ret > INT_MAX) | |
874 | return INT_MAX; | |
875 | else | |
876 | return (int) ret; | |
877 | } | |
878 | ||
879 | int BIO_nread(BIO *bio, char **buf, int num) | |
880 | { | |
881 | int ret; | |
882 | ||
883 | if (!bio->init) | |
884 | { | |
885 | BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); | |
886 | return -2; | |
887 | } | |
888 | ||
889 | ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); | |
890 | if (ret > 0) | |
891 | bio->num_read += ret; | |
892 | return ret; | |
893 | } | |
894 | ||
895 | int BIO_nwrite0(BIO *bio, char **buf) | |
896 | { | |
897 | long ret; | |
898 | ||
899 | if (!bio->init) | |
900 | { | |
901 | BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); | |
902 | return -2; | |
903 | } | |
904 | ||
905 | ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); | |
906 | if (ret > INT_MAX) | |
907 | return INT_MAX; | |
908 | else | |
909 | return (int) ret; | |
910 | } | |
911 | ||
912 | int BIO_nwrite(BIO *bio, char **buf, int num) | |
913 | { | |
914 | int ret; | |
915 | ||
916 | if (!bio->init) | |
917 | { | |
918 | BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); | |
919 | return -2; | |
920 | } | |
921 | ||
922 | ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); | |
923 | if (ret > 0) | |
44390fad | 924 | bio->num_write += ret; |
c1082a90 BM |
925 | return ret; |
926 | } |