Coverage Report

Created: 2023-06-08 06:43

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