Coverage Report

Created: 2023-02-22 06:39

/src/wolfssl/wolfcrypt/src/coding.c
Line
Count
Source (jump to first uncovered line)
1
/* coding.c
2
 *
3
 * Copyright (C) 2006-2022 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 2 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
23
#ifdef HAVE_CONFIG_H
24
    #include <config.h>
25
#endif
26
27
#include <wolfssl/wolfcrypt/settings.h>
28
29
#ifndef NO_CODING
30
31
#include <wolfssl/wolfcrypt/coding.h>
32
#include <wolfssl/wolfcrypt/error-crypt.h>
33
#include <wolfssl/wolfcrypt/logging.h>
34
#ifndef NO_ASN
35
    #include <wolfssl/wolfcrypt/asn.h> /* For PEM_LINE_SZ */
36
#endif
37
#ifdef NO_INLINE
38
    #include <wolfssl/wolfcrypt/misc.h>
39
#else
40
    #define WOLFSSL_MISC_INCLUDED
41
    #include <wolfcrypt/src/misc.c>
42
#endif
43
44
enum {
45
    BAD         = 0xFF,  /* invalid encoding */
46
    PAD         = '=',
47
    BASE64_MIN  = 0x2B,
48
    BASE16_MIN  = 0x30,
49
};
50
51
52
#ifndef BASE64_LINE_SZ
53
    #ifdef NO_ASN
54
        #define BASE64_LINE_SZ 64
55
    #else
56
0
        #define BASE64_LINE_SZ PEM_LINE_SZ
57
    #endif
58
#endif
59
60
#ifdef WOLFSSL_BASE64_DECODE
61
62
#ifdef BASE64_NO_TABLE
63
static WC_INLINE byte Base64_Char2Val(byte c)
64
{
65
    word16 v = 0x0000;
66
67
    v |= 0xff3E & ctMask16Eq(c, 0x2b);
68
    v |= 0xff3F & ctMask16Eq(c, 0x2f);
69
    v |= (c + 0xff04) & ctMask16GTE(c, 0x30) & ctMask16LTE(c, 0x39);
70
    v |= (0xff00 + c - 0x41) & ctMask16GTE(c, 0x41) & ctMask16LTE(c, 0x5a);
71
    v |= (0xff00 + c - 0x47) & ctMask16GTE(c, 0x61) & ctMask16LTE(c, 0x7a);
72
    v |= ~(v >> 8);
73
74
    return (byte)v;
75
}
76
#else
77
static
78
ALIGN64 const byte base64Decode[] = {          /* + starts at 0x2B */
79
/* 0x28:       + , - . / */                   62, BAD, BAD, BAD,  63,
80
/* 0x30: 0 1 2 3 4 5 6 7 */    52,  53,  54,  55,  56,  57,  58,  59,
81
/* 0x38: 8 9 : ; < = > ? */    60,  61, BAD, BAD, BAD, BAD, BAD, BAD,
82
/* 0x40: @ A B C D E F G */   BAD,   0,   1,   2,   3,   4,   5,   6,
83
/* 0x48: H I J K L M N O */     7,   8,   9,  10,  11,  12,  13,  14,
84
/* 0x50: P Q R S T U V W */    15,  16,  17,  18,  19,  20,  21,  22,
85
/* 0x58: X Y Z [ \ ] ^ _ */    23,  24,  25, BAD, BAD, BAD, BAD, BAD,
86
/* 0x60: ` a b c d e f g */   BAD,  26,  27,  28,  29,  30,  31,  32,
87
/* 0x68: h i j k l m n o */    33,  34,  35,  36,  37,  38,  39,  40,
88
/* 0x70: p q r s t u v w */    41,  42,  43,  44,  45,  46,  47,  48,
89
/* 0x78: x y z           */    49,  50,  51
90
                            };
