Coverage Report

Created: 2026-04-01 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-sp-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
9.00M
{
57
9.00M
    int v;
58
9.00M
    int smallEnd   = (int)c - 0x7b;
59
9.00M
    int smallStart = (int)c - 0x61;
60
9.00M
    int bigEnd     = (int)c - 0x5b;
61
9.00M
    int bigStart   = (int)c - 0x41;
62
9.00M
    int numEnd     = (int)c - 0x3a;
63
9.00M
    int numStart   = (int)c - 0x30;
64
9.00M
    int slashEnd   = (int)c - 0x30;
65
9.00M
    int slashStart = (int)c - 0x2f;
66
9.00M
    int plusEnd    = (int)c - 0x2c;
67
9.00M
    int plusStart  = (int)c - 0x2b;
68
69
9.00M
    v  = ((smallStart >> 8) ^ (smallEnd >> 8)) & (smallStart + 26 + 1);
70
9.00M
    v |= ((bigStart   >> 8) ^ (bigEnd   >> 8)) & (bigStart   +  0 + 1);
71
9.00M
    v |= ((numStart   >> 8) ^ (numEnd   >> 8)) & (numStart   + 52 + 1);
72
9.00M
    v |= ((slashStart >> 8) ^ (slashEnd >> 8)) & (slashStart + 63 + 1);
73
9.00M
    v |= ((plusStart  >> 8) ^ (plusEnd  >> 8)) & (plusStart  + 62 + 1);
74
75
9.00M
    return (byte)(v - 1);
76
9.00M
}
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.05M
{
123
9.05M
    word32 len = *inLen;
124
9.05M
    word32 j = *outJ;
125
9.05M
    byte curChar;
126
127
9.05M
    if (len == 0) {
128
707
        return BUFFER_E;
129
707
    }
130
9.05M
    curChar = in[j];
131
132
9.08M
    while (len > 1 && curChar == ' ') {
133
        /* skip whitespace in the middle or end of line */
134
29.5k
        curChar = in[++j];
135
29.5k
        len--;
136
29.5k
    }
137
9.05M
    if (len && (curChar == '\r' || curChar == '\n')) {
138
68.5k
        j++;
139
68.5k
        len--;
140
68.5k
        if (curChar == '\r') {
141
7.44k
            if (len) {
142
6.64k
                curChar = in[j++];
143
6.64k
                len--;
144
6.64k
            }
145
7.44k
        }
146
68.5k
        if (curChar != '\n') {
147
961
            WOLFSSL_MSG("Bad end of line in Base64 Decode");
148
961
            return ASN_INPUT_E;
149
961
        }
150
151
67.6k
        if (len) {
152
66.7k
            curChar = in[j];
153
66.7k
        }
154
67.6k
    }
155
9.06M
    while (len && curChar == ' ') {
156
4.96k
        if (--len > 0) {
157
3.96k
            curChar = in[++j];
158
3.96k
        }
159
4.96k
    }
160
9.05M
    if (!len) {
161
1.84k
        return BUFFER_E;
162
1.84k
    }
163
9.05M
    *inLen = len;
164
9.05M
    *outJ = j;
165
9.05M
    return 0;
166
9.05M
}
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.8k
{
272
27.8k
    word32 i = 0;
273
27.8k
    word32 j = 0;
274
27.8k
    int ret;
275
276
2.27M
    while (inLen > 3) {
277
2.25M
        int pad3 = 0;
278
2.25M
        int pad4 = 0;
279
2.25M
        byte b1, b2, b3;
280
2.25M
        byte e1, e2, e3, e4;
281
282
2.25M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
283
715
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
284
                /* Running out of buffer here is not an error */
285
471
                break;
286
471
            }
287
244
            return ret;
288
715
        }
289
2.25M
        e1 = in[j++];
290
2.25M
        if (e1 == '\0') {
291
11
            break;
292
11
        }
293
2.25M
        inLen--;
294
2.25M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
295
854
            return ret;
296
854
        }
297
2.25M
        e2 = in[j++];
298
2.25M
        inLen--;
299
2.25M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
300
1.00k
            return ret;
301
1.00k
        }
302
2.25M
        e3 = in[j++];
303
2.25M
        inLen--;
304
2.25M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
305
931
            return ret;
306
931
        }
307
2.25M
        e4 = in[j++];
308
2.25M
        inLen--;
309
310
2.25M
        if (e3 == PAD)
311
1.68k
            pad3 = 1;
312
2.25M
        if (e4 == PAD)
313
2.73k
            pad4 = 1;
314
315
2.25M
        if (pad3 && !pad4)
316
206
            return ASN_INPUT_E;
317
318
2.25M
        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.25M
        e1 = Base64_Char2Val_CT(e1);
324
2.25M
        e2 = Base64_Char2Val_CT(e2);
325
2.25M
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_CT(e3));
326
2.25M
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_CT(e4));
327
328
2.25M
        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.25M
        b1 = (byte)((e1 << 2) | (e2 >> 4));
334
2.25M
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
335
2.25M
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
336
337
2.25M
        out[i++] = b1;
338
2.25M
        if (!pad3)
339
2.25M
            out[i++] = b2;
340
2.25M
        if (!pad4)
341
2.24M
            out[i++] = b3;
342
2.66k
        else
343
2.66k
            break;
344
2.25M
    }
345
346
    /* If the output buffer has a room for an extra byte, add a null terminator */
347
23.2k
    if (out && *outLen > i)
348
23.2k
        out[i]= '\0';
349
350
    /* Note, *outLen won't reflect the optional terminating null. */
351
23.2k
    *outLen = i;
352
353
23.2k
    return 0;
354
27.8k
}
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 */