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