source: rtems-libbsd/freebsd/lib/libc/net/base64.c @ f41a394

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

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