Make BIO opaque
[openssl.git] / crypto / evp / bio_b64.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 #include <stdio.h>
59 #include <errno.h>
60 #include "internal/cryptlib.h"
61 #include <openssl/buffer.h>
62 #include <openssl/evp.h>
63 #include "internal/bio.h"
64
65 static int b64_write(BIO *h, const char *buf, int num);
66 static int b64_read(BIO *h, char *buf, int size);
67 static int b64_puts(BIO *h, const char *str);
68 /*
69  * static int b64_gets(BIO *h, char *str, int size);
70  */
71 static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2);
72 static int b64_new(BIO *h);
73 static int b64_free(BIO *data);
74 static long b64_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
75 #define B64_BLOCK_SIZE  1024
76 #define B64_BLOCK_SIZE2 768
77 #define B64_NONE        0
78 #define B64_ENCODE      1
79 #define B64_DECODE      2
80
81 typedef struct b64_struct {
82     /*
83      * BIO *bio; moved to the BIO structure
84      */
85     int buf_len;
86     int buf_off;
87     int tmp_len;                /* used to find the start when decoding */
88     int tmp_nl;                 /* If true, scan until '\n' */
89     int encode;
90     int start;                  /* have we started decoding yet? */
91     int cont;                   /* <= 0 when finished */
92     EVP_ENCODE_CTX *base64;
93     char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10];
94     char tmp[B64_BLOCK_SIZE];
95 } BIO_B64_CTX;
96
97 static const BIO_METHOD methods_b64 = {
98     BIO_TYPE_BASE64, "base64 encoding",
99     b64_write,
100     b64_read,
101     b64_puts,
102     NULL,                       /* b64_gets, */
103     b64_ctrl,
104     b64_new,
105     b64_free,
106     b64_callback_ctrl,
107 };
108
109
110 const BIO_METHOD *BIO_f_base64(void)
111 {
112     return &methods_b64;
113 }
114
115 static int b64_new(BIO *bi)
116 {
117     BIO_B64_CTX *ctx;
118
119     ctx = OPENSSL_zalloc(sizeof(*ctx));
120     if (ctx == NULL)
121         return (0);
122
123     ctx->cont = 1;
124     ctx->start = 1;
125     ctx->base64 = EVP_ENCODE_CTX_new();
126     BIO_set_data(bi, ctx);
127     BIO_set_init(bi, 1);
128
129     return 1;
130 }
131
132 static int b64_free(BIO *a)
133 {
134     BIO_B64_CTX *ctx;
135     if (a == NULL)
136         return 0;
137
138     ctx = BIO_get_data(a);
139     if (ctx == NULL)
140         return 0;
141
142     EVP_ENCODE_CTX_free(ctx->base64);
143     OPENSSL_free(ctx);
144     BIO_set_data(a, NULL);
145     BIO_set_init(a, 0);
146
147     return 1;
148 }
149
150 static int b64_read(BIO *b, char *out, int outl)
151 {
152     int ret = 0, i, ii, j, k, x, n, num, ret_code = 0;
153     BIO_B64_CTX *ctx;
154     unsigned char *p, *q;
155     BIO *next;
156
157     if (out == NULL)
158         return (0);
159     ctx = (BIO_B64_CTX *)BIO_get_data(b);
160
161     next = BIO_next(b);
162     if ((ctx == NULL) || (next == NULL))
163         return 0;
164
165     BIO_clear_retry_flags(b);
166
167     if (ctx->encode != B64_DECODE) {
168         ctx->encode = B64_DECODE;
169         ctx->buf_len = 0;
170         ctx->buf_off = 0;
171         ctx->tmp_len = 0;
172         EVP_DecodeInit(ctx->base64);
173     }
174
175     /* First check if there are bytes decoded/encoded */
176     if (ctx->buf_len > 0) {
177         OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
178         i = ctx->buf_len - ctx->buf_off;
179         if (i > outl)
180             i = outl;
181         OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf));
182         memcpy(out, &(ctx->buf[ctx->buf_off]), i);
183         ret = i;
184         out += i;
185         outl -= i;
186         ctx->buf_off += i;
187         if (ctx->buf_len == ctx->buf_off) {
188             ctx->buf_len = 0;
189             ctx->buf_off = 0;
190         }
191     }
192
193     /*
194      * At this point, we have room of outl bytes and an empty buffer, so we
195      * should read in some more.
196      */
197
198     ret_code = 0;
199     while (outl > 0) {
200         if (ctx->cont <= 0)
201             break;
202
203         i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]),
204                      B64_BLOCK_SIZE - ctx->tmp_len);
205
206         if (i <= 0) {
207             ret_code = i;
208
209             /* Should we continue next time we are called? */
210             if (!BIO_should_retry(next)) {
211                 ctx->cont = i;
212                 /* If buffer empty break */
213                 if (ctx->tmp_len == 0)
214                     break;
215                 /* Fall through and process what we have */
216                 else
217                     i = 0;
218             }
219             /* else we retry and add more data to buffer */
220             else
221                 break;
222         }
223         i += ctx->tmp_len;
224         ctx->tmp_len = i;
225
226         /*
227          * We need to scan, a line at a time until we have a valid line if we
228          * are starting.
229          */
230         if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) {
231             /* ctx->start=1; */
232             ctx->tmp_len = 0;
233         } else if (ctx->start) {
234             q = p = (unsigned char *)ctx->tmp;
235             num = 0;
236             for (j = 0; j < i; j++) {
237                 if (*(q++) != '\n')
238                     continue;
239
240                 /*
241                  * due to a previous very long line, we need to keep on
242                  * scanning for a '\n' before we even start looking for
243                  * base64 encoded stuff.
244                  */
245                 if (ctx->tmp_nl) {
246                     p = q;
247                     ctx->tmp_nl = 0;
248                     continue;
249                 }
250
251                 k = EVP_DecodeUpdate(ctx->base64,
252                                      (unsigned char *)ctx->buf,
253                                      &num, p, q - p);
254                 if ((k <= 0) && (num == 0) && (ctx->start))
255                     EVP_DecodeInit(ctx->base64);
256                 else {
257                     if (p != (unsigned char *)
258                         &(ctx->tmp[0])) {
259                         i -= (p - (unsigned char *)
260                               &(ctx->tmp[0]));
261                         for (x = 0; x < i; x++)
262                             ctx->tmp[x] = p[x];
263                     }
264                     EVP_DecodeInit(ctx->base64);
265                     ctx->start = 0;
266                     break;
267                 }
268                 p = q;
269             }
270
271             /* we fell off the end without starting */
272             if ((j == i) && (num == 0)) {
273                 /*
274                  * Is this is one long chunk?, if so, keep on reading until a
275                  * new line.
276                  */
277                 if (p == (unsigned char *)&(ctx->tmp[0])) {
278                     /* Check buffer full */
279                     if (i == B64_BLOCK_SIZE) {
280                         ctx->tmp_nl = 1;
281                         ctx->tmp_len = 0;
282                     }
283                 } else if (p != q) { /* finished on a '\n' */
284                     n = q - p;
285                     for (ii = 0; ii < n; ii++)
286                         ctx->tmp[ii] = p[ii];
287                     ctx->tmp_len = n;
288                 }
289                 /* else finished on a '\n' */
290                 continue;
291             } else {
292                 ctx->tmp_len = 0;
293             }
294         } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) {
295             /*
296              * If buffer isn't full and we can retry then restart to read in
297              * more data.
298              */
299             continue;
300         }
301
302         if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
303             int z, jj;
304
305             jj = i & ~3;        /* process per 4 */
306             z = EVP_DecodeBlock((unsigned char *)ctx->buf,
307                                 (unsigned char *)ctx->tmp, jj);
308             if (jj > 2) {
309                 if (ctx->tmp[jj - 1] == '=') {
310                     z--;
311                     if (ctx->tmp[jj - 2] == '=')
312                         z--;
313                 }
314             }
315             /*
316              * z is now number of output bytes and jj is the number consumed
317              */
318             if (jj != i) {
319                 memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
320                 ctx->tmp_len = i - jj;
321             }
322             ctx->buf_len = 0;
323             if (z > 0) {
324                 ctx->buf_len = z;
325             }
326             i = z;
327         } else {
328             i = EVP_DecodeUpdate(ctx->base64,
329                                  (unsigned char *)ctx->buf, &ctx->buf_len,
330                                  (unsigned char *)ctx->tmp, i);
331             ctx->tmp_len = 0;
332         }
333         ctx->buf_off = 0;
334         if (i < 0) {
335             ret_code = 0;
336             ctx->buf_len = 0;
337             break;
338         }
339
340         if (ctx->buf_len <= outl)
341             i = ctx->buf_len;
342         else
343             i = outl;
344
345         memcpy(out, ctx->buf, i);
346         ret += i;
347         ctx->buf_off = i;
348         if (ctx->buf_off == ctx->buf_len) {
349             ctx->buf_len = 0;
350             ctx->buf_off = 0;
351         }
352         outl -= i;
353         out += i;
354     }
355     /* BIO_clear_retry_flags(b); */
356     BIO_copy_next_retry(b);
357     return ((ret == 0) ? ret_code : ret);
358 }
359
360 static int b64_write(BIO *b, const char *in, int inl)
361 {
362     int ret = 0;
363     int n;
364     int i;
365     BIO_B64_CTX *ctx;
366     BIO *next;
367
368     ctx = (BIO_B64_CTX *)BIO_get_data(b);
369     next = BIO_next(b);
370     if ((ctx == NULL) || (next == NULL))
371         return 0;
372
373     BIO_clear_retry_flags(b);
374
375     if (ctx->encode != B64_ENCODE) {
376         ctx->encode = B64_ENCODE;
377         ctx->buf_len = 0;
378         ctx->buf_off = 0;
379         ctx->tmp_len = 0;
380         EVP_EncodeInit(ctx->base64);
381     }
382
383     OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
384     OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
385     OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
386     n = ctx->buf_len - ctx->buf_off;
387     while (n > 0) {
388         i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
389         if (i <= 0) {
390             BIO_copy_next_retry(b);
391             return (i);
392         }
393         OPENSSL_assert(i <= n);
394         ctx->buf_off += i;
395         OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
396         OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
397         n -= i;
398     }
399     /* at this point all pending data has been written */
400     ctx->buf_off = 0;
401     ctx->buf_len = 0;
402
403     if ((in == NULL) || (inl <= 0))
404         return (0);
405
406     while (inl > 0) {
407         n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl;
408
409         if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
410             if (ctx->tmp_len > 0) {
411                 OPENSSL_assert(ctx->tmp_len <= 3);
412                 n = 3 - ctx->tmp_len;
413                 /*
414                  * There's a theoretical possibility for this
415                  */
416                 if (n > inl)
417                     n = inl;
418                 memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
419                 ctx->tmp_len += n;
420                 ret += n;
421                 if (ctx->tmp_len < 3)
422                     break;
423                 ctx->buf_len =
424                     EVP_EncodeBlock((unsigned char *)ctx->buf,
425                                     (unsigned char *)ctx->tmp, ctx->tmp_len);
426                 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
427                 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
428                 /*
429                  * Since we're now done using the temporary buffer, the
430                  * length should be 0'd
431                  */
432                 ctx->tmp_len = 0;
433             } else {
434                 if (n < 3) {
435                     memcpy(ctx->tmp, in, n);
436                     ctx->tmp_len = n;
437                     ret += n;
438                     break;
439                 }
440                 n -= n % 3;
441                 ctx->buf_len =
442                     EVP_EncodeBlock((unsigned char *)ctx->buf,
443                                     (const unsigned char *)in, n);
444                 OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
445                 OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
446                 ret += n;
447             }
448         } else {
449             EVP_EncodeUpdate(ctx->base64,
450                              (unsigned char *)ctx->buf, &ctx->buf_len,
451                              (unsigned char *)in, n);
452             OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
453             OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
454             ret += n;
455         }
456         inl -= n;
457         in += n;
458
459         ctx->buf_off = 0;
460         n = ctx->buf_len;
461         while (n > 0) {
462             i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
463             if (i <= 0) {
464                 BIO_copy_next_retry(b);
465                 return ((ret == 0) ? i : ret);
466             }
467             OPENSSL_assert(i <= n);
468             n -= i;
469             ctx->buf_off += i;
470             OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
471             OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
472         }
473         ctx->buf_len = 0;
474         ctx->buf_off = 0;
475     }
476     return (ret);
477 }
478
479 static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
480 {
481     BIO_B64_CTX *ctx;
482     long ret = 1;
483     int i;
484     BIO *next;
485
486     ctx = (BIO_B64_CTX *)BIO_get_data(b);
487     next = BIO_next(b);
488     if ((ctx == NULL) || (next == NULL))
489         return 0;
490
491     switch (cmd) {
492     case BIO_CTRL_RESET:
493         ctx->cont = 1;
494         ctx->start = 1;
495         ctx->encode = B64_NONE;
496         ret = BIO_ctrl(next, cmd, num, ptr);
497         break;
498     case BIO_CTRL_EOF:         /* More to read */
499         if (ctx->cont <= 0)
500             ret = 1;
501         else
502             ret = BIO_ctrl(next, cmd, num, ptr);
503         break;
504     case BIO_CTRL_WPENDING:    /* More to write in buffer */
505         OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
506         ret = ctx->buf_len - ctx->buf_off;
507         if ((ret == 0) && (ctx->encode != B64_NONE)
508             && (EVP_ENCODE_CTX_num(ctx->base64) != 0))
509             ret = 1;
510         else if (ret <= 0)
511             ret = BIO_ctrl(next, cmd, num, ptr);
512         break;
513     case BIO_CTRL_PENDING:     /* More to read in buffer */
514         OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
515         ret = ctx->buf_len - ctx->buf_off;
516         if (ret <= 0)
517             ret = BIO_ctrl(next, cmd, num, ptr);
518         break;
519     case BIO_CTRL_FLUSH:
520         /* do a final write */
521  again:
522         while (ctx->buf_len != ctx->buf_off) {
523             i = b64_write(b, NULL, 0);
524             if (i < 0)
525                 return i;
526         }
527         if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
528             if (ctx->tmp_len != 0) {
529                 ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf,
530                                                (unsigned char *)ctx->tmp,
531                                                ctx->tmp_len);
532                 ctx->buf_off = 0;
533                 ctx->tmp_len = 0;
534                 goto again;
535             }
536         } else if (ctx->encode != B64_NONE
537                    && EVP_ENCODE_CTX_num(ctx->base64) != 0) {
538             ctx->buf_off = 0;
539             EVP_EncodeFinal(ctx->base64,
540                             (unsigned char *)ctx->buf, &(ctx->buf_len));
541             /* push out the bytes */
542             goto again;
543         }
544         /* Finally flush the underlying BIO */
545         ret = BIO_ctrl(next, cmd, num, ptr);
546         break;
547
548     case BIO_C_DO_STATE_MACHINE:
549         BIO_clear_retry_flags(b);
550         ret = BIO_ctrl(next, cmd, num, ptr);
551         BIO_copy_next_retry(b);
552         break;
553
554     case BIO_CTRL_DUP:
555         break;
556     case BIO_CTRL_INFO:
557     case BIO_CTRL_GET:
558     case BIO_CTRL_SET:
559     default:
560         ret = BIO_ctrl(next, cmd, num, ptr);
561         break;
562     }
563     return ret;
564 }
565
566 static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
567 {
568     long ret = 1;
569     BIO *next = BIO_next(b);
570
571     if (next == NULL)
572         return 0;
573     switch (cmd) {
574     default:
575         ret = BIO_callback_ctrl(next, cmd, fp);
576         break;
577     }
578     return (ret);
579 }
580
581 static int b64_puts(BIO *b, const char *str)
582 {
583     return b64_write(b, str, strlen(str));
584 }