• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/err.h>
59 #include <openssl/mem.h>
60 
61 #include "../internal.h"
62 
63 
64 struct bio_bio_st {
65   BIO *peer;  // NULL if buf == NULL.
66               // If peer != NULL, then peer->ptr is also a bio_bio_st,
67               // and its "peer" member points back to us.
68               // peer != NULL iff init != 0 in the BIO.
69 
70   // This is for what we write (i.e. reading uses peer's struct):
71   int closed;     // valid iff peer != NULL
72   size_t len;     // valid iff buf != NULL; 0 if peer == NULL
73   size_t offset;  // valid iff buf != NULL; 0 if len == 0
74   size_t size;
75   uint8_t *buf;  // "size" elements (if != NULL)
76 
77   size_t request;  // valid iff peer != NULL; 0 if len != 0,
78                    // otherwise set by peer to number of bytes
79                    // it (unsuccessfully) tried to read,
80                    // never more than buffer space (size-len) warrants.
81 };
82 
bio_new(BIO * bio)83 static int bio_new(BIO *bio) {
84   struct bio_bio_st *b;
85 
86   b = OPENSSL_malloc(sizeof *b);
87   if (b == NULL) {
88     return 0;
89   }
90   OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
91 
92   b->size = 17 * 1024;  // enough for one TLS record (just a default)
93   bio->ptr = b;
94   return 1;
95 }
96 
bio_destroy_pair(BIO * bio)97 static void bio_destroy_pair(BIO *bio) {
98   struct bio_bio_st *b = bio->ptr;
99   BIO *peer_bio;
100   struct bio_bio_st *peer_b;
101 
102   if (b == NULL) {
103     return;
104   }
105 
106   peer_bio = b->peer;
107   if (peer_bio == NULL) {
108     return;
109   }
110 
111   peer_b = peer_bio->ptr;
112 
113   assert(peer_b != NULL);
114   assert(peer_b->peer == bio);
115 
116   peer_b->peer = NULL;
117   peer_bio->init = 0;
118   assert(peer_b->buf != NULL);
119   peer_b->len = 0;
120   peer_b->offset = 0;
121 
122   b->peer = NULL;
123   bio->init = 0;
124   assert(b->buf != NULL);
125   b->len = 0;
126   b->offset = 0;
127 }
128 
bio_free(BIO * bio)129 static int bio_free(BIO *bio) {
130   struct bio_bio_st *b;
131 
132   if (bio == NULL) {
133     return 0;
134   }
135   b = bio->ptr;
136 
137   assert(b != NULL);
138 
139   if (b->peer) {
140     bio_destroy_pair(bio);
141   }
142 
143   OPENSSL_free(b->buf);
144   OPENSSL_free(b);
145 
146   return 1;
147 }
148 
bio_read(BIO * bio,char * buf,int size_)149 static int bio_read(BIO *bio, char *buf, int size_) {
150   size_t size = size_;
151   size_t rest;
152   struct bio_bio_st *b, *peer_b;
153 
154   BIO_clear_retry_flags(bio);
155 
156   if (!bio->init) {
157     return 0;
158   }
159 
160   b = bio->ptr;
161   assert(b != NULL);
162   assert(b->peer != NULL);
163   peer_b = b->peer->ptr;
164   assert(peer_b != NULL);
165   assert(peer_b->buf != NULL);
166 
167   peer_b->request = 0;  // will be set in "retry_read" situation
168 
169   if (buf == NULL || size == 0) {
170     return 0;
171   }
172 
173   if (peer_b->len == 0) {
174     if (peer_b->closed) {
175       return 0;  // writer has closed, and no data is left
176     } else {
177       BIO_set_retry_read(bio);  // buffer is empty
178       if (size <= peer_b->size) {
179         peer_b->request = size;
180       } else {
181         // don't ask for more than the peer can
182         // deliver in one write
183         peer_b->request = peer_b->size;
184       }
185       return -1;
186     }
187   }
188 
189   // we can read
190   if (peer_b->len < size) {
191     size = peer_b->len;
192   }
193 
194   // now read "size" bytes
195   rest = size;
196 
197   assert(rest > 0);
198   // one or two iterations
199   do {
200     size_t chunk;
201 
202     assert(rest <= peer_b->len);
203     if (peer_b->offset + rest <= peer_b->size) {
204       chunk = rest;
205     } else {
206       // wrap around ring buffer
207       chunk = peer_b->size - peer_b->offset;
208     }
209     assert(peer_b->offset + chunk <= peer_b->size);
210 
211     OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
212 
213     peer_b->len -= chunk;
214     if (peer_b->len) {
215       peer_b->offset += chunk;
216       assert(peer_b->offset <= peer_b->size);
217       if (peer_b->offset == peer_b->size) {
218         peer_b->offset = 0;
219       }
220       buf += chunk;
221     } else {
222       // buffer now empty, no need to advance "buf"
223       assert(chunk == rest);
224       peer_b->offset = 0;
225     }
226     rest -= chunk;
227   } while (rest);
228 
229   return size;
230 }
231 
bio_write(BIO * bio,const char * buf,int num_)232 static int bio_write(BIO *bio, const char *buf, int num_) {
233   size_t num = num_;
234   size_t rest;
235   struct bio_bio_st *b;
236 
237   BIO_clear_retry_flags(bio);
238 
239   if (!bio->init || buf == NULL || num == 0) {
240     return 0;
241   }
242 
243   b = bio->ptr;
244   assert(b != NULL);
245   assert(b->peer != NULL);
246   assert(b->buf != NULL);
247 
248   b->request = 0;
249   if (b->closed) {
250     // we already closed
251     OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
252     return -1;
253   }
254 
255   assert(b->len <= b->size);
256 
257   if (b->len == b->size) {
258     BIO_set_retry_write(bio);  // buffer is full
259     return -1;
260   }
261 
262   // we can write
263   if (num > b->size - b->len) {
264     num = b->size - b->len;
265   }
266 
267   // now write "num" bytes
268   rest = num;
269 
270   assert(rest > 0);
271   // one or two iterations
272   do {
273     size_t write_offset;
274     size_t chunk;
275 
276     assert(b->len + rest <= b->size);
277 
278     write_offset = b->offset + b->len;
279     if (write_offset >= b->size) {
280       write_offset -= b->size;
281     }
282     // b->buf[write_offset] is the first byte we can write to.
283 
284     if (write_offset + rest <= b->size) {
285       chunk = rest;
286     } else {
287       // wrap around ring buffer
288       chunk = b->size - write_offset;
289     }
290 
291     OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
292 
293     b->len += chunk;
294 
295     assert(b->len <= b->size);
296 
297     rest -= chunk;
298     buf += chunk;
299   } while (rest);
300 
301   return num;
302 }
303 
bio_make_pair(BIO * bio1,BIO * bio2,size_t writebuf1_len,size_t writebuf2_len)304 static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
305                          size_t writebuf2_len) {
306   struct bio_bio_st *b1, *b2;
307 
308   assert(bio1 != NULL);
309   assert(bio2 != NULL);
310 
311   b1 = bio1->ptr;
312   b2 = bio2->ptr;
313 
314   if (b1->peer != NULL || b2->peer != NULL) {
315     OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
316     return 0;
317   }
318 
319   if (b1->buf == NULL) {
320     if (writebuf1_len) {
321       b1->size = writebuf1_len;
322     }
323     b1->buf = OPENSSL_malloc(b1->size);
324     if (b1->buf == NULL) {
325       OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
326       return 0;
327     }
328     b1->len = 0;
329     b1->offset = 0;
330   }
331 
332   if (b2->buf == NULL) {
333     if (writebuf2_len) {
334       b2->size = writebuf2_len;
335     }
336     b2->buf = OPENSSL_malloc(b2->size);
337     if (b2->buf == NULL) {
338       OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
339       return 0;
340     }
341     b2->len = 0;
342     b2->offset = 0;
343   }
344 
345   b1->peer = bio2;
346   b1->closed = 0;
347   b1->request = 0;
348   b2->peer = bio1;
349   b2->closed = 0;
350   b2->request = 0;
351 
352   bio1->init = 1;
353   bio2->init = 1;
354 
355   return 1;
356 }
357 
bio_ctrl(BIO * bio,int cmd,long num,void * ptr)358 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
359   long ret;
360   struct bio_bio_st *b = bio->ptr;
361 
362   assert(b != NULL);
363 
364   switch (cmd) {
365     // specific CTRL codes
366 
367     case BIO_C_GET_WRITE_BUF_SIZE:
368       ret = (long)b->size;
369       break;
370 
371     case BIO_C_GET_WRITE_GUARANTEE:
372       // How many bytes can the caller feed to the next write
373       // without having to keep any?
374       if (b->peer == NULL || b->closed) {
375         ret = 0;
376       } else {
377         ret = (long)b->size - b->len;
378       }
379       break;
380 
381     case BIO_C_GET_READ_REQUEST:
382       // If the peer unsuccessfully tried to read, how many bytes
383       // were requested?  (As with BIO_CTRL_PENDING, that number
384       // can usually be treated as boolean.)
385       ret = (long)b->request;
386       break;
387 
388     case BIO_C_RESET_READ_REQUEST:
389       // Reset request.  (Can be useful after read attempts
390       // at the other side that are meant to be non-blocking,
391       // e.g. when probing SSL_read to see if any data is
392       // available.)
393       b->request = 0;
394       ret = 1;
395       break;
396 
397     case BIO_C_SHUTDOWN_WR:
398       // similar to shutdown(..., SHUT_WR)
399       b->closed = 1;
400       ret = 1;
401       break;
402 
403     // standard CTRL codes follow
404 
405     case BIO_CTRL_GET_CLOSE:
406       ret = bio->shutdown;
407       break;
408 
409     case BIO_CTRL_SET_CLOSE:
410       bio->shutdown = (int)num;
411       ret = 1;
412       break;
413 
414     case BIO_CTRL_PENDING:
415       if (b->peer != NULL) {
416         struct bio_bio_st *peer_b = b->peer->ptr;
417         ret = (long)peer_b->len;
418       } else {
419         ret = 0;
420       }
421       break;
422 
423     case BIO_CTRL_WPENDING:
424       ret = 0;
425       if (b->buf != NULL) {
426         ret = (long)b->len;
427       }
428       break;
429 
430     case BIO_CTRL_FLUSH:
431       ret = 1;
432       break;
433 
434     case BIO_CTRL_EOF: {
435       BIO *other_bio = ptr;
436 
437       if (other_bio) {
438         struct bio_bio_st *other_b = other_bio->ptr;
439         assert(other_b != NULL);
440         ret = other_b->len == 0 && other_b->closed;
441       } else {
442         ret = 1;
443       }
444     } break;
445 
446     default:
447       ret = 0;
448   }
449   return ret;
450 }
451 
452 
453 static const BIO_METHOD methods_biop = {
454     BIO_TYPE_BIO,    "BIO pair", bio_write, bio_read, NULL /* puts */,
455     NULL /* gets */, bio_ctrl,   bio_new,   bio_free, NULL /* callback_ctrl */,
456 };
457 
bio_s_bio(void)458 static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
459 
BIO_new_bio_pair(BIO ** bio1_p,size_t writebuf1_len,BIO ** bio2_p,size_t writebuf2_len)460 int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
461                      BIO** bio2_p, size_t writebuf2_len) {
462   BIO *bio1 = BIO_new(bio_s_bio());
463   BIO *bio2 = BIO_new(bio_s_bio());
464   if (bio1 == NULL || bio2 == NULL ||
465       !bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
466     BIO_free(bio1);
467     BIO_free(bio2);
468     *bio1_p = NULL;
469     *bio2_p = NULL;
470     return 0;
471   }
472 
473   *bio1_p = bio1;
474   *bio2_p = bio2;
475   return 1;
476 }
477 
BIO_ctrl_get_read_request(BIO * bio)478 size_t BIO_ctrl_get_read_request(BIO *bio) {
479   return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
480 }
481 
BIO_ctrl_get_write_guarantee(BIO * bio)482 size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
483   return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
484 }
485 
BIO_shutdown_wr(BIO * bio)486 int BIO_shutdown_wr(BIO *bio) {
487   return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
488 }
489