Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-sp-math-all/wolfcrypt/src/coding.c
Line
Count
Source
1
/* coding.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#include <wolfssl/wolfcrypt/coding.h>
25
26
#ifndef NO_CODING
27
28
#ifndef NO_ASN
29
    #include <wolfssl/wolfcrypt/asn.h> /* For PEM_LINE_SZ */
30
#endif
31
#ifdef NO_INLINE
32
    #include <wolfssl/wolfcrypt/misc.h>
33
#else
34
    #define WOLFSSL_MISC_INCLUDED
35
    #include <wolfcrypt/src/misc.c>
36
#endif
37
38
enum {
39
    BAD         = 0xFF,  /* invalid encoding */
40
    PAD         = '=',
41
    BASE64_MIN  = 0x2B,
42
    BASE16_MIN  = 0x30
43
};
44
45
46
#ifndef BASE64_LINE_SZ
47
    #ifdef NO_ASN
48
        #define BASE64_LINE_SZ 64
49
    #else
50
18.4M
        #define BASE64_LINE_SZ PEM_LINE_SZ
51
    #endif
52
#endif
53
54
#ifdef WOLFSSL_BASE64_DECODE
55
56
static WC_INLINE byte Base64_Char2Val_CT(byte c)
57
12.1M
{
58
12.1M
    int v;
59
12.1M
    int smallEnd   = (int)c - 0x7b;
60
12.1M
    int smallStart = (int)c - 0x61;
61
12.1M
    int bigEnd     = (int)c - 0x5b;
62
12.1M
    int bigStart   = (int)c - 0x41;
63
12.1M
    int numEnd     = (int)c - 0x3a;
64
12.1M
    int numStart   = (int)c - 0x30;
65
12.1M
    int slashEnd   = (int)c - 0x30;
66
12.1M
    int slashStart = (int)c - 0x2f;
67
12.1M
    int plusEnd    = (int)c - 0x2c;
68
12.1M
    int plusStart  = (int)c - 0x2b;
69
70
12.1M
    v  = ((smallStart >> 8) ^ (smallEnd >> 8)) & (smallStart + 26 + 1);
71
12.1M
    v |= ((bigStart   >> 8) ^ (bigEnd   >> 8)) & (bigStart   +  0 + 1);
72
12.1M
    v |= ((numStart   >> 8) ^ (numEnd   >> 8)) & (numStart   + 52 + 1);
73
12.1M
    v |= ((slashStart >> 8) ^ (slashEnd >> 8)) & (slashStart + 63 + 1);
74
12.1M
    v |= ((plusStart  >> 8) ^ (plusEnd  >> 8)) & (plusStart  + 62 + 1);
75
76
12.1M
    return WC_OCTET(v - 1);
77
12.1M
}
78
79
#ifndef BASE64_NO_TABLE
80
81
static
82
ALIGN64 const byte base64Decode_table[] = {    /* + starts at 0x2B */
83
/* 0x28:       + , - . / */                   62, BAD, BAD, BAD,  63,
84
/* 0x30: 0 1 2 3 4 5 6 7 */    52,  53,  54,  55,  56,  57,  58,  59,
85
/* 0x38: 8 9 : ; < = > ? */    60,  61, BAD, BAD, BAD, BAD, BAD, BAD,
86
/* 0x40: @ A B C D E F G */   BAD,   0,   1,   2,   3,   4,   5,   6,
87
/* 0x48: H I J K L M N O */     7,   8,   9,  10,  11,  12,  13,  14,
88
/* 0x50: P Q R S T U V W */    15,  16,  17,  18,  19,  20,  21,  22,
89
/* 0x58: X Y Z [ \ ] ^ _ */    23,  24,  25, BAD, BAD, BAD, BAD, BAD,
90
/* 0x60: ` a b c d e f g */   BAD,  26,  27,  28,  29,  30,  31,  32,
91
/* 0x68: h i j k l m n o */    33,  34,  35,  36,  37,  38,  39,  40,
92
/* 0x70: p q r s t u v w */    41,  42,  43,  44,  45,  46,  47,  48,
93
/* 0x78: x y z           */    49,  50,  51
94
                            };
