Coverage Report

Created: 2026-09-28 07:09

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