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