1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdio.h>
11e1051a39Sopenharmony_ci#include <limits.h>
12e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
13e1051a39Sopenharmony_ci#include <openssl/evp.h>
14e1051a39Sopenharmony_ci#include "crypto/evp.h"
15e1051a39Sopenharmony_ci#include "evp_local.h"
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_cistatic unsigned char conv_ascii2bin(unsigned char a,
18e1051a39Sopenharmony_ci                                    const unsigned char *table);
19e1051a39Sopenharmony_cistatic int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
20e1051a39Sopenharmony_ci                               const unsigned char *f, int dlen);
21e1051a39Sopenharmony_cistatic int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
22e1051a39Sopenharmony_ci                               const unsigned char *f, int n);
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ci#ifndef CHARSET_EBCDIC
25e1051a39Sopenharmony_ci# define conv_bin2ascii(a, table)       ((table)[(a)&0x3f])
26e1051a39Sopenharmony_ci#else
27e1051a39Sopenharmony_ci/*
28e1051a39Sopenharmony_ci * We assume that PEM encoded files are EBCDIC files (i.e., printable text
29e1051a39Sopenharmony_ci * files). Convert them here while decoding. When encoding, output is EBCDIC
30e1051a39Sopenharmony_ci * (text) format again. (No need for conversion in the conv_bin2ascii macro,
31e1051a39Sopenharmony_ci * as the underlying textstring data_bin2ascii[] is already EBCDIC)
32e1051a39Sopenharmony_ci */
33e1051a39Sopenharmony_ci# define conv_bin2ascii(a, table)       ((table)[(a)&0x3f])
34e1051a39Sopenharmony_ci#endif
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci/*-
37e1051a39Sopenharmony_ci * 64 char lines
38e1051a39Sopenharmony_ci * pad input with 0
39e1051a39Sopenharmony_ci * left over chars are set to =
40e1051a39Sopenharmony_ci * 1 byte  => xx==
41e1051a39Sopenharmony_ci * 2 bytes => xxx=
42e1051a39Sopenharmony_ci * 3 bytes => xxxx
43e1051a39Sopenharmony_ci */
44e1051a39Sopenharmony_ci#define BIN_PER_LINE    (64/4*3)
45e1051a39Sopenharmony_ci#define CHUNKS_PER_LINE (64/4)
46e1051a39Sopenharmony_ci#define CHAR_PER_LINE   (64+1)
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_cistatic const unsigned char data_bin2ascii[65] =
49e1051a39Sopenharmony_ci    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ci/* SRP uses a different base64 alphabet */
52e1051a39Sopenharmony_cistatic const unsigned char srpdata_bin2ascii[65] =
53e1051a39Sopenharmony_ci    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_ci/*-
57e1051a39Sopenharmony_ci * 0xF0 is a EOLN
58e1051a39Sopenharmony_ci * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
59e1051a39Sopenharmony_ci * 0xF2 is EOF
60e1051a39Sopenharmony_ci * 0xE0 is ignore at start of line.
61e1051a39Sopenharmony_ci * 0xFF is error
62e1051a39Sopenharmony_ci */
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci#define B64_EOLN                0xF0
65e1051a39Sopenharmony_ci#define B64_CR                  0xF1
66e1051a39Sopenharmony_ci#define B64_EOF                 0xF2
67e1051a39Sopenharmony_ci#define B64_WS                  0xE0
68e1051a39Sopenharmony_ci#define B64_ERROR               0xFF
69e1051a39Sopenharmony_ci#define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
70e1051a39Sopenharmony_ci#define B64_BASE64(a)           (!B64_NOT_BASE64(a))
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_cistatic const unsigned char data_ascii2bin[128] = {
73e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74e1051a39Sopenharmony_ci    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
75e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
76e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
77e1051a39Sopenharmony_ci    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
78e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
79e1051a39Sopenharmony_ci    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
80e1051a39Sopenharmony_ci    0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
81e1051a39Sopenharmony_ci    0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
82e1051a39Sopenharmony_ci    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
83e1051a39Sopenharmony_ci    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
84e1051a39Sopenharmony_ci    0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85e1051a39Sopenharmony_ci    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
86e1051a39Sopenharmony_ci    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
87e1051a39Sopenharmony_ci    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
88e1051a39Sopenharmony_ci    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89e1051a39Sopenharmony_ci};
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_cistatic const unsigned char srpdata_ascii2bin[128] = {
92e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
93e1051a39Sopenharmony_ci    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
94e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
95e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
96e1051a39Sopenharmony_ci    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
97e1051a39Sopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x3E, 0x3F,
98e1051a39Sopenharmony_ci    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
99e1051a39Sopenharmony_ci    0x08, 0x09, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
100e1051a39Sopenharmony_ci    0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
101e1051a39Sopenharmony_ci    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
102e1051a39Sopenharmony_ci    0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
103e1051a39Sopenharmony_ci    0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104e1051a39Sopenharmony_ci    0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
105e1051a39Sopenharmony_ci    0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
106e1051a39Sopenharmony_ci    0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
107e1051a39Sopenharmony_ci    0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108e1051a39Sopenharmony_ci};
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ci#ifndef CHARSET_EBCDIC
111e1051a39Sopenharmony_cistatic unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
112e1051a39Sopenharmony_ci{
113e1051a39Sopenharmony_ci    if (a & 0x80)
114e1051a39Sopenharmony_ci        return B64_ERROR;
115e1051a39Sopenharmony_ci    return table[a];
116e1051a39Sopenharmony_ci}
117e1051a39Sopenharmony_ci#else
118e1051a39Sopenharmony_cistatic unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
119e1051a39Sopenharmony_ci{
120e1051a39Sopenharmony_ci    a = os_toascii[a];
121e1051a39Sopenharmony_ci    if (a & 0x80)
122e1051a39Sopenharmony_ci        return B64_ERROR;
123e1051a39Sopenharmony_ci    return table[a];
124e1051a39Sopenharmony_ci}
125e1051a39Sopenharmony_ci#endif
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ciEVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
128e1051a39Sopenharmony_ci{
129e1051a39Sopenharmony_ci    return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX));
130e1051a39Sopenharmony_ci}
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_civoid EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
133e1051a39Sopenharmony_ci{
134e1051a39Sopenharmony_ci    OPENSSL_free(ctx);
135e1051a39Sopenharmony_ci}
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ciint EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, const EVP_ENCODE_CTX *sctx)
138e1051a39Sopenharmony_ci{
139e1051a39Sopenharmony_ci    memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX));
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci    return 1;
142e1051a39Sopenharmony_ci}
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ciint EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx)
145e1051a39Sopenharmony_ci{
146e1051a39Sopenharmony_ci    return ctx->num;
147e1051a39Sopenharmony_ci}
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_civoid evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags)
150e1051a39Sopenharmony_ci{
151e1051a39Sopenharmony_ci    ctx->flags = flags;
152e1051a39Sopenharmony_ci}
153e1051a39Sopenharmony_ci
154e1051a39Sopenharmony_civoid EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
155e1051a39Sopenharmony_ci{
156e1051a39Sopenharmony_ci    ctx->length = 48;
157e1051a39Sopenharmony_ci    ctx->num = 0;
158e1051a39Sopenharmony_ci    ctx->line_num = 0;
159e1051a39Sopenharmony_ci    ctx->flags = 0;
160e1051a39Sopenharmony_ci}
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ciint EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
163e1051a39Sopenharmony_ci                      const unsigned char *in, int inl)
164e1051a39Sopenharmony_ci{
165e1051a39Sopenharmony_ci    int i, j;
166e1051a39Sopenharmony_ci    size_t total = 0;
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ci    *outl = 0;
169e1051a39Sopenharmony_ci    if (inl <= 0)
170e1051a39Sopenharmony_ci        return 0;
171e1051a39Sopenharmony_ci    OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
172e1051a39Sopenharmony_ci    if (ctx->length - ctx->num > inl) {
173e1051a39Sopenharmony_ci        memcpy(&(ctx->enc_data[ctx->num]), in, inl);
174e1051a39Sopenharmony_ci        ctx->num += inl;
175e1051a39Sopenharmony_ci        return 1;
176e1051a39Sopenharmony_ci    }
177e1051a39Sopenharmony_ci    if (ctx->num != 0) {
178e1051a39Sopenharmony_ci        i = ctx->length - ctx->num;
179e1051a39Sopenharmony_ci        memcpy(&(ctx->enc_data[ctx->num]), in, i);
180e1051a39Sopenharmony_ci        in += i;
181e1051a39Sopenharmony_ci        inl -= i;
182e1051a39Sopenharmony_ci        j = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->length);
183e1051a39Sopenharmony_ci        ctx->num = 0;
184e1051a39Sopenharmony_ci        out += j;
185e1051a39Sopenharmony_ci        total = j;
186e1051a39Sopenharmony_ci        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
187e1051a39Sopenharmony_ci            *(out++) = '\n';
188e1051a39Sopenharmony_ci            total++;
189e1051a39Sopenharmony_ci        }
190e1051a39Sopenharmony_ci        *out = '\0';
191e1051a39Sopenharmony_ci    }
192e1051a39Sopenharmony_ci    while (inl >= ctx->length && total <= INT_MAX) {
193e1051a39Sopenharmony_ci        j = evp_encodeblock_int(ctx, out, in, ctx->length);
194e1051a39Sopenharmony_ci        in += ctx->length;
195e1051a39Sopenharmony_ci        inl -= ctx->length;
196e1051a39Sopenharmony_ci        out += j;
197e1051a39Sopenharmony_ci        total += j;
198e1051a39Sopenharmony_ci        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
199e1051a39Sopenharmony_ci            *(out++) = '\n';
200e1051a39Sopenharmony_ci            total++;
201e1051a39Sopenharmony_ci        }
202e1051a39Sopenharmony_ci        *out = '\0';
203e1051a39Sopenharmony_ci    }
204e1051a39Sopenharmony_ci    if (total > INT_MAX) {
205e1051a39Sopenharmony_ci        /* Too much output data! */
206e1051a39Sopenharmony_ci        *outl = 0;
207e1051a39Sopenharmony_ci        return 0;
208e1051a39Sopenharmony_ci    }
209e1051a39Sopenharmony_ci    if (inl != 0)
210e1051a39Sopenharmony_ci        memcpy(&(ctx->enc_data[0]), in, inl);
211e1051a39Sopenharmony_ci    ctx->num = inl;
212e1051a39Sopenharmony_ci    *outl = total;
213e1051a39Sopenharmony_ci
214e1051a39Sopenharmony_ci    return 1;
215e1051a39Sopenharmony_ci}
216e1051a39Sopenharmony_ci
217e1051a39Sopenharmony_civoid EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
218e1051a39Sopenharmony_ci{
219e1051a39Sopenharmony_ci    unsigned int ret = 0;
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ci    if (ctx->num != 0) {
222e1051a39Sopenharmony_ci        ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num);
223e1051a39Sopenharmony_ci        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
224e1051a39Sopenharmony_ci            out[ret++] = '\n';
225e1051a39Sopenharmony_ci        out[ret] = '\0';
226e1051a39Sopenharmony_ci        ctx->num = 0;
227e1051a39Sopenharmony_ci    }
228e1051a39Sopenharmony_ci    *outl = ret;
229e1051a39Sopenharmony_ci}
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_cistatic int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
232e1051a39Sopenharmony_ci                               const unsigned char *f, int dlen)
233e1051a39Sopenharmony_ci{
234e1051a39Sopenharmony_ci    int i, ret = 0;
235e1051a39Sopenharmony_ci    unsigned long l;
236e1051a39Sopenharmony_ci    const unsigned char *table;
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
239e1051a39Sopenharmony_ci        table = srpdata_bin2ascii;
240e1051a39Sopenharmony_ci    else
241e1051a39Sopenharmony_ci        table = data_bin2ascii;
242e1051a39Sopenharmony_ci
243e1051a39Sopenharmony_ci    for (i = dlen; i > 0; i -= 3) {
244e1051a39Sopenharmony_ci        if (i >= 3) {
245e1051a39Sopenharmony_ci            l = (((unsigned long)f[0]) << 16L) |
246e1051a39Sopenharmony_ci                (((unsigned long)f[1]) << 8L) | f[2];
247e1051a39Sopenharmony_ci            *(t++) = conv_bin2ascii(l >> 18L, table);
248e1051a39Sopenharmony_ci            *(t++) = conv_bin2ascii(l >> 12L, table);
249e1051a39Sopenharmony_ci            *(t++) = conv_bin2ascii(l >> 6L, table);
250e1051a39Sopenharmony_ci            *(t++) = conv_bin2ascii(l, table);
251e1051a39Sopenharmony_ci        } else {
252e1051a39Sopenharmony_ci            l = ((unsigned long)f[0]) << 16L;
253e1051a39Sopenharmony_ci            if (i == 2)
254e1051a39Sopenharmony_ci                l |= ((unsigned long)f[1] << 8L);
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_ci            *(t++) = conv_bin2ascii(l >> 18L, table);
257e1051a39Sopenharmony_ci            *(t++) = conv_bin2ascii(l >> 12L, table);
258e1051a39Sopenharmony_ci            *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L, table);
259e1051a39Sopenharmony_ci            *(t++) = '=';
260e1051a39Sopenharmony_ci        }
261e1051a39Sopenharmony_ci        ret += 4;
262e1051a39Sopenharmony_ci        f += 3;
263e1051a39Sopenharmony_ci    }
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    *t = '\0';
266e1051a39Sopenharmony_ci    return ret;
267e1051a39Sopenharmony_ci}
268e1051a39Sopenharmony_ci
269e1051a39Sopenharmony_ciint EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
270e1051a39Sopenharmony_ci{
271e1051a39Sopenharmony_ci    return evp_encodeblock_int(NULL, t, f, dlen);
272e1051a39Sopenharmony_ci}
273e1051a39Sopenharmony_ci
274e1051a39Sopenharmony_civoid EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
275e1051a39Sopenharmony_ci{
276e1051a39Sopenharmony_ci    /* Only ctx->num and ctx->flags are used during decoding. */
277e1051a39Sopenharmony_ci    ctx->num = 0;
278e1051a39Sopenharmony_ci    ctx->length = 0;
279e1051a39Sopenharmony_ci    ctx->line_num = 0;
280e1051a39Sopenharmony_ci    ctx->flags = 0;
281e1051a39Sopenharmony_ci}
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_ci/*-
284e1051a39Sopenharmony_ci * -1 for error
285e1051a39Sopenharmony_ci *  0 for last line
286e1051a39Sopenharmony_ci *  1 for full line
287e1051a39Sopenharmony_ci *
288e1051a39Sopenharmony_ci * Note: even though EVP_DecodeUpdate attempts to detect and report end of
289e1051a39Sopenharmony_ci * content, the context doesn't currently remember it and will accept more data
290e1051a39Sopenharmony_ci * in the next call. Therefore, the caller is responsible for checking and
291e1051a39Sopenharmony_ci * rejecting a 0 return value in the middle of content.
292e1051a39Sopenharmony_ci *
293e1051a39Sopenharmony_ci * Note: even though EVP_DecodeUpdate has historically tried to detect end of
294e1051a39Sopenharmony_ci * content based on line length, this has never worked properly. Therefore,
295e1051a39Sopenharmony_ci * we now return 0 when one of the following is true:
296e1051a39Sopenharmony_ci *   - Padding or B64_EOF was detected and the last block is complete.
297e1051a39Sopenharmony_ci *   - Input has zero-length.
298e1051a39Sopenharmony_ci * -1 is returned if:
299e1051a39Sopenharmony_ci *   - Invalid characters are detected.
300e1051a39Sopenharmony_ci *   - There is extra trailing padding, or data after padding.
301e1051a39Sopenharmony_ci *   - B64_EOF is detected after an incomplete base64 block.
302e1051a39Sopenharmony_ci */
303e1051a39Sopenharmony_ciint EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
304e1051a39Sopenharmony_ci                     const unsigned char *in, int inl)
305e1051a39Sopenharmony_ci{
306e1051a39Sopenharmony_ci    int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
307e1051a39Sopenharmony_ci    unsigned char *d;
308e1051a39Sopenharmony_ci    const unsigned char *table;
309e1051a39Sopenharmony_ci
310e1051a39Sopenharmony_ci    n = ctx->num;
311e1051a39Sopenharmony_ci    d = ctx->enc_data;
312e1051a39Sopenharmony_ci
313e1051a39Sopenharmony_ci    if (n > 0 && d[n - 1] == '=') {
314e1051a39Sopenharmony_ci        eof++;
315e1051a39Sopenharmony_ci        if (n > 1 && d[n - 2] == '=')
316e1051a39Sopenharmony_ci            eof++;
317e1051a39Sopenharmony_ci    }
318e1051a39Sopenharmony_ci
319e1051a39Sopenharmony_ci     /* Legacy behaviour: an empty input chunk signals end of input. */
320e1051a39Sopenharmony_ci    if (inl == 0) {
321e1051a39Sopenharmony_ci        rv = 0;
322e1051a39Sopenharmony_ci        goto end;
323e1051a39Sopenharmony_ci    }
324e1051a39Sopenharmony_ci
325e1051a39Sopenharmony_ci    if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
326e1051a39Sopenharmony_ci        table = srpdata_ascii2bin;
327e1051a39Sopenharmony_ci    else
328e1051a39Sopenharmony_ci        table = data_ascii2bin;
329e1051a39Sopenharmony_ci
330e1051a39Sopenharmony_ci    for (i = 0; i < inl; i++) {
331e1051a39Sopenharmony_ci        tmp = *(in++);
332e1051a39Sopenharmony_ci        v = conv_ascii2bin(tmp, table);
333e1051a39Sopenharmony_ci        if (v == B64_ERROR) {
334e1051a39Sopenharmony_ci            rv = -1;
335e1051a39Sopenharmony_ci            goto end;
336e1051a39Sopenharmony_ci        }
337e1051a39Sopenharmony_ci
338e1051a39Sopenharmony_ci        if (tmp == '=') {
339e1051a39Sopenharmony_ci            eof++;
340e1051a39Sopenharmony_ci        } else if (eof > 0 && B64_BASE64(v)) {
341e1051a39Sopenharmony_ci            /* More data after padding. */
342e1051a39Sopenharmony_ci            rv = -1;
343e1051a39Sopenharmony_ci            goto end;
344e1051a39Sopenharmony_ci        }
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_ci        if (eof > 2) {
347e1051a39Sopenharmony_ci            rv = -1;
348e1051a39Sopenharmony_ci            goto end;
349e1051a39Sopenharmony_ci        }
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_ci        if (v == B64_EOF) {
352e1051a39Sopenharmony_ci            seof = 1;
353e1051a39Sopenharmony_ci            goto tail;
354e1051a39Sopenharmony_ci        }
355e1051a39Sopenharmony_ci
356e1051a39Sopenharmony_ci        /* Only save valid base64 characters. */
357e1051a39Sopenharmony_ci        if (B64_BASE64(v)) {
358e1051a39Sopenharmony_ci            if (n >= 64) {
359e1051a39Sopenharmony_ci                /*
360e1051a39Sopenharmony_ci                 * We increment n once per loop, and empty the buffer as soon as
361e1051a39Sopenharmony_ci                 * we reach 64 characters, so this can only happen if someone's
362e1051a39Sopenharmony_ci                 * manually messed with the ctx. Refuse to write any more data.
363e1051a39Sopenharmony_ci                 */
364e1051a39Sopenharmony_ci                rv = -1;
365e1051a39Sopenharmony_ci                goto end;
366e1051a39Sopenharmony_ci            }
367e1051a39Sopenharmony_ci            OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
368e1051a39Sopenharmony_ci            d[n++] = tmp;
369e1051a39Sopenharmony_ci        }
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_ci        if (n == 64) {
372e1051a39Sopenharmony_ci            decoded_len = evp_decodeblock_int(ctx, out, d, n);
373e1051a39Sopenharmony_ci            n = 0;
374e1051a39Sopenharmony_ci            if (decoded_len < 0 || eof > decoded_len) {
375e1051a39Sopenharmony_ci                rv = -1;
376e1051a39Sopenharmony_ci                goto end;
377e1051a39Sopenharmony_ci            }
378e1051a39Sopenharmony_ci            ret += decoded_len - eof;
379e1051a39Sopenharmony_ci            out += decoded_len - eof;
380e1051a39Sopenharmony_ci        }
381e1051a39Sopenharmony_ci    }
382e1051a39Sopenharmony_ci
383e1051a39Sopenharmony_ci    /*
384e1051a39Sopenharmony_ci     * Legacy behaviour: if the current line is a full base64-block (i.e., has
385e1051a39Sopenharmony_ci     * 0 mod 4 base64 characters), it is processed immediately. We keep this
386e1051a39Sopenharmony_ci     * behaviour as applications may not be calling EVP_DecodeFinal properly.
387e1051a39Sopenharmony_ci     */
388e1051a39Sopenharmony_citail:
389e1051a39Sopenharmony_ci    if (n > 0) {
390e1051a39Sopenharmony_ci        if ((n & 3) == 0) {
391e1051a39Sopenharmony_ci            decoded_len = evp_decodeblock_int(ctx, out, d, n);
392e1051a39Sopenharmony_ci            n = 0;
393e1051a39Sopenharmony_ci            if (decoded_len < 0 || eof > decoded_len) {
394e1051a39Sopenharmony_ci                rv = -1;
395e1051a39Sopenharmony_ci                goto end;
396e1051a39Sopenharmony_ci            }
397e1051a39Sopenharmony_ci            ret += (decoded_len - eof);
398e1051a39Sopenharmony_ci        } else if (seof) {
399e1051a39Sopenharmony_ci            /* EOF in the middle of a base64 block. */
400e1051a39Sopenharmony_ci            rv = -1;
401e1051a39Sopenharmony_ci            goto end;
402e1051a39Sopenharmony_ci        }
403e1051a39Sopenharmony_ci    }
404e1051a39Sopenharmony_ci
405e1051a39Sopenharmony_ci    rv = seof || (n == 0 && eof) ? 0 : 1;
406e1051a39Sopenharmony_ciend:
407e1051a39Sopenharmony_ci    /* Legacy behaviour. This should probably rather be zeroed on error. */
408e1051a39Sopenharmony_ci    *outl = ret;
409e1051a39Sopenharmony_ci    ctx->num = n;
410e1051a39Sopenharmony_ci    return rv;
411e1051a39Sopenharmony_ci}
412e1051a39Sopenharmony_ci
413e1051a39Sopenharmony_cistatic int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
414e1051a39Sopenharmony_ci                               const unsigned char *f, int n)
415e1051a39Sopenharmony_ci{
416e1051a39Sopenharmony_ci    int i, ret = 0, a, b, c, d;
417e1051a39Sopenharmony_ci    unsigned long l;
418e1051a39Sopenharmony_ci    const unsigned char *table;
419e1051a39Sopenharmony_ci
420e1051a39Sopenharmony_ci    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
421e1051a39Sopenharmony_ci        table = srpdata_ascii2bin;
422e1051a39Sopenharmony_ci    else
423e1051a39Sopenharmony_ci        table = data_ascii2bin;
424e1051a39Sopenharmony_ci
425e1051a39Sopenharmony_ci    /* trim whitespace from the start of the line. */
426e1051a39Sopenharmony_ci    while ((n > 0) && (conv_ascii2bin(*f, table) == B64_WS)) {
427e1051a39Sopenharmony_ci        f++;
428e1051a39Sopenharmony_ci        n--;
429e1051a39Sopenharmony_ci    }
430e1051a39Sopenharmony_ci
431e1051a39Sopenharmony_ci    /*
432e1051a39Sopenharmony_ci     * strip off stuff at the end of the line ascii2bin values B64_WS,
433e1051a39Sopenharmony_ci     * B64_EOLN, B64_EOLN and B64_EOF
434e1051a39Sopenharmony_ci     */
435e1051a39Sopenharmony_ci    while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table))))
436e1051a39Sopenharmony_ci        n--;
437e1051a39Sopenharmony_ci
438e1051a39Sopenharmony_ci    if (n % 4 != 0)
439e1051a39Sopenharmony_ci        return -1;
440e1051a39Sopenharmony_ci
441e1051a39Sopenharmony_ci    for (i = 0; i < n; i += 4) {
442e1051a39Sopenharmony_ci        a = conv_ascii2bin(*(f++), table);
443e1051a39Sopenharmony_ci        b = conv_ascii2bin(*(f++), table);
444e1051a39Sopenharmony_ci        c = conv_ascii2bin(*(f++), table);
445e1051a39Sopenharmony_ci        d = conv_ascii2bin(*(f++), table);
446e1051a39Sopenharmony_ci        if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
447e1051a39Sopenharmony_ci            return -1;
448e1051a39Sopenharmony_ci        l = ((((unsigned long)a) << 18L) |
449e1051a39Sopenharmony_ci             (((unsigned long)b) << 12L) |
450e1051a39Sopenharmony_ci             (((unsigned long)c) << 6L) | (((unsigned long)d)));
451e1051a39Sopenharmony_ci        *(t++) = (unsigned char)(l >> 16L) & 0xff;
452e1051a39Sopenharmony_ci        *(t++) = (unsigned char)(l >> 8L) & 0xff;
453e1051a39Sopenharmony_ci        *(t++) = (unsigned char)(l) & 0xff;
454e1051a39Sopenharmony_ci        ret += 3;
455e1051a39Sopenharmony_ci    }
456e1051a39Sopenharmony_ci    return ret;
457e1051a39Sopenharmony_ci}
458e1051a39Sopenharmony_ci
459e1051a39Sopenharmony_ciint EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
460e1051a39Sopenharmony_ci{
461e1051a39Sopenharmony_ci    return evp_decodeblock_int(NULL, t, f, n);
462e1051a39Sopenharmony_ci}
463e1051a39Sopenharmony_ci
464e1051a39Sopenharmony_ciint EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
465e1051a39Sopenharmony_ci{
466e1051a39Sopenharmony_ci    int i;
467e1051a39Sopenharmony_ci
468e1051a39Sopenharmony_ci    *outl = 0;
469e1051a39Sopenharmony_ci    if (ctx->num != 0) {
470e1051a39Sopenharmony_ci        i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num);
471e1051a39Sopenharmony_ci        if (i < 0)
472e1051a39Sopenharmony_ci            return -1;
473e1051a39Sopenharmony_ci        ctx->num = 0;
474e1051a39Sopenharmony_ci        *outl = i;
475e1051a39Sopenharmony_ci        return 1;
476e1051a39Sopenharmony_ci    } else
477e1051a39Sopenharmony_ci        return 1;
478e1051a39Sopenharmony_ci}
479