95
20
#define BASE64DECODE_TABLE_SZ    (byte)(sizeof(base64Decode_table))
96
97
static WC_INLINE byte Base64_Char2Val_by_table(byte c)
98
33.6k
{
99
#ifdef WC_CACHE_RESISTANT_BASE64_TABLE
100
    /* 80 characters in table.
101
     * 64 bytes in a cache line - first line has 64, second has 16
102
     */
103
    byte v;
104
    byte mask;
105
106
    c = (byte)(c - BASE64_MIN);
107
    mask = (byte)((((byte)(0x3f - c)) >> 7) - 1);
108
    /* Load a value from the first cache line and use when mask set. */
109
    v  = (byte)(base64Decode_table[ c & 0x3f        ] &   mask);
110
    /* Load a value from the second cache line and use when mask not set. */
111
    v |= (byte)(base64Decode_table[(c & 0x0f) | 0x40] & (~mask));
112
113
    return v;
114
#else
115
33.6k
    return base64Decode_table[c - BASE64_MIN];
116
33.6k
#endif
117
33.6k
}
118
119
#endif /* !BASE64_NO_TABLE */
120
121
int Base64_SkipNewline(const byte* in, word32 *inLen,
122
  word32 *outJ)
123
12.9M
{
124
12.9M
    word32 len = *inLen;
125
12.9M
    word32 j = *outJ;
126
12.9M
    byte curChar;
127
128
12.9M
    if (len == 0) {
129
703
        return BUFFER_E;
130
703
    }
131
12.9M
    curChar = in[j];
132
133
14.1M
    while (len > 1 && curChar == ' ') {
134
        /* skip whitespace in the middle or end of line */
135
1.14M
        curChar = in[++j];
136
1.14M
        len--;
137
1.14M
    }
138
12.9M
    if (curChar == '\r' || curChar == '\n') {
139
933k
        j++;
140
933k
        len--;
141
933k
        if (curChar == '\r') {
142
17.4k
            if (len) {
143
16.4k
                curChar = in[j++];
144
16.4k
                len--;
145
16.4k
            }
146
17.4k
        }
147
933k
        if (curChar != '\n') {
148
1.23k
            WOLFSSL_MSG("Bad end of line in Base64 Decode");
149
1.23k
            return ASN_INPUT_E;
150
1.23k
        }
151
152
932k
        if (len) {
153
923k
            curChar = in[j];
154
923k
        }
155
932k
    }
156
13.0M
    while (len && curChar == ' ') {
157
53.6k
        if (--len > 0) {
158
52.3k
            curChar = in[++j];
159
52.3k
        }
160
53.6k
    }
161
12.9M
    if (!len) {
162
9.76k
        return BUFFER_E;
163
9.76k
    }
164
12.9M
    *inLen = len;
165
12.9M
    *outJ = j;
166
12.9M
    return 0;
167
12.9M
}
168
169
#ifndef BASE64_NO_TABLE
170
171
int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen)
172
20
{
173
20
    word32 i = 0;
174
20
    word32 j = 0;
175
20
    int ret;
176
20
    const byte maxIdx = BASE64DECODE_TABLE_SZ + BASE64_MIN - 1;
177
178
20
    if ((in == NULL && inLen > 0) || out == NULL || outLen == NULL)
179
0
        return BAD_FUNC_ARG;
180
181
8.44k
    while (inLen > 3) {
182
8.42k
        int pad3 = 0;
183
8.42k
        int pad4 = 0;
184
8.42k
        byte b1, b2, b3;
185
8.42k
        byte e1, e2, e3, e4;
186
187
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
188
0
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
189
                /* Running out of buffer here is not an error */
190
0
                break;
191
0
            }
192
0
            return ret;
193
0
        }
