Coverage Report

Created: 2026-02-22 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/evp/encode.c
Line
Count
Source
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 <assert.h>
13
#include "internal/cryptlib.h"
14
#include <openssl/evp.h>
15
#include "crypto/evp.h"
16
#include "evp_local.h"
17
18
#if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64))
19
20
#define HAS_IA32CAP_IS_64
21
#endif
22
23
#include "enc_b64_avx2.h"
24
#include "enc_b64_scalar.h"
25
26
static unsigned char conv_ascii2bin(unsigned char a,
27
    const unsigned char *table);
28
int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
29
    const unsigned char *f, int dlen, int *wrap_cnt);
30
static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
31
    const unsigned char *f, int n, int eof);
32
/*-
33
 * 64 char lines
34
 * pad input with 0
35
 * left over chars are set to =
36
 * 1 byte  => xx==
37
 * 2 bytes => xxx=
38
 * 3 bytes => xxxx
39
 */
40
#define BIN_PER_LINE (64 / 4 * 3)
41
#define CHUNKS_PER_LINE (64 / 4)
42
#define CHAR_PER_LINE (64 + 1)
43
44
/*-
45
 * 0xF0 is a EOLN
46
 * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
47
 * 0xF2 is EOF
48
 * 0xE0 is ignore at start of line.
49
 * 0xFF is error
50
 */