91
0
#define BASE64DECODE_SZ    (byte)(sizeof(base64Decode))
92
93
static WC_INLINE byte Base64_Char2Val(byte c)
94
0
{
95
0
#ifndef WC_NO_CACHE_RESISTANT
96
    /* 80 characters in table.
97
     * 64 bytes in a cache line - first line has 64, second has 16
98
     */
99
0
    byte v;
100
0
    byte mask;
101
102
0
    c -= BASE64_MIN;
103
0
    mask = (((byte)(0x3f - c)) >> 7) - 1;
104
    /* Load a value from the first cache line and use when mask set. */
105
0
    v  = base64Decode[ c & 0x3f        ] &   mask ;
106
    /* Load a value from the second cache line and use when mask not set. */
107
0
    v |= base64Decode[(c & 0x0f) | 0x40] & (~mask);
108
109
0
    return v;
110
#else
111
    return base64Decode[c - BASE64_MIN];
112
#endif
113
0
}
114
#endif
115
116
int Base64_SkipNewline(const byte* in, word32 *inLen,
117
  word32 *outJ)
118
0
{
119
0
    word32 len = *inLen;
120
0
    word32 j = *outJ;
121
0
    byte curChar;
122
123
0
    if (len == 0) {
124
0
        return BUFFER_E;
125
0
    }
126
0
    curChar = in[j];
127
128
0
    while (len > 1 && curChar == ' ') {
129
        /* skip whitespace in the middle or end of line */
130
0
        curChar = in[++j];
131
0
        len--;
132
0
    }
133
0
    if (len && (curChar == '\r' || curChar == '\n')) {
134
0
        j++;
135
0
        len--;
136
0
        if (curChar == '\r') {
137
0
            if (len) {
138
0
                curChar = in[j++];
139
0
                len--;
140
0
            }
141
0
        }
142
0
        if (curChar != '\n') {
143
0
            WOLFSSL_MSG("Bad end of line in Base64 Decode");
144
0
            return ASN_INPUT_E;
145
0
        }
146
147
0
        if (len) {
148
0
            curChar = in[j];
149
0
        }
150
0
    }
151
0
    while (len && curChar == ' ') {
152
0
        if (--len > 0) {
153
0
            curChar = in[++j];
154
0
        }
155
0
    }
156
0
    if (!len) {
157
0
        return BUFFER_E;
158
0
    }
159
0
    *inLen = len;
160
0
    *outJ = j;
161
0
    return 0;
162
0
}
163
164
int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
165
0
{
166
0
    word32 i = 0;
167
0
    word32 j = 0;
168
0
    word32 plainSz = inLen - ((inLen + (BASE64_LINE_SZ - 1)) / BASE64_LINE_SZ );
169
0
    int ret;
170
0
#ifndef BASE64_NO_TABLE
171
0
    const byte maxIdx = BASE64DECODE_SZ + BASE64_MIN - 1;
172
0
#endif
173
174
0
    plainSz = (plainSz * 3 + 3) / 4;
175
0
    if (plainSz > *outLen) return BAD_FUNC_ARG;
176
177
0
    while (inLen > 3) {
178
0
        int pad3 = 0;
179
0
        int pad4 = 0;
180
0
        byte b1, b2, b3;
181
0
        byte e1, e2, e3, e4;
182
183
0
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
184
0
            if (ret == BUFFER_E) {
185
                /* Running out of buffer here is not an error */
186
0
                break;
187
0
            }
188
0
            return ret;
189
0
        }
190
0
        e1 = in[j++];
191
0
        if (e1 == '\0') {
192
0
            break;
193
0
        }
194
0
        inLen--;
195
0
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
196
0
            return ret;
197
0
        }
198
0
        e2 = in[j++];
199
0
        inLen--;
200
0
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
201
0
            return ret;
202
0
        }
203
0
        e3 = in[j++];
204
0
        inLen--;
205
0
        if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
206
0
            return ret;
207
0
        }
208
0
        e4 = in[j++];
209
0
        inLen--;
210
211
0
        if (e3 == PAD)
212
0
            pad3 = 1;
213
0
        if (e4 == PAD)
