2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 #include "bio_local.h"
13 #include "internal/cryptlib.h"
15 static int buffer_write(BIO
*h
, const char *buf
, int num
);
16 static int buffer_read(BIO
*h
, char *buf
, int size
);
17 static int buffer_puts(BIO
*h
, const char *str
);
18 static int buffer_gets(BIO
*h
, char *str
, int size
);
19 static long buffer_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
20 static int buffer_new(BIO
*h
);
21 static int buffer_free(BIO
*data
);
22 static long buffer_callback_ctrl(BIO
*h
, int cmd
, BIO_info_cb
*fp
);
23 #define DEFAULT_BUFFER_SIZE 4096
25 static const BIO_METHOD methods_buffer
= {
40 const BIO_METHOD
*BIO_f_buffer(void)
42 return &methods_buffer
;
45 static int buffer_new(BIO
*bi
)
47 BIO_F_BUFFER_CTX
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
51 ctx
->ibuf_size
= DEFAULT_BUFFER_SIZE
;
52 ctx
->ibuf
= OPENSSL_malloc(DEFAULT_BUFFER_SIZE
);
53 if (ctx
->ibuf
== NULL
) {
57 ctx
->obuf_size
= DEFAULT_BUFFER_SIZE
;
58 ctx
->obuf
= OPENSSL_malloc(DEFAULT_BUFFER_SIZE
);
59 if (ctx
->obuf
== NULL
) {
60 OPENSSL_free(ctx
->ibuf
);
66 bi
->ptr
= (char *)ctx
;
71 static int buffer_free(BIO
*a
)
77 b
= (BIO_F_BUFFER_CTX
*)a
->ptr
;
78 OPENSSL_free(b
->ibuf
);
79 OPENSSL_free(b
->obuf
);
87 static int buffer_read(BIO
*b
, char *out
, int outl
)
90 BIO_F_BUFFER_CTX
*ctx
;
94 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
96 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
99 BIO_clear_retry_flags(b
);
103 /* If there is stuff left over, grab it */
107 memcpy(out
, &(ctx
->ibuf
[ctx
->ibuf_off
]), i
);
118 * We may have done a partial read. try to do more. We have nothing in
119 * the buffer. If we get an error and have read some data, just return it
120 * and let them retry to get the error again. copy direct to parent
123 if (outl
> ctx
->ibuf_size
) {
125 i
= BIO_read(b
->next_bio
, out
, outl
);
127 BIO_copy_next_retry(b
);
129 return ((num
> 0) ? num
: i
);
142 /* we are going to be doing some buffering */
143 i
= BIO_read(b
->next_bio
, ctx
->ibuf
, ctx
->ibuf_size
);
145 BIO_copy_next_retry(b
);
147 return ((num
> 0) ? num
: i
);
154 /* Lets re-read using ourselves :-) */
158 static int buffer_write(BIO
*b
, const char *in
, int inl
)
161 BIO_F_BUFFER_CTX
*ctx
;
163 if ((in
== NULL
) || (inl
<= 0))
165 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
166 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
169 BIO_clear_retry_flags(b
);
171 i
= ctx
->obuf_size
- (ctx
->obuf_len
+ ctx
->obuf_off
);
172 /* add to buffer and return */
174 memcpy(&(ctx
->obuf
[ctx
->obuf_off
+ ctx
->obuf_len
]), in
, inl
);
175 ctx
->obuf_len
+= inl
;
179 /* stuff already in buffer, so add to it first, then flush */
180 if (ctx
->obuf_len
!= 0) {
181 if (i
> 0) { /* lets fill it up if we can */
182 memcpy(&(ctx
->obuf
[ctx
->obuf_off
+ ctx
->obuf_len
]), in
, i
);
188 /* we now have a full buffer needing flushing */
190 i
= BIO_write(b
->next_bio
, &(ctx
->obuf
[ctx
->obuf_off
]),
193 BIO_copy_next_retry(b
);
196 return ((num
> 0) ? num
: i
);
202 if (ctx
->obuf_len
== 0)
207 * we only get here if the buffer has been flushed and we still have
212 /* we now have inl bytes to write */
213 while (inl
>= ctx
->obuf_size
) {
214 i
= BIO_write(b
->next_bio
, in
, inl
);
216 BIO_copy_next_retry(b
);
218 return ((num
> 0) ? num
: i
);
230 * copy the rest into the buffer since we have only a small amount left
235 static long buffer_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
238 BIO_F_BUFFER_CTX
*ctx
;
244 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
252 if (b
->next_bio
== NULL
)
254 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
257 if (ctx
->ibuf_len
> 0)
259 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
262 ret
= (long)ctx
->obuf_len
;
264 case BIO_C_GET_BUFF_NUM_LINES
:
267 for (i
= 0; i
< ctx
->ibuf_len
; i
++) {
268 if (p1
[ctx
->ibuf_off
+ i
] == '\n')
272 case BIO_CTRL_WPENDING
:
273 ret
= (long)ctx
->obuf_len
;
275 if (b
->next_bio
== NULL
)
277 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
280 case BIO_CTRL_PENDING
:
281 ret
= (long)ctx
->ibuf_len
;
283 if (b
->next_bio
== NULL
)
285 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
288 case BIO_C_SET_BUFF_READ_DATA
:
289 if (num
> ctx
->ibuf_size
) {
292 p1
= OPENSSL_malloc((size_t)num
);
295 OPENSSL_free(ctx
->ibuf
);
299 ctx
->ibuf_len
= (int)num
;
300 memcpy(ctx
->ibuf
, ptr
, (int)num
);
303 case BIO_C_SET_BUFF_SIZE
:
308 obs
= ctx
->obuf_size
;
309 } else { /* if (*ip == 1) */
311 ibs
= ctx
->ibuf_size
;
320 if ((ibs
> DEFAULT_BUFFER_SIZE
) && (ibs
!= ctx
->ibuf_size
)) {
323 p1
= OPENSSL_malloc((size_t)num
);
327 if ((obs
> DEFAULT_BUFFER_SIZE
) && (obs
!= ctx
->obuf_size
)) {
328 p2
= OPENSSL_malloc((size_t)num
);
335 if (ctx
->ibuf
!= p1
) {
336 OPENSSL_free(ctx
->ibuf
);
340 ctx
->ibuf_size
= ibs
;
342 if (ctx
->obuf
!= p2
) {
343 OPENSSL_free(ctx
->obuf
);
347 ctx
->obuf_size
= obs
;
350 case BIO_C_DO_STATE_MACHINE
:
351 if (b
->next_bio
== NULL
)
353 BIO_clear_retry_flags(b
);
354 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
355 BIO_copy_next_retry(b
);
359 if (b
->next_bio
== NULL
)
361 if (ctx
->obuf_len
<= 0) {
362 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
367 BIO_clear_retry_flags(b
);
368 if (ctx
->obuf_len
> 0) {
369 r
= BIO_write(b
->next_bio
,
370 &(ctx
->obuf
[ctx
->obuf_off
]), ctx
->obuf_len
);
371 BIO_copy_next_retry(b
);
382 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
386 if (!BIO_set_read_buffer_size(dbio
, ctx
->ibuf_size
) ||
387 !BIO_set_write_buffer_size(dbio
, ctx
->obuf_size
))
391 /* Ensure there's stuff in the input buffer */
394 (void)buffer_read(b
, fake_buf
, 0);
396 if (num
> ctx
->ibuf_len
)
398 memcpy(ptr
, &(ctx
->ibuf
[ctx
->ibuf_off
]), num
);
402 if (b
->next_bio
== NULL
)
404 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
410 static long buffer_callback_ctrl(BIO
*b
, int cmd
, BIO_info_cb
*fp
)
412 if (b
->next_bio
== NULL
)
414 return BIO_callback_ctrl(b
->next_bio
, cmd
, fp
);
417 static int buffer_gets(BIO
*b
, char *buf
, int size
)
419 BIO_F_BUFFER_CTX
*ctx
;
420 int num
= 0, i
, flag
;
423 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
424 size
--; /* reserve space for a '\0' */
425 BIO_clear_retry_flags(b
);
428 if (ctx
->ibuf_len
> 0) {
429 p
= &(ctx
->ibuf
[ctx
->ibuf_off
]);
431 for (i
= 0; (i
< ctx
->ibuf_len
) && (i
< size
); i
++) {
443 if (flag
|| size
== 0) {
447 } else { /* read another chunk */
449 i
= BIO_read(b
->next_bio
, ctx
->ibuf
, ctx
->ibuf_size
);
451 BIO_copy_next_retry(b
);
454 return ((num
> 0) ? num
: i
);
464 static int buffer_puts(BIO
*b
, const char *str
)
466 return buffer_write(b
, str
, strlen(str
));