Coverage Report

Created: 2026-01-07 06:10

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