194
8.42k
        e1 = in[j++];
195
8.42k
        if (e1 == '\0') {
196
0
            inLen = 0;
197
0
            break;
198
0
        }
199
8.42k
        inLen--;
200
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
201
0
            return ret;
202
0
        }
203
8.42k
        e2 = in[j++];
204
8.42k
        inLen--;
205
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
206
0
            return ret;
207
0
        }
208
8.42k
        e3 = in[j++];
209
8.42k
        inLen--;
210
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
211
0
            return ret;
212
0
        }
213
8.42k
        e4 = in[j++];
214
8.42k
        inLen--;
215
216
8.42k
        if (e3 == PAD)
217
0
            pad3 = 1;
218
8.42k
        if (e4 == PAD)
219
0
            pad4 = 1;
220
221
8.42k
        if (pad3 && !pad4)
222
0
            return ASN_INPUT_E;
223
224
8.42k
        if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN ||
225
8.42k
                                                              e4 < BASE64_MIN) {
226
0
            WOLFSSL_MSG("Bad Base64 Decode data, too small");
227
0
            return ASN_INPUT_E;
228
0
        }
229
230
8.42k
        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
231
0
            WOLFSSL_MSG("Bad Base64 Decode data, too big");
232
0
            return ASN_INPUT_E;
233
0
        }
234
235
8.42k
        e1 = Base64_Char2Val_by_table(e1);
236
8.42k
        e2 = Base64_Char2Val_by_table(e2);
237
8.42k
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_by_table(e3));
238
8.42k
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_by_table(e4));
239
240
8.42k
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
241
0
            WOLFSSL_MSG("Bad Base64 Decode bad character");
242
0
            return ASN_INPUT_E;
243
0
        }
244
245
8.42k
        if (i + 1 + !pad3 + !pad4 > *outLen) {
246
0
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
247
0
            return BUFFER_E;
248
0
        }
249
250
8.42k
        b1 = (byte)((e1 << 2) | (e2 >> 4));
251
8.42k
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
252
8.42k
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
253
254
8.42k
        out[i++] = b1;
255
8.42k
        if (!pad3)
256
8.42k
            out[i++] = b2;
257
8.42k
        if (!pad4)
258
8.42k
            out[i++] = b3;
259
0
        else
260
0
            break;
261
8.42k
    }
262
263
    /* If there is still input available, and it's not whitespace or nulls, then
264
     * the input is invalid.
265
     */
266
20
    while (inLen > 0) {
267
20
        word32 cur_j = j;
268
20
        if (in[j] == 0)
269
0
            break;
270
20
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
271
20
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
272
                /* Running out of buffer here is not an error */
273
20
                break;
274
20
            }
275
0
            return ret;
276
20
        }
277
0
        if (j == cur_j)
278
0
            return ASN_INPUT_E;
279
0
    }
280
281
    /* If the output buffer has a room for an extra byte, add a null terminator */
282
20
    if (*outLen > i)
283
20
        out[i]= '\0';
284
285
    /* Note, *outLen won't reflect the optional terminating null. */
286
20
    *outLen = i;
287
288
20
    return 0;
289
20
}
290
291
#endif /* !BASE64_NO_TABLE */
292
293
int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
294
31.7k
{
295
31.7k
    word32 i = 0;
296
31.7k
    word32 j = 0;
297
31.7k
    int ret;
298
299
31.7k
    if ((in == NULL && inLen > 0) || out == NULL || outLen == NULL)
300
0
        return BAD_FUNC_ARG;
301
302
3.05M
    while (inLen > 3) {
303
3.03M
        int pad3 = 0;
304
3.03M
        int pad4 = 0;
305
3.03M
        byte b1, b2, b3;
306
3.03M
        byte e1, e2, e3, e4;
307
308
3.03M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
309
678
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
310
                /* Running out of buffer here is not an error */
311
448
                break;
312
448
            }
313
230
            return ret;
314
678
        }
