Coverage Report

Created: 2026-07-22 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-fastmath/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
#ifndef NO_CODING
25
26
#include <wolfssl/wolfcrypt/coding.h>
27
#ifndef NO_ASN
28
    #include <wolfssl/wolfcrypt/asn.h> /* For PEM_LINE_SZ */
29
#endif
30
#ifdef NO_INLINE
31
    #include <wolfssl/wolfcrypt/misc.h>
32
#else
33
    #define WOLFSSL_MISC_INCLUDED
34
    #include <wolfcrypt/src/misc.c>
35
#endif
36
37
enum {
38
    BAD         = 0xFF,  /* invalid encoding */
39
    PAD         = '=',
40
    BASE64_MIN  = 0x2B,
41
    BASE16_MIN  = 0x30
42
};
43
44
45
#ifndef BASE64_LINE_SZ
46
    #ifdef NO_ASN
47
        #define BASE64_LINE_SZ 64
48
    #else
49
21.1M
        #define BASE64_LINE_SZ PEM_LINE_SZ
50
    #endif
51
#endif
52
53
#ifdef WOLFSSL_BASE64_DECODE
54
55
static WC_INLINE byte Base64_Char2Val_CT(byte c)
56
9.07M
{
57
9.07M
    int v;
58
9.07M
    int smallEnd   = (int)c - 0x7b;
59
9.07M
    int smallStart = (int)c - 0x61;
60
9.07M
    int bigEnd     = (int)c - 0x5b;
61
9.07M
    int bigStart   = (int)c - 0x41;
62
9.07M
    int numEnd     = (int)c - 0x3a;
63
9.07M
    int numStart   = (int)c - 0x30;
64
9.07M
    int slashEnd   = (int)c - 0x30;
65
9.07M
    int slashStart = (int)c - 0x2f;
66
9.07M
    int plusEnd    = (int)c - 0x2c;
67
9.07M
    int plusStart  = (int)c - 0x2b;
68
69
9.07M
    v  = ((smallStart >> 8) ^ (smallEnd >> 8)) & (smallStart + 26 + 1);
70
9.07M
    v |= ((bigStart   >> 8) ^ (bigEnd   >> 8)) & (bigStart   +  0 + 1);
71
9.07M
    v |= ((numStart   >> 8) ^ (numEnd   >> 8)) & (numStart   + 52 + 1);
72
9.07M
    v |= ((slashStart >> 8) ^ (slashEnd >> 8)) & (slashStart + 63 + 1);
73
9.07M
    v |= ((plusStart  >> 8) ^ (plusEnd  >> 8)) & (plusStart  + 62 + 1);
74
75
9.07M
    return (byte)(v - 1);
76
9.07M
}
77
78
#ifndef BASE64_NO_TABLE
79
80
static
81
ALIGN64 const byte base64Decode_table[] = {    /* + starts at 0x2B */
82
/* 0x28:       + , - . / */                   62, BAD, BAD, BAD,  63,
83
/* 0x30: 0 1 2 3 4 5 6 7 */    52,  53,  54,  55,  56,  57,  58,  59,
84
/* 0x38: 8 9 : ; < = > ? */    60,  61, BAD, BAD, BAD, BAD, BAD, BAD,
85
/* 0x40: @ A B C D E F G */   BAD,   0,   1,   2,   3,   4,   5,   6,
86
/* 0x48: H I J K L M N O */     7,   8,   9,  10,  11,  12,  13,  14,
87
/* 0x50: P Q R S T U V W */    15,  16,  17,  18,  19,  20,  21,  22,
88
/* 0x58: X Y Z [ \ ] ^ _ */    23,  24,  25, BAD, BAD, BAD, BAD, BAD,
89
/* 0x60: ` a b c d e f g */   BAD,  26,  27,  28,  29,  30,  31,  32,
90
/* 0x68: h i j k l m n o */    33,  34,  35,  36,  37,  38,  39,  40,
91
/* 0x70: p q r s t u v w */    41,  42,  43,  44,  45,  46,  47,  48,
92
/* 0x78: x y z           */    49,  50,  51
93
                            };
