• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/usign/base64.c

  1 /*
  2  * base64 - libubox base64 functions
  3  *
  4  * Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org>
  5  *
  6  * Permission to use, copy, modify, and/or distribute this software for any
  7  * purpose with or without fee is hereby granted, provided that the above
  8  * copyright notice and this permission notice appear in all copies.
  9  *
 10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 17  */
 18 
 19 /*      $OpenBSD: base64.c,v 1.7 2013/12/31 02:32:56 tedu Exp $ */
 20 
 21 /*
 22  * Copyright (c) 1996 by Internet Software Consortium.
 23  *
 24  * Permission to use, copy, modify, and distribute this software for any
 25  * purpose with or without fee is hereby granted, provided that the above
 26  * copyright notice and this permission notice appear in all copies.
 27  *
 28  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 29  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 30  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 31  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 32  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 33  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 34  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 35  * SOFTWARE.
 36  */
 37 
 38 /*
 39  * Portions Copyright (c) 1995 by International Business Machines, Inc.
 40  *
 41  * International Business Machines, Inc. (hereinafter called IBM) grants
 42  * permission under its copyrights to use, copy, modify, and distribute this
 43  * Software with or without fee, provided that the above copyright notice and
 44  * all paragraphs of this notice appear in all copies, and that the name of IBM
 45  * not be used in connection with the marketing of any product incorporating
 46  * the Software or modifications thereof, without specific, written prior
 47  * permission.
 48  *
 49  * To the extent it has a right to do so, IBM grants an immunity from suit
 50  * under its patents, if any, for the use, sale or manufacture of products to
 51  * the extent that such products are used for performing Domain Name System
 52  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
 53  * granted for any product per se or for any other function of any product.
 54  *
 55  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
 56  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 57  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
 58  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
 59  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
 60  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
 61  */
 62 
 63 #include <sys/types.h>
 64 #include <ctype.h>
 65 #include <stdio.h>
 66 #include <stdlib.h>
 67 #include <string.h>
 68 #include "base64.h"
 69 
 70 static const char Base64[] =
 71         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 72 static const char Pad64 = '=';
 73 
 74 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
 75    The following encoding technique is taken from RFC 1521 by Borenstein
 76    and Freed.  It is reproduced here in a slightly edited form for
 77    convenience.
 78 
 79    A 65-character subset of US-ASCII is used, enabling 6 bits to be
 80    represented per printable character. (The extra 65th character, "=",
 81    is used to signify a special processing function.)
 82 
 83    The encoding process represents 24-bit groups of input bits as output
 84    strings of 4 encoded characters. Proceeding from left to right, a
 85    24-bit input group is formed by concatenating 3 8-bit input groups.
 86    These 24 bits are then treated as 4 concatenated 6-bit groups, each
 87    of which is translated into a single digit in the base64 alphabet.
 88 
 89    Each 6-bit group is used as an index into an array of 64 printable
 90    characters. The character referenced by the index is placed in the
 91    output string.
 92 
 93                          Table 1: The Base64 Alphabet
 94 
 95       Value Encoding  Value Encoding  Value Encoding  Value Encoding
 96           0 A            17 R            34 i            51 z
 97           1 B            18 S            35 j            52 0
 98           2 C            19 T            36 k            53 1
 99           3 D            20 U            37 l            54 2
