1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 #include "tomcrypt_private.h"
11 
12 /**
13   @file base64_decode.c
14   Compliant base64 code donated by Wayne Scott (wscott@bitmover.com)
15   base64 URL Safe variant (RFC 4648 section 5) by Karel Miko
16 */
17 
18 
19 #if defined(LTC_BASE64) || defined (LTC_BASE64_URL)
20 
21 /* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32)
22  * 254 - padding character '=' (allowed only at the end)
23  * 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode
24  */
25 
26 #if defined(LTC_BASE64)
27 static const unsigned char map_base64[256] = {
28 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255,
29 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
30 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,
31 255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
32  52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
33 255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
34   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
35  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
36 255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
37  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
38  49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
39 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
40 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
41 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
42 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
43 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
44 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
45 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
46 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
47 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
48 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
49 255, 255, 255, 255 };
50 #endif /* LTC_BASE64 */
51 
52 static const unsigned char map_base64url[] = {
53 #if defined(LTC_BASE64_URL)
54 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255,
55 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255,
57 255, 255, 255, 255, 255, 255, 255, 255, 255,  62, 255, 255,
58  52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
59 255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
60   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
61  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255,  63,
62 255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
63  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
64  49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75 255, 255, 255, 255
76 #endif /* LTC_BASE64_URL */
77 };
78 
79 enum {
80    insane = 0,
81    strict = 1,
82    relaxed = 2
83 };
84 
_base64_decode_internal(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,const unsigned char * map,int mode)85 static int _base64_decode_internal(const char *in,  unsigned long inlen,
86                                  unsigned char *out, unsigned long *outlen,
87                            const unsigned char *map, int mode)
88 {
89    unsigned long t, x, y, z;
90    unsigned char c;
91    int           g;
92 
93    LTC_ARGCHK(in     != NULL);
94    LTC_ARGCHK(out    != NULL);
95    LTC_ARGCHK(outlen != NULL);
96 
97    g = 0; /* '=' counter */
98    for (x = y = z = t = 0; x < inlen; x++) {
99        if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) {
100           continue; /* allow the last byte to be NUL (relaxed+insane) */
101        }
102        c = map[(unsigned char)in[x]&0xFF];
103        if (c == 254) {
104           g++;
105           continue;
106        }
107        if (c == 253) {
108           if (mode == strict) {
109              return CRYPT_INVALID_PACKET;
110           }
111           continue; /* allow to ignore white-spaces (relaxed+insane) */
112        }
113        if (c == 255) {
114           if (mode == insane) {
115              continue; /* allow to ignore invalid garbage (insane) */
116           }
117           return CRYPT_INVALID_PACKET;
118        }
119        if ((g > 0) && (mode != insane)) {
120           /* we only allow '=' to be at the end (strict+relaxed) */
121           return CRYPT_INVALID_PACKET;
122        }
123 
124        t = (t<<6)|c;
125 
126        if (++y == 4) {
127           if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW;
128           out[z++] = (unsigned char)((t>>16)&255);
129           out[z++] = (unsigned char)((t>>8)&255);
130           out[z++] = (unsigned char)(t&255);
131           y = t = 0;
132        }
133    }
134 
135    if (y != 0) {
136       if (y == 1) return CRYPT_INVALID_PACKET;
137       if (((y + g) != 4) && (mode == strict) && (map != map_base64url)) return CRYPT_INVALID_PACKET;
138       t = t << (6 * (4 - y));
139       if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW;
140       if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255);
141       if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255);
142    }
143    *outlen = z;
144    return CRYPT_OK;
145 }
146 
147 #if defined(LTC_BASE64)
148 /**
149    Dangerously relaxed base64 decode a block of memory
150    @param in       The base64 data to decode
151    @param inlen    The length of the base64 data
152    @param out      [out] The destination of the binary decoded data
153    @param outlen   [in/out] The max size and resulting size of the decoded data
154    @return CRYPT_OK if successful
155 */
base64_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)156 int base64_decode(const char *in,  unsigned long inlen,
157                         unsigned char *out, unsigned long *outlen)
158 {
159     return _base64_decode_internal(in, inlen, out, outlen, map_base64, insane);
160 }
161 
162 /**
163    Strict base64 decode a block of memory
164    @param in       The base64 data to decode
165    @param inlen    The length of the base64 data
166    @param out      [out] The destination of the binary decoded data
167    @param outlen   [in/out] The max size and resulting size of the decoded data
168    @return CRYPT_OK if successful
169 */
base64_strict_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)170 int base64_strict_decode(const char *in,  unsigned long inlen,
171                         unsigned char *out, unsigned long *outlen)
172 {
173    return _base64_decode_internal(in, inlen, out, outlen, map_base64, strict);
174 }
175 
176 /**
177    Sane base64 decode a block of memory
178    @param in       The base64 data to decode
179    @param inlen    The length of the base64 data
180    @param out      [out] The destination of the binary decoded data
181    @param outlen   [in/out] The max size and resulting size of the decoded data
182    @return CRYPT_OK if successful
183 */
base64_sane_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)184 int base64_sane_decode(const char *in,  unsigned long inlen,
185                         unsigned char *out, unsigned long *outlen)
186 {
187    return _base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed);
188 }
189 #endif /* LTC_BASE64 */
190 
191 #if defined(LTC_BASE64_URL)
192 /**
193    Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) decode a block of memory
194    @param in       The base64 data to decode
195    @param inlen    The length of the base64 data
196    @param out      [out] The destination of the binary decoded data
197    @param outlen   [in/out] The max size and resulting size of the decoded data
198    @return CRYPT_OK if successful
199 */
base64url_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)200 int base64url_decode(const char *in,  unsigned long inlen,
201                            unsigned char *out, unsigned long *outlen)
202 {
203     return _base64_decode_internal(in, inlen, out, outlen, map_base64url, insane);
204 }
205 
206 /**
207    Strict base64 (URL Safe, RFC 4648 section 5) decode a block of memory
208    @param in       The base64 data to decode
209    @param inlen    The length of the base64 data
210    @param out      [out] The destination of the binary decoded data
211    @param outlen   [in/out] The max size and resulting size of the decoded data
212    @return CRYPT_OK if successful
213 */
base64url_strict_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)214 int base64url_strict_decode(const char *in,  unsigned long inlen,
215                            unsigned char *out, unsigned long *outlen)
216 {
217     return _base64_decode_internal(in, inlen, out, outlen, map_base64url, strict);
218 }
219 
220 /**
221    Sane base64 (URL Safe, RFC 4648 section 5) decode a block of memory
222    @param in       The base64 data to decode
223    @param inlen    The length of the base64 data
224    @param out      [out] The destination of the binary decoded data
225    @param outlen   [in/out] The max size and resulting size of the decoded data
226    @return CRYPT_OK if successful
227 */
base64url_sane_decode(const char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)228 int base64url_sane_decode(const char *in,  unsigned long inlen,
229                            unsigned char *out, unsigned long *outlen)
230 {
231     return _base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed);
232 }
233 #endif /* LTC_BASE64_URL */
234 
235 #endif
236 
237 
238 /* ref:         $Format:%D$ */
239 /* git commit:  $Format:%H$ */
240 /* commit time: $Format:%ai$ */
241