94
20
#define BASE64DECODE_TABLE_SZ    (byte)(sizeof(base64Decode_table))
95
96
static WC_INLINE byte Base64_Char2Val_by_table(byte c)
97
33.6k
{
98
#ifdef WC_CACHE_RESISTANT_BASE64_TABLE
99
    /* 80 characters in table.
100
     * 64 bytes in a cache line - first line has 64, second has 16
101
     */
102
    byte v;
103
    byte mask;
104
105
    c = (byte)(c - BASE64_MIN);
106
    mask = (byte)((((byte)(0x3f - c)) >> 7) - 1);
107
    /* Load a value from the first cache line and use when mask set. */
108
    v  = (byte)(base64Decode_table[ c & 0x3f        ] &   mask);
109
    /* Load a value from the second cache line and use when mask not set. */
110
    v |= (byte)(base64Decode_table[(c & 0x0f) | 0x40] & (~mask));
111
112
    return v;
113
#else
114
33.6k
    return base64Decode_table[c - BASE64_MIN];
115
33.6k
#endif
116
33.6k
}
117
118
#endif /* !BASE64_NO_TABLE */
119
120
int Base64_SkipNewline(const byte* in, word32 *inLen,
121
  word32 *outJ)
122
9.21M
{
123
9.21M
    word32 len = *inLen;
124
9.21M
    word32 j = *outJ;
125
9.21M
    byte curChar;
126
127
9.21M
    if (len == 0) {
128
696
        return BUFFER_E;
129
696
    }
130
9.21M
    curChar = in[j];
131
132
9.34M
    while (len > 1 && curChar == ' ') {
133
        /* skip whitespace in the middle or end of line */
134
132k
        curChar = in[++j];
135
132k
        len--;
136
132k
    }
137
9.21M
    if (len && (curChar == '\r' || curChar == '\n')) {
138
155k
        j++;
139
155k
        len--;
140
155k
        if (curChar == '\r') {
141
7.27k
            if (len) {
142
6.08k
                curChar = in[j++];
143
6.08k
                len--;
144
6.08k
            }
145
7.27k
        }
146
155k
        if (curChar != '\n') {
147
1.46k
            WOLFSSL_MSG("Bad end of line in Base64 Decode");
148
1.46k
            return ASN_INPUT_E;
149
1.46k
        }
150
151
153k
        if (len) {
152
150k
            curChar = in[j];
153
150k
        }
154
153k
    }
155
9.22M
    while (len && curChar == ' ') {
156
15.8k
        if (--len > 0) {
157
14.6k
            curChar = in[++j];
158
14.6k
        }
159
15.8k
    }
160
9.21M
    if (!len) {
161
4.21k
        return BUFFER_E;
162
4.21k
    }
163
9.20M
    *inLen = len;
164
9.20M
    *outJ = j;
165
9.20M
    return 0;
166
9.21M
}
167
168
#ifndef BASE64_NO_TABLE
169
170
int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen)
171
20
{
172
20
    word32 i = 0;
173
20
    word32 j = 0;
174
20
    int ret;
175
20
    const byte maxIdx = BASE64DECODE_TABLE_SZ + BASE64_MIN - 1;
176
177
20
    if ((in == NULL && inLen > 0) || out == NULL || outLen == NULL)
178
0
        return BAD_FUNC_ARG;
179
180
8.44k
    while (inLen > 3) {
181
8.42k
        int pad3 = 0;
182
8.42k
        int pad4 = 0;
183
8.42k
        byte b1, b2, b3;
184
8.42k
        byte e1, e2, e3, e4;
185
186
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
187
0
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
188
                /* Running out of buffer here is not an error */
189
0
                break;
190
0
            }
191
0
            return ret;
192
0
        }
193
8.42k
        e1 = in[j++];
194
8.42k
        if (e1 == '\0') {
195
0
            inLen = 0;
196
0
            break;
197
0
        }
198
8.42k
        inLen--;
199
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
200
0
            return ret;
201
0
        }
202
8.42k
        e2 = in[j++];
203
8.42k
        inLen--;
204
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
205
0
            return ret;
206
0
        }
207
8.42k
        e3 = in[j++];
208
8.42k
        inLen--;
209
8.42k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
210
0
            return ret;
211
0
        }
212
8.42k
        e4 = in[j++];
213
8.42k
        inLen--;
214
215
8.42k
        if (e3 == PAD)
216
0
            pad3 = 1;
217
8.42k
        if (e4 == PAD)
218
0
            pad4 = 1;
219
220
8.42k
        if (pad3 && !pad4)
221
0
            return ASN_INPUT_E;
222
223
8.42k
        if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN ||
224
8.42k
                                                              e4 < BASE64_MIN) {
225
0
            WOLFSSL_MSG("Bad Base64 Decode data, too small");
226
0
            return ASN_INPUT_E;
227
0
        }
