Coverage Report

Created: 2026-04-05 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-normal-math/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
16.9M
        #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
8.77M
{
57
8.77M
    int v;
58
8.77M
    int smallEnd   = (int)c - 0x7b;
59
8.77M
    int smallStart = (int)c - 0x61;
60
8.77M
    int bigEnd     = (int)c - 0x5b;
61
8.77M
    int bigStart   = (int)c - 0x41;
62
8.77M
    int numEnd     = (int)c - 0x3a;
63
8.77M
    int numStart   = (int)c - 0x30;
64
8.77M
    int slashEnd   = (int)c - 0x30;
65
8.77M
    int slashStart = (int)c - 0x2f;
66
8.77M
    int plusEnd    = (int)c - 0x2c;
67
8.77M
    int plusStart  = (int)c - 0x2b;
68
69
8.77M
    v  = ((smallStart >> 8) ^ (smallEnd >> 8)) & (smallStart + 26 + 1);
70
8.77M
    v |= ((bigStart   >> 8) ^ (bigEnd   >> 8)) & (bigStart   +  0 + 1);
71
8.77M
    v |= ((numStart   >> 8) ^ (numEnd   >> 8)) & (numStart   + 52 + 1);
72
8.77M
    v |= ((slashStart >> 8) ^ (slashEnd >> 8)) & (slashStart + 63 + 1);
73
8.77M
    v |= ((plusStart  >> 8) ^ (plusEnd  >> 8)) & (plusStart  + 62 + 1);
74
75
8.77M
    return (byte)(v - 1);
76
8.77M
}
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
8.82M
{
123
8.82M
    word32 len = *inLen;
124
8.82M
    word32 j = *outJ;
125
8.82M
    byte curChar;
126
127
8.82M
    if (len == 0) {
128
709
        return BUFFER_E;
129
709
    }
130
8.82M
    curChar = in[j];
131
132
8.85M
    while (len > 1 && curChar == ' ') {
133
        /* skip whitespace in the middle or end of line */
134
28.8k
        curChar = in[++j];
135
28.8k
        len--;
136
28.8k
    }
137
8.82M
    if (len && (curChar == '\r' || curChar == '\n')) {
138
65.9k
        j++;
139
65.9k
        len--;
140
65.9k
        if (curChar == '\r') {
141
7.68k
            if (len) {
142
6.88k
                curChar = in[j++];
143
6.88k
                len--;
144
6.88k
            }
145
7.68k
        }
146
65.9k
        if (curChar != '\n') {
147
976
            WOLFSSL_MSG("Bad end of line in Base64 Decode");
148
976
            return ASN_INPUT_E;
149
976
        }
150
151
64.9k
        if (len) {
152
64.1k
            curChar = in[j];
153
64.1k
        }
154
64.9k
    }
155
8.82M
    while (len && curChar == ' ') {
156
4.99k
        if (--len > 0) {
157
4.05k
            curChar = in[++j];
158
4.05k
        }
159
4.99k
    }
160
8.82M
    if (!len) {
161
1.75k
        return BUFFER_E;
162
1.75k
    }
163
8.81M
    *inLen = len;
164
8.81M
    *outJ = j;
165
8.81M
    return 0;
166
8.82M
}
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
8.42k
    while (inLen > 3) {
178
8.40k
        int pad3 = 0;
179
8.40k
        int pad4 = 0;
180
8.40k
        byte b1, b2, b3;
181
8.40k
        byte e1, e2, e3, e4;
182
183
8.40k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
184
0
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
185
                /* Running out of buffer here is not an error */
186
0
                break;
187
0
            }
188
0
            return ret;
189
0
        }
190
8.40k
        e1 = in[j++];
191
8.40k
        if (e1 == '\0') {
192
0
            break;
193
0
        }
194
8.40k
        inLen--;
195
8.40k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
196
0
            return ret;
197
0
        }
198
8.40k
        e2 = in[j++];
199
8.40k
        inLen--;
200
8.40k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
201
0
            return ret;
202
0
        }
203
8.40k
        e3 = in[j++];