315
3.03M
        e1 = in[j++];
316
3.03M
        if (e1 == '\0') {
317
8
            inLen = 0;
318
8
            break;
319
8
        }
320
3.03M
        inLen--;
321
3.03M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
322
837
            return ret;
323
837
        }
324
3.03M
        e2 = in[j++];
325
3.03M
        inLen--;
326
3.03M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
327
938
            return ret;
328
938
        }
329
3.03M
        e3 = in[j++];
330
3.03M
        inLen--;
331
3.03M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
332
1.03k
            return ret;
333
1.03k
        }
334
3.03M
        e4 = in[j++];
335
3.03M
        inLen--;
336
337
3.03M
        if (e3 == PAD)
338
8.64k
            pad3 = 1;
339
3.03M
        if (e4 == PAD)
340
10.4k
            pad4 = 1;
341
342
3.03M
        if (pad3 && !pad4)
343
238
            return ASN_INPUT_E;
344
345
3.03M
        e1 = Base64_Char2Val_CT(e1);
346
3.03M
        e2 = Base64_Char2Val_CT(e2);
347
3.03M
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_CT(e3));
348
3.03M
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_CT(e4));
349
350
3.03M
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
351
1.69k
            WOLFSSL_MSG("Bad Base64 Decode bad character");
352
1.69k
            return ASN_INPUT_E;
353
1.69k
        }
354
355
        /* Output space check needs to follow input character validation to
356
         * assure ASN_INPUT_E is returned on truncated input with the
357
         * terminating null included in the input buffer.
358
         */
359
3.03M
        if (i + 1 + !pad3 + !pad4 > *outLen) {
360
2
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
361
2
            return BUFFER_E;
362
2
        }
363
364
3.03M
        b1 = (byte)((e1 << 2) | (e2 >> 4));
365
3.03M
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
366
3.03M
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
367
368
3.03M
        out[i++] = b1;
369
3.03M
        if (!pad3)
370
3.02M
            out[i++] = b2;
371
3.03M
        if (!pad4)
372
3.02M
            out[i++] = b3;
373
10.3k
        else
374
10.3k
            break;
375
3.03M
    }
376
377
    /* If there is still input available, and it's not whitespace or nulls, then
378
     * the input is invalid.
379
     */
380
831k
    while (inLen > 0) {
381
814k
        word32 cur_j = j;
382
814k
        if (in[j] == 0)
383
10
            break;
384
814k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
385
8.19k
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
386
                /* Running out of buffer here is not an error */
387
7.95k
                break;
388
7.95k
            }
389
236
            return ret;
390
8.19k
        }
391
805k
        if (j == cur_j)
392
899
            return ASN_INPUT_E;
393
805k
    }
394
395
    /* If the output buffer has a room for an extra byte, add a null terminator */
396
25.6k
    if (*outLen > i)
397
25.6k
        out[i]= '\0';
398
399
    /* Note, *outLen won't reflect the optional terminating null. */
400
25.6k
    *outLen = i;
401
402
25.6k
    return 0;
403
26.7k
}
404
405
#ifdef BASE64_NO_TABLE
406
int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen) {
407
    return Base64_Decode(in, inLen, out, outLen);
408
}
409
#endif /* BASE64_NO_TABLE */
410
411
#endif /* WOLFSSL_BASE64_DECODE */
412
413
#if defined(WOLFSSL_BASE64_ENCODE)
414
415
static
416
const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
417
                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
418
                              'U', 'V', 'W', 'X', 'Y', 'Z',
419
                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
420
                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
421
                              'u', 'v', 'w', 'x', 'y', 'z',
422
                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
423
                              '+', '/'
424
                            };
425
426
427
/* make sure *i (idx) won't exceed max, store and possibly escape to out,
428
 * raw means use e w/o decode,  0 on success */