228
229
8.42k
        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
230
0
            WOLFSSL_MSG("Bad Base64 Decode data, too big");
231
0
            return ASN_INPUT_E;
232
0
        }
233
234
8.42k
        e1 = Base64_Char2Val_by_table(e1);
235
8.42k
        e2 = Base64_Char2Val_by_table(e2);
236
8.42k
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_by_table(e3));
237
8.42k
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_by_table(e4));
238
239
8.42k
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
240
0
            WOLFSSL_MSG("Bad Base64 Decode bad character");
241
0
            return ASN_INPUT_E;
242
0
        }
243
244
8.42k
        if (i + 1 + !pad3 + !pad4 > *outLen) {
245
0
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
246
0
            return BUFFER_E;
247
0
        }
248
249
8.42k
        b1 = (byte)((e1 << 2) | (e2 >> 4));
250
8.42k
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
251
8.42k
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
252
253
8.42k
        out[i++] = b1;
254
8.42k
        if (!pad3)
255
8.42k
            out[i++] = b2;
256
8.42k
        if (!pad4)
257
8.42k
            out[i++] = b3;
258
0
        else
259
0
            break;
260
8.42k
    }
261
262
    /* If there is still input available, and it's not whitespace or nulls, then
263
     * the input is invalid.
264
     */
265
20
    while (inLen > 0) {
266
20
        word32 cur_j = j;
267
20
        if (in[j] == 0)
268
0
            break;
269
20
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
270
20
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
271
                /* Running out of buffer here is not an error */
272
20
                break;
273
20
            }
274
0
            return ret;
275
20
        }
276
0
        if (j == cur_j)
277
0
            return ASN_INPUT_E;
278
0
    }
279
280
    /* If the output buffer has a room for an extra byte, add a null terminator */
281
20
    if (out && *outLen > i)
282
20
        out[i]= '\0';
283
284
    /* Note, *outLen won't reflect the optional terminating null. */
285
20
    *outLen = i;
286
287
20
    return 0;
288
20
}
289
290
#endif /* !BASE64_NO_TABLE */
291
292
int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
293
29.0k
{
294
29.0k
    word32 i = 0;
295
29.0k
    word32 j = 0;
296
29.0k
    int ret;
297
298
29.0k
    if ((in == NULL && inLen > 0) || out == NULL || outLen == NULL)
299
0
        return BAD_FUNC_ARG;
300
301
2.29M
    while (inLen > 3) {
302
2.27M
        int pad3 = 0;
303
2.27M
        int pad4 = 0;
304
2.27M
        byte b1, b2, b3;
305
2.27M
        byte e1, e2, e3, e4;
306
307
2.27M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
308
781
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
309
                /* Running out of buffer here is not an error */
310
543
                break;
311
543
            }
312
238
            return ret;
313
781
        }
314
2.27M
        e1 = in[j++];
315
2.27M
        if (e1 == '\0') {
316
13
            inLen = 0;
317
13
            break;
318
13
        }
319
2.27M
        inLen--;
320
2.27M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
321
914
            return ret;
322
914
        }
323
2.27M
        e2 = in[j++];
324
2.27M
        inLen--;
325
2.27M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
326
1.04k
            return ret;
327
1.04k
        }
328
2.27M
        e3 = in[j++];
329
2.27M
        inLen--;
330
2.27M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
331
967
            return ret;
332
967
        }
333
2.27M
        e4 = in[j++];
334
2.27M
        inLen--;
335
336
2.27M
        if (e3 == PAD)
337
2.07k
            pad3 = 1;
338
2.27M
        if (e4 == PAD)
339
3.15k
            pad4 = 1;
340
341
2.27M
        if (pad3 && !pad4)
342
203
            return ASN_INPUT_E;
343
344
2.26M
        e1 = Base64_Char2Val_CT(e1);
345
2.26M
        e2 = Base64_Char2Val_CT(e2);
346
2.26M
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_CT(e3));
347
2.26M
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_CT(e4));
348
349
2.26M
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
350
1.48k
            WOLFSSL_MSG("Bad Base64 Decode bad character");
351
1.48k
            return ASN_INPUT_E;
352
1.48k
        }
353
354
        /* Output space check needs to follow input character validation to
355
         * assure ASN_INPUT_E is returned on truncated input with the
356
         * terminating null included in the input buffer.
357
         */