204
8.40k
        inLen--;
205
8.40k
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
206
0
            return ret;
207
0
        }
208
8.40k
        e4 = in[j++];
209
8.40k
        inLen--;
210
211
8.40k
        if (e3 == PAD)
212
0
            pad3 = 1;
213
8.40k
        if (e4 == PAD)
214
0
            pad4 = 1;
215
216
8.40k
        if (pad3 && !pad4)
217
0
            return ASN_INPUT_E;
218
219
8.40k
        if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN ||
220
8.40k
                                                              e4 < BASE64_MIN) {
221
0
            WOLFSSL_MSG("Bad Base64 Decode data, too small");
222
0
            return ASN_INPUT_E;
223
0
        }
224
225
8.40k
        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
226
0
            WOLFSSL_MSG("Bad Base64 Decode data, too big");
227
0
            return ASN_INPUT_E;
228
0
        }
229
230
8.40k
        if (i + 1 + !pad3 + !pad4 > *outLen) {
231
0
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
232
0
            return BUFFER_E;
233
0
        }
234
235
8.40k
        e1 = Base64_Char2Val_by_table(e1);
236
8.40k
        e2 = Base64_Char2Val_by_table(e2);
237
8.40k
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_by_table(e3));
238
8.40k
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_by_table(e4));
239
240
8.40k
        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.40k
        b1 = (byte)((e1 << 2) | (e2 >> 4));
246
8.40k
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
247
8.40k
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
248
249
8.40k
        out[i++] = b1;
250
8.40k
        if (!pad3)
251
8.40k
            out[i++] = b2;
252
8.40k
        if (!pad4)
253
8.40k
            out[i++] = b3;
254
0
        else
255
0
            break;
256
8.40k
    }
257
258
    /* If the output buffer has a room for an extra byte, add a null terminator */
259
20
    if (out && *outLen > i)
260
20
        out[i]= '\0';
261
262
    /* Note, *outLen won't reflect the optional terminating null. */
263
20
    *outLen = i;
264
265
20
    return 0;
266
20
}
267
268
#endif /* !BASE64_NO_TABLE */
269
270
int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
271
27.5k
{
272
27.5k
    word32 i = 0;
273
27.5k
    word32 j = 0;
274
27.5k
    int ret;
275
276
2.21M
    while (inLen > 3) {
277
2.19M
        int pad3 = 0;
278
2.19M
        int pad4 = 0;
279
2.19M
        byte b1, b2, b3;
280
2.19M
        byte e1, e2, e3, e4;
281
282
2.19M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
283
662
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
284
                /* Running out of buffer here is not an error */
285
416
                break;
286
416
            }
287
246
            return ret;
288
662
        }
289
2.19M
        e1 = in[j++];
290
2.19M
        if (e1 == '\0') {
291
11
            break;
292
11
        }
293
2.19M
        inLen--;
294
2.19M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
295
858
            return ret;
296
858
        }
297
2.19M
        e2 = in[j++];
298
2.19M
        inLen--;
299
2.19M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
300
989
            return ret;
301
989
        }
302
2.19M
        e3 = in[j++];
303
2.19M
        inLen--;
304
2.19M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
305
933
            return ret;
306
933
        }
307
2.19M
        e4 = in[j++];
308
2.19M
        inLen--;
309
310
2.19M
        if (e3 == PAD)
311
1.60k
            pad3 = 1;
312
2.19M
        if (e4 == PAD)
313
2.58k
            pad4 = 1;
314
315
2.19M
        if (pad3 && !pad4)
316
205
            return ASN_INPUT_E;
317
318
2.19M
        if (i + 1 + !pad3 + !pad4 > *outLen) {
319
10
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
320
10
            return BUFFER_E;
321
10
        }
322
323
2.19M
        e1 = Base64_Char2Val_CT(e1);
324
2.19M
        e2 = Base64_Char2Val_CT(e2);
325
2.19M
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_CT(e3));
326
2.19M
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_CT(e4));
327
328
2.19M
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
329
1.31k
            WOLFSSL_MSG("Bad Base64 Decode bad character");