214
0
            pad4 = 1;
215
216
0
        if (pad3 && !pad4)
217
0
            return ASN_INPUT_E;
218
219
0
#ifndef BASE64_NO_TABLE
220
0
        if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN ||
221
0
                                                              e4 < BASE64_MIN) {
222
0
            WOLFSSL_MSG("Bad Base64 Decode data, too small");
223
0
            return ASN_INPUT_E;
224
0
        }
225
226
0
        if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
227
0
            WOLFSSL_MSG("Bad Base64 Decode data, too big");
228
0
            return ASN_INPUT_E;
229
0
        }
230
0
#endif
231
232
0
        if (i + 1 + !pad3 + !pad4 > *outLen) {
233
0
            WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
234
0
            return BAD_FUNC_ARG;
235
0
        }
236
237
0
        e1 = Base64_Char2Val(e1);
238
0
        e2 = Base64_Char2Val(e2);
239
0
        e3 = (e3 == PAD) ? 0 : Base64_Char2Val(e3);
240
0
        e4 = (e4 == PAD) ? 0 : Base64_Char2Val(e4);
241
242
0
        if (e1 == BAD || e2 == BAD || e3 == BAD || e4 == BAD) {
243
0
            WOLFSSL_MSG("Bad Base64 Decode bad character");
244
0
            return ASN_INPUT_E;
245
0
        }
246
247
0
        b1 = (byte)((e1 << 2) | (e2 >> 4));
248
0
        b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
249
0
        b3 = (byte)(((e3 & 0x3) << 6) | e4);
250
251
0
        out[i++] = b1;
252
0
        if (!pad3)
253
0
            out[i++] = b2;
254
0
        if (!pad4)
255
0
            out[i++] = b3;
256
0
        else
257
0
            break;
258
0
    }
259
/* If the output buffer has a room for an extra byte, add a null terminator */
260
0
    if (out && *outLen > i)
261
0
        out[i]= '\0';
262
263
0
    *outLen = i;
264
265
0
    return 0;
266
0
}
267
268
#endif /* WOLFSSL_BASE64_DECODE */
269
270
#if defined(WOLFSSL_BASE64_ENCODE)
271
272
static
273
const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
274
                              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
275
                              'U', 'V', 'W', 'X', 'Y', 'Z',
276
                              'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
277
                              'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
278
                              'u', 'v', 'w', 'x', 'y', 'z',
279
                              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
280
                              '+', '/'
281
                            };
282
283
284
/* make sure *i (idx) won't exceed max, store and possibly escape to out,
285
 * raw means use e w/o decode,  0 on success */
286
static int CEscape(int escaped, byte e, byte* out, word32* i, word32 maxSz,
287
                  int raw, int getSzOnly)
288
0
{
289
0
    int    doEscape = 0;
290
0
    word32 needed = 1;
291
0
    word32 idx = *i;
292
293
0
    byte basic;
294
0
    byte plus    = 0;
295
0
    byte equals  = 0;
296
0
    byte newline = 0;
297
298
0
    if (raw)
299
0
        basic = e;
300
0
    else
301
0
        basic = base64Encode[e];
302
303
    /* check whether to escape. Only escape for EncodeEsc */
304
0
    if (escaped == WC_ESC_NL_ENC) {
305
0
        switch ((char)basic) {
306
0
            case '+' :
307
0
                plus     = 1;
308
0
                doEscape = 1;
309
0
                needed  += 2;
310
0
                break;
311
0
            case '=' :
312
0
                equals   = 1;
313
0
                doEscape = 1;
314
0
                needed  += 2;
315
0
                break;
316
0
            case '\n' :
317
0
                newline  = 1;
318
0
                doEscape = 1;
319
0
                needed  += 2;
320
0
                break;
321
0
            default:
322
                /* do nothing */
323
0
                break;
324
0
        }
325
0
    }
326
327
    /* check size */
328
0
    if ( (idx+needed) > maxSz && !getSzOnly) {
329
0
        WOLFSSL_MSG("Escape buffer max too small");
330
0
        return BUFFER_E;
331
0
    }
332
333
    /* store it */
334
0
    if (doEscape == 0) {
335
0
        if(getSzOnly)
336
0
            idx++;
337
0
        else
338
0
            out[idx++] = basic;
339
0
    }
340
0
    else {
341
0
        if(getSzOnly)
342
0
            idx+=3;
343
0
        else {
344
0
            out[idx++] = '%';  /* start escape */
345
346
0
            if (plus) {
347
0
                out[idx++] = '2';
348
0
                out[idx++] = 'B';
349
0
            }
350
0
            else if (equals) {
351
0
                out[idx++] = '3';
352
0
                out[idx++] = 'D';
353
0
            }
354
0
            else if (newline) {
355
0
                out[idx++] = '0';
356
0
                out[idx++] = 'A';
357
0
            }
358
0
        }
359
0
    }
360
0
    *i = idx;
361
362
0
    return 0;
363
0
}
364
365
366
/* internal worker, handles both escaped and normal line endings.
367
   If out buffer is NULL, will return sz needed in outLen */
