b64_ntop.c revision 1.1.1.1.4.2 1 1.1.1.1.4.2 pgoyette /*
2 1.1.1.1.4.2 pgoyette * Copyright (c) 1996, 1998 by Internet Software Consortium.
3 1.1.1.1.4.2 pgoyette *
4 1.1.1.1.4.2 pgoyette * Permission to use, copy, modify, and distribute this software for any
5 1.1.1.1.4.2 pgoyette * purpose with or without fee is hereby granted, provided that the above
6 1.1.1.1.4.2 pgoyette * copyright notice and this permission notice appear in all copies.
7 1.1.1.1.4.2 pgoyette *
8 1.1.1.1.4.2 pgoyette * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 1.1.1.1.4.2 pgoyette * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 1.1.1.1.4.2 pgoyette * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 1.1.1.1.4.2 pgoyette * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 1.1.1.1.4.2 pgoyette * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 1.1.1.1.4.2 pgoyette * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 1.1.1.1.4.2 pgoyette * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 1.1.1.1.4.2 pgoyette * SOFTWARE.
16 1.1.1.1.4.2 pgoyette */
17 1.1.1.1.4.2 pgoyette
18 1.1.1.1.4.2 pgoyette /*
19 1.1.1.1.4.2 pgoyette * Portions Copyright (c) 1995 by International Business Machines, Inc.
20 1.1.1.1.4.2 pgoyette *
21 1.1.1.1.4.2 pgoyette * International Business Machines, Inc. (hereinafter called IBM) grants
22 1.1.1.1.4.2 pgoyette * permission under its copyrights to use, copy, modify, and distribute this
23 1.1.1.1.4.2 pgoyette * Software with or without fee, provided that the above copyright notice and
24 1.1.1.1.4.2 pgoyette * all paragraphs of this notice appear in all copies, and that the name of IBM
25 1.1.1.1.4.2 pgoyette * not be used in connection with the marketing of any product incorporating
26 1.1.1.1.4.2 pgoyette * the Software or modifications thereof, without specific, written prior
27 1.1.1.1.4.2 pgoyette * permission.
28 1.1.1.1.4.2 pgoyette *
29 1.1.1.1.4.2 pgoyette * To the extent it has a right to do so, IBM grants an immunity from suit
30 1.1.1.1.4.2 pgoyette * under its patents, if any, for the use, sale or manufacture of products to
31 1.1.1.1.4.2 pgoyette * the extent that such products are used for performing Domain Name System
32 1.1.1.1.4.2 pgoyette * dynamic updates in TCP/IP networks by means of the Software. No immunity is
33 1.1.1.1.4.2 pgoyette * granted for any product per se or for any other function of any product.
34 1.1.1.1.4.2 pgoyette *
35 1.1.1.1.4.2 pgoyette * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
36 1.1.1.1.4.2 pgoyette * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37 1.1.1.1.4.2 pgoyette * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
38 1.1.1.1.4.2 pgoyette * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
39 1.1.1.1.4.2 pgoyette * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
40 1.1.1.1.4.2 pgoyette * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
41 1.1.1.1.4.2 pgoyette */
42 1.1.1.1.4.2 pgoyette #include <config.h>
43 1.1.1.1.4.2 pgoyette
44 1.1.1.1.4.2 pgoyette #include <sys/types.h>
45 1.1.1.1.4.2 pgoyette #include <sys/param.h>
46 1.1.1.1.4.2 pgoyette #include <sys/socket.h>
47 1.1.1.1.4.2 pgoyette
48 1.1.1.1.4.2 pgoyette #include <netinet/in.h>
49 1.1.1.1.4.2 pgoyette #include <arpa/inet.h>
50 1.1.1.1.4.2 pgoyette
51 1.1.1.1.4.2 pgoyette #include <ctype.h>
52 1.1.1.1.4.2 pgoyette #include <stdio.h>
53 1.1.1.1.4.2 pgoyette #include <stdlib.h>
54 1.1.1.1.4.2 pgoyette #include <string.h>
55 1.1.1.1.4.2 pgoyette
56 1.1.1.1.4.2 pgoyette #define Assert(Cond) if (!(Cond)) abort()
57 1.1.1.1.4.2 pgoyette
58 1.1.1.1.4.2 pgoyette static const char Base64[] =
59 1.1.1.1.4.2 pgoyette "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60 1.1.1.1.4.2 pgoyette static const char Pad64 = '=';
61 1.1.1.1.4.2 pgoyette
62 1.1.1.1.4.2 pgoyette /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
63 1.1.1.1.4.2 pgoyette The following encoding technique is taken from RFC 1521 by Borenstein
64 1.1.1.1.4.2 pgoyette and Freed. It is reproduced here in a slightly edited form for
65 1.1.1.1.4.2 pgoyette convenience.
66 1.1.1.1.4.2 pgoyette
67 1.1.1.1.4.2 pgoyette A 65-character subset of US-ASCII is used, enabling 6 bits to be
68 1.1.1.1.4.2 pgoyette represented per printable character. (The extra 65th character, "=",
69 1.1.1.1.4.2 pgoyette is used to signify a special processing function.)
70 1.1.1.1.4.2 pgoyette
71 1.1.1.1.4.2 pgoyette The encoding process represents 24-bit groups of input bits as output
72 1.1.1.1.4.2 pgoyette strings of 4 encoded characters. Proceeding from left to right, a
73 1.1.1.1.4.2 pgoyette 24-bit input group is formed by concatenating 3 8-bit input groups.
74 1.1.1.1.4.2 pgoyette These 24 bits are then treated as 4 concatenated 6-bit groups, each
75 1.1.1.1.4.2 pgoyette of which is translated into a single digit in the base64 alphabet.
76 1.1.1.1.4.2 pgoyette
77 1.1.1.1.4.2 pgoyette Each 6-bit group is used as an index into an array of 64 printable
78 1.1.1.1.4.2 pgoyette characters. The character referenced by the index is placed in the
79 1.1.1.1.4.2 pgoyette output string.
80 1.1.1.1.4.2 pgoyette
81 1.1.1.1.4.2 pgoyette Table 1: The Base64 Alphabet
82 1.1.1.1.4.2 pgoyette
83 1.1.1.1.4.2 pgoyette Value Encoding Value Encoding Value Encoding Value Encoding
84 1.1.1.1.4.2 pgoyette 0 A 17 R 34 i 51 z
85 1.1.1.1.4.2 pgoyette 1 B 18 S 35 j 52 0
86 1.1.1.1.4.2 pgoyette 2 C 19 T 36 k 53 1
87 1.1.1.1.4.2 pgoyette 3 D 20 U 37 l 54 2
88 1.1.1.1.4.2 pgoyette 4 E 21 V 38 m 55 3
89 1.1.1.1.4.2 pgoyette 5 F 22 W 39 n 56 4
90 1.1.1.1.4.2 pgoyette 6 G 23 X 40 o 57 5
91 1.1.1.1.4.2 pgoyette 7 H 24 Y 41 p 58 6
92 1.1.1.1.4.2 pgoyette 8 I 25 Z 42 q 59 7
93 1.1.1.1.4.2 pgoyette 9 J 26 a 43 r 60 8
94 1.1.1.1.4.2 pgoyette 10 K 27 b 44 s 61 9
95 1.1.1.1.4.2 pgoyette 11 L 28 c 45 t 62 +
96 1.1.1.1.4.2 pgoyette 12 M 29 d 46 u 63 /
97 1.1.1.1.4.2 pgoyette 13 N 30 e 47 v
98 1.1.1.1.4.2 pgoyette 14 O 31 f 48 w (pad) =
99 1.1.1.1.4.2 pgoyette 15 P 32 g 49 x
100 1.1.1.1.4.2 pgoyette 16 Q 33 h 50 y
101 1.1.1.1.4.2 pgoyette
102 1.1.1.1.4.2 pgoyette Special processing is performed if fewer than 24 bits are available
103 1.1.1.1.4.2 pgoyette at the end of the data being encoded. A full encoding quantum is
104 1.1.1.1.4.2 pgoyette always completed at the end of a quantity. When fewer than 24 input
105 1.1.1.1.4.2 pgoyette bits are available in an input group, zero bits are added (on the
106 1.1.1.1.4.2 pgoyette right) to form an integral number of 6-bit groups. Padding at the
107 1.1.1.1.4.2 pgoyette end of the data is performed using the '=' character.
108 1.1.1.1.4.2 pgoyette
109 1.1.1.1.4.2 pgoyette Since all base64 input is an integral number of octets, only the
110 1.1.1.1.4.2 pgoyette -------------------------------------------------
111 1.1.1.1.4.2 pgoyette following cases can arise:
112 1.1.1.1.4.2 pgoyette
113 1.1.1.1.4.2 pgoyette (1) the final quantum of encoding input is an integral
114 1.1.1.1.4.2 pgoyette multiple of 24 bits; here, the final unit of encoded
115 1.1.1.1.4.2 pgoyette output will be an integral multiple of 4 characters
116 1.1.1.1.4.2 pgoyette with no "=" padding,
117 1.1.1.1.4.2 pgoyette (2) the final quantum of encoding input is exactly 8 bits;
118 1.1.1.1.4.2 pgoyette here, the final unit of encoded output will be two
119 1.1.1.1.4.2 pgoyette characters followed by two "=" padding characters, or
120 1.1.1.1.4.2 pgoyette (3) the final quantum of encoding input is exactly 16 bits;
121 1.1.1.1.4.2 pgoyette here, the final unit of encoded output will be three
122 1.1.1.1.4.2 pgoyette characters followed by one "=" padding character.
123 1.1.1.1.4.2 pgoyette */
124 1.1.1.1.4.2 pgoyette
125 1.1.1.1.4.2 pgoyette int
126 1.1.1.1.4.2 pgoyette b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
127 1.1.1.1.4.2 pgoyette size_t datalength = 0;
128 1.1.1.1.4.2 pgoyette uint8_t input[3];
129 1.1.1.1.4.2 pgoyette uint8_t output[4];
130 1.1.1.1.4.2 pgoyette size_t i;
131 1.1.1.1.4.2 pgoyette
132 1.1.1.1.4.2 pgoyette while (2 < srclength) {
133 1.1.1.1.4.2 pgoyette input[0] = *src++;
134 1.1.1.1.4.2 pgoyette input[1] = *src++;
135 1.1.1.1.4.2 pgoyette input[2] = *src++;
136 1.1.1.1.4.2 pgoyette srclength -= 3;
137 1.1.1.1.4.2 pgoyette
138 1.1.1.1.4.2 pgoyette output[0] = input[0] >> 2;
139 1.1.1.1.4.2 pgoyette output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
140 1.1.1.1.4.2 pgoyette output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
141 1.1.1.1.4.2 pgoyette output[3] = input[2] & 0x3f;
142 1.1.1.1.4.2 pgoyette Assert(output[0] < 64);
143 1.1.1.1.4.2 pgoyette Assert(output[1] < 64);
144 1.1.1.1.4.2 pgoyette Assert(output[2] < 64);
145 1.1.1.1.4.2 pgoyette Assert(output[3] < 64);
146 1.1.1.1.4.2 pgoyette
147 1.1.1.1.4.2 pgoyette if (datalength + 4 > targsize)
148 1.1.1.1.4.2 pgoyette return (-1);
149 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[0]];
150 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[1]];
151 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[2]];
152 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[3]];
153 1.1.1.1.4.2 pgoyette }
154 1.1.1.1.4.2 pgoyette
155 1.1.1.1.4.2 pgoyette /* Now we worry about padding. */
156 1.1.1.1.4.2 pgoyette if (0 != srclength) {
157 1.1.1.1.4.2 pgoyette /* Get what's left. */
158 1.1.1.1.4.2 pgoyette input[0] = input[1] = input[2] = '\0';
159 1.1.1.1.4.2 pgoyette for (i = 0; i < srclength; i++)
160 1.1.1.1.4.2 pgoyette input[i] = *src++;
161 1.1.1.1.4.2 pgoyette
162 1.1.1.1.4.2 pgoyette output[0] = input[0] >> 2;
163 1.1.1.1.4.2 pgoyette output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
164 1.1.1.1.4.2 pgoyette output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
165 1.1.1.1.4.2 pgoyette Assert(output[0] < 64);
166 1.1.1.1.4.2 pgoyette Assert(output[1] < 64);
167 1.1.1.1.4.2 pgoyette Assert(output[2] < 64);
168 1.1.1.1.4.2 pgoyette
169 1.1.1.1.4.2 pgoyette if (datalength + 4 > targsize)
170 1.1.1.1.4.2 pgoyette return (-1);
171 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[0]];
172 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[1]];
173 1.1.1.1.4.2 pgoyette if (srclength == 1)
174 1.1.1.1.4.2 pgoyette target[datalength++] = Pad64;
175 1.1.1.1.4.2 pgoyette else
176 1.1.1.1.4.2 pgoyette target[datalength++] = Base64[output[2]];
177 1.1.1.1.4.2 pgoyette target[datalength++] = Pad64;
178 1.1.1.1.4.2 pgoyette }
179 1.1.1.1.4.2 pgoyette if (datalength >= targsize)
180 1.1.1.1.4.2 pgoyette return (-1);
181 1.1.1.1.4.2 pgoyette target[datalength] = '\0'; /* Returned value doesn't count \0. */
182 1.1.1.1.4.2 pgoyette return (datalength);
183 1.1.1.1.4.2 pgoyette }
184