330
1.31k
            return ASN_INPUT_E;
331
1.31k
        }
332
333
2.19M
        b1 = (byte)((e1 << 2) | (e2 >> 4));
334
2.19M
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
335
2.19M
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
336
337
2.19M
        out[i++] = b1;
338
2.19M
        if (!pad3)
339
2.19M
            out[i++] = b2;
340
2.19M
        if (!pad4)
341
2.19M
            out[i++] = b3;
342
2.51k
        else
343
2.51k
            break;
344
2.19M
    }
345
346
    /* If the output buffer has a room for an extra byte, add a null terminator */
347
23.0k
    if (out && *outLen > i)
348
23.0k
        out[i]= '\0';
349
350
    /* Note, *outLen won't reflect the optional terminating null. */
351
23.0k
    *outLen = i;
352
353
23.0k
    return 0;
354
27.5k
}
355
356
#ifdef BASE64_NO_TABLE
357
int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen) {
358
    return Base64_Decode(in, inLen, out, outLen);
359
}
360
#endif /* BASE64_NO_TABLE */
361
362
#endif /* WOLFSSL_BASE64_DECODE */
363
364
#if defined(WOLFSSL_BASE64_ENCODE)
365
366
static
367
const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
368
                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
369
                              'U', 'V', 'W', 'X', 'Y', 'Z',
370
                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
371
                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
372
                              'u', 'v', 'w', 'x', 'y', 'z',
373
                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
374
                              '+', '/'
375
                            };
376
377
378
/* make sure *i (idx) won't exceed max, store and possibly escape to out,
379
 * raw means use e w/o decode,  0 on success */
380
static int CEscape(int escaped, byte e, byte* out, word32* i, word32 maxSz,
381
                  int raw, int getSzOnly)
382
68.9M
{
383
68.9M
    int    doEscape = 0;
384
68.9M
    word32 needed = 1;
385
68.9M
    word32 idx = *i;
386
387
68.9M
    byte basic;
388
68.9M
    byte plus    = 0;
389
68.9M
    byte equals  = 0;
390
68.9M
    byte newline = 0;
391
392
68.9M
    if (raw)
393
1.08M
        basic = e;
394
67.8M
    else if (e < sizeof(base64Encode))
395
67.8M
        basic = base64Encode[e];
396
0
    else
397
0
        return BAD_FUNC_ARG;
398
399
    /* check whether to escape. Only escape for EncodeEsc */
400
68.9M
    if (escaped == WC_ESC_NL_ENC) {
401
8.64M
        switch ((char)basic) {
402
2.46M
            case '+' :
403
2.46M
                plus     = 1;
404
2.46M
                doEscape = 1;
405
2.46M
                needed  += 2;
406
2.46M
                break;
407
96
            case '=' :
408
96
                equals   = 1;
409
96
                doEscape = 1;
410
96
                needed  += 2;
411
96
                break;
412
133k
            case '\n' :
413
133k
                newline  = 1;
414
133k
                doEscape = 1;
415
133k
                needed  += 2;
416
133k
                break;
417
6.04M
            default:
418
                /* do nothing */
419
6.04M
                break;
420
8.64M
        }
421
8.64M
    }
422
423
    /* check size */
424
68.9M
    if ( (idx+needed) > maxSz && !getSzOnly) {
425
46
        WOLFSSL_MSG("Escape buffer max too small");
426
46
        return BUFFER_E;
427
46
    }
428
429
    /* store it */
430
68.9M
    if (doEscape == 0) {
431
66.3M
        if(getSzOnly)
432
29.2M
            idx++;
433
37.1M
        else
434
37.1M
            out[idx++] = basic;
435
66.3M
    }
436
2.59M
    else {
437
2.59M
        if(getSzOnly)
438
0
            idx+=3;
439
2.59M
        else {
440
2.59M
            out[idx++] = '%';  /* start escape */
441
442
2.59M
            if (plus) {
443
2.46M
                out[idx++] = '2';
444
2.46M
                out[idx++] = 'B';
445
2.46M
            }
446
133k
            else if (equals) {
447
92
                out[idx++] = '3';
448
92
                out[idx++] = 'D';
449
92
            }
450
133k
            else if (newline) {
451
133k
                out[idx++] = '0';
452
133k
                out[idx++] = 'A';
453
133k
            }
454
2.59M
        }
455
2.59M
    }
456
68.9M
    *i = idx;
457
458
68.9M
    return 0;
459
68.9M
}
460
461
462
/* internal worker, handles both escaped and normal line endings.
463
   If out buffer is NULL, will return sz needed in outLen */