429
static int CEscape(int escaped, byte e, byte* out, word32* i, word32 maxSz,
430
                  int raw, int getSzOnly)
431
78.8M
{
432
78.8M
    int    doEscape = 0;
433
78.8M
    word32 needed = 1;
434
78.8M
    word32 idx = *i;
435
436
78.8M
    byte basic;
437
78.8M
    byte plus    = 0;
438
78.8M
    byte equals  = 0;
439
78.8M
    byte newline = 0;
440
441
78.8M
    if (raw)
442
1.17M
        basic = e;
443
77.6M
    else if (e < sizeof(base64Encode))
444
77.6M
        basic = base64Encode[e];
445
0
    else
446
0
        return BAD_FUNC_ARG;
447
448
    /* check whether to escape. Only escape for EncodeEsc */
449
78.8M
    if (escaped == WC_ESC_NL_ENC) {
450
4.40M
        switch ((char)basic) {
451
665k
            case '+' :
452
665k
                plus     = 1;
453
665k
                doEscape = 1;
454
665k
                needed  += 2;
455
665k
                break;
456
85
            case '=' :
457
85
                equals   = 1;
458
85
                doEscape = 1;
459
85
                needed  += 2;
460
85
                break;
461
67.9k
            case '\n' :
462
67.9k
                newline  = 1;
463
67.9k
                doEscape = 1;
464
67.9k
                needed  += 2;
465
67.9k
                break;
466
3.67M
            default:
467
                /* do nothing */
468
3.67M
                break;
469
4.40M
        }
470
4.40M
    }
471
472
    /* check size */
473
78.8M
    if ( (idx+needed) > maxSz && !getSzOnly) {
474
32
        WOLFSSL_MSG("Escape buffer max too small");
475
32
        return BUFFER_E;
476
32
    }
477
478
    /* store it */
479
78.8M
    if (doEscape == 0) {
480
78.0M
        if(getSzOnly)
481
35.0M
            idx++;
482
43.0M
        else
483
43.0M
            out[idx++] = basic;
484
78.0M
    }
485
733k
    else {
486
733k
        if(getSzOnly)
487
0
            idx+=3;
488
733k
        else {
489
733k
            out[idx++] = '%';  /* start escape */
490
491
733k
            if (plus) {
492
665k
                out[idx++] = '2';
493
665k
                out[idx++] = 'B';
494
665k
            }
495
67.9k
            else if (equals) {
496
82
                out[idx++] = '3';
497
82
                out[idx++] = 'D';
498
82
            }
499
67.9k
            else if (newline) {
500
67.9k
                out[idx++] = '0';
501
67.9k
                out[idx++] = 'A';
502
67.9k
            }
503
733k
        }
504
733k
    }
505
78.8M
    *i = idx;
506
507
78.8M
    return 0;
508
78.8M
}
509
510
511
/* internal worker, handles both escaped and normal line endings.
512
   If out buffer is NULL, will return sz needed in outLen */
513
static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
514
                           word32* outLen, int escaped)