358
2.26M
        if (i + 1 + !pad3 + !pad4 > *outLen) {
359
4
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
360
4
            return BUFFER_E;
361
4
        }
362
363
2.26M
        b1 = (byte)((e1 << 2) | (e2 >> 4));
364
2.26M
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
365
2.26M
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
366
367
2.26M
        out[i++] = b1;
368
2.26M
        if (!pad3)
369
2.26M
            out[i++] = b2;
370
2.26M
        if (!pad4)
371
2.26M
            out[i++] = b3;
372
3.08k
        else
373
3.08k
            break;
374
2.26M
    }
375
376
    /* If there is still input available, and it's not whitespace or nulls, then
377
     * the input is invalid.
378
     */
379
110k
    while (inLen > 0) {
380
90.7k
        word32 cur_j = j;
381
90.7k
        if (in[j] == 0)
382
8
            break;
383
90.7k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
384
2.64k
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
385
                /* Running out of buffer here is not an error */
386
2.36k
                break;
387
2.36k
            }
388
280
            return ret;
389
2.64k
        }
390
88.0k
        if (j == cur_j)
391
1.57k
            return ASN_INPUT_E;
392
88.0k
    }
393
394
    /* If the output buffer has a room for an extra byte, add a null terminator */
395
22.3k
    if (out && *outLen > i)
396
22.3k
        out[i]= '\0';
397
398
    /* Note, *outLen won't reflect the optional terminating null. */
399
22.3k
    *outLen = i;
400
401
22.3k
    return 0;
402
24.1k
}
403
404
#ifdef BASE64_NO_TABLE
405
int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen) {
406
    return Base64_Decode(in, inLen, out, outLen);
407
}
408
#endif /* BASE64_NO_TABLE */
409
410
#endif /* WOLFSSL_BASE64_DECODE */
411
412
#if defined(WOLFSSL_BASE64_ENCODE)
413
414
static
415
const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
416
                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
417
                              'U', 'V', 'W', 'X', 'Y', 'Z',
418
                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
419
                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
420
                              'u', 'v', 'w', 'x', 'y', 'z',
421
                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
422
                              '+', '/'
423
                            };
424
425
426
/* make sure *i (idx) won't exceed max, store and possibly escape to out,
427
 * raw means use e w/o decode,  0 on success */
428
static int CEscape(int escaped, byte e, byte* out, word32* i, word32 maxSz,
429
                  int raw, int getSzOnly)
430
87.1M
{
431
87.1M
    int    doEscape = 0;
432
87.1M
    word32 needed = 1;
433
87.1M
    word32 idx = *i;
434
435
87.1M
    byte basic;
436
87.1M
    byte plus    = 0;
437
87.1M
    byte equals  = 0;
438
87.1M
    byte newline = 0;
439
440
87.1M
    if (raw)
441
1.34M
        basic = e;
442
85.8M
    else if (e < sizeof(base64Encode))
443
85.8M
        basic = base64Encode[e];
444
0
    else
445
0
        return BAD_FUNC_ARG;
446
447
    /* check whether to escape. Only escape for EncodeEsc */
448
87.1M
    if (escaped == WC_ESC_NL_ENC) {
449
6.11M
        switch ((char)basic) {
450
1.27M
            case '+' :
451
1.27M
                plus     = 1;
452
1.27M
                doEscape = 1;
453
1.27M
                needed  += 2;
454
1.27M
                break;
455
100
            case '=' :
456
100
                equals   = 1;
457
100
                doEscape = 1;
458
100
                needed  += 2;
459
100
                break;
460
94.1k
            case '\n' :
461
94.1k
                newline  = 1;
462
94.1k
                doEscape = 1;
463
94.1k
                needed  += 2;
464
94.1k
                break;
465
4.74M
            default:
466
                /* do nothing */
467
4.74M
                break;
468
6.11M
        }
469
6.11M
    }
470
471
    /* check size */
472
87.1M
    if ( (idx+needed) > maxSz && !getSzOnly) {
473
29
        WOLFSSL_MSG("Escape buffer max too small");
474
29
        return BUFFER_E;
475
29
    }
476
477
    /* store it */
478
87.1M
    if (doEscape == 0) {
479
85.8M
        if(getSzOnly)
480
37.9M
            idx++;
481
47.8M
        else
482
47.8M
            out[idx++] = basic;
483
85.8M
    }
484
1.37M
    else {
485
1.37M
        if(getSzOnly)
486
0
            idx+=3;
487
1.37M
        else {
488
1.37M
            out[idx++] = '%';  /* start escape */
489
490
1.37M
            if (plus) {
491
1.27M
                out[idx++] = '2';
492
1.27M
                out[idx++] = 'B';
493
1.27M
            }
494
94.2k
            else if (equals) {
495
96
                out[idx++] = '3';
496
96
                out[idx++] = 'D';
497
96
            }
498
94.1k
            else if (newline) {
499
94.1k
                out[idx++] = '0';
500
94.1k
                out[idx++] = 'A';
501
94.1k
            }
502
1.37M
        }
503
1.37M
    }
504
87.1M
    *i = idx;
505
506
87.1M
    return 0;
507
87.1M
}
508
509
510
/* internal worker, handles both escaped and normal line endings.
511
   If out buffer is NULL, will return sz needed in outLen */