51
52
#define B64_EOLN 0xF0
53
#define B64_CR 0xF1
54
0
#define B64_EOF 0xF2
55
0
#define B64_WS 0xE0
56
0
#define B64_ERROR 0xFF
57
0
#define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)
58
0
#define B64_BASE64(a) (!B64_NOT_BASE64(a))
59
60
static const unsigned char data_ascii2bin[128] = {
61
    0xFF,
62
    0xFF,
63
    0xFF,
64
    0xFF,
65
    0xFF,
66
    0xFF,
67
    0xFF,
68
    0xFF,
69
    0xFF,
70
    0xE0,
71
    0xF0,
72
    0xFF,
73
    0xFF,
74
    0xF1,
75
    0xFF,
76
    0xFF,
77
    0xFF,
78
    0xFF,
79
    0xFF,
80
    0xFF,
81
    0xFF,
82
    0xFF,
83
    0xFF,
84
    0xFF,
85
    0xFF,
86
    0xFF,
87
    0xFF,
88
    0xFF,
89
    0xFF,
90
    0xFF,
91
    0xFF,
92
    0xFF,
93
    0xE0,
94
    0xFF,
95
    0xFF,
96
    0xFF,
97
    0xFF,
98
    0xFF,
99
    0xFF,
100
    0xFF,
101
    0xFF,
102
    0xFF,
103
    0xFF,
104
    0x3E,
105
    0xFF,
106
    0xF2,
107
    0xFF,
108
    0x3F,
109
    0x34,
110
    0x35,
111
    0x36,
112
    0x37,
113
    0x38,
114
    0x39,
115
    0x3A,
116
    0x3B,
117
    0x3C,
118
    0x3D,
119
    0xFF,
120
    0xFF,
121
    0xFF,
122
    0x00,
123
    0xFF,
124
    0xFF,
125
    0xFF,
126
    0x00,
127
    0x01,
128
    0x02,
129
    0x03,
130
    0x04,
131
    0x05,
132
    0x06,
133
    0x07,
134
    0x08,
135
    0x09,
136
    0x0A,
137
    0x0B,
138
    0x0C,
139
    0x0D,
140
    0x0E,
141
    0x0F,
142
    0x10,
143
    0x11,
144
    0x12,
145
    0x13,
146
    0x14,
147
    0x15,
148
    0x16,
149
    0x17,
150
    0x18,
151
    0x19,
152
    0xFF,
153
    0xFF,
154
    0xFF,
155
    0xFF,
156
    0xFF,
157
    0xFF,
158
    0x1A,
159
    0x1B,
160
    0x1C,
161
    0x1D,
162
    0x1E,
163
    0x1F,
164
    0x20,
165
    0x21,
166
    0x22,
167
    0x23,
168
    0x24,
169
    0x25,
170
    0x26,
171
    0x27,
172
    0x28,
173
    0x29,
174
    0x2A,
175
    0x2B,
176
    0x2C,
177
    0x2D,
178
    0x2E,
179
    0x2F,
180
    0x30,
181
    0x31,
182
    0x32,
183
    0x33,
184
    0xFF,
185
    0xFF,
186
    0xFF,
187
    0xFF,
188
    0xFF,
189
};
190
191
static const unsigned char srpdata_ascii2bin[128] = {
192
    0xFF,
193
    0xFF,
194
    0xFF,
195
    0xFF,
196
    0xFF,
197
    0xFF,
198
    0xFF,
199
    0xFF,
200
    0xFF,
201
    0xE0,
202
    0xF0,
203
    0xFF,
204
    0xFF,
205
    0xF1,
206
    0xFF,
207
    0xFF,
208
    0xFF,
209
    0xFF,
210
    0xFF,
211
    0xFF,
212
    0xFF,
213
    0xFF,
214
    0xFF,
215
    0xFF,
216
    0xFF,
217
    0xFF,
218
    0xFF,
219
    0xFF,
220
    0xFF,
221
    0xFF,
222
    0xFF,
223
    0xFF,
224
    0xE0,
225
    0xFF,
226
    0xFF,
227
    0xFF,
228
    0xFF,
229
    0xFF,
230
    0xFF,
231
    0xFF,
232
    0xFF,
233
    0xFF,
234
    0xFF,
235
    0xFF,
236
    0xFF,
237
    0xF2,
238
    0x3E,
239
    0x3F,
240
    0x00,
241
    0x01,
242
    0x02,
243
    0x03,
244
    0x04,
245
    0x05,
246
    0x06,
247
    0x07,
248
    0x08,
249
    0x09,
250
    0xFF,
251
    0xFF,
252
    0xFF,
253
    0x00,
254
    0xFF,
255
    0xFF,
256
    0xFF,
257
    0x0A,
258
    0x0B,
259
    0x0C,
260
    0x0D,
261
    0x0E,
262
    0x0F,
263
    0x10,
264
    0x11,
265
    0x12,
266
    0x13,
267
    0x14,
268
    0x15,
269
    0x16,
270
    0x17,
271
    0x18,
272
    0x19,
273
    0x1A,
274
    0x1B,
275
    0x1C,
276
    0x1D,
277
    0x1E,
278
    0x1F,
279
    0x20,
280
    0x21,
281
    0x22,
282
    0x23,
283
    0xFF,
284
    0xFF,
285
    0xFF,
286
    0xFF,
287
    0xFF,
288
    0xFF,
289
    0x24,
290
    0x25,
291
    0x26,
292
    0x27,
293
    0x28,
294
    0x29,
295
    0x2A,
296
    0x2B,
297
    0x2C,
298
    0x2D,
299
    0x2E,
300
    0x2F,
301
    0x30,
302
    0x31,
303
    0x32,
304
    0x33,
305
    0x34,
306
    0x35,
307
    0x36,
308
    0x37,
309
    0x38,
310
    0x39,
311
    0x3A,
312
    0x3B,
313
    0x3C,
314
    0x3D,
315
    0xFF,
316
    0xFF,
317
    0xFF,
318
    0xFF,
319
    0xFF,
320
};
321
322
#ifndef CHARSET_EBCDIC
323
static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
324
0
{
325
0
    if (a & 0x80)
326
0
        return B64_ERROR;
327
0
    return table[a];
328
0
}
329
#else
330
static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table)
331
{
332
    a = os_toascii[a];
333
    if (a & 0x80)
334
        return B64_ERROR;
335
    return table[a];
336
}
337
#endif
338
339
EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
340
0
{
341
0
    return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX));
342
0
}
343
344
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
345
0
{
346
0
    OPENSSL_free(ctx);
347
0
}
348
349
int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, const EVP_ENCODE_CTX *sctx)
350
0
{
351
0
    memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX));
352
353
0
    return 1;
354
0
}
355
356
int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx)
357
0
{
358
0
    return ctx->num;
359
0
}
360
361
void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags)
362
0
{
363
0
    ctx->flags = flags;
364
0
}
365
366
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
367
0
{
368
0
    ctx->num = 0;
369
0
    ctx->line_num = 0;
370
0
    ctx->flags = 0;
371
0
}
372
373
int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
374
    const unsigned char *in, int inl)
