1 /* 2 * Copyright (c) 1996, 1998 by Internet Software Consortium. 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 15 * SOFTWARE. 16 */ 17 18 /* 19 * Portions Copyright (c) 1995 by International Business Machines, Inc. 20 * 21 * International Business Machines, Inc. (hereinafter called IBM) grants 22 * permission under its copyrights to use, copy, modify, and distribute this 23 * Software with or without fee, provided that the above copyright notice and 24 * all paragraphs of this notice appear in all copies, and that the name of IBM 25 * not be used in connection with the marketing of any product incorporating 26 * the Software or modifications thereof, without specific, written prior 27 * permission. 28 * 29 * To the extent it has a right to do so, IBM grants an immunity from suit 30 * under its patents, if any, for the use, sale or manufacture of products to 31 * the extent that such products are used for performing Domain Name System 32 * dynamic updates in TCP/IP networks by means of the Software. No immunity is 33 * granted for any product per se or for any other function of any product. 34 * 35 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 37 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 38 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 39 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 40 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 41 */ 42 #include <ldns/config.h> 43 #ifndef HAVE_B64_PTON 44 45 #include <sys/types.h> 46 #include <sys/param.h> 47 #ifdef HAVE_SYS_SOCKET_H 48 #include <sys/socket.h> 49 #endif 50 51 #ifdef HAVE_NETINET_IN_H 52 #include <netinet/in.h> 53 #endif 54 #ifdef HAVE_ARPA_INET_H 55 #include <arpa/inet.h> 56 #endif 57 58 #include <ctype.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 63 #include <ldns/util.h> 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 /* skips all whitespace anywhere. 133 converts characters, four at a time, starting at (or after) 134 src from base - 64 numbers into three 8 bit bytes in the target area. 135 it returns the number of data bytes stored at the target, or -1 on error. 136 */ 137 138 int 139 ldns_b64_pton(char const *src, uint8_t *target, size_t targsize) 140 { 141 int tarindex, state, ch; 142 char *pos; 143 144 state = 0; 145 tarindex = 0; 146 147 if (strlen(src) == 0) { 148 return 0; 149 } 150 151 while ((ch = *src++) != '\0') { 152 if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ 153 continue; 154 155 if (ch == Pad64) 156 break; 157 158 pos = strchr(Base64, ch); 159 if (pos == 0) { 160 /* A non-base64 character. */ 161 return (-1); 162 } 163 164 switch (state) { 165 case 0: 166 if (target) { 167 if ((size_t)tarindex >= targsize) 168 return (-1); 169 target[tarindex] = (pos - Base64) << 2; 170 } 171 state = 1; 172 break; 173 case 1: 174 if (target) { 175 if ((size_t)tarindex + 1 >= targsize) 176 return (-1); 177 target[tarindex] |= (pos - Base64) >> 4; 178 target[tarindex+1] = ((pos - Base64) & 0x0f) 179 << 4 ; 180 } 181 tarindex++; 182 state = 2; 183 break; 184 case 2: 185 if (target) { 186 if ((size_t)tarindex + 1 >= targsize) 187 return (-1); 188 target[tarindex] |= (pos - Base64) >> 2; 189 target[tarindex+1] = ((pos - Base64) & 0x03) 190 << 6; 191 } 192 tarindex++; 193 state = 3; 194 break; 195 case 3: 196 if (target) { 197 if ((size_t)tarindex >= targsize) 198 return (-1); 199 target[tarindex] |= (pos - Base64); 200 } 201 tarindex++; 202 state = 0; 203 break; 204 default: 205 abort(); 206 } 207 } 208 209 /* 210 * We are done decoding Base-64 chars. Let's see if we ended 211 * on a byte boundary, and/or with erroneous trailing characters. 212 */ 213 214 if (ch == Pad64) { /* We got a pad char. */ 215 ch = *src++; /* Skip it, get next. */ 216 switch (state) { 217 case 0: /* Invalid = in first position */ 218 case 1: /* Invalid = in second position */ 219 return (-1); 220 221 case 2: /* Valid, means one byte of info */ 222 /* Skip any number of spaces. */ 223 for ((void)NULL; ch != '\0'; ch = *src++) 224 if (!isspace((unsigned char)ch)) 225 break; 226 /* Make sure there is another trailing = sign. */ 227 if (ch != Pad64) 228 return (-1); 229 ch = *src++; /* Skip the = */ 230 /* Fall through to "single trailing =" case. */ 231 /* FALLTHROUGH */ 232 233 case 3: /* Valid, means two bytes of info */ 234 /* 235 * We know this char is an =. Is there anything but 236 * whitespace after it? 237 */ 238 for ((void)NULL; ch != '\0'; ch = *src++) 239 if (!isspace((unsigned char)ch)) 240 return (-1); 241 242 /* 243 * Now make sure for cases 2 and 3 that the "extra" 244 * bits that slopped past the last full byte were 245 * zeros. If we don't check them, they become a 246 * subliminal channel. 247 */ 248 if (target && target[tarindex] != 0) 249 return (-1); 250 } 251 } else { 252 /* 253 * We ended by seeing the end of the string. Make sure we 254 * have no partial bytes lying around. 255 */ 256 if (state != 0) 257 return (-1); 258 } 259 260 return (tarindex); 261 } 262 263 #endif /* !HAVE_B64_PTON */ 264