Coverage Report

Created: 2025-11-16 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/wolfcrypt/src/coding.c
Line
Count
Source
1
/* coding.c
2
 *
3
 * Copyright (C) 2006-2025 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
23.2M
        #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.10M
{
57
9.10M
    int v;
58
9.10M
    int smallEnd   = (int)c - 0x7b;
59
9.10M
    int smallStart = (int)c - 0x61;
60
9.10M
    int bigEnd     = (int)c - 0x5b;
61
9.10M
    int bigStart   = (int)c - 0x41;
62
9.10M
    int numEnd     = (int)c - 0x3a;
63
9.10M
    int numStart   = (int)c - 0x30;
64
9.10M
    int slashEnd   = (int)c - 0x30;
65
9.10M
    int slashStart = (int)c - 0x2f;
66
9.10M
    int plusEnd    = (int)c - 0x2c;
67
9.10M
    int plusStart  = (int)c - 0x2b;
68
69
9.10M
    v  = ((smallStart >> 8) ^ (smallEnd >> 8)) & (smallStart + 26 + 1);
70
9.10M
    v |= ((bigStart   >> 8) ^ (bigEnd   >> 8)) & (bigStart   +  0 + 1);
71
9.10M
    v |= ((numStart   >> 8) ^ (numEnd   >> 8)) & (numStart   + 52 + 1);
72
9.10M
    v |= ((slashStart >> 8) ^ (slashEnd >> 8)) & (slashStart + 63 + 1);
73
9.10M
    v |= ((plusStart  >> 8) ^ (plusEnd  >> 8)) & (plusStart  + 62 + 1);
74
75
9.10M
    return (byte)(v - 1);
76
9.10M
}
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.15M
{
123
9.15M
    word32 len = *inLen;
124
9.15M
    word32 j = *outJ;
125
9.15M
    byte curChar;
126
127
9.15M
    if (len == 0) {
128
745
        return BUFFER_E;
129
745
    }
130
9.15M
    curChar = in[j];
131
132
9.17M
    while (len > 1 && curChar == ' ') {
133
        /* skip whitespace in the middle or end of line */
134
22.0k
        curChar = in[++j];
135
22.0k
        len--;
136
22.0k
    }
137
9.15M
    if (len && (curChar == '\r' || curChar == '\n')) {
138
59.7k
        j++;
139
59.7k
        len--;
140
59.7k
        if (curChar == '\r') {
141
5.24k
            if (len) {
142
4.45k
                curChar = in[j++];
143
4.45k
                len--;
144
4.45k
            }
145
5.24k
        }
146
59.7k
        if (curChar != '\n') {
147
924
            WOLFSSL_MSG("Bad end of line in Base64 Decode");
148
924
            return ASN_INPUT_E;
149
924
        }
150
151
58.8k
        if (len) {
152
58.0k
            curChar = in[j];
153
58.0k
        }
154
58.8k
    }
155
9.15M
    while (len && curChar == ' ') {
156
4.74k
        if (--len > 0) {
157
3.90k
            curChar = in[++j];
158
3.90k
        }
159
4.74k
    }
160
9.15M
    if (!len) {
161
1.66k
        return BUFFER_E;
162
1.66k
    }
163
9.15M
    *inLen = len;
164
9.15M
    *outJ = j;
165
9.15M
    return 0;
166
9.15M
}
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
26.7k
{
272
26.7k
    word32 i = 0;
273
26.7k
    word32 j = 0;
274
26.7k
    int ret;
275
276
2.30M
    while (inLen > 3) {
277
2.28M
        int pad3 = 0;
278
2.28M
        int pad4 = 0;
279
2.28M
        byte b1, b2, b3;
280
2.28M
        byte e1, e2, e3, e4;
281
282
2.28M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
283
638
            if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
284
                /* Running out of buffer here is not an error */
285
414
                break;
286
414
            }
287
224
            return ret;
288
638
        }
289
2.28M
        e1 = in[j++];
290
2.28M
        if (e1 == '\0') {
291
11
            break;
292
11
        }
293
2.28M
        inLen--;
294
2.28M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
295
845
            return ret;
296
845
        }
297
2.28M
        e2 = in[j++];
298
2.28M
        inLen--;
299
2.28M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
300
924
            return ret;
301
924
        }
302
2.27M
        e3 = in[j++];
303
2.27M
        inLen--;
304
2.27M
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
305
927
            return ret;
306
927
        }
307
2.27M
        e4 = in[j++];
308
2.27M
        inLen--;
309
310
2.27M
        if (e3 == PAD)
311
1.49k
            pad3 = 1;
312
2.27M
        if (e4 == PAD)
313
2.71k
            pad4 = 1;
314
315
2.27M
        if (pad3 && !pad4)
316
205
            return ASN_INPUT_E;
317
318
2.27M
        if (i + 1 + !pad3 + !pad4 > *outLen) {
319
3
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
320
3
            return BUFFER_E;
321
3
        }
322
323
2.27M
        e1 = Base64_Char2Val_CT(e1);
324
2.27M
        e2 = Base64_Char2Val_CT(e2);