512
static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
513
                           word32* outLen, int escaped)
514
16.9k
{
515
16.9k
    int    ret = 0;
516
16.9k
    word32 i = 0,
517
16.9k
           j = 0,
518
16.9k
           n = 0;   /* new line counter */
519
520
16.9k
    int    getSzOnly = (out == NULL);
521
522
16.9k
    word32 outSz;
523
16.9k
    word32 addSz;
524
525
16.9k
    if (in == NULL && inLen > 0)
526
0
        return BAD_FUNC_ARG;
527
528
    /* Reject lengths that would wrap the encoded-size calculation below. */
529
16.9k
    if (inLen >= (WOLFSSL_MAX_32BIT / 4))
530
0
        return BAD_FUNC_ARG;
531
532
16.9k
    outSz = (inLen + 3 - 1) / 3 * 4;
533
16.9k
    addSz = (outSz + BASE64_LINE_SZ - 1) / BASE64_LINE_SZ;  /* new lines */
534
535
16.9k
    if (escaped == WC_ESC_NL_ENC)
536
191
        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
537
16.7k
    else if (escaped == WC_NO_NL_ENC)
538
27
        addSz = 0;    /* encode without \n */
539
540
16.9k
    outSz += addSz;
541
542
    /* if escaped we can't predetermine size for one pass encoding, but
543
     * make sure we have enough if no escapes are in input
544
     * Also need to ensure outLen valid before dereference */
545
16.9k
    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
546
547
21.4M
    while (inLen > 2) {
548
21.4M
        byte b1 = in[j++];
549
21.4M
        byte b2 = in[j++];
550
21.4M
        byte b3 = in[j++];
551
552
        /* encoded idx */
553
21.4M
        byte e1 = b1 >> 2;
554
21.4M
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
555
21.4M
        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
556
21.4M
        byte e4 = b3 & 0x3F;
557
558
        /* store */
559
21.4M
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
560
21.4M
        if (ret != 0) break;
561
21.4M
        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
562
21.4M
        if (ret != 0) break;
563
21.4M
        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
564
21.4M
        if (ret != 0) break;
565
21.4M
        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
566
21.4M
        if (ret != 0) break;
567
568
21.4M
        inLen -= 3;
569
570
        /* Insert newline after BASE64_LINE_SZ, unless no \n requested */
571
21.4M
        if (escaped != WC_NO_NL_ENC && (++n % (BASE64_LINE_SZ/4)) == 0 && inLen) {
572
1.31M
            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
573
1.31M
            if (ret != 0) break;
574
1.31M
        }
575
21.4M
    }
576
577
    /* last integral */
578
16.8k
    if (inLen && ret == 0) {
579
13.1k
        int twoBytes = (inLen == 2);
580
581
13.1k
        byte b1 = in[j++];
582
13.1k
        byte b2 = (twoBytes) ? in[j++] : 0;
583
584
13.1k
        byte e1 = b1 >> 2;
585
13.1k
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
586
13.1k
        byte e3 = (byte)((b2 & 0xF) << 2);
587
588
13.1k
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
589
13.1k
        if (ret == 0)
590
13.1k
            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
591
13.1k
        if (ret == 0) {
592
            /* third */
593
13.1k
            if (twoBytes)
594
9.89k
                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
595
3.26k
            else
596
3.26k
                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
597
13.1k
        }
598
        /* fourth always pad */
599
13.1k
        if (ret == 0)
600
13.1k
            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
601
13.1k
    }
602
603
16.8k
    if (ret == 0 && escaped != WC_NO_NL_ENC)
604
16.8k
        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
605
606
16.8k
    if (i != outSz && escaped != 1 && ret == 0)
607
15
        return ASN_INPUT_E;
608
/* If the output buffer has a room for an extra byte, add a null terminator */
609
16.8k
    if (out && *outLen > i)
610
225
        out[i]= '\0';
611
612
16.8k
    *outLen = i;
613
614
16.8k
    if (ret == 0)
615
16.8k
        return getSzOnly ? WC_NO_ERR_TRACE(LENGTH_ONLY_E) : 0;
616
617
29
    return ret;
618
16.8k
}
619
620
621
/* Base64 Encode, PEM style, with \n line endings */
622
int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
623
16.6k
{
624
16.6k
    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
625
16.6k
}
626
627
628
/* Base64 Encode, with %0A escaped line endings instead of \n */
629
int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
630
191
{
631
191
    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
632
191
}
633
634
int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
635
27
{
636
27
    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
637
27
}
638
639
#endif /* WOLFSSL_BASE64_ENCODE */
640
641
642
#ifdef WOLFSSL_BASE16
643
644
static
645
const ALIGN64 byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
646
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD,
647
                           10, 11, 12, 13, 14, 15,  /* upper case A-F */
