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 int
ldns_b64_ntop(uint8_t const * src,size_t srclength,char * target,size_t targsize)115825eb42bSJan Lentfer ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
116825eb42bSJan Lentfer size_t datalength = 0;
117825eb42bSJan Lentfer uint8_t input[3];
118825eb42bSJan Lentfer uint8_t output[4];
119825eb42bSJan Lentfer size_t i;
120825eb42bSJan Lentfer
121825eb42bSJan Lentfer if (srclength == 0) {
122825eb42bSJan Lentfer if (targsize > 0) {
123825eb42bSJan Lentfer target[0] = '\0';
124825eb42bSJan Lentfer return 0;
125825eb42bSJan Lentfer } else {
126825eb42bSJan Lentfer return -1;
127825eb42bSJan Lentfer }
128825eb42bSJan Lentfer }
129825eb42bSJan Lentfer
130825eb42bSJan Lentfer while (2 < srclength) {
131825eb42bSJan Lentfer input[0] = *src++;
132825eb42bSJan Lentfer input[1] = *src++;
133825eb42bSJan Lentfer input[2] = *src++;
134825eb42bSJan Lentfer srclength -= 3;
135825eb42bSJan Lentfer
136825eb42bSJan Lentfer output[0] = input[0] >> 2;
137825eb42bSJan Lentfer output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
138825eb42bSJan Lentfer output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
139825eb42bSJan Lentfer output[3] = input[2] & 0x3f;
140*5340022aSzrj assert(output[0] < 64);
141*5340022aSzrj assert(output[1] < 64);
142*5340022aSzrj assert(output[2] < 64);
143*5340022aSzrj assert(output[3] < 64);
144825eb42bSJan Lentfer
145825eb42bSJan Lentfer if (datalength + 4 > targsize) {
146825eb42bSJan Lentfer return (-1);
147825eb42bSJan Lentfer }
148825eb42bSJan Lentfer target[datalength++] = Base64[output[0]];
149825eb42bSJan Lentfer target[datalength++] = Base64[output[1]];
150825eb42bSJan Lentfer target[datalength++] = Base64[output[2]];
151825eb42bSJan Lentfer target[datalength++] = Base64[output[3]];
152825eb42bSJan Lentfer }
153825eb42bSJan Lentfer
154825eb42bSJan Lentfer /* Now we worry about padding. */
155825eb42bSJan Lentfer if (0 != srclength) {
156825eb42bSJan Lentfer /* Get what's left. */
157825eb42bSJan Lentfer input[0] = input[1] = input[2] = (uint8_t) '\0';
158825eb42bSJan Lentfer for (i = 0; i < srclength; i++)
159825eb42bSJan Lentfer input[i] = *src++;
160825eb42bSJan Lentfer
161825eb42bSJan Lentfer output[0] = input[0] >> 2;
162825eb42bSJan Lentfer output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
163825eb42bSJan Lentfer output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
164*5340022aSzrj assert(output[0] < 64);
165*5340022aSzrj assert(output[1] < 64);
166*5340022aSzrj assert(output[2] < 64);
167825eb42bSJan Lentfer
168825eb42bSJan Lentfer if (datalength + 4 > targsize) {
169825eb42bSJan Lentfer return (-2);
170825eb42bSJan Lentfer }
171825eb42bSJan Lentfer target[datalength++] = Base64[output[0]];
172825eb42bSJan Lentfer target[datalength++] = Base64[output[1]];
173825eb42bSJan Lentfer if (srclength == 1) {
174825eb42bSJan Lentfer target[datalength++] = Pad64;
175825eb42bSJan Lentfer } else {
176825eb42bSJan Lentfer target[datalength++] = Base64[output[2]];
177825eb42bSJan Lentfer }
178825eb42bSJan Lentfer target[datalength++] = Pad64;
179825eb42bSJan Lentfer }
180825eb42bSJan Lentfer if (datalength >= targsize) {
181825eb42bSJan Lentfer return (-3);
182825eb42bSJan Lentfer }
183825eb42bSJan Lentfer target[datalength] = '\0'; /* Returned value doesn't count \0. */
184825eb42bSJan Lentfer return (int) (datalength);
185825eb42bSJan Lentfer }
186