Coverage Report

Created: 2025-08-28 07:07

/src/openssl35/crypto/evp/encode.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-2025 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, int eof);
23
24
#ifndef CHARSET_EBCDIC
25
14.7k
# 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
137M
#define B64_EOF                 0xF2
67
2.11M
#define B64_WS                  0xE0
68
137M
#define B64_ERROR               0xFF
69
142M
#define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
70
139M
#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
656M
{
113
656M
    if (a & 0x80)
114
3.86k
        return B64_ERROR;
115
656M
    return table[a];
116
656M
}
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
219k
{
129
219k
    return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX));
130
219k
}
131
132
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
133
260k
{
134
260k
    OPENSSL_free(ctx);
135
260k
}
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
13.4k
{
146
13.4k
    return ctx->num;
147
13.4k
}
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
6.50k
{
156
6.50k
    ctx->length = 48;
157
6.50k
    ctx->num = 0;
158
6.50k
    ctx->line_num = 0;
159
6.50k
    ctx->flags = 0;
160
6.50k
}
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
732
{
219
732
    unsigned int ret = 0;
220
221
732
    if (ctx->num != 0) {
222
732
        ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num);
223
732
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
224
732
            out[ret++] = '\n';
225
732
        out[ret] = '\0';
226
732
        ctx->num = 0;
227
732
    }
228
732
    *outl = ret;
229
732
}
230
231
static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
232
                               const unsigned char *f, int dlen)
233
732
{
234
732
    int i, ret = 0;
235
732
    unsigned long l;
236
732
    const unsigned char *table;
237
238
732
    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
239
0
        table = srpdata_bin2ascii;
240
732
    else
241
732
        table = data_bin2ascii;
242
243
4.49k
    for (i = dlen; i > 0; i -= 3) {
244
3.76k
        if (i >= 3) {
245
3.20k
            l = (((unsigned long)f[0]) << 16L) |
246
3.20k
                (((unsigned long)f[1]) << 8L) | f[2];
247
3.20k
            *(t++) = conv_bin2ascii(l >> 18L, table);
248
3.20k
            *(t++) = conv_bin2ascii(l >> 12L, table);
249
3.20k
            *(t++) = conv_bin2ascii(l >> 6L, table);
250
3.20k
            *(t++) = conv_bin2ascii(l, table);
251
3.20k
        } else {
252
562
            l = ((unsigned long)f[0]) << 16L;
253
562
            if (i == 2)
254
231
                l |= ((unsigned long)f[1] << 8L);
255
256
562
            *(t++) = conv_bin2ascii(l >> 18L, table);
257
562
            *(t++) = conv_bin2ascii(l >> 12L, table);
258
562
            *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L, table);
259
562
            *(t++) = '=';
260
562
        }
261
3.76k
        ret += 4;
262
3.76k
        f += 3;
263
3.76k
    }
264
265
732
    *t = '\0';
266
732
    return ret;
267
732
}
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
458k
{
276
    /* Only ctx->num and ctx->flags are used during decoding. */
277
458k
    ctx->num = 0;
278
458k
    ctx->length = 0;
279
458k
    ctx->line_num = 0;
280
458k
    ctx->flags = 0;
281
458k
}
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
267k
{
306
267k
    int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
307
267k
    unsigned char *d;
308
267k
    const unsigned char *table;
309
310
267k
    n = ctx->num;
311
267k
    d = ctx->enc_data;
312
313
267k
    if (n > 0 && d[n - 1] == '=') {
314
2.11k
        eof++;
315
2.11k
        if (n > 1 && d[n - 2] == '=')
316
510
            eof++;
317
2.11k
    }
318
319
     /* Legacy behaviour: an empty input chunk signals end of input. */
320
267k
    if (inl == 0) {
321
0
        rv = 0;
322
0
        goto end;
323
0
    }
324
325
267k
    if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
326
0
        table = srpdata_ascii2bin;
327
267k
    else
328
267k
        table = data_ascii2bin;
329
330
137M
    for (i = 0; i < inl; i++) {
331
137M
        tmp = *(in++);
332
137M
        v = conv_ascii2bin(tmp, table);
333
137M
        if (v == B64_ERROR) {
334
101k
            rv = -1;
335
101k
            goto end;
336
101k
        }
337
338
137M
        if (tmp == '=') {
339
115k
            eof++;
340
137M
        } else if (eof > 0 && B64_BASE64(v)) {
341
            /* More data after padding. */
342
425
            rv = -1;
343
425
            goto end;
344
425
        }
345
346
137M
        if (eof > 2) {
347
509
            rv = -1;
348
509
            goto end;
349
509
        }
350
351
137M
        if (v == B64_EOF) {
352
1.79k
            seof = 1;
353
1.79k
            goto tail;
354
1.79k
        }
355
356
        /* Only save valid base64 characters. */
357
137M
        if (B64_BASE64(v)) {
358
132M
            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
132M
            OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
368
132M
            d[n++] = tmp;
369
132M
        }
370
371
137M
        if (n == 64) {
372
2.02M
            decoded_len = evp_decodeblock_int(ctx, out, d, n, eof);
373
2.02M
            n = 0;
374
2.02M
            if (decoded_len < 0 || (decoded_len == 0 && eof > 0)) {
375
0
                rv = -1;
376
0
                goto end;
377
0
            }
378
2.02M
            ret += decoded_len;
379
2.02M
            out += decoded_len;
380
2.02M
        }
381
137M
    }
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
165k
tail:
389
165k
    if (n > 0) {
390
147k
        if ((n & 3) == 0) {
391
94.0k
            decoded_len = evp_decodeblock_int(ctx, out, d, n, eof);
392
94.0k
            n = 0;
393
94.0k
            if (decoded_len < 0 || (decoded_len == 0 && eof > 0)) {
394
0
                rv = -1;
395
0
                goto end;
396
0
            }
397
94.0k
            ret += decoded_len;
398
94.0k
        } else if (seof) {
399
            /* EOF in the middle of a base64 block. */
400
782
            rv = -1;
401
782
            goto end;
402
782
        }
403
147k
    }
404
405
164k
    rv = seof || (n == 0 && eof) ? 0 : 1;
406
267k
end:
407
    /* Legacy behaviour. This should probably rather be zeroed on error. */
408
267k
    *outl = ret;
409
267k
    ctx->num = n;
410
267k
    return rv;
411
164k
}
412
413
static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
414
                               const unsigned char *f, int n,