648
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
649
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
650
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
651
                           BAD, BAD,  /* G - ` */
652
                           10, 11, 12, 13, 14, 15   /* lower case a-f */
653
                         };  /* A starts at 0x41 not 0x3A */
654
655
int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
656
108
{
657
108
    word32 inIdx  = 0;
658
108
    word32 outIdx = 0;
659
660
108
    if (in == NULL || out == NULL || outLen == NULL)
661
0
        return BAD_FUNC_ARG;
662
663
108
    if (inLen == 1 && *outLen && in) {
664
28
        byte b = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
665
666
        /* sanity check */
667
28
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
668
15
            return ASN_INPUT_E;
669
670
13
        b  = hexDecode[b];
671
672
13
        if (b == BAD)
673
6
            return ASN_INPUT_E;
674
675
7
        out[outIdx++] = b;
676
677
7
        *outLen = outIdx;
678
7
        return 0;
679
13
    }
680
681
80
    if (inLen % 2)
682
2
        return BAD_FUNC_ARG;
683
684
78
    if (*outLen < (inLen / 2))
685
1
        return BUFFER_E;
686
687
300
    while (inLen) {
688
255
        byte b  = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
689
255
        byte b2 = (byte)(in[inIdx++] - BASE16_MIN);
690
691
        /* sanity checks */
692
255
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
693
15
            return ASN_INPUT_E;
694
240
        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
695
10
            return ASN_INPUT_E;
696
697
230
        b  = hexDecode[b];
698
230
        b2 = hexDecode[b2];
699
700
230
        if (b == BAD || b2 == BAD)
701
7
            return ASN_INPUT_E;
702
703
223
        out[outIdx++] = (byte)((b << 4) | b2);
704
223
        inLen -= 2;
705
223
    }
706
707
45
    *outLen = outIdx;
708
45
    return 0;
709
77
}
710
711
static
712
const ALIGN64 byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7',
713
                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
714
};
715
716
int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
717
81
{
718
81
    word32 outIdx = 0;
719
81
    word32 i;
720
721
81
    if (in == NULL || out == NULL || outLen == NULL)
722
0
        return BAD_FUNC_ARG;
723
724
81
    if (inLen > (WOLFSSL_MAX_32BIT / 2))
725
0
        return BAD_FUNC_ARG;
726
727
81
    if (*outLen < (2 * inLen))
728
4
        return BAD_FUNC_ARG;
729
730
2.16M
    for (i = 0; i < inLen; i++) {
731
2.16M
        byte hb = in[i] >> 4;
732
2.16M
        byte lb = in[i] & 0x0f;
733
734
2.16M
        hb = hexEncode[hb];
735
2.16M
        lb = hexEncode[lb];
736
737
2.16M
        out[outIdx++] = hb;
738
2.16M
        out[outIdx++] = lb;
739
2.16M
    }
740
741
    /* If the output buffer has a room for an extra byte, add a null terminator */
742
77
    if (*outLen > outIdx)
743
75
        out[outIdx++]= '\0';
744
745
77
    *outLen = outIdx;
746
77
    return 0;
747
81
}
748
749
#endif /* WOLFSSL_BASE16 */
750
751
#endif /* !NO_CODING */