375
0
{
376
0
    int i, j;
377
0
    size_t total = 0;
378
379
0
    *outl = 0;
380
0
    if (inl <= 0)
381
0
        return 0;
382
0
    assert(EVP_ENCODE_B64_LENGTH <= (int)sizeof(ctx->enc_data));
383
0
    if (EVP_ENCODE_B64_LENGTH - ctx->num > inl) {
384
0
        memcpy(&(ctx->enc_data[ctx->num]), in, inl);
385
0
        ctx->num += inl;
386
0
        return 1;
387
0
    }
388
0
    if (ctx->num != 0) {
389
0
        i = EVP_ENCODE_B64_LENGTH - ctx->num;
390
0
        memcpy(&(ctx->enc_data[ctx->num]), in, i);
391
0
        in += i;
392
0
        inl -= i;
393
0
        int wrap_cnt = 0;
394
0
        j = evp_encodeblock_int(ctx, out, ctx->enc_data, EVP_ENCODE_B64_LENGTH,
395
0
            &wrap_cnt);
396
0
        ctx->num = 0;
397
0
        out += j;
398
0
        total = j;
399
0
        *out = '\0';
400
0
    }
401
0
    int wrap_cnt = 0;
402
0
    if (EVP_ENCODE_B64_LENGTH % 3 != 0) {
403
0
        j = evp_encodeblock_int(ctx, out, in, inl - (inl % EVP_ENCODE_B64_LENGTH),
404
0
            &wrap_cnt);
405
0
    } else {
406
#if defined(__AVX2__)
407
        const int newlines = !(ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) ? EVP_ENCODE_B64_LENGTH : 0;
408
409
        j = encode_base64_avx2(ctx,
410
            (unsigned char *)out,
411
            (const unsigned char *)in,
412
            inl - (inl % EVP_ENCODE_B64_LENGTH), newlines, &wrap_cnt);
413
#elif defined(HAS_IA32CAP_IS_64)
414
        if ((OPENSSL_ia32cap_P[2] & (1u << 5)) != 0) {
415
            const int newlines = !(ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) ? EVP_ENCODE_B64_LENGTH : 0;
416
417
            j = encode_base64_avx2(ctx,
418
                (unsigned char *)out,
419
                (const unsigned char *)in,
420
                inl - (inl % EVP_ENCODE_B64_LENGTH), newlines, &wrap_cnt);
421
        } else {
422
            j = evp_encodeblock_int(ctx, out, in, inl - (inl % EVP_ENCODE_B64_LENGTH),
423
                &wrap_cnt);
424
        }
425
#else
426
0
        j = evp_encodeblock_int(ctx, out, in, inl - (inl % EVP_ENCODE_B64_LENGTH),
427
0
            &wrap_cnt);
428
0
#endif
429
0
    }
430
0
    in += inl - (inl % EVP_ENCODE_B64_LENGTH);
431
0
    inl -= inl - (inl % EVP_ENCODE_B64_LENGTH);
432
0
    out += j;
433
0
    total += j;
434
0
    if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0 && EVP_ENCODE_B64_LENGTH % 3 != 0) {
435
0
        *(out++) = '\n';
436
0
        total++;
437
0
    }
438
0
    *out = '\0';
439
0
    if (total > INT_MAX) {
440
        /* Too much output data! */
441
0
        *outl = 0;
442
0
        return 0;
443
0
    }
444
0
    if (inl != 0)
445
0
        memcpy(&(ctx->enc_data[0]), in, inl);
446
0
    ctx->num = inl;
447
0
    *outl = (int)total;
448
449
0
    return 1;