515
14.3k
{
516
14.3k
    int    ret = 0;
517
14.3k
    word32 i = 0,
518
14.3k
           j = 0,
519
14.3k
           n = 0;   /* new line counter */
520
521
14.3k
    int    getSzOnly = (out == NULL);
522
523
14.3k
    word32 outSz;
524
14.3k
    word32 addSz;
525
526
14.3k
    if (in == NULL && inLen > 0)
527
0
        return BAD_FUNC_ARG;
528
529
    /* Reject lengths that would wrap the encoded-size calculation below. */
530
14.3k
    if (inLen >= (WOLFSSL_MAX_32BIT / 4))
531
0
        return BAD_FUNC_ARG;
532
533
14.3k
    outSz = (inLen + 3 - 1) / 3 * 4;
534
14.3k
    addSz = (outSz + BASE64_LINE_SZ - 1) / BASE64_LINE_SZ;  /* new lines */
535
536
14.3k
    if (escaped == WC_ESC_NL_ENC)
537
145
        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
538
14.1k
    else if (escaped == WC_NO_NL_ENC)
539
36
        addSz = 0;    /* encode without \n */
540
541
14.3k
    outSz += addSz;
542
543
    /* if escaped we can't predetermine size for one pass encoding, but
544
     * make sure we have enough if no escapes are in input
545
     * Also need to ensure outLen valid before dereference */
546
14.3k
    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
547
548
19.4M
    while (inLen > 2) {
549
19.4M
        byte b1 = in[j++];
550
19.4M
        byte b2 = in[j++];
551
19.4M
        byte b3 = in[j++];
552
553
        /* encoded idx */
554
19.4M
        byte e1 = b1 >> 2;
555
19.4M
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
556
19.4M
        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
557
19.4M
        byte e4 = b3 & 0x3F;
558
559
        /* store */
560
19.4M
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
561
19.4M
        if (ret != 0) break;
562
19.4M
        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
563
19.4M
        if (ret != 0) break;
564
19.4M
        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
565
19.4M
        if (ret != 0) break;
566
19.4M
        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
567
19.4M
        if (ret != 0) break;
568
569
19.4M
        inLen -= 3;
570
571
        /* Insert newline after BASE64_LINE_SZ, unless no \n requested */
572
19.4M
        if (escaped != WC_NO_NL_ENC && (++n % (BASE64_LINE_SZ/4)) == 0 && inLen) {
573
1.14M
            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
574
1.14M
            if (ret != 0) break;
575
1.14M
        }
576
19.4M
    }
577
578
    /* last integral */
579
14.3k
    if (inLen && ret == 0) {
580
11.1k
        int twoBytes = (inLen == 2);
581
582
11.1k
        byte b1 = in[j++];
583
11.1k
        byte b2 = (twoBytes) ? in[j++] : 0;
584
585
11.1k
        byte e1 = b1 >> 2;
586
11.1k
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
587
11.1k
        byte e3 = (byte)((b2 & 0xF) << 2);
588
589
11.1k
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
590
11.1k
        if (ret == 0)
591
11.1k
            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
592
11.1k
        if (ret == 0) {
593
            /* third */
594
11.1k
            if (twoBytes)
595
8.31k
                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
596
2.82k
            else
597
2.82k
                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
598
11.1k
        }
599
        /* fourth always pad */
600
11.1k
        if (ret == 0)
601
11.1k
            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
602
11.1k
    }
603
604
14.3k
    if (ret == 0 && escaped != WC_NO_NL_ENC)
605
14.2k
        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
606
607
14.3k
    if (i != outSz && escaped != 1 && ret == 0)
608
2
        return ASN_INPUT_E;
609
/* If the output buffer has a room for an extra byte, add a null terminator */
610
14.3k
    if (out && *outLen > i)
611
210
        out[i]= '\0';
612
613
14.3k
    *outLen = i;
614
615
14.3k
    if (ret == 0)
616
14.2k
        return getSzOnly ? WC_NO_ERR_TRACE(LENGTH_ONLY_E) : 0;
617
618
32
    return ret;
619
14.3k
}
620
621
622
/* Base64 Encode, PEM style, with \n line endings */
623
int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
624
14.1k
{
625
14.1k
    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
626
14.1k
}
627
628
629
/* Base64 Encode, with %0A escaped line endings instead of \n */
630
int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
631
145
{
632
145
    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
633
145
}
634
635
int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
636
36
{
637
36
    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
638
36
}
639
640
#endif /* WOLFSSL_BASE64_ENCODE */
641
642
643
#ifdef WOLFSSL_BASE16
644
645
static
646
const ALIGN64 byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
647
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD,
648
                           10, 11, 12, 13, 14, 15,  /* upper case A-F */