464
static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
465
                           word32* outLen, int escaped)
466
16.4k
{
467
16.4k
    int    ret = 0;
468
16.4k
    word32 i = 0,
469
16.4k
           j = 0,
470
16.4k
           n = 0;   /* new line counter */
471
472
16.4k
    int    getSzOnly = (out == NULL);
473
474
16.4k
    word32 outSz = (inLen + 3 - 1) / 3 * 4;
475
16.4k
    word32 addSz = (outSz + BASE64_LINE_SZ - 1) / BASE64_LINE_SZ;  /* new lines */
476
477
16.4k
    if (escaped == WC_ESC_NL_ENC)
478
180
        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
479
16.2k
    else if (escaped == WC_NO_NL_ENC)
480
42
        addSz = 0;    /* encode without \n */
481
482
16.4k
    outSz += addSz;
483
484
    /* if escaped we can't predetermine size for one pass encoding, but
485
     * make sure we have enough if no escapes are in input
486
     * Also need to ensure outLen valid before dereference */
487
16.4k
    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
488
489
16.9M
    while (inLen > 2) {
490
16.9M
        byte b1 = in[j++];
491
16.9M
        byte b2 = in[j++];
492
16.9M
        byte b3 = in[j++];
493
494
        /* encoded idx */
495
16.9M
        byte e1 = b1 >> 2;
496
16.9M
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
497
16.9M
        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
498
16.9M
        byte e4 = b3 & 0x3F;
499
500
        /* store */
501
16.9M
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
502
16.9M
        if (ret != 0) break;
503
16.9M
        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
504
16.9M
        if (ret != 0) break;
505
16.9M
        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
506
16.9M
        if (ret != 0) break;
507
16.9M
        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
508
16.9M
        if (ret != 0) break;
509
510
16.9M
        inLen -= 3;
511
512
        /* Insert newline after BASE64_LINE_SZ, unless no \n requested */
513
16.9M
        if (escaped != WC_NO_NL_ENC && (++n % (BASE64_LINE_SZ/4)) == 0 && inLen) {
514
1.05M
            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
515
1.05M
            if (ret != 0) break;
516
1.05M
        }
517
16.9M
    }
518
519
    /* last integral */
520
16.3k
    if (inLen && ret == 0) {
521
12.6k
        int twoBytes = (inLen == 2);
522
523
12.6k
        byte b1 = in[j++];
524
12.6k
        byte b2 = (twoBytes) ? in[j++] : 0;
525
526
12.6k
        byte e1 = b1 >> 2;
527
12.6k
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
528
12.6k
        byte e3 = (byte)((b2 & 0xF) << 2);
529
530
12.6k
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
531
12.6k
        if (ret == 0)
532
12.6k
            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
533
12.6k
        if (ret == 0) {
534
            /* third */
535
12.6k
            if (twoBytes)
536
9.19k
                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
537
3.41k
            else
538
3.41k
                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
539
12.6k
        }
540
        /* fourth always pad */
541
12.6k
        if (ret == 0)
542
12.6k
            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
543
12.6k
    }
544
545
16.3k
    if (ret == 0 && escaped != WC_NO_NL_ENC)
546
16.3k
        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
547
548
16.3k
    if (i != outSz && escaped != 1 && ret == 0)
549
5
        return ASN_INPUT_E;
550
/* If the output buffer has a room for an extra byte, add a null terminator */
551
16.3k
    if (out && *outLen > i)
552
225
        out[i]= '\0';
553
554
16.3k
    *outLen = i;
555
556
16.3k
    if (ret == 0)
557
16.3k
        return getSzOnly ? WC_NO_ERR_TRACE(LENGTH_ONLY_E) : 0;
558
559
46
    return ret;
560
16.3k
}
561
562
563
/* Base64 Encode, PEM style, with \n line endings */
564
int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
565
16.1k
{
566
16.1k
    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
567
16.1k
}
568
569
570
/* Base64 Encode, with %0A escaped line endings instead of \n */
571
int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
572
180
{
573
180
    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
574
180
}
575
576
int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
577
42
{
578
42
    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
579
42
}
580
581
#endif /* WOLFSSL_BASE64_ENCODE */
582
583
584
#ifdef WOLFSSL_BASE16
585
586
static
587
const ALIGN64 byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
588
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD,
589
                           10, 11, 12, 13, 14, 15,  /* upper case A-F */
