1/*
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdio.h>
11#include <errno.h>
12#include "internal/cryptlib.h"
13#include <openssl/buffer.h>
14#include <openssl/evp.h>
15#include "internal/bio.h"
16
17static int b64_write(BIO *h, const char *buf, int num);
18static int b64_read(BIO *h, char *buf, int size);
19static int b64_puts(BIO *h, const char *str);
20static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2);
21static int b64_new(BIO *h);
22static int b64_free(BIO *data);
23static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
24#define B64_BLOCK_SIZE  1024
25#define B64_BLOCK_SIZE2 768
26#define B64_NONE        0
27#define B64_ENCODE      1
28#define B64_DECODE      2
29
30typedef struct b64_struct {
31    /*
32     * BIO *bio; moved to the BIO structure
33     */
34    int buf_len;
35    int buf_off;
36    int tmp_len;                /* used to find the start when decoding */
37    int tmp_nl;                 /* If true, scan until '\n' */
38    int encode;
39    int start;                  /* have we started decoding yet? */
40    int cont;                   /* <= 0 when finished */
41    EVP_ENCODE_CTX *base64;
42    char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10];
43    char tmp[B64_BLOCK_SIZE];
44} BIO_B64_CTX;
45
46static const BIO_METHOD methods_b64 = {
47    BIO_TYPE_BASE64,
48    "base64 encoding",
49    bwrite_conv,
50    b64_write,
51    bread_conv,
52    b64_read,
53    b64_puts,
54    NULL,                       /* b64_gets, */
55    b64_ctrl,
56    b64_new,
57    b64_free,
58    b64_callback_ctrl,
59};
60
61
62const BIO_METHOD *BIO_f_base64(void)
63{
64    return &methods_b64;
65}
66
67static int b64_new(BIO *bi)
68{
69    BIO_B64_CTX *ctx;
70
71    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
72        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
73        return 0;
74    }
75
76    ctx->cont = 1;
77    ctx->start = 1;
78    ctx->base64 = EVP_ENCODE_CTX_new();
79    if (ctx->base64 == NULL) {
80        OPENSSL_free(ctx);
81        return 0;
82    }
83
84    BIO_set_data(bi, ctx);
85    BIO_set_init(bi, 1);
86
87    return 1;
88}
89
90static int b64_free(BIO *a)
91{
92    BIO_B64_CTX *ctx;
93    if (a == NULL)
94        return 0;
95
96    ctx = BIO_get_data(a);
97    if (ctx == NULL)
98        return 0;
99
100    EVP_ENCODE_CTX_free(ctx->base64);
101    OPENSSL_free(ctx);
102    BIO_set_data(a, NULL);
103    BIO_set_init(a, 0);
104
105    return 1;
106}
107
108static int b64_read(BIO *b, char *out, int outl)
109{
110    int ret = 0, i, ii, j, k, x, n, num, ret_code = 0;
111    BIO_B64_CTX *ctx;
112    unsigned char *p, *q;
113    BIO *next;
114
115    if (out == NULL)
116        return 0;
117    ctx = (BIO_B64_CTX *)BIO_get_data(b);
118
119    next = BIO_next(b);
120    if ((ctx == NULL) || (next == NULL))
121        return 0;
122
123    BIO_clear_retry_flags(b);
124
125    if (ctx->encode != B64_DECODE) {
126        ctx->encode = B64_DECODE;
127        ctx->buf_len = 0;
128        ctx->buf_off = 0;
129        ctx->tmp_len = 0;
130        EVP_DecodeInit(ctx->base64);
131    }
132
133    /* First check if there are bytes decoded/encoded */
134    if (ctx->buf_len > 0) {
135        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
136        i = ctx->buf_len - ctx->buf_off;
137        if (i > outl)
138            i = outl;
139        OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf));
140        memcpy(out, &(ctx->buf[ctx->buf_off]), i);
141        ret = i;
142        out += i;
143        outl -= i;
144        ctx->buf_off += i;
145        if (ctx->buf_len == ctx->buf_off) {
146            ctx->buf_len = 0;
147            ctx->buf_off = 0;
148        }
149    }
150
151    /*
152     * At this point, we have room of outl bytes and an empty buffer, so we
153     * should read in some more.
154     */
155
156    ret_code = 0;
157    while (outl > 0) {
158        if (ctx->cont <= 0)
159            break;
160
161        i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]),
162                     B64_BLOCK_SIZE - ctx->tmp_len);
163
164        if (i <= 0) {
165            ret_code = i;
166
167            /* Should we continue next time we are called? */
168            if (!BIO_should_retry(next)) {
169                ctx->cont = i;
170                /* If buffer empty break */
171                if (ctx->tmp_len == 0)
172                    break;
173                /* Fall through and process what we have */
174                else
175                    i = 0;
176            }
177            /* else we retry and add more data to buffer */
178            else
179                break;
180        }
181        i += ctx->tmp_len;
182        ctx->tmp_len = i;
183
184        /*
185         * We need to scan, a line at a time until we have a valid line if we
186         * are starting.
187         */
188        if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) {
189            /* ctx->start=1; */
190            ctx->tmp_len = 0;
191        } else if (ctx->start) {
192            q = p = (unsigned char *)ctx->tmp;
193            num = 0;
194            for (j = 0; j < i; j++) {
195                if (*(q++) != '\n')
196                    continue;
197
198                /*
199                 * due to a previous very long line, we need to keep on
200                 * scanning for a '\n' before we even start looking for
201                 * base64 encoded stuff.
202                 */
203                if (ctx->tmp_nl) {
204                    p = q;
205                    ctx->tmp_nl = 0;
206                    continue;
207                }
208
209                k = EVP_DecodeUpdate(ctx->base64,
210                                     (unsigned char *)ctx->buf,
211                                     &num, p, q - p);
212                if ((k <= 0) && (num == 0) && (ctx->start))
213                    EVP_DecodeInit(ctx->base64);
214                else {
215                    if (p != (unsigned char *)
216                        &(ctx->tmp[0])) {
217                        i -= (p - (unsigned char *)
218                              &(ctx->tmp[0]));
219                        for (x = 0; x < i; x++)
220                            ctx->tmp[x] = p[x];
221                    }
222                    EVP_DecodeInit(ctx->base64);
223                    ctx->start = 0;
224                    break;
225                }
226                p = q;
227            }
228
229            /* we fell off the end without starting */
230            if ((j == i) && (num == 0)) {
231                /*
232                 * Is this is one long chunk?, if so, keep on reading until a
233                 * new line.
234                 */
235                if (p == (unsigned char *)&(ctx->tmp[0])) {
236                    /* Check buffer full */
237                    if (i == B64_BLOCK_SIZE) {
238                        ctx->tmp_nl = 1;
239                        ctx->tmp_len = 0;
240                    }
241                } else if (p != q) { /* finished on a '\n' */
242                    n = q - p;
243                    for (ii = 0; ii < n; ii++)
244                        ctx->tmp[ii] = p[ii];
245                    ctx->tmp_len = n;
246                }
247                /* else finished on a '\n' */
248                continue;
249            } else {
250                ctx->tmp_len = 0;
251            }
252        } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) {
253            /*
254             * If buffer isn't full and we can retry then restart to read in
255             * more data.
256             */
257            continue;
258        }
259
260        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
261            int z, jj;
262
263            jj = i & ~3;        /* process per 4 */
264            z = EVP_DecodeBlock((unsigned char *)ctx->buf,
265                                (unsigned char *)ctx->tmp, jj);
266            if (jj > 2) {
267                if (ctx->tmp[jj - 1] == '=') {
268                    z--;
269                    if (ctx->tmp[jj - 2] == '=')
270                        z--;
271                }
272            }
273            /*
274             * z is now number of output bytes and jj is the number consumed
275             */
276            if (jj != i) {
277                memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
278                ctx->tmp_len = i - jj;
279            }
280            ctx->buf_len = 0;
281            if (z > 0) {
282                ctx->buf_len = z;
283            }
284            i = z;
285        } else {
286            i = EVP_DecodeUpdate(ctx->base64,
287                                 (unsigned char *)ctx->buf, &ctx->buf_len,
288                                 (unsigned char *)ctx->tmp, i);
289            ctx->tmp_len = 0;
290        }
291        /*
292         * If eof or an error was signalled, then the condition
293         * 'ctx->cont <= 0' will prevent b64_read() from reading
294         * more data on subsequent calls. This assignment was
295         * deleted accidentally in commit 5562cfaca4f3.
296         */
297        ctx->cont = i;
298
299        ctx->buf_off = 0;
300        if (i < 0) {
301            ret_code = 0;
302            ctx->buf_len = 0;
303            break;
304        }
305
306        if (ctx->buf_len <= outl)
307            i = ctx->buf_len;
308        else
309            i = outl;
310
311        memcpy(out, ctx->buf, i);
312        ret += i;
313        ctx->buf_off = i;
314        if (ctx->buf_off == ctx->buf_len) {
315            ctx->buf_len = 0;
316            ctx->buf_off = 0;
317        }
318        outl -= i;
319        out += i;
320    }
321    /* BIO_clear_retry_flags(b); */
322    BIO_copy_next_retry(b);
323    return ((ret == 0) ? ret_code : ret);
324}
325
326static int b64_write(BIO *b, const char *in, int inl)
327{
328    int ret = 0;
329    int n;
330    int i;
331    BIO_B64_CTX *ctx;
332    BIO *next;
333
334    ctx = (BIO_B64_CTX *)BIO_get_data(b);
335    next = BIO_next(b);
336    if ((ctx == NULL) || (next == NULL))
337        return 0;
338
339    BIO_clear_retry_flags(b);
340
341    if (ctx->encode != B64_ENCODE) {
342        ctx->encode = B64_ENCODE;
343        ctx->buf_len = 0;
344        ctx->buf_off = 0;
345        ctx->tmp_len = 0;
346        EVP_EncodeInit(ctx->base64);
347    }
348
349    OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
350    OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
351    OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
352    n = ctx->buf_len - ctx->buf_off;
353    while (n > 0) {
354        i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
355        if (i <= 0) {
356            BIO_copy_next_retry(b);
357            return i;
358        }
359        OPENSSL_assert(i <= n);
360        ctx->buf_off += i;
361        OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
362        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
363        n -= i;
364    }
365    /* at this point all pending data has been written */
366    ctx->buf_off = 0;
367    ctx->buf_len = 0;
368
369    if ((in == NULL) || (inl <= 0))
370        return 0;
371
372    while (inl > 0) {
373        n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl;
374
375        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
376            if (ctx->tmp_len > 0) {
377                OPENSSL_assert(ctx->tmp_len <= 3);
378                n = 3 - ctx->tmp_len;
379                /*
380                 * There's a theoretical possibility for this
381                 */
382                if (n > inl)
383                    n = inl;
384                memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
385                ctx->tmp_len += n;
386                ret += n;
387                if (ctx->tmp_len < 3)
388                    break;
389                ctx->buf_len =
390                    EVP_EncodeBlock((unsigned char *)ctx->buf,
391                                    (unsigned char *)ctx->tmp, ctx->tmp_len);
392                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
393                OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
394                /*
395                 * Since we're now done using the temporary buffer, the
396                 * length should be 0'd
397                 */
398                ctx->tmp_len = 0;
399            } else {
400                if (n < 3) {
401                    memcpy(ctx->tmp, in, n);
402                    ctx->tmp_len = n;
403                    ret += n;
404                    break;
405                }
406                n -= n % 3;
407                ctx->buf_len =
408                    EVP_EncodeBlock((unsigned char *)ctx->buf,
409                                    (const unsigned char *)in, n);
410                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
411                OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
412                ret += n;
413            }
414        } else {
415            if (!EVP_EncodeUpdate(ctx->base64,
416                                 (unsigned char *)ctx->buf, &ctx->buf_len,
417                                 (unsigned char *)in, n))
418                return ((ret == 0) ? -1 : ret);
419            OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
420            OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
421            ret += n;
422        }
423        inl -= n;
424        in += n;
425
426        ctx->buf_off = 0;
427        n = ctx->buf_len;
428        while (n > 0) {
429            i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n);
430            if (i <= 0) {
431                BIO_copy_next_retry(b);
432                return ((ret == 0) ? i : ret);
433            }
434            OPENSSL_assert(i <= n);
435            n -= i;
436            ctx->buf_off += i;
437            OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
438            OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
439        }
440        ctx->buf_len = 0;
441        ctx->buf_off = 0;
442    }
443    return ret;
444}
445
446static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
447{
448    BIO_B64_CTX *ctx;
449    long ret = 1;
450    int i;
451    BIO *next;
452
453    ctx = (BIO_B64_CTX *)BIO_get_data(b);
454    next = BIO_next(b);
455    if ((ctx == NULL) || (next == NULL))
456        return 0;
457
458    switch (cmd) {
459    case BIO_CTRL_RESET:
460        ctx->cont = 1;
461        ctx->start = 1;
462        ctx->encode = B64_NONE;
463        ret = BIO_ctrl(next, cmd, num, ptr);
464        break;
465    case BIO_CTRL_EOF:         /* More to read */
466        if (ctx->cont <= 0)
467            ret = 1;
468        else
469            ret = BIO_ctrl(next, cmd, num, ptr);
470        break;
471    case BIO_CTRL_WPENDING:    /* More to write in buffer */
472        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
473        ret = ctx->buf_len - ctx->buf_off;
474        if ((ret == 0) && (ctx->encode != B64_NONE)
475            && (EVP_ENCODE_CTX_num(ctx->base64) != 0))
476            ret = 1;
477        else if (ret <= 0)
478            ret = BIO_ctrl(next, cmd, num, ptr);
479        break;
480    case BIO_CTRL_PENDING:     /* More to read in buffer */
481        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
482        ret = ctx->buf_len - ctx->buf_off;
483        if (ret <= 0)
484            ret = BIO_ctrl(next, cmd, num, ptr);
485        break;
486    case BIO_CTRL_FLUSH:
487        /* do a final write */
488 again:
489        while (ctx->buf_len != ctx->buf_off) {
490            i = b64_write(b, NULL, 0);
491            if (i < 0)
492                return i;
493        }
494        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
495            if (ctx->tmp_len != 0) {
496                ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf,
497                                               (unsigned char *)ctx->tmp,
498                                               ctx->tmp_len);
499                ctx->buf_off = 0;
500                ctx->tmp_len = 0;
501                goto again;
502            }
503        } else if (ctx->encode != B64_NONE
504                   && EVP_ENCODE_CTX_num(ctx->base64) != 0) {
505            ctx->buf_off = 0;
506            EVP_EncodeFinal(ctx->base64,
507                            (unsigned char *)ctx->buf, &(ctx->buf_len));
508            /* push out the bytes */
509            goto again;
510        }
511        /* Finally flush the underlying BIO */
512        ret = BIO_ctrl(next, cmd, num, ptr);
513        break;
514
515    case BIO_C_DO_STATE_MACHINE:
516        BIO_clear_retry_flags(b);
517        ret = BIO_ctrl(next, cmd, num, ptr);
518        BIO_copy_next_retry(b);
519        break;
520
521    case BIO_CTRL_DUP:
522        break;
523    case BIO_CTRL_INFO:
524    case BIO_CTRL_GET:
525    case BIO_CTRL_SET:
526    default:
527        ret = BIO_ctrl(next, cmd, num, ptr);
528        break;
529    }
530    return ret;
531}
532
533static long b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
534{
535    BIO *next = BIO_next(b);
536
537    if (next == NULL)
538        return 0;
539
540    return BIO_callback_ctrl(next, cmd, fp);
541}
542
543static int b64_puts(BIO *b, const char *str)
544{
545    return b64_write(b, str, strlen(str));
546}
547