649
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
650
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
651
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
652
                           BAD, BAD,  /* G - ` */
653
                           10, 11, 12, 13, 14, 15   /* lower case a-f */
654
                         };  /* A starts at 0x41 not 0x3A */
655
656
int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
657
113
{
658
113
    word32 inIdx  = 0;
659
113
    word32 outIdx = 0;
660
661
113
    if (in == NULL || out == NULL || outLen == NULL)
662
0
        return BAD_FUNC_ARG;
663
664
113
    if (inLen == 1 && *outLen) {
665
28
        byte b = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
666
667
        /* sanity check */
668
28
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
669
14
            return ASN_INPUT_E;
670
671
14
        b  = hexDecode[b];
672
673
14
        if (b == BAD)
674
7
            return ASN_INPUT_E;
675
676
7
        out[outIdx++] = b;
677
678
7
        *outLen = outIdx;
679
7
        return 0;
680
14
    }
681
682
85
    if (inLen % 2)
683
1
        return BAD_FUNC_ARG;
684
685
84
    if (*outLen < (inLen / 2))
686
2
        return BUFFER_E;
687
688
493
    while (inLen) {
689
448
        byte b  = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
690
448
        byte b2 = (byte)(in[inIdx++] - BASE16_MIN);
691
692
        /* sanity checks */
693
448
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
694
18
            return ASN_INPUT_E;
695
430
        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
696
7
            return ASN_INPUT_E;
697
698
423
        b  = hexDecode[b];
699
423
        b2 = hexDecode[b2];
700
701
423
        if (b == BAD || b2 == BAD)
702
12
            return ASN_INPUT_E;
703
704
411
        out[outIdx++] = (byte)((b << 4) | b2);
705
411
        inLen -= 2;
706
411
    }
707
708
45
    *outLen = outIdx;
709
45
    return 0;
710
82
}
711
712
static
713
const ALIGN64 byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7',
714
                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
715
};
716
717
int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
718
62
{
719
62
    word32 outIdx = 0;
720
62
    word32 i;
721
722
62
    if (in == NULL || out == NULL || outLen == NULL)
723
0
        return BAD_FUNC_ARG;
724
725
62
    if (inLen > (WOLFSSL_MAX_32BIT / 2))
726
0
        return BAD_FUNC_ARG;
727
728
62
    if (*outLen < (2 * inLen))
729
1
        return BAD_FUNC_ARG;
730
731
548k
    for (i = 0; i < inLen; i++) {
732
548k
        byte hb = in[i] >> 4;
733
548k
        byte lb = in[i] & 0x0f;
734
735
548k
        hb = hexEncode[hb];
736
548k
        lb = hexEncode[lb];
737
738
548k
        out[outIdx++] = hb;
739
548k
        out[outIdx++] = lb;
740
548k
    }
741
742
    /* If the output buffer has a room for an extra byte, add a null terminator */
743
61
    if (*outLen > outIdx)
744
60
        out[outIdx++]= '\0';
745
746
61
    *outLen = outIdx;
747
61
    return 0;
748
62
}
749
750
#endif /* WOLFSSL_BASE16 */
751
752
#endif /* !NO_CODING */
753
754
#ifdef WOLFSSL_UTF8_DECODE
755
756
/**
757
 * Decode the UTF-8 encoding of one code point.
758
 *
759
 * The encodings that RFC 3629 Sec. 3 requires a decoder to reject are
760
 * rejected: overlong forms, the code points reserved for UTF-16 surrogates,
761
 * code points past the end of the Unicode range, the five and six octet forms
762
 * that RFC 3629 removed, and sequences whose continuation octets are missing
763
 * or malformed. Any of these decoding to a character would let one octet
764
 * sequence impersonate another.
765
 *
766
 * *inOutIdx only moves when a code point is decoded, so a caller that wants to
767
 * keep going after a bad sequence is free to choose how far to skip.
768
 *
769
 * @param [in]      in        Buffer holding UTF-8 encoded text.
770
 * @param [in]      inLen     Length of buffer in octets.
771
 * @param [in, out] inOutIdx  On in, index of the first octet to decode.
772
 *                            On out, index of the first octet after the code
773
 *                            point decoded.
774
 * @param [out]     cp        Code point decoded.
775
 * @return  0 on success.
776
 * @return  BAD_FUNC_ARG when in, inOutIdx or cp is NULL.
777
 * @return  BUFFER_E when no octets remain, or when the sequence needs more
778
 *          continuation octets than the buffer holds.
779
 * @return  ASN_INPUT_E when the octets are not a valid encoding of a code
780
 *          point.
781
 */