450
0
}
451
452
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
453
0
{
454
0
    int ret = 0;
455
0
    int wrap_cnt = 0;
456
457
0
    if (ctx->num != 0) {
458
0
        ret = evp_encodeblock_int(ctx, out, ctx->enc_data, ctx->num,
459
0
            &wrap_cnt);
460
0
        if (ossl_assert(ret >= 0)) {
461
0
            if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
462
0
                out[ret++] = '\n';
463
0
            out[ret] = '\0';
464
0
            ctx->num = 0;
465
0
        }
466
0
    }
467
0
    *outl = ret;
468
0
}
469
470
int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
471
0
{
472
0
    int wrap_cnt = 0;
473
474
#if defined(__AVX2__)
475
    return encode_base64_avx2(NULL, t, f, dlen, 0, &wrap_cnt);
476
#elif defined(HAS_IA32CAP_IS_64)
477
    if ((OPENSSL_ia32cap_P[2] & (1u << 5)) != 0)
478
        return encode_base64_avx2(NULL, t, f, dlen, 0, &wrap_cnt);
479
    else
480
        return evp_encodeblock_int(NULL, t, f, dlen, &wrap_cnt);
481
#else
482
0
    return evp_encodeblock_int(NULL, t, f, dlen, &wrap_cnt);
483
0
#endif
484
0
}
485
486
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
487
0
{
488
    /* Only ctx->num and ctx->flags are used during decoding. */
489
0
    ctx->num = 0;
490
0
    ctx->line_num = 0;
491
0
    ctx->flags = 0;
492
0
}
493
494
/*-
495
 * -1 for error
496
 *  0 for last line
497
 *  1 for full line
498
 *
499
 * Note: even though EVP_DecodeUpdate attempts to detect and report end of
500
 * content, the context doesn't currently remember it and will accept more data
501
 * in the next call. Therefore, the caller is responsible for checking and
502
 * rejecting a 0 return value in the middle of content.
503
 *
504
 * Note: even though EVP_DecodeUpdate has historically tried to detect end of
505
 * content based on line length, this has never worked properly. Therefore,
506
 * we now return 0 when one of the following is true:
507
 *   - Padding or B64_EOF was detected and the last block is complete.
508
 *   - Input has zero-length.
509
 * -1 is returned if:
510
 *   - Invalid characters are detected.
511
 *   - There is extra trailing padding, or data after padding.
512
 *   - B64_EOF is detected after an incomplete base64 block.
513
 */
514
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
515
    const unsigned char *in, int inl)
516
0
{
517
0
    int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
518
0
    unsigned char *d;
519
0
    const unsigned char *table;
520
521
0
    n = ctx->num;
522
0
    d = ctx->enc_data;
523
524
0
    if (n > 0 && d[n - 1] == '=') {
525
0
        eof++;
526
0
        if (n > 1 && d[n - 2] == '=')
527
0
            eof++;
528
0
    }
529
530
    /* Legacy behaviour: an empty input chunk signals end of input. */
531
0
    if (inl == 0) {
532
0
        rv = 0;
533
0
        goto end;
534
0
    }
535
536
0
    if ((ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
537
0
        table = srpdata_ascii2bin;
538
0
    else
539
0
        table = data_ascii2bin;
540
541
0
    for (i = 0; i < inl; i++) {
542
0
        tmp = *(in++);
543
0
        v = conv_ascii2bin(tmp, table);
544
0
        if (v == B64_ERROR) {
545
0
            rv = -1;
546
0
            goto end;
547
0
        }
548
549
0
        if (tmp == '=') {
550
0
            eof++;
551
0
        } else if (eof > 0 && B64_BASE64(v)) {
552
            /* More data after padding. */
553
0
            rv = -1;
554
0
            goto end;
555
0
        }
556
557
0
        if (eof > 2) {
558
0
            rv = -1;
559
0
            goto end;
560
0
        }
561
562
0
        if (v == B64_EOF) {
563
0
            seof = 1;
564
0
            goto tail;
565
0
        }
566
567
        /* Only save valid base64 characters. */
568
0
        if (B64_BASE64(v)) {
569
0
            if (n >= 64) {
570
                /*
571
                 * We increment n once per loop, and empty the buffer as soon as
572
                 * we reach 64 characters, so this can only happen if someone's
573
                 * manually messed with the ctx. Refuse to write any more data.
574
                 */
575
0
                rv = -1;
576
0
                goto end;
577
0
            }
578
0
            OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
579
0
            d[n++] = tmp;
580
0
        }
581
582
0
        if (n == 64) {
583
0
            decoded_len = evp_decodeblock_int(ctx, out, d, n, eof);
584
0
            n = 0;
585
0
            if (decoded_len < 0 || (decoded_len == 0 && eof > 0)) {
586
0
                rv = -1;
587
0
                goto end;
588
0
            }
589
0
            ret += decoded_len;
590
0
            out += decoded_len;
591
0
        }
592
0
    }
593
594
    /*
595
     * Legacy behaviour: if the current line is a full base64-block (i.e., has
596
     * 0 mod 4 base64 characters), it is processed immediately. We keep this
597
     * behaviour as applications may not be calling EVP_DecodeFinal properly.
598
     */
599
0
tail:
600
0
    if (n > 0) {
601
0
        if ((n & 3) == 0) {
602
0
            decoded_len = evp_decodeblock_int(ctx, out, d, n, eof);
603
0
            n = 0;
604
0
            if (decoded_len < 0 || (decoded_len == 0 && eof > 0)) {
605
0
                rv = -1;
606
0
                goto end;
607
0
            }
608
0
            ret += decoded_len;
609
0
        } else if (seof) {
610
            /* EOF in the middle of a base64 block. */
611
0
            rv = -1;
612
0
            goto end;
613
0
        }
614
0
    }
615
616
0
    rv = seof || (n == 0 && eof) ? 0 : 1;
617
0
end:
618
    /* Legacy behaviour. This should probably rather be zeroed on error. */
619
0
    *outl = ret;
620
0
    ctx->num = n;
621
0
    return rv;
622
0
}
623
624
static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t,
625
    const unsigned char *f, int n,
626
    int eof)
627
0
{
628
0
    int i, ret = 0, a, b, c, d;
629
0
    unsigned long l;
630
0
    const unsigned char *table;
631
632
0
    if (eof < -1 || eof > 2)
633
0
        return -1;
634
635
0
    if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0)
636
0
        table = srpdata_ascii2bin;
637
0
    else
638
0
        table = data_ascii2bin;
639
640
    /* trim whitespace from the start of the line. */
641
0
    while ((n > 0) && (conv_ascii2bin(*f, table) == B64_WS)) {
642
0
        f++;
643
0
        n--;
644
0
    }
645
646
    /*
647
     * strip off stuff at the end of the line ascii2bin values B64_WS,
648
     * B64_EOLN, B64_EOLN and B64_EOF
649
     */
650
0
    while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1], table))))