368
static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
369
                           word32* outLen, int escaped)
370
0
{
371
0
    int    ret = 0;
372
0
    word32 i = 0,
373
0
           j = 0,
374
0
           n = 0;   /* new line counter */
375
376
0
    int    getSzOnly = (out == NULL);
377
378
0
    word32 outSz = (inLen + 3 - 1) / 3 * 4;
379
0
    word32 addSz = (outSz + BASE64_LINE_SZ - 1) / BASE64_LINE_SZ;  /* new lines */
380
381
0
    if (escaped == WC_ESC_NL_ENC)
382
0
        addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
383
0
    else if (escaped == WC_NO_NL_ENC)
384
0
        addSz = 0;    /* encode without \n */
385
386
0
    outSz += addSz;
387
388
    /* if escaped we can't predetermine size for one pass encoding, but
389
     * make sure we have enough if no escapes are in input
390
     * Also need to ensure outLen valid before dereference */
391
0
    if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
392
393
0
    while (inLen > 2) {
394
0
        byte b1 = in[j++];
395
0
        byte b2 = in[j++];
396
0
        byte b3 = in[j++];
397
398
        /* encoded idx */
399
0
        byte e1 = b1 >> 2;
400
0
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
401
0
        byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
402
0
        byte e4 = b3 & 0x3F;
403
404
        /* store */
405
0
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
406
0
        if (ret != 0) break;
407
0
        ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
408
0
        if (ret != 0) break;
409
0
        ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
410
0
        if (ret != 0) break;
411
0
        ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
412
0
        if (ret != 0) break;
413
414
0
        inLen -= 3;
415
416
        /* Insert newline after BASE64_LINE_SZ, unless no \n requested */
417
0
        if (escaped != WC_NO_NL_ENC && (++n % (BASE64_LINE_SZ/4)) == 0 && inLen) {
418
0
            ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
419
0
            if (ret != 0) break;
420
0
        }
421
0
    }
422
423
    /* last integral */
424
0
    if (inLen && ret == 0) {
425
0
        int twoBytes = (inLen == 2);
426
427
0
        byte b1 = in[j++];
428
0
        byte b2 = (twoBytes) ? in[j++] : 0;
429
430
0
        byte e1 = b1 >> 2;
431
0
        byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
432
0
        byte e3 = (byte)((b2 & 0xF) << 2);
433
434
0
        ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
435
0
        if (ret == 0)
436
0
            ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
437
0
        if (ret == 0) {
438
            /* third */
439
0
            if (twoBytes)
440
0
                ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
441
0
            else
442
0
                ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
443
0
        }
444
        /* fourth always pad */
445
0
        if (ret == 0)
446
0
            ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
447
0
    }
448
449
0
    if (ret == 0 && escaped != WC_NO_NL_ENC)
450
0
        ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
451
452
0
    if (i != outSz && escaped != 1 && ret == 0)
453
0
        return ASN_INPUT_E;
454
/* If the output buffer has a room for an extra byte, add a null terminator */
455
0
    if (out && *outLen > i)
456
0
        out[i]= '\0';
457
458
0
    *outLen = i;
459
460
0
    if (ret == 0)
461
0
        return getSzOnly ? LENGTH_ONLY_E : 0;
462
463
0
    return ret;
464
0
}
465
466
467
/* Base64 Encode, PEM style, with \n line endings */
468
int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
469
0
{
470
0
    return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
471
0
}
472
473
474
/* Base64 Encode, with %0A escaped line endings instead of \n */
475
int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
476
0
{
477
0
    return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
478
0
}
479
480
int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
481
0
{
482
0
    return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
483
0
}
484
485
#endif /* WOLFSSL_BASE64_ENCODE */
486
487
488
#ifdef WOLFSSL_BASE16
489
490
static
491
const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
492
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD,
493
                           10, 11, 12, 13, 14, 15,  /* upper case A-F */
