Coverage Report

Created: 2026-04-08 06:20

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