651
0
        n--;
652
653
0
    if (n % 4 != 0)
654
0
        return -1;
655
0
    if (n == 0)
656
0
        return 0;
657
658
    /* all 4-byte blocks except the last one do not have padding. */
659
0
    for (i = 0; i < n - 4; i += 4) {
660
0
        a = conv_ascii2bin(*(f++), table);
661
0
        b = conv_ascii2bin(*(f++), table);
662
0
        c = conv_ascii2bin(*(f++), table);
663
0
        d = conv_ascii2bin(*(f++), table);
664
0
        if ((a | b | c | d) & 0x80)
665
0
            return -1;
666
0
        l = ((((unsigned long)a) << 18L) | (((unsigned long)b) << 12L) | (((unsigned long)c) << 6L) | (((unsigned long)d)));
667
0
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
668
0
        *(t++) = (unsigned char)(l >> 8L) & 0xff;
669
0
        *(t++) = (unsigned char)(l) & 0xff;
670
0
        ret += 3;
671
0
    }
672
673
    /* process the last block that may have padding. */
674
0
    a = conv_ascii2bin(*(f++), table);
675
0
    b = conv_ascii2bin(*(f++), table);
676
0
    c = conv_ascii2bin(*(f++), table);
677
0
    d = conv_ascii2bin(*(f++), table);
678
0
    if ((a | b | c | d) & 0x80)
679
0
        return -1;
680
0
    l = ((((unsigned long)a) << 18L) | (((unsigned long)b) << 12L) | (((unsigned long)c) << 6L) | (((unsigned long)d)));
681
682
0
    if (eof == -1)
683
0
        eof = (f[2] == '=') + (f[3] == '=');
684
685
0
    switch (eof) {
686
0
    case 2:
687
0
        *t = (unsigned char)(l >> 16L) & 0xff;
688
0
        break;
689
0
    case 1:
690
0
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
691
0
        *t = (unsigned char)(l >> 8L) & 0xff;
692
0
        break;
693
0
    case 0:
694
0
        *(t++) = (unsigned char)(l >> 16L) & 0xff;
695
0
        *(t++) = (unsigned char)(l >> 8L) & 0xff;
696
0
        *t = (unsigned char)(l) & 0xff;
697
0
        break;
698
0
    }
699
0
    ret += 3 - eof;
700
701
0
    return ret;
702
0
}
703
704
int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
705
0
{
706
0
    return evp_decodeblock_int(NULL, t, f, n, 0);
707
0
}
708
709
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
710
0
{
711
0
    int i;
712
713
0
    *outl = 0;
714
0
    if (ctx->num != 0) {
715
0
        i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num, -1);
716
0
        if (i < 0)
717
0
            return -1;
718
0
        ctx->num = 0;
719
0
        *outl = i;
720
0
        return 1;
721
0
    } else
722
0
        return 1;
723
0
}