100           4 E            21 V            38 m            55 3
101           5 F            22 W            39 n            56 4
102           6 G            23 X            40 o            57 5
103           7 H            24 Y            41 p            58 6
104           8 I            25 Z            42 q            59 7
105           9 J            26 a            43 r            60 8
106          10 K            27 b            44 s            61 9
107          11 L            28 c            45 t            62 +
108          12 M            29 d            46 u            63 /
109          13 N            30 e            47 v
110          14 O            31 f            48 w         (pad) =
111          15 P            32 g            49 x
112          16 Q            33 h            50 y
113 
114    Special processing is performed if fewer than 24 bits are available
115    at the end of the data being encoded.  A full encoding quantum is
116    always completed at the end of a quantity.  When fewer than 24 input
117    bits are available in an input group, zero bits are added (on the
118    right) to form an integral number of 6-bit groups.  Padding at the
119    end of the data is performed using the '=' character.
120 
121    Since all base64 input is an integral number of octets, only the
122          -------------------------------------------------                       
123    following cases can arise:
124    
125        (1) the final quantum of encoding input is an integral
126            multiple of 24 bits; here, the final unit of encoded
127            output will be an integral multiple of 4 characters
128            with no "=" padding,
129        (2) the final quantum of encoding input is exactly 8 bits;
130            here, the final unit of encoded output will be two
131            characters followed by two "=" padding characters, or
132        (3) the final quantum of encoding input is exactly 16 bits;
133            here, the final unit of encoded output will be three
134            characters followed by one "=" padding character.
135    */
136 
137 int b64_encode(const void *_src, size_t srclength,
138                void *dest, size_t targsize)
139 {
140         const unsigned char *src = _src;
141         char *target = dest;
142         size_t datalength = 0;
143         u_char input[3];
144         u_char output[4];
145         int i;
146 
147         while (2 < srclength) {
148                 input[0] = *src++;
149                 input[1] = *src++;
150                 input[2] = *src++;
151                 srclength -= 3;
152 
153                 output[0] = input[0] >> 2;
154                 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
155                 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
156                 output[3] = input[2] & 0x3f;
157 
158                 if (datalength + 4 > targsize)
159                         return (-1);
160                 target[datalength++] = Base64[output[0]];
161                 target[datalength++] = Base64[output[1]];
162                 target[datalength++] = Base64[output[2]];
163                 target[datalength++] = Base64[output[3]];
164         }
165 
166         /* Now we worry about padding. */
167         if (0 != srclength) {
168                 /* Get what's left. */
169                 input[0] = input[1] = input[2] = '\0';
170                 for (i = 0; i < srclength; i++)
171                         input[i] = *src++;
172 
173                 output[0] = input[0] >> 2;
174                 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
175                 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
176 
177                 if (datalength + 4 > targsize)
178                         return (-1);
179                 target[datalength++] = Base64[output[0]];
180                 target[datalength++] = Base64[output[1]];
181                 if (srclength == 1)
182                         target[datalength++] = Pad64;
183                 else
184                         target[datalength++] = Base64[output[2]];
185                 target[datalength++] = Pad64;
186         }
187         if (datalength >= targsize)
188                 return (-1);
189         target[datalength] = '\0';      /* Returned value doesn't count \0. */
190         return (datalength);
191 }
192 
193 /* skips all whitespace anywhere.
194    converts characters, four at a time, starting at (or after)
195    src from base - 64 numbers into three 8 bit bytes in the target area.
196    it returns the number of data bytes stored at the target, or -1 on error.
197  */
198 
199 int b64_decode(const void *_src, void *dest, size_t targsize)
200 {
201         const char *src = _src;
202         unsigned char *target = dest;
203         int tarindex, state, ch;
204         u_char nextbyte;
205         char *pos;
206 
207         state = 0;
208         tarindex = 0;
209 
210         while ((ch = (unsigned char)*src++) != '\0') {
211                 if (isspace(ch))        /* Skip whitespace anywhere. */
212                         continue;
213 
214                 if (ch == Pad64)
215                         break;
216 
217                 pos = strchr(Base64, ch);
218                 if (pos == 0)           /* A non-base64 character. */
219                         return (-1);
220 
221                 switch (state) {
222                 case 0:
223                         if (target) {
224                                 if (tarindex >= targsize)
225                                         return (-1);
226                                 target[tarindex] = (pos - Base64) << 2;
227                         }
228                         state = 1;
229                         break;
230                 case 1:
231                         if (target) {
232                                 if (tarindex >= targsize)
233                                         return (-1);
234                                 target[tarindex]   |=  (pos - Base64) >> 4;
235                                 nextbyte = ((pos - Base64) & 0x0f) << 4;
236                                 if (tarindex + 1 < targsize)
237                                         target[tarindex+1] = nextbyte;
238                                 else if (nextbyte)
239                                         return (-1);
240                         }
241                         tarindex++;
242                         state = 2;
243                         break;
244                 case 2:
245                         if (target) {
246                                 if (tarindex >= targsize)
247                                         return (-1);
248                                 target[tarindex]   |=  (pos - Base64) >> 2;
249                                 nextbyte = ((pos - Base64) & 0x03) << 6;
250                                 if (tarindex + 1 < targsize)
251                                         target[tarindex+1] = nextbyte;
252                                 else if (nextbyte)
253                                         return (-1);
254                         }
255                         tarindex++;
256                         state = 3;
257                         break;
258                 case 3:
259                         if (target) {
260                                 if (tarindex >= targsize)
261                                         return (-1);
262                                 target[tarindex] |= (pos - Base64);
263                         }
264                         tarindex++;
265                         state = 0;
266                         break;
267                 }
268         }
269 
270         /*
271          * We are done decoding Base-64 chars.  Let's see if we ended
272          * on a byte boundary, and/or with erroneous trailing characters.
273          */
274 
275         if (ch == Pad64) {                      /* We got a pad char. */
276                 ch = (unsigned char)*src++;     /* Skip it, get next. */
277                 switch (state) {
278                 case 0:         /* Invalid = in first position */
279                 case 1:         /* Invalid = in second position */
280                         return (-1);
281 
282                 case 2:         /* Valid, means one byte of info */
283                         /* Skip any number of spaces. */
284                         for (; ch != '\0'; ch = (unsigned char)*src++)
285                                 if (!isspace(ch))
286                                         break;
287                         /* Make sure there is another trailing = sign. */
288                         if (ch != Pad64)
289                                 return (-1);
290                         ch = (unsigned char)*src++;             /* Skip the = */
291                         /* Fall through to "single trailing =" case. */
292                         /* FALLTHROUGH */
293 
294                 case 3:         /* Valid, means two bytes of info */
295                         /*
296                          * We know this char is an =.  Is there anything but
297                          * whitespace after it?
298                          */
299                         for (; ch != '\0'; ch = (unsigned char)*src++)
300                                 if (!isspace(ch))
301                                         return (-1);
302 
303                         /*
304                          * Now make sure for cases 2 and 3 that the "extra"
305                          * bits that slopped past the last full byte were
306                          * zeros.  If we don't check them, they become a
307                          * subliminal channel.
308                          */
309                         if (target && tarindex < targsize &&
310                             target[tarindex] != 0)
311                                 return (-1);
312                 }
313         } else {
314                 /*
315                  * We ended by seeing the end of the string.  Make sure we
316                  * have no partial bytes lying around.
317                  */
318                 if (state != 0)
319                         return (-1);
320         }
321 
322         /* Null-terminate if we have room left */
323         if (tarindex < targsize)
324                 target[tarindex] = 0;
325 
326         return (tarindex);
327 }
328 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt