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