summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bio/bss_bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bio/bss_bio.c')
-rw-r--r--src/lib/libcrypto/bio/bss_bio.c256
1 files changed, 252 insertions, 4 deletions
diff --git a/src/lib/libcrypto/bio/bss_bio.c b/src/lib/libcrypto/bio/bss_bio.c
index 562e9d8de2..0d0f9356f7 100644
--- a/src/lib/libcrypto/bio/bss_bio.c
+++ b/src/lib/libcrypto/bio/bss_bio.c
@@ -13,6 +13,7 @@
13#endif 13#endif
14 14
15#include <assert.h> 15#include <assert.h>
16#include <limits.h>
16#include <stdlib.h> 17#include <stdlib.h>
17#include <string.h> 18#include <string.h>
18 19
@@ -40,7 +41,8 @@ static BIO_METHOD methods_biop =
40 NULL /* no bio_gets */, 41 NULL /* no bio_gets */,
41 bio_ctrl, 42 bio_ctrl,
42 bio_new, 43 bio_new,
43 bio_free 44 bio_free,
45 NULL /* no bio_callback_ctrl */
44}; 46};
45 47
46BIO_METHOD *BIO_s_bio(void) 48BIO_METHOD *BIO_s_bio(void)
@@ -64,7 +66,7 @@ struct bio_bio_st
64 66
65 size_t request; /* valid iff peer != NULL; 0 if len != 0, 67 size_t request; /* valid iff peer != NULL; 0 if len != 0,
66 * otherwise set by peer to number of bytes 68 * otherwise set by peer to number of bytes
67 * it (unsuccesfully) tried to read, 69 * it (unsuccessfully) tried to read,
68 * never more than buffer space (size-len) warrants. */ 70 * never more than buffer space (size-len) warrants. */
69}; 71};
70 72
@@ -195,6 +197,81 @@ static int bio_read(BIO *bio, char *buf, int size_)
195 return size; 197 return size;
196 } 198 }
197 199
200/* non-copying interface: provide pointer to available data in buffer
201 * bio_nread0: return number of available bytes
202 * bio_nread: also advance index
203 * (example usage: bio_nread0(), read from buffer, bio_nread()
204 * or just bio_nread(), read from buffer)
205 */
206/* WARNING: The non-copying interface is largely untested as of yet
207 * and may contain bugs. */
208static size_t bio_nread0(BIO *bio, char **buf)
209 {
210 struct bio_bio_st *b, *peer_b;
211 size_t num;
212
213 BIO_clear_retry_flags(bio);
214
215 if (!bio->init)
216 return 0;
217
218 b = bio->ptr;
219 assert(b != NULL);
220 assert(b->peer != NULL);
221 peer_b = b->peer->ptr;
222 assert(peer_b != NULL);
223 assert(peer_b->buf != NULL);
224
225 peer_b->request = 0;
226
227 if (peer_b->len == 0)
228 {
229 char dummy;
230
231 /* avoid code duplication -- nothing available for reading */
232 return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
233 }
234
235 num = peer_b->len;
236 if (peer_b->size < peer_b->offset + num)
237 /* no ring buffer wrap-around for non-copying interface */
238 num = peer_b->size - peer_b->offset;
239 assert(num > 0);
240
241 if (buf != NULL)
242 *buf = peer_b->buf + peer_b->offset;
243 return num;
244 }
245
246static size_t bio_nread(BIO *bio, char **buf, size_t num)
247 {
248 struct bio_bio_st *b, *peer_b;
249 size_t available;
250
251 available = bio_nread0(bio, buf);
252 if (num > available)
253 num = available;
254 if (num == 0)
255 return num;
256
257 b = bio->ptr;
258 peer_b = b->peer->ptr;
259
260 peer_b->len -= num;
261 if (peer_b->len)
262 {
263 peer_b->offset += num;
264 assert(peer_b->offset <= peer_b->size);
265 if (peer_b->offset == peer_b->size)
266 peer_b->offset = 0;
267 }
268 else
269 peer_b->offset = 0;
270
271 return num;
272 }
273
274
198static int bio_write(BIO *bio, char *buf, int num_) 275static int bio_write(BIO *bio, char *buf, int num_)
199 { 276 {
200 size_t num = num_; 277 size_t num = num_;
@@ -268,6 +345,78 @@ static int bio_write(BIO *bio, char *buf, int num_)
268 return num; 345 return num;
269 } 346 }
270 347
348/* non-copying interface: provide pointer to region to write to
349 * bio_nwrite0: check how much space is available
350 * bio_nwrite: also increase length
351 * (example usage: bio_nwrite0(), write to buffer, bio_nwrite()
352 * or just bio_nwrite(), write to buffer)
353 */
354static size_t bio_nwrite0(BIO *bio, char **buf)
355 {
356 struct bio_bio_st *b;
357 size_t num;
358 size_t write_offset;
359
360 BIO_clear_retry_flags(bio);
361
362 if (!bio->init)
363 return 0;
364
365 b = bio->ptr;
366 assert(b != NULL);
367 assert(b->peer != NULL);
368 assert(b->buf != NULL);
369
370 b->request = 0;
371 if (b->closed)
372 {
373 BIOerr(BIO_F_BIO_NWRITE0, 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);
382 return -1;
383 }
384
385 num = b->size - b->len;
386 write_offset = b->offset + b->len;
387 if (write_offset >= b->size)
388 write_offset -= b->size;
389 if (write_offset + num > b->size)
390 /* no ring buffer wrap-around for non-copying interface
391 * (to fulfil the promise by BIO_ctrl_get_write_guarantee,
392 * BIO_nwrite may have to be called twice) */
393 num = b->size - write_offset;
394
395 if (buf != NULL)
396 *buf = b->buf + write_offset;
397 assert(write_offset + num <= b->size);
398
399 return num;
400 }
401
402static size_t bio_nwrite(BIO *bio, char **buf, size_t num)
403 {
404 struct bio_bio_st *b;
405 size_t space;
406
407 space = bio_nwrite0(bio, buf);
408 if (num > space)
409 num = space;
410 if (num == 0)
411 return num;
412 b = bio->ptr;
413 assert(b != NULL);
414 b->len += num;
415 assert(b->len <= b->size);
416
417 return num;
418 }
419
271 420
272static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 421static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
273 { 422 {
@@ -331,7 +480,7 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
331 480
332 case BIO_C_GET_WRITE_GUARANTEE: 481 case BIO_C_GET_WRITE_GUARANTEE:
333 /* How many bytes can the caller feed to the next write 482 /* How many bytes can the caller feed to the next write
334 * withouth having to keep any? */ 483 * without having to keep any? */
335 if (b->peer == NULL || b->closed) 484 if (b->peer == NULL || b->closed)
336 ret = 0; 485 ret = 0;
337 else 486 else
@@ -339,18 +488,42 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
339 break; 488 break;
340 489
341 case BIO_C_GET_READ_REQUEST: 490 case BIO_C_GET_READ_REQUEST:
342 /* If the peer unsuccesfully tried to read, how many bytes 491 /* If the peer unsuccessfully tried to read, how many bytes
343 * were requested? (As with BIO_CTRL_PENDING, that number 492 * were requested? (As with BIO_CTRL_PENDING, that number
344 * can usually be treated as boolean.) */ 493 * can usually be treated as boolean.) */
345 ret = (long) b->request; 494 ret = (long) b->request;
346 break; 495 break;
347 496
497 case BIO_C_RESET_READ_REQUEST:
498 /* Reset request. (Can be useful after read attempts
499 * at the other side that are meant to be non-blocking,
500 * e.g. when probing SSL_read to see if any data is
501 * available.) */
502 b->request = 0;
503 ret = 1;
504 break;
505
348 case BIO_C_SHUTDOWN_WR: 506 case BIO_C_SHUTDOWN_WR:
349 /* similar to shutdown(..., SHUT_WR) */ 507 /* similar to shutdown(..., SHUT_WR) */
350 b->closed = 1; 508 b->closed = 1;
351 ret = 1; 509 ret = 1;
352 break; 510 break;
353 511
512 case BIO_C_NREAD:
513 /* non-copying read */
514 ret = (long) bio_nread(bio, ptr, (size_t) num);
515 break;
516
517 case BIO_C_NWRITE0:
518 /* prepare for non-copying write */
519 ret = (long) bio_nwrite0(bio, ptr);
520 break;
521
522 case BIO_C_NWRITE:
523 /* non-copying write */
524 ret = (long) bio_nwrite(bio, ptr, (size_t) num);
525 break;
526
354 527
355 /* standard CTRL codes follow */ 528 /* standard CTRL codes follow */
356 529
@@ -586,3 +759,78 @@ size_t BIO_ctrl_get_read_request(BIO *bio)
586 { 759 {
587 return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 760 return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
588 } 761 }
762
763int BIO_ctrl_reset_read_request(BIO *bio)
764 {
765 return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
766 }
767
768
769/* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
770 * (conceivably some other BIOs could allow non-copying reads and writes too.)
771 */
772int BIO_nread0(BIO *bio, char **buf)
773 {
774 long ret;
775
776 if (!bio->init)
777 {
778 BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
779 return -2;
780 }
781
782 ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
783 if (ret > INT_MAX)
784 return INT_MAX;
785 else
786 return (int) ret;
787 }
788
789int BIO_nread(BIO *bio, char **buf, int num)
790 {
791 int ret;
792
793 if (!bio->init)
794 {
795 BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
796 return -2;
797 }
798
799 ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf);
800 if (ret > 0)
801 bio->num_read += ret;
802 return ret;
803 }
804
805int BIO_nwrite0(BIO *bio, char **buf)
806 {
807 long ret;
808
809 if (!bio->init)
810 {
811 BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
812 return -2;
813 }
814
815 ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
816 if (ret > INT_MAX)
817 return INT_MAX;
818 else
819 return (int) ret;
820 }
821
822int BIO_nwrite(BIO *bio, char **buf, int num)
823 {
824 int ret;
825
826 if (!bio->init)
827 {
828 BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
829 return -2;
830 }
831
832 ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
833 if (ret > 0)
834 bio->num_read += ret;
835 return ret;
836 }