325
2.27M
        e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_CT(e3));
326
2.27M
        e4 = (byte)((e4 == PAD) ? 0 : Base64_Char2Val_CT(e4));
327
328
2.27M
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
329
1.19k
            WOLFSSL_MSG("Bad Base64 Decode bad character");
330
1.19k
            return ASN_INPUT_E;
331
1.19k
        }
332
333
2.27M
        b1 = (byte)((e1 << 2) | (e2 >> 4));
334
2.27M
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
335
2.27M
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
336
337
2.27M
        out[i++] = b1;
338
2.27M
        if (!pad3)
339
2.27M
            out[i++] = b2;
340
2.27M
        if (!pad4)
341
2.27M
            out[i++] = b3;
342
2.65k
        else
343
2.65k
            break;
344
2.27M
    }
345
346
    /* If the output buffer has a room for an extra byte, add a null terminator */
347
22.4k
    if (out && *outLen > i)
348
22.4k
        out[i]= '\0';
349
350
    /* Note, *outLen won't reflect the optional terminating null. */
351
22.4k
    *outLen = i;
352
353
22.4k
    return 0;
354
26.7k
}
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
94.3M
{
383
94.3M
    int    doEscape = 0;
384
94.3M
    word32 needed = 1;
385
94.3M
    word32 idx = *i;
386
387
94.3M
    byte basic;
388
94.3M
    byte plus    = 0;
389
94.3M
    byte equals  = 0;
390
94.3M
    byte newline = 0;
391
392
94.3M
    if (raw)
393
1.47M
        basic = e;
394
92.8M
    else if (e < sizeof(base64Encode))
395
92.8M
        basic = base64Encode[e];
396
0
    else
397
0
        return BAD_FUNC_ARG;
398
399
    /* check whether to escape. Only escape for EncodeEsc */
400
94.3M
    if (escaped == WC_ESC_NL_ENC) {
401
5.06M
        switch ((char)basic) {
402
448k
            case '+' :
403
448k
                plus     = 1;
404
448k
                doEscape = 1;
405
448k
                needed  += 2;
406
448k
                break;
407
99
            case '=' :
408
99
                equals   = 1;
409
99
                doEscape = 1;
410
99
                needed  += 2;
411
99
                break;
412
77.9k
            case '\n' :
413
77.9k
                newline  = 1;
414
77.9k
                doEscape = 1;
415
77.9k
                needed  += 2;
416
77.9k
                break;
417
4.53M
            default:
418
                /* do nothing */
419
4.53M
                break;
420
5.06M
        }
421
5.06M
    }
422
423
    /* check size */
424
94.3M
    if ( (idx+needed) > maxSz && !getSzOnly) {
425
32
        WOLFSSL_MSG("Escape buffer max too small");
426
32
        return BUFFER_E;
427
32
    }
428
429
    /* store it */
430
94.3M
    if (doEscape == 0) {
431
93.8M
        if(getSzOnly)
432
43.3M
            idx++;
433
50.5M
        else
434
50.5M
            out[idx++] = basic;
435
93.8M
    }
436
526k
    else {
437
526k
        if(getSzOnly)
438
0
            idx+=3;
439
526k
        else {
440
526k
            out[idx++] = '%';  /* start escape */
441
442
526k
            if (plus) {
443
448k
                out[idx++] = '2';
444
448k
                out[idx++] = 'B';
445
448k
            }
446
78.0k
            else if (equals) {
447
93
                out[idx++] = '3';
448
93
                out[idx++] = 'D';
449
93
            }
450
77.9k
            else if (newline) {
451
77.9k
                out[idx++] = '0';
452
77.9k
                out[idx++] = 'A';
453
77.9k
            }
454
526k
        }
455
526k
    }
456
94.3M
    *i = idx;
457
458
94.3M
    return 0;
459
94.3M
}
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
15.6k
{
467
15.6k
    int    ret = 0;
468
15.6k
    word32 i = 0,
469
15.6k
           j = 0,
470
15.6k
           n = 0;   /* new line counter */
471
472
15.6k
    int    getSzOnly = (out == NULL);
473
474
15.6k
    word32 outSz = (inLen + 3 - 1) / 3 * 4;
475
15.6k
    word32 addSz = (outSz + BASE64_LINE_SZ - 1) / BASE64_LINE_SZ;  /* new lines */
476
477
15.6k
    if (escaped == WC_ESC_NL_ENC)
478
151
        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
479
15.4k
    else if (escaped == WC_NO_NL_ENC)
480
29
        addSz = 0;    /* encode without \n */
481
482
15.6k
    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
15.6k
    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
488
489
23.2M
    while (inLen > 2) {
490
23.2M
        byte b1 = in[j++];
491
23.2M
        byte b2 = in[j++];
492
23.2M
        byte b3 = in[j++];
493
494
        /* encoded idx */
495
23.2M
        byte e1 = b1 >> 2;
496
23.2M
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
497
23.2M
        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
498
23.2M
        byte e4 = b3 & 0x3F;
499
500
        /* store */
501
23.2M
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
502
23.2M
        if (ret != 0) break;
503
23.2M
        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
504
23.2M
        if (ret != 0) break;
505
23.2M
        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
506
23.2M
        if (ret != 0) break;
507
23.2M
        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
508
23.2M
        if (ret != 0) break;
509
510
23.2M
        inLen -= 3;
511
512
        /* Insert newline after BASE64_LINE_SZ, unless no \n requested */
513
23.2M
        if (escaped != WC_NO_NL_ENC && (++n % (BASE64_LINE_SZ/4)) == 0 && inLen) {
514
1.44M
            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
515
1.44M
            if (ret != 0) break;
516
1.44M
        }
517
23.2M
    }
518
519
    /* last integral */
520
15.5k
    if (inLen && ret == 0) {
521
10.8k
        int twoBytes = (inLen == 2);
522
523
10.8k
        byte b1 = in[j++];
524
10.8k
        byte b2 = (twoBytes) ? in[j++] : 0;
525
526
10.8k
        byte e1 = b1 >> 2;
527
10.8k
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
528
10.8k
        byte e3 = (byte)((b2 & 0xF) << 2);
529
530
10.8k
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
531
10.8k
        if (ret == 0)
532
10.8k
            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
533
10.8k
        if (ret == 0) {
534
            /* third */
535
10.8k
            if (twoBytes)
536
6.93k
                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
537
3.93k
            else
538
3.93k
                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
539
10.8k
        }
540
        /* fourth always pad */
541
10.8k
        if (ret == 0)
542
10.8k
            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
543
10.8k
    }
544
545
15.5k
    if (ret == 0 && escaped != WC_NO_NL_ENC)
546
15.5k
        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
547
548
15.5k
    if (i != outSz && escaped != 1 && ret == 0)
549
4
        return ASN_INPUT_E;
550
/* If the output buffer has a room for an extra byte, add a null terminator */
551
15.5k
    if (out && *outLen > i)
552
190
        out[i]= '\0';
553
554
15.5k
    *outLen = i;
555
556
15.5k
    if (ret == 0)
557
15.5k
        return getSzOnly ? WC_NO_ERR_TRACE(LENGTH_ONLY_E) : 0;
558
559
32
    return ret;
560
15.5k
}
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
15.4k
{
566
15.4k
    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
567
15.4k
}
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
151
{
573
151
    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
574
151
}
575
576
int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
577
29
{
578
29
    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
579
29
}
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
113
{
599
113
    word32 inIdx  = 0;
600
113
    word32 outIdx = 0;
601
602
113
    if (in == NULL || out == NULL || outLen == NULL)
603
0
        return BAD_FUNC_ARG;
604
605
113
    if (inLen == 1 && *outLen && in) {
606
25
        byte b = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
607
608
        /* sanity check */
609
25
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
610
12
            return ASN_INPUT_E;
611
612
13
        b  = hexDecode[b];
613
614
13
        if (b == BAD)
615
6
            return ASN_INPUT_E;
616
617
7
        out[outIdx++] = b;
618
619
7
        *outLen = outIdx;
620
7
        return 0;
621
13
    }
622
623
88
    if (inLen % 2)
624
2
        return BAD_FUNC_ARG;
625
626
86
    if (*outLen < (inLen / 2))
627
7
        return BUFFER_E;
628
629
291
    while (inLen) {
630
249
        byte b  = (byte)(in[inIdx++] - BASE16_MIN);  /* 0 starts at 0x30 */
631
249
        byte b2 = (byte)(in[inIdx++] - BASE16_MIN);
632
633
        /* sanity checks */
634
249
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
635
24
            return ASN_INPUT_E;
636
225
        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
637
5
            return ASN_INPUT_E;
638
639
220
        b  = hexDecode[b];
640
220
        b2 = hexDecode[b2];
641
642
220
        if (b == BAD || b2 == BAD)
643
8
            return ASN_INPUT_E;
644
645
212
        out[outIdx++] = (byte)((b << 4) | b2);
646
212
        inLen -= 2;
647
212
    }
648
649
42
    *outLen = outIdx;
650
42
    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
43
{
660
43
    word32 outIdx = 0;
661
43
    word32 i;
662
663
43
    if (in == NULL || out == NULL || outLen == NULL)
664
0
        return BAD_FUNC_ARG;
665
666
43
    if (*outLen < (2 * inLen))
667
1
        return BAD_FUNC_ARG;
668
669
251
    for (i = 0; i < inLen; i++) {
670
209
        byte hb = in[i] >> 4;
671
209
        byte lb = in[i] & 0x0f;
672
673
209
        hb = hexEncode[hb];
674
209
        lb = hexEncode[lb];
675
676
209
        out[outIdx++] = hb;
677
209
        out[outIdx++] = lb;
678
209
    }
679
680
    /* If the output buffer has a room for an extra byte, add a null terminator */
681
42
    if (*outLen > outIdx)
682
41
        out[outIdx++]= '\0';
683
684
42
    *outLen = outIdx;
685
42
    return 0;
686
43
}
687
688
#endif /* WOLFSSL_BASE16 */
689
690
#endif /* !NO_CODING */