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