590
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
591
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
592
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
593
                           BAD, BAD,  /* G - ` */
594
                           10, 11, 12, 13, 14, 15   /* lower case a-f */
595
                         };  /* A starts at 0x41 not 0x3A */
596
597
int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
598
108
{
599
108
    word32 inIdx  = 0;
600
108
    word32 outIdx = 0;
601
602
108
    if (in == NULL || out == NULL || outLen == NULL)
603
0
        return BAD_FUNC_ARG;
604
605
108
    if (inLen == 1 && *outLen && in) {
606
26
        byte b = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
607
608
        /* sanity check */
609
26
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
610
12
            return ASN_INPUT_E;
611
612
14
        b  = hexDecode[b];
613
614
14
        if (b == BAD)
615
6
            return ASN_INPUT_E;
616
617
8
        out[outIdx++] = b;
618
619
8
        *outLen = outIdx;
620
8
        return 0;
621
14
    }
622
623
82
    if (inLen % 2)
624
1
        return BAD_FUNC_ARG;
625
626
81
    if (*outLen < (inLen / 2))
627
2
        return BUFFER_E;
628
629
301
    while (inLen) {
630
250
        byte b  = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
631
250
        byte b2 = (byte)(in[inIdx++] - BASE16_MIN);
632
633
        /* sanity checks */
634
250
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
635
12
            return ASN_INPUT_E;
636
238
        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
637
9
            return ASN_INPUT_E;
638
639
229
        b  = hexDecode[b];
640
229
        b2 = hexDecode[b2];
641
642
229
        if (b == BAD || b2 == BAD)
643
7
            return ASN_INPUT_E;
644
645
222
        out[outIdx++] = (byte)((b << 4) | b2);
646
222
        inLen -= 2;
647
222
    }
648
649
51
    *outLen = outIdx;
650
51
    return 0;
651
79
}
652
653
static
654
const ALIGN64 byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7',
655
                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
656
};
657
658
int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
659
62
{
660
62
    word32 outIdx = 0;
661
62
    word32 i;
662
663
62
    if (in == NULL || out == NULL || outLen == NULL)
664
0
        return BAD_FUNC_ARG;
665
666
62
    if (*outLen < (2 * inLen))
667
2
        return BAD_FUNC_ARG;
668
669
1.09M
    for (i = 0; i < inLen; i++) {
670
1.09M
        byte hb = in[i] >> 4;
671
1.09M
        byte lb = in[i] & 0x0f;
672
673
1.09M
        hb = hexEncode[hb];
674
1.09M
        lb = hexEncode[lb];
675
676
1.09M
        out[outIdx++] = hb;
677
1.09M
        out[outIdx++] = lb;
678
1.09M
    }
679
680
    /* If the output buffer has a room for an extra byte, add a null terminator */
681
60
    if (*outLen > outIdx)
682
59
        out[outIdx++]= '\0';
683
684
60
    *outLen = outIdx;
685
60
    return 0;
686
62
}
687
688
#endif /* WOLFSSL_BASE16 */
689
690
#endif /* !NO_CODING */