415
                               int eof)
416
2.11M
{
417
2.11M
    int i, ret = 0, a, b, c, d;
418
2.11M
    unsigned long l;
419
2.11M
    const unsigned char *table;
420
421
2.11M
    if (eof < -1 || eof > 2)
422
0
        return -1;
423
424
2.11M
    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
425
0
        table = srpdata_ascii2bin;
426
2.11M
    else
427
2.11M
        table = data_ascii2bin;
428
429
    /* trim whitespace from the start of the line. */
430
2.11M
    while ((n > 0) && (conv_ascii2bin(*f, table) == B64_WS)) {
431
0
        f++;
432
0
        n--;
433
0
    }
434
435
    /*
436
     * strip off stuff at the end of the line ascii2bin values B64_WS,
437
     * B64_EOLN, B64_EOLN and B64_EOF
438
     */
439
2.11M
    while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table))))
440
0
        n--;
441
442
2.11M
    if (n % 4 != 0)
443
449
        return -1;
444
2.11M
    if (n == 0)
445
0
        return 0;
446
447
    /* all 4-byte blocks except the last one do not have padding. */
448
33.0M
    for (i = 0; i < n - 4; i += 4) {
449
30.8M
        a = conv_ascii2bin(*(f++), table);
450
30.8M
        b = conv_ascii2bin(*(f++), table);
451
30.8M
        c = conv_ascii2bin(*(f++), table);
452
30.8M
        d = conv_ascii2bin(*(f++), table);
453
30.8M
        if ((a | b | c | d) & 0x80)
454
0
            return -1;
455
30.8M
        l = ((((unsigned long)a) << 18L) |
456
30.8M
             (((unsigned long)b) << 12L) |
457
30.8M
             (((unsigned long)c) << 6L) | (((unsigned long)d)));
458
30.8M
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
459
30.8M
        *(t++) = (unsigned char)(l >> 8L) & 0xff;
460
30.8M
        *(t++) = (unsigned char)(l) & 0xff;
461
30.8M
        ret += 3;
462
30.8M
    }
463
464
    /* process the last block that may have padding. */
465
2.11M
    a = conv_ascii2bin(*(f++), table);
466
2.11M
    b = conv_ascii2bin(*(f++), table);
467
2.11M
    c = conv_ascii2bin(*(f++), table);
468
2.11M
    d = conv_ascii2bin(*(f++), table);
469
2.11M
    if ((a | b | c | d) & 0x80)
470
0
        return -1;
471
2.11M
    l = ((((unsigned long)a) << 18L) |
472
2.11M
         (((unsigned long)b) << 12L) |
473
2.11M
         (((unsigned long)c) << 6L) | (((unsigned long)d)));
474
475
2.11M
    if (eof == -1)
476
0
        eof = (f[2] == '=') + (f[3] == '=');
477
478
2.11M
    switch (eof) {
479
52.4k
    case 2:
480
52.4k
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
481
52.4k
        break;
482
7.95k
    case 1:
483
7.95k
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
484
7.95k
        *(t++) = (unsigned char)(l >> 8L) & 0xff;
485
7.95k
        break;
486
2.05M
    case 0:
487
2.05M
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
488
2.05M
        *(t++) = (unsigned char)(l >> 8L) & 0xff;
489
2.05M
        *(t++) = (unsigned char)(l) & 0xff;
490
2.05M
        break;
491
2.11M
    }
492
2.11M
    ret += 3 - eof;
493
494
2.11M
    return ret;
495
2.11M
}
496
497
int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
498
0
{
499
0
    return evp_decodeblock_int(NULL, t, f, n, 0);
500
0
}
501
502
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
503
208k
{
504
208k
    int i;
505
506
208k
    *outl = 0;
507
208k
    if (ctx->num != 0) {
508
771
        i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num, -1);
509
771
        if (i < 0)
510
771
            return -1;
511
0
        ctx->num = 0;
512
0
        *outl = i;
513
0
        return 1;
514
771
    } else
515
207k
        return 1;
516
208k
}