1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer * Copyright (c) 1996, 1998 by Internet Software Consortium.
3825eb42bSJan Lentfer *
4825eb42bSJan Lentfer * Permission to use, copy, modify, and distribute this software for any
5825eb42bSJan Lentfer * purpose with or without fee is hereby granted, provided that the above
6825eb42bSJan Lentfer * copyright notice and this permission notice appear in all copies.
7825eb42bSJan Lentfer *
8825eb42bSJan Lentfer * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9825eb42bSJan Lentfer * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10825eb42bSJan Lentfer * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11825eb42bSJan Lentfer * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12825eb42bSJan Lentfer * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13825eb42bSJan Lentfer * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14825eb42bSJan Lentfer * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15825eb42bSJan Lentfer * SOFTWARE.
16825eb42bSJan Lentfer */
17825eb42bSJan Lentfer
18825eb42bSJan Lentfer /*
19825eb42bSJan Lentfer * Portions Copyright (c) 1995 by International Business Machines, Inc.
20825eb42bSJan Lentfer *
21825eb42bSJan Lentfer * International Business Machines, Inc. (hereinafter called IBM) grants
22825eb42bSJan Lentfer * permission under its copyrights to use, copy, modify, and distribute this
23825eb42bSJan Lentfer * Software with or without fee, provided that the above copyright notice and
24825eb42bSJan Lentfer * all paragraphs of this notice appear in all copies, and that the name of IBM
25825eb42bSJan Lentfer * not be used in connection with the marketing of any product incorporating
26825eb42bSJan Lentfer * the Software or modifications thereof, without specific, written prior
27825eb42bSJan Lentfer * permission.
28825eb42bSJan Lentfer *
29825eb42bSJan Lentfer * To the extent it has a right to do so, IBM grants an immunity from suit
30825eb42bSJan Lentfer * under its patents, if any, for the use, sale or manufacture of products to
31825eb42bSJan Lentfer * the extent that such products are used for performing Domain Name System
32825eb42bSJan Lentfer * dynamic updates in TCP/IP networks by means of the Software. No immunity is
33825eb42bSJan Lentfer * granted for any product per se or for any other function of any product.
34825eb42bSJan Lentfer *
35825eb42bSJan Lentfer * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
36825eb42bSJan Lentfer * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37825eb42bSJan Lentfer * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
38825eb42bSJan Lentfer * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
39825eb42bSJan Lentfer * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
40825eb42bSJan Lentfer * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
41825eb42bSJan Lentfer */
42825eb42bSJan Lentfer #include <ldns/config.h>
43825eb42bSJan Lentfer #include <ctype.h>
44825eb42bSJan Lentfer #include <stdlib.h>
45825eb42bSJan Lentfer #include <string.h>
46825eb42bSJan Lentfer
47825eb42bSJan Lentfer static const char Base64[] =
48825eb42bSJan Lentfer "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
49825eb42bSJan Lentfer static const char Pad64 = '=';
50825eb42bSJan Lentfer
51825eb42bSJan Lentfer /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
52825eb42bSJan Lentfer The following encoding technique is taken from RFC 1521 by Borenstein
53825eb42bSJan Lentfer and Freed. It is reproduced here in a slightly edited form for
54825eb42bSJan Lentfer convenience.
55825eb42bSJan Lentfer
56825eb42bSJan Lentfer A 65-character subset of US-ASCII is used, enabling 6 bits to be
57825eb42bSJan Lentfer represented per printable character. (The extra 65th character, "=",
58825eb42bSJan Lentfer is used to signify a special processing function.)
59825eb42bSJan Lentfer
60825eb42bSJan Lentfer The encoding process represents 24-bit groups of input bits as output
61825eb42bSJan Lentfer strings of 4 encoded characters. Proceeding from left to right, a
62825eb42bSJan Lentfer 24-bit input group is formed by concatenating 3 8-bit input groups.
63825eb42bSJan Lentfer These 24 bits are then treated as 4 concatenated 6-bit groups, each
64825eb42bSJan Lentfer of which is translated into a single digit in the base64 alphabet.
65825eb42bSJan Lentfer
66825eb42bSJan Lentfer Each 6-bit group is used as an index into an array of 64 printable
67825eb42bSJan Lentfer characters. The character referenced by the index is placed in the
68825eb42bSJan Lentfer output string.
69825eb42bSJan Lentfer
70825eb42bSJan Lentfer Table 1: The Base64 Alphabet
71825eb42bSJan Lentfer
72825eb42bSJan Lentfer Value Encoding Value Encoding Value Encoding Value Encoding
73825eb42bSJan Lentfer 0 A 17 R 34 i 51 z
74825eb42bSJan Lentfer 1 B 18 S 35 j 52 0
75825eb42bSJan Lentfer 2 C 19 T 36 k 53 1
76825eb42bSJan Lentfer 3 D 20 U 37 l 54 2
77825eb42bSJan Lentfer 4 E 21 V 38 m 55 3
78825eb42bSJan Lentfer 5 F 22 W 39 n 56 4
79825eb42bSJan Lentfer 6 G 23 X 40 o 57 5
80825eb42bSJan Lentfer 7 H 24 Y 41 p 58 6
81825eb42bSJan Lentfer 8 I 25 Z 42 q 59 7
82825eb42bSJan Lentfer 9 J 26 a 43 r 60 8
83825eb42bSJan Lentfer 10 K 27 b 44 s 61 9
84825eb42bSJan Lentfer 11 L 28 c 45 t 62 +
85825eb42bSJan Lentfer 12 M 29 d 46 u 63 /
86825eb42bSJan Lentfer 13 N 30 e 47 v
87825eb42bSJan Lentfer 14 O 31 f 48 w (pad) =
88825eb42bSJan Lentfer 15 P 32 g 49 x
89825eb42bSJan Lentfer 16 Q 33 h 50 y
90825eb42bSJan Lentfer
91825eb42bSJan Lentfer Special processing is performed if fewer than 24 bits are available
92825eb42bSJan Lentfer at the end of the data being encoded. A full encoding quantum is
93825eb42bSJan Lentfer always completed at the end of a quantity. When fewer than 24 input
94825eb42bSJan Lentfer bits are available in an input group, zero bits are added (on the
95825eb42bSJan Lentfer right) to form an integral number of 6-bit groups. Padding at the
96825eb42bSJan Lentfer end of the data is performed using the '=' character.
97825eb42bSJan Lentfer
98825eb42bSJan Lentfer Since all base64 input is an integral number of octets, only the
99825eb42bSJan Lentfer -------------------------------------------------
100825eb42bSJan Lentfer following cases can arise:
101825eb42bSJan Lentfer
102825eb42bSJan Lentfer (1) the final quantum of encoding input is an integral
103825eb42bSJan Lentfer multiple of 24 bits; here, the final unit of encoded
104825eb42bSJan Lentfer output will be an integral multiple of 4 characters
105825eb42bSJan Lentfer with no "=" padding,
106825eb42bSJan Lentfer (2) the final quantum of encoding input is exactly 8 bits;
107825eb42bSJan Lentfer here, the final unit of encoded output will be two
108825eb42bSJan Lentfer characters followed by two "=" padding characters, or
109825eb42bSJan Lentfer (3) the final quantum of encoding input is exactly 16 bits;
110825eb42bSJan Lentfer here, the final unit of encoded output will be three
111825eb42bSJan Lentfer characters followed by one "=" padding character.
112825eb42bSJan Lentfer */
113825eb42bSJan Lentfer
114825eb42bSJan Lentfer /* skips all whitespace anywhere.
115825eb42bSJan Lentfer converts characters, four at a time, starting at (or after)
116825eb42bSJan Lentfer src from base - 64 numbers into three 8 bit bytes in the target area.
117825eb42bSJan Lentfer it returns the number of data bytes stored at the target, or -1 on error.
118825eb42bSJan Lentfer */
119825eb42bSJan Lentfer
120825eb42bSJan Lentfer int
ldns_b64_pton(char const * origsrc,uint8_t * target,size_t targsize)121*5340022aSzrj ldns_b64_pton(char const *origsrc, uint8_t *target, size_t targsize)
122825eb42bSJan Lentfer {
123*5340022aSzrj unsigned char const* src = (unsigned char*)origsrc;
124825eb42bSJan Lentfer int tarindex, state, ch;
125825eb42bSJan Lentfer char *pos;
126825eb42bSJan Lentfer
127825eb42bSJan Lentfer state = 0;
128825eb42bSJan Lentfer tarindex = 0;
129825eb42bSJan Lentfer
130*5340022aSzrj if (strlen(origsrc) == 0) {
131825eb42bSJan Lentfer return 0;
132825eb42bSJan Lentfer }
133825eb42bSJan Lentfer
134825eb42bSJan Lentfer while ((ch = *src++) != '\0') {
135825eb42bSJan Lentfer if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */
136825eb42bSJan Lentfer continue;
137825eb42bSJan Lentfer
138825eb42bSJan Lentfer if (ch == Pad64)
139825eb42bSJan Lentfer break;
140825eb42bSJan Lentfer
141825eb42bSJan Lentfer pos = strchr(Base64, ch);
142825eb42bSJan Lentfer if (pos == 0) {
143825eb42bSJan Lentfer /* A non-base64 character. */
144825eb42bSJan Lentfer return (-1);
145825eb42bSJan Lentfer }
146825eb42bSJan Lentfer
147825eb42bSJan Lentfer switch (state) {
148825eb42bSJan Lentfer case 0:
149825eb42bSJan Lentfer if (target) {
150825eb42bSJan Lentfer if ((size_t)tarindex >= targsize)
151825eb42bSJan Lentfer return (-1);
152825eb42bSJan Lentfer target[tarindex] = (pos - Base64) << 2;
153825eb42bSJan Lentfer }
154825eb42bSJan Lentfer state = 1;
155825eb42bSJan Lentfer break;
156825eb42bSJan Lentfer case 1:
157825eb42bSJan Lentfer if (target) {
158825eb42bSJan Lentfer if ((size_t)tarindex + 1 >= targsize)
159825eb42bSJan Lentfer return (-1);
160825eb42bSJan Lentfer target[tarindex] |= (pos - Base64) >> 4;
161825eb42bSJan Lentfer target[tarindex+1] = ((pos - Base64) & 0x0f)
162825eb42bSJan Lentfer << 4 ;
163825eb42bSJan Lentfer }
164825eb42bSJan Lentfer tarindex++;
165825eb42bSJan Lentfer state = 2;
166825eb42bSJan Lentfer break;
167825eb42bSJan Lentfer case 2:
168825eb42bSJan Lentfer if (target) {
169825eb42bSJan Lentfer if ((size_t)tarindex + 1 >= targsize)
170825eb42bSJan Lentfer return (-1);
171825eb42bSJan Lentfer target[tarindex] |= (pos - Base64) >> 2;
172825eb42bSJan Lentfer target[tarindex+1] = ((pos - Base64) & 0x03)
173825eb42bSJan Lentfer << 6;
174825eb42bSJan Lentfer }
175825eb42bSJan Lentfer tarindex++;
176825eb42bSJan Lentfer state = 3;
177825eb42bSJan Lentfer break;
178825eb42bSJan Lentfer case 3:
179825eb42bSJan Lentfer if (target) {
180825eb42bSJan Lentfer if ((size_t)tarindex >= targsize)
181825eb42bSJan Lentfer return (-1);
182825eb42bSJan Lentfer target[tarindex] |= (pos - Base64);
183825eb42bSJan Lentfer }
184825eb42bSJan Lentfer tarindex++;
185825eb42bSJan Lentfer state = 0;
186825eb42bSJan Lentfer break;
187825eb42bSJan Lentfer default:
188825eb42bSJan Lentfer abort();
189825eb42bSJan Lentfer }
190825eb42bSJan Lentfer }
191825eb42bSJan Lentfer
192825eb42bSJan Lentfer /*
193825eb42bSJan Lentfer * We are done decoding Base-64 chars. Let's see if we ended
194825eb42bSJan Lentfer * on a byte boundary, and/or with erroneous trailing characters.
195825eb42bSJan Lentfer */
196825eb42bSJan Lentfer
197825eb42bSJan Lentfer if (ch == Pad64) { /* We got a pad char. */
198825eb42bSJan Lentfer ch = *src++; /* Skip it, get next. */
199825eb42bSJan Lentfer switch (state) {
200825eb42bSJan Lentfer case 0: /* Invalid = in first position */
201825eb42bSJan Lentfer case 1: /* Invalid = in second position */
202825eb42bSJan Lentfer return (-1);
203825eb42bSJan Lentfer
204825eb42bSJan Lentfer case 2: /* Valid, means one byte of info */
205825eb42bSJan Lentfer /* Skip any number of spaces. */
206825eb42bSJan Lentfer for ((void)NULL; ch != '\0'; ch = *src++)
207825eb42bSJan Lentfer if (!isspace((unsigned char)ch))
208825eb42bSJan Lentfer break;
209825eb42bSJan Lentfer /* Make sure there is another trailing = sign. */
210825eb42bSJan Lentfer if (ch != Pad64)
211825eb42bSJan Lentfer return (-1);
212825eb42bSJan Lentfer ch = *src++; /* Skip the = */
213825eb42bSJan Lentfer /* Fall through to "single trailing =" case. */
214825eb42bSJan Lentfer /* FALLTHROUGH */
215825eb42bSJan Lentfer
216825eb42bSJan Lentfer case 3: /* Valid, means two bytes of info */
217825eb42bSJan Lentfer /*
218825eb42bSJan Lentfer * We know this char is an =. Is there anything but
219825eb42bSJan Lentfer * whitespace after it?
220825eb42bSJan Lentfer */
221825eb42bSJan Lentfer for ((void)NULL; ch != '\0'; ch = *src++)
222825eb42bSJan Lentfer if (!isspace((unsigned char)ch))
223825eb42bSJan Lentfer return (-1);
224825eb42bSJan Lentfer
225825eb42bSJan Lentfer /*
226825eb42bSJan Lentfer * Now make sure for cases 2 and 3 that the "extra"
227825eb42bSJan Lentfer * bits that slopped past the last full byte were
228825eb42bSJan Lentfer * zeros. If we don't check them, they become a
229825eb42bSJan Lentfer * subliminal channel.
230825eb42bSJan Lentfer */
231825eb42bSJan Lentfer if (target && target[tarindex] != 0)
232825eb42bSJan Lentfer return (-1);
233825eb42bSJan Lentfer }
234825eb42bSJan Lentfer } else {
235825eb42bSJan Lentfer /*
236825eb42bSJan Lentfer * We ended by seeing the end of the string. Make sure we
237825eb42bSJan Lentfer * have no partial bytes lying around.
238825eb42bSJan Lentfer */
239825eb42bSJan Lentfer if (state != 0)
240825eb42bSJan Lentfer return (-1);
241825eb42bSJan Lentfer }
242825eb42bSJan Lentfer
243825eb42bSJan Lentfer return (tarindex);
244825eb42bSJan Lentfer }
245