]> andersk Git - gssapi-openssh.git/blob - openssh/openbsd-compat/base64.c
Initial revision
[gssapi-openssh.git] / openssh / openbsd-compat / base64.c
1 /*      $OpenBSD: base64.c,v 1.3 1997/11/08 20:46:55 deraadt Exp $      */
2
3 /*
4  * Copyright (c) 1996 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 "config.h"
46
47 #if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)
48
49 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
54
55 #include <ctype.h>
56 #include <stdio.h>
57
58 #include <stdlib.h>
59 #include <string.h>
60
61 #include "base64.h"
62
63 #define Assert(Cond) if (!(Cond)) abort()
64
65 static const char Base64[] =
66         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
67 static const char Pad64 = '=';
68
69 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
70    The following encoding technique is taken from RFC 1521 by Borenstein
71    and Freed.  It is reproduced here in a slightly edited form for
72    convenience.
73
74    A 65-character subset of US-ASCII is used, enabling 6 bits to be
75    represented per printable character. (The extra 65th character, "=",
76    is used to signify a special processing function.)
77
78    The encoding process represents 24-bit groups of input bits as output
79    strings of 4 encoded characters. Proceeding from left to right, a
80    24-bit input group is formed by concatenating 3 8-bit input groups.
81    These 24 bits are then treated as 4 concatenated 6-bit groups, each
82    of which is translated into a single digit in the base64 alphabet.
83
84    Each 6-bit group is used as an index into an array of 64 printable
85    characters. The character referenced by the index is placed in the
86    output string.
87
88                          Table 1: The Base64 Alphabet
89
90       Value Encoding  Value Encoding  Value Encoding  Value Encoding
91           0 A            17 R            34 i            51 z
92           1 B            18 S            35 j            52 0
93           2 C            19 T            36 k            53 1
94           3 D            20 U            37 l            54 2
95           4 E            21 V            38 m            55 3
96           5 F            22 W            39 n            56 4
97           6 G            23 X            40 o            57 5
98           7 H            24 Y            41 p            58 6
99           8 I            25 Z            42 q            59 7
100           9 J            26 a            43 r            60 8
101          10 K            27 b            44 s            61 9
102          11 L            28 c            45 t            62 +
103          12 M            29 d            46 u            63 /
104          13 N            30 e            47 v
105          14 O            31 f            48 w         (pad) =
106          15 P            32 g            49 x
107          16 Q            33 h            50 y
108
109    Special processing is performed if fewer than 24 bits are available
110    at the end of the data being encoded.  A full encoding quantum is
111    always completed at the end of a quantity.  When fewer than 24 input
112    bits are available in an input group, zero bits are added (on the
113    right) to form an integral number of 6-bit groups.  Padding at the
114    end of the data is performed using the '=' character.
115
116    Since all base64 input is an integral number of octets, only the
117          -------------------------------------------------                       
118    following cases can arise:
119    
120        (1) the final quantum of encoding input is an integral
121            multiple of 24 bits; here, the final unit of encoded
122            output will be an integral multiple of 4 characters
123            with no "=" padding,
124        (2) the final quantum of encoding input is exactly 8 bits;
125            here, the final unit of encoded output will be two
126            characters followed by two "=" padding characters, or
127        (3) the final quantum of encoding input is exactly 16 bits;
128            here, the final unit of encoded output will be three
129            characters followed by one "=" padding character.
130    */
131
132 int
133 b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
134 {
135         size_t datalength = 0;
136         u_char input[3];
137         u_char output[4];
138         int i;
139
140         while (2 < srclength) {
141                 input[0] = *src++;
142                 input[1] = *src++;
143                 input[2] = *src++;
144                 srclength -= 3;
145
146                 output[0] = input[0] >> 2;
147                 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
148                 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
149                 output[3] = input[2] & 0x3f;
150                 Assert(output[0] < 64);
151                 Assert(output[1] < 64);
152                 Assert(output[2] < 64);
153                 Assert(output[3] < 64);
154
155                 if (datalength + 4 > targsize)
156                         return (-1);
157                 target[datalength++] = Base64[output[0]];
158                 target[datalength++] = Base64[output[1]];
159                 target[datalength++] = Base64[output[2]];
160                 target[datalength++] = Base64[output[3]];
161         }
162     
163         /* Now we worry about padding. */
164         if (0 != srclength) {
165                 /* Get what's left. */
166                 input[0] = input[1] = input[2] = '\0';
167                 for (i = 0; i < srclength; i++)
168                         input[i] = *src++;
169         
170                 output[0] = input[0] >> 2;
171                 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
172                 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
173                 Assert(output[0] < 64);
174                 Assert(output[1] < 64);
175                 Assert(output[2] < 64);
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
200 b64_pton(char const *src, u_char *target, size_t targsize)
201 {
202         int tarindex, state, ch;
203         char *pos;
204
205         state = 0;
206         tarindex = 0;
207
208         while ((ch = *src++) != '\0') {
209                 if (isspace(ch))        /* Skip whitespace anywhere. */
210                         continue;
211
212                 if (ch == Pad64)
213                         break;
214
215                 pos = strchr(Base64, ch);
216                 if (pos == 0)           /* A non-base64 character. */
217                         return (-1);
218
219                 switch (state) {
220                 case 0:
221                         if (target) {
222                                 if (tarindex >= targsize)
223                                         return (-1);
224                                 target[tarindex] = (pos - Base64) << 2;
225                         }
226                         state = 1;
227                         break;
228                 case 1:
229                         if (target) {
230                                 if (tarindex + 1 >= targsize)
231                                         return (-1);
232                                 target[tarindex]   |=  (pos - Base64) >> 4;
233                                 target[tarindex+1]  = ((pos - Base64) & 0x0f)
234                                                         << 4 ;
235                         }
236                         tarindex++;
237                         state = 2;
238                         break;
239                 case 2:
240                         if (target) {
241                                 if (tarindex + 1 >= targsize)
242                                         return (-1);
243                                 target[tarindex]   |=  (pos - Base64) >> 2;
244                                 target[tarindex+1]  = ((pos - Base64) & 0x03)
245                                                         << 6;
246                         }
247                         tarindex++;
248                         state = 3;
249                         break;
250                 case 3:
251                         if (target) {
252                                 if (tarindex >= targsize)
253                                         return (-1);
254                                 target[tarindex] |= (pos - Base64);
255                         }
256                         tarindex++;
257                         state = 0;
258                         break;
259                 }
260         }
261
262         /*
263          * We are done decoding Base-64 chars.  Let's see if we ended
264          * on a byte boundary, and/or with erroneous trailing characters.
265          */
266
267         if (ch == Pad64) {              /* We got a pad char. */
268                 ch = *src++;            /* Skip it, get next. */
269                 switch (state) {
270                 case 0:         /* Invalid = in first position */
271                 case 1:         /* Invalid = in second position */
272                         return (-1);
273
274                 case 2:         /* Valid, means one byte of info */
275                         /* Skip any number of spaces. */
276                         for (; ch != '\0'; ch = *src++)
277                                 if (!isspace(ch))
278                                         break;
279                         /* Make sure there is another trailing = sign. */
280                         if (ch != Pad64)
281                                 return (-1);
282                         ch = *src++;            /* Skip the = */
283                         /* Fall through to "single trailing =" case. */
284                         /* FALLTHROUGH */
285
286                 case 3:         /* Valid, means two bytes of info */
287                         /*
288                          * We know this char is an =.  Is there anything but
289                          * whitespace after it?
290                          */
291                         for (; ch != '\0'; ch = *src++)
292                                 if (!isspace(ch))
293                                         return (-1);
294
295                         /*
296                          * Now make sure for cases 2 and 3 that the "extra"
297                          * bits that slopped past the last full byte were
298                          * zeros.  If we don't check them, they become a
299                          * subliminal channel.
300                          */
301                         if (target && target[tarindex] != 0)
302                                 return (-1);
303                 }
304         } else {
305                 /*
306                  * We ended by seeing the end of the string.  Make sure we
307                  * have no partial bytes lying around.
308                  */
309                 if (state != 0)
310                         return (-1);
311         }
312
313         return (tarindex);
314 }
315
316 #endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */
This page took 0.05915 seconds and 5 git commands to generate.