782
int wc_Utf8_DecodeChar(const byte* in, word32 inLen, word32* inOutIdx,
783
                       word32* cp)
784
0
{
785
0
    word32 idx;
786
0
    word32 c;
787
0
    word32 minCp;
788
0
    word32 need;
789
0
    word32 i;
790
791
0
    if ((in == NULL) || (inOutIdx == NULL) || (cp == NULL)) {
792
0
        return BAD_FUNC_ARG;
793
0
    }
794
795
0
    idx = *inOutIdx;
796
0
    if (idx >= inLen) {
797
0
        return BUFFER_E;
798
0
    }
799
800
0
    c = in[idx];
801
0
    if (c < 0x80U) {
802
        /* 0xxxxxxx: the octet is the code point. */
803
0
        *inOutIdx = idx + 1U;
804
0
        *cp = c;
805
0
        return 0;
806
0
    }
807
808
    /* Take the code point bits out of the lead octet and note how many
809
     * continuation octets follow and the smallest code point that the form is
810
     * allowed to carry. */
811
0
    if ((c & 0xE0U) == 0xC0U) {
812
0
        need = 1U;
813
0
        minCp = 0x80U;
814
0
        c &= 0x1FU;
815
0
    }
816
0
    else if ((c & 0xF0U) == 0xE0U) {
817
0
        need = 2U;
818
0
        minCp = 0x800U;
819
0
        c &= 0x0FU;
820
0
    }
821
0
    else if ((c & 0xF8U) == 0xF0U) {
822
0
        need = 3U;
823
0
        minCp = 0x10000U;
824
0
        c &= 0x07U;
825
0
    }
826
0
    else {
827
        /* A continuation octet with no lead, or a lead octet of one of the
828
         * longer forms that are no longer part of UTF-8. */
829
0
        return ASN_INPUT_E;
830
0
    }
831
832
    /* Every continuation octet must be in the buffer. */
833
0
    if ((inLen - idx) <= need) {
834
0
        return BUFFER_E;
835
0
    }
836
0
    for (i = 1; i <= need; i++) {
837
        /* 10xxxxxx. */
838
0
        if ((in[idx + i] & 0xC0U) != 0x80U) {
839
0
            return ASN_INPUT_E;
840
0
        }
841
0
        c = (c << 6U) | (word32)(in[idx + i] & 0x3FU);
842
0
    }
843
844
0
    if ((c < minCp) || (c > WC_UNICODE_MAX_CODEPOINT) ||
845
0
            ((c >= WC_UTF16_HI_SURROGATE_MIN) &&
846
0
             (c <= WC_UTF16_LO_SURROGATE_MAX))) {
847
0
        return ASN_INPUT_E;
848
0
    }
849
850
0
    *inOutIdx = idx + need + 1U;
851
0
    *cp = c;
852
0
    return 0;
853
0
}
854
855
#endif /* WOLFSSL_UTF8_DECODE */
856
857
/* An empty translation unit is a constraint violation in C89, so emit a
858
 * harmless typedef to keep it well-formed in case everything above is
859
 * compiled out. */
860
typedef int wolfssl_coding_dummy_decl;