99c5cc6d0d6d459b2eeba507021a7ee65c33a391
[openssl.git] / crypto / bio / bss_bio.c
1 /* crypto/bio/bss_bio.c  -*- Mode: C; c-file-style: "eay" -*- */
2
3 /* Special method for a BIO where the other endpoint is also a BIO
4  * of this kind, handled by the same thread (i.e. the "peer" is actually
5  * ourselves, wearing a different hat).
6  * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces
7  * for which no specific BIO method is available.
8  * See ssl/ssltest.c for some hints on how this can be used. */
9
10 #ifndef BIO_PAIR_DEBUG
11 # undef NDEBUG /* avoid conflicting definitions */
12 # define NDEBUG
13 #endif
14
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <openssl/bio.h>
20 #include <openssl/err.h>
21 #include <openssl/crypto.h>
22
23 static int bio_new(BIO *bio);
24 static int bio_free(BIO *bio);
25 static int bio_read(BIO *bio, char *buf, int size);
26 static int bio_write(BIO *bio, char *buf, int num);
27 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr);
28 static int bio_puts(BIO *bio, char *str);
29
30 static int bio_make_pair(BIO *bio1, BIO *bio2);
31 static void bio_destroy_pair(BIO *bio);
32
33 static BIO_METHOD methods_biop =
34 {
35         BIO_TYPE_BIO,
36         "BIO pair",
37         bio_write,
38         bio_read,
39         bio_puts,
40         NULL /* no bio_gets */,
41         bio_ctrl,
42         bio_new,
43         bio_free
44 };
45
46 BIO_METHOD *BIO_s_bio(void)
47         {
48         return &methods_biop;
49         }
50
51 struct bio_bio_st
52 {
53         BIO *peer;     /* NULL if buf == NULL.
54                         * If peer != NULL, then peer->ptr is also a bio_bio_st,
55                         * and its "peer" member points back to us.
56                         * peer != NULL iff init != 0 in the BIO. */
57         
58         /* This is for what we write (i.e. reading uses peer's struct): */
59         int closed;     /* valid iff peer != NULL */
60         size_t len;     /* valid iff buf != NULL; 0 if peer == NULL */
61         size_t offset;  /* valid iff buf != NULL; 0 if len == 0 */
62         size_t size;
63         char *buf;      /* "size" elements (if != NULL) */
64
65         size_t request; /* valid iff peer != NULL; 0 if len != 0,
66                          * otherwise set by peer to number of bytes
67                          * it (unsuccesfully) tried to read,
68                          * never more than buffer space (size-len) warrants. */
69 };
70
71 static int bio_new(BIO *bio)
72         {
73         struct bio_bio_st *b;
74         
75         b = Malloc(sizeof *b);
76         if (b == NULL)
77                 return 0;
78
79         b->peer = NULL;
80         b->size = 17*1024; /* enough for one TLS record (just a default) */
81         b->buf = NULL;
82
83         bio->ptr = b;
84         return 1;
85         }
86
87
88 static int bio_free(BIO *bio)
89         {
90         struct bio_bio_st *b;
91
92         if (bio == NULL)
93                 return 0;
94         b = bio->ptr;
95
96         assert(b != NULL);
97
98         if (b->peer)
99                 bio_destroy_pair(bio);
100         
101         if (b->buf != NULL)
102                 {
103                 Free(b->buf);
104                 }
105
106         Free(b);
107
108         return 1;
109         }
110
111
112
113 static int bio_read(BIO *bio, char *buf, int size_)
114         {
115         size_t size = size_;
116         size_t rest;
117         struct bio_bio_st *b, *peer_b;
118
119         BIO_clear_retry_flags(bio);
120
121         if (!bio->init)
122                 return 0;
123
124         b = bio->ptr;
125         assert(b != NULL);
126         assert(b->peer != NULL);
127         peer_b = b->peer->ptr;
128         assert(peer_b != NULL);
129         assert(peer_b->buf != NULL);
130
131         peer_b->request = 0; /* will be set in "retry_read" situation */
132
133         if (buf == NULL || size == 0)
134                 return 0;
135
136         if (peer_b->len == 0)
137                 {
138                 if (peer_b->closed)
139                         return 0; /* writer has closed, and no data is left */
140                 else
141                         {
142                         BIO_set_retry_read(bio); /* buffer is empty */
143                         if (size <= peer_b->size)
144                                 peer_b->request = size;
145                         else
146                                 peer_b->request = peer_b->size; /* don't ask for more than
147                                                                  * the peer can deliver
148                                                                  * in one write */
149                         return -1;
150                         }
151                 }
152
153         /* we can read */
154         if (peer_b->len < size)
155                 size = peer_b->len;
156
157         /* now read "size" bytes */
158         
159         rest = size;
160         
161         assert(rest > 0);
162         do /* one or two iterations */
163                 {
164                 size_t chunk;
165                 
166                 assert(rest <= peer_b->len);
167                 if (peer_b->offset + rest <= peer_b->size)
168                         chunk = rest;
169                 else
170                         /* wrap around ring buffer */
171                         chunk = peer_b->size - peer_b->offset;
172                 assert(peer_b->offset + chunk <= peer_b->size);
173                 
174                 memcpy(buf, peer_b->buf + peer_b->offset, chunk);
175                 
176                 peer_b->len -= chunk;
177                 if (peer_b->len)
178                         {
179                         peer_b->offset += chunk;
180                         assert(peer_b->offset <= peer_b->size);
181                         if (peer_b->offset == peer_b->size)
182                                 peer_b->offset = 0;
183                         buf += chunk;
184                         }
185                 else
186                         {
187                         /* buffer now empty, no need to advance "buf" */
188                         assert(chunk == rest);
189                         peer_b->offset = 0;
190                         }
191                 rest -= chunk;
192                 }
193         while (rest);
194         
195         return size;
196         }
197
198 static int bio_write(BIO *bio, char *buf, int num_)
199         {
200         size_t num = num_;
201         size_t rest;
202         struct bio_bio_st *b;
203
204         BIO_clear_retry_flags(bio);
205
206         if (!bio->init || buf == NULL || num == 0)
207                 return 0;
208
209         b = bio->ptr;           
210         assert(b != NULL);
211         assert(b->peer != NULL);
212         assert(b->buf != NULL);
213
214         b->request = 0;
215         if (b->closed)
216                 {
217                 /* we already closed */
218                 BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);
219                 return -1;
220                 }
221
222         assert(b->len <= b->size);
223
224         if (b->len == b->size)
225                 {
226                 BIO_set_retry_write(bio); /* buffer is full */
227                 return -1;
228                 }
229
230         /* we can write */
231         if (num > b->size - b->len)
232                 num = b->size - b->len;
233         
234         /* now write "num" bytes */
235
236         rest = num;
237         
238         assert(rest > 0);
239         do /* one or two iterations */
240                 {
241                 size_t write_offset;
242                 size_t chunk;
243
244                 assert(b->len + rest <= b->size);
245
246                 write_offset = b->offset + b->len;
247                 if (write_offset >= b->size)
248                         write_offset -= b->size;
249                 /* b->buf[write_offset] is the first byte we can write to. */
250
251                 if (write_offset + rest <= b->size)
252                         chunk = rest;
253                 else
254                         /* wrap around ring buffer */
255                         chunk = b->size - write_offset;
256                 
257                 memcpy(b->buf + write_offset, buf, chunk);
258                 
259                 b->len += chunk;
260
261                 assert(b->len <= b->size);
262                 
263                 rest -= chunk;
264                 buf += chunk;
265                 }
266         while (rest);
267
268         return num;
269         }
270
271
272 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
273         {
274         long ret;
275         struct bio_bio_st *b = bio->ptr;
276         
277         assert(b != NULL);
278
279         switch (cmd)
280                 {
281         /* specific CTRL codes */
282
283         case BIO_C_SET_WRITE_BUF_SIZE:
284                 if (b->peer)
285                         {
286                         BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
287                         ret = 0;
288                         }
289                 else if (num == 0)
290                         {
291                         BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
292                         ret = 0;
293                         }
294                 else
295                         {
296                         size_t new_size = num;
297
298                         if (b->size != new_size)
299                                 {
300                                 if (b->buf) 
301                                         {
302                                         Free(b->buf);
303                                         b->buf = NULL;
304                                         }
305                                 b->size = new_size;
306                                 }
307                         ret = 1;
308                         }
309                 break;
310
311         case BIO_C_GET_WRITE_BUF_SIZE:
312                 num = (long) b->size;
313
314         case BIO_C_MAKE_BIO_PAIR:
315                 {
316                 BIO *other_bio = ptr;
317                 
318                 if (bio_make_pair(bio, other_bio))
319                         ret = 1;
320                 else
321                         ret = 0;
322                 }
323                 break;
324                 
325         case BIO_C_DESTROY_BIO_PAIR:
326                 /* Effects both BIOs in the pair -- call just once!
327                  * Or let BIO_free(bio1); BIO_free(bio2); do the job. */
328                 bio_destroy_pair(bio);
329                 ret = 1;
330                 break;
331
332         case BIO_C_GET_WRITE_GUARANTEE:
333                 /* How many bytes can the caller feed to the next write
334                  * withouth having to keep any? */
335                 if (b->peer == NULL || b->closed)
336                         ret = 0;
337                 else
338                         ret = (long) b->size - b->len;
339                 break;
340
341         case BIO_C_GET_READ_REQUEST:
342                 /* If the peer unsuccesfully tried to read, how many bytes
343                  * were requested?  (As with BIO_CTRL_PENDING, that number
344                  * can usually be treated as boolean.) */
345                 ret = (long) b->request;
346                 break;
347
348         case BIO_C_SHUTDOWN_WR:
349                 /* similar to shutdown(..., SHUT_WR) */
350                 b->closed = 1;
351                 ret = 1;
352                 break;
353
354
355         /* standard CTRL codes follow */
356
357         case BIO_CTRL_RESET:
358                 if (b->buf != NULL)
359                         {
360                         b->len = 0;
361                         b->offset = 0;
362                         }
363                 ret = 0;
364                 break;          
365
366         case BIO_CTRL_GET_CLOSE:
367                 ret = bio->shutdown;
368                 break;
369
370         case BIO_CTRL_SET_CLOSE:
371                 bio->shutdown = (int) num;
372                 ret = 1;
373                 break;
374
375         case BIO_CTRL_PENDING:
376                 if (b->peer != NULL)
377                         {
378                         struct bio_bio_st *peer_b = b->peer->ptr;
379                         
380                         ret = (long) peer_b->len;
381                         }
382                 else
383                         ret = 0;
384                 break;
385
386         case BIO_CTRL_WPENDING:
387                 if (b->buf != NULL)
388                         ret = (long) b->len;
389                 else
390                         ret = 0;
391                 break;
392
393         case BIO_CTRL_DUP:
394                 /* See BIO_dup_chain for circumstances we have to expect. */
395                 {
396                 BIO *other_bio = ptr;
397                 struct bio_bio_st *other_b;
398                 
399                 assert(other_bio != NULL);
400                 other_b = other_bio->ptr;
401                 assert(other_b != NULL);
402                 
403                 assert(other_b->buf == NULL); /* other_bio is always fresh */
404
405                 other_b->size = b->size;
406                 }
407
408                 ret = 1;
409                 break;
410
411         case BIO_CTRL_FLUSH:
412                 ret = 1;
413                 break;
414
415         case BIO_CTRL_EOF:
416                 {
417                 BIO *other_bio = ptr;
418                 
419                 if (other_bio)
420                         {
421                         struct bio_bio_st *other_b = other_bio->ptr;
422                         
423                         assert(other_b != NULL);
424                         ret = other_b->len == 0 && other_b->closed;
425                         }
426                 else
427                         ret = 1;
428                 }
429                 break;
430
431         default:
432                 ret = 0;
433                 }
434         return ret;
435         }
436
437 static int bio_puts(BIO *bio, char *str)
438         {
439         return bio_write(bio, str, strlen(str));
440         }
441
442
443 static int bio_make_pair(BIO *bio1, BIO *bio2)
444         {
445         struct bio_bio_st *b1, *b2;
446
447         assert(bio1 != NULL);
448         assert(bio2 != NULL);
449
450         b1 = bio1->ptr;
451         b2 = bio2->ptr;
452         
453         if (b1->peer != NULL || b2->peer != NULL)
454                 {
455                 BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
456                 return 0;
457                 }
458         
459         if (b1->buf == NULL)
460                 {
461                 b1->buf = Malloc(b1->size);
462                 if (b1->buf == NULL)
463                         {
464                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
465                         return 0;
466                         }
467                 b1->len = 0;
468                 b1->offset = 0;
469                 }
470         
471         if (b2->buf == NULL)
472                 {
473                 b2->buf = Malloc(b2->size);
474                 if (b2->buf == NULL)
475                         {
476                         BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
477                         return 0;
478                         }
479                 b2->len = 0;
480                 b2->offset = 0;
481                 }
482         
483         b1->peer = bio2;
484         b1->closed = 0;
485         b1->request = 0;
486         b2->peer = bio1;
487         b2->closed = 0;
488         b2->request = 0;
489
490         bio1->init = 1;
491         bio2->init = 1;
492
493         return 1;
494         }
495
496 static void bio_destroy_pair(BIO *bio)
497         {
498         struct bio_bio_st *b = bio->ptr;
499
500         if (b != NULL)
501                 {
502                 BIO *peer_bio = b->peer;
503
504                 if (peer_bio != NULL)
505                         {
506                         struct bio_bio_st *peer_b = peer_bio->ptr;
507
508                         assert(peer_b != NULL);
509                         assert(peer_b->peer == bio);
510
511                         peer_b->peer = NULL;
512                         peer_bio->init = 0;
513                         assert(peer_b->buf != NULL);
514                         peer_b->len = 0;
515                         peer_b->offset = 0;
516                         
517                         b->peer = NULL;
518                         bio->init = 0;
519                         assert(b->buf != NULL);
520                         b->len = 0;
521                         b->offset = 0;
522                         }
523                 }
524         }
525  
526
527 /* Exported convenience functions */
528 int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1,
529         BIO **bio2_p, size_t writebuf2)
530          {
531          BIO *bio1 = NULL, *bio2 = NULL;
532          long r;
533          int ret = 0;
534
535          bio1 = BIO_new(BIO_s_bio());
536          if (bio1 == NULL)
537                  goto err;
538          bio2 = BIO_new(BIO_s_bio());
539          if (bio2 == NULL)
540                  goto err;
541
542          if (writebuf1)
543                  {
544                  r = BIO_set_write_buf_size(bio1, writebuf1);
545                  if (!r)
546                          goto err;
547                  }
548          if (writebuf2)
549                  {
550                  r = BIO_set_write_buf_size(bio2, writebuf2);
551                  if (!r)
552                          goto err;
553                  }
554
555          r = BIO_make_bio_pair(bio1, bio2);
556          if (!r)
557                  goto err;
558          ret = 1;
559
560  err:
561          if (ret == 0)
562                  {
563                  if (bio1)
564                          {
565                          BIO_free(bio1);
566                          bio1 = NULL;
567                          }
568                  if (bio2)
569                          {
570                          BIO_free(bio2);
571                          bio2 = NULL;
572                          }
573                  }
574
575          *bio1_p = bio1;
576          *bio2_p = bio2;
577          return ret;
578          }
579
580 size_t BIO_ctrl_get_write_guarantee(BIO *bio)
581     {
582         return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
583         }
584
585 size_t BIO_ctrl_get_read_request(BIO *bio)
586     {
587         return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
588         }