494
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
495
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
496
                           BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
497
                           BAD, BAD,  /* G - ` */
498
                           10, 11, 12, 13, 14, 15   /* lower case a-f */
499
                         };  /* A starts at 0x41 not 0x3A */
500
501
int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
502
{
503
    word32 inIdx  = 0;
504
    word32 outIdx = 0;
505
506
    if (in == NULL || out == NULL || outLen == NULL)
507
        return BAD_FUNC_ARG;
508
509
    if (inLen == 1 && *outLen && in) {
510
        byte b = in[inIdx++] - BASE16_MIN;  /* 0 starts at 0x30 */
511
512
        /* sanity check */
513
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
514
            return ASN_INPUT_E;
515
516
        b  = hexDecode[b];
517
518
        if (b == BAD)
519
            return ASN_INPUT_E;
520
521
        out[outIdx++] = b;
522
523
        *outLen = outIdx;
524
        return 0;
525
    }
526
527
    if (inLen % 2)
528
        return BAD_FUNC_ARG;
529
530
    if (*outLen < (inLen / 2))
531
        return BAD_FUNC_ARG;
532
533
    while (inLen) {
534
        byte b  = in[inIdx++] - BASE16_MIN;  /* 0 starts at 0x30 */
535
        byte b2 = in[inIdx++] - BASE16_MIN;
536
537
        /* sanity checks */
538
        if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
539
            return ASN_INPUT_E;
540
        if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
541
            return ASN_INPUT_E;
542
543
        b  = hexDecode[b];
544
        b2 = hexDecode[b2];
545
546
        if (b == BAD || b2 == BAD)
547
            return ASN_INPUT_E;
548
549
        out[outIdx++] = (byte)((b << 4) | b2);
550
        inLen -= 2;
551
    }
552
553
    *outLen = outIdx;
554
    return 0;
555
}
556
557
int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
558
{
559
    word32 outIdx = 0;
560
    word32 i;
561
    byte   hb, lb;
562
563
    if (in == NULL || out == NULL || outLen == NULL)
564
        return BAD_FUNC_ARG;
565
566
    if (*outLen < (2 * inLen))
567
        return BAD_FUNC_ARG;
568
569
    for (i = 0; i < inLen; i++) {
570
        hb = in[i] >> 4;
571
        lb = in[i] & 0x0f;
572
573
        /* ASCII value */
574
        hb += '0';
575
        if (hb > '9')
576
            hb += 7;
577
578
        /* ASCII value */
579
        lb += '0';
580
        if (lb>'9')
581
            lb += 7;
582
583
        out[outIdx++] = hb;
584
        out[outIdx++] = lb;
585
    }
586
587
    /* If the output buffer has a room for an extra byte, add a null terminator */
588
    if (*outLen > outIdx)
589
        out[outIdx++]= '\0';
590
591
    *outLen = outIdx;
592
    return 0;
593
}
594
595
#endif /* WOLFSSL_BASE16 */
596
597
#endif /* !NO_CODING */