1/* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (c) 1996-2003 by Internet Software Consortium 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * Internet Systems Consortium, Inc. 18 * 950 Charter Street 19 * Redwood City, CA 94063 20 * <info@isc.org> 21 * http://www.isc.org/ 22 */ 23 24/* 25 * Portions Copyright (c) 1995 by International Business Machines, Inc. 26 * 27 * International Business Machines, Inc. (hereinafter called IBM) grants 28 * permission under its copyrights to use, copy, modify, and distribute this 29 * Software with or without fee, provided that the above copyright notice and 30 * all paragraphs of this notice appear in all copies, and that the name of IBM 31 * not be used in connection with the marketing of any product incorporating 32 * the Software or modifications thereof, without specific, written prior 33 * permission. 34 * 35 * To the extent it has a right to do so, IBM grants an immunity from suit 36 * under its patents, if any, for the use, sale or manufacture of products to 37 * the extent that such products are used for performing Domain Name System 38 * dynamic updates in TCP/IP networks by means of the Software. No immunity is 39 * granted for any product per se or for any other function of any product. 40 * 41 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 42 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 43 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 44 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 45 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 46 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 47 */ 48 49#if !defined(LINT) && !defined(CODECENTER) 50static const char rcsid[] = "$Id: base64.c,v 1.3 2005/08/11 17:13:21 drochner Exp $"; 51#endif /* not lint */ 52 53#include <sys/types.h> 54#include <sys/param.h> 55#include <sys/socket.h> 56 57#include <netinet/in.h> 58#include <arpa/inet.h> 59 60#include <ctype.h> 61#include <stdio.h> 62#include <stdlib.h> 63#include <string.h> 64 65#include <sys/socket.h> 66 67#include "minires/minires.h" 68#include "arpa/nameser.h" 69 70#define Assert(Cond) if (!(Cond)) abort() 71 72static const char Base64[] = 73 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 74static const char Pad64 = '='; 75 76/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 77 The following encoding technique is taken from RFC 1521 by Borenstein 78 and Freed. It is reproduced here in a slightly edited form for 79 convenience. 80 81 A 65-character subset of US-ASCII is used, enabling 6 bits to be 82 represented per printable character. (The extra 65th character, "=", 83 is used to signify a special processing function.) 84 85 The encoding process represents 24-bit groups of input bits as output 86 strings of 4 encoded characters. Proceeding from left to right, a 87 24-bit input group is formed by concatenating 3 8-bit input groups. 88 These 24 bits are then treated as 4 concatenated 6-bit groups, each 89 of which is translated into a single digit in the base64 alphabet. 90 91 Each 6-bit group is used as an index into an array of 64 printable 92 characters. The character referenced by the index is placed in the 93 output string. 94 95 Table 1: The Base64 Alphabet 96 97 Value Encoding Value Encoding Value Encoding Value Encoding 98 0 A 17 R 34 i 51 z 99 1 B 18 S 35 j 52 0 100 2 C 19 T 36 k 53 1 101 3 D 20 U 37 l 54 2 102 4 E 21 V 38 m 55 3 103 5 F 22 W 39 n 56 4 104 6 G 23 X 40 o 57 5 105 7 H 24 Y 41 p 58 6 106 8 I 25 Z 42 q 59 7 107 9 J 26 a 43 r 60 8 108 10 K 27 b 44 s 61 9 109 11 L 28 c 45 t 62 + 110 12 M 29 d 46 u 63 / 111 13 N 30 e 47 v 112 14 O 31 f 48 w (pad) = 113 15 P 32 g 49 x 114 16 Q 33 h 50 y 115 116 Special processing is performed if fewer than 24 bits are available 117 at the end of the data being encoded. A full encoding quantum is 118 always completed at the end of a quantity. When fewer than 24 input 119 bits are available in an input group, zero bits are added (on the 120 right) to form an integral number of 6-bit groups. Padding at the 121 end of the data is performed using the '=' character. 122 123 Since all base64 input is an integral number of octets, only the 124 ------------------------------------------------- 125 following cases can arise: 126 127 (1) the final quantum of encoding input is an integral 128 multiple of 24 bits; here, the final unit of encoded 129 output will be an integral multiple of 4 characters 130 with no "=" padding, 131 (2) the final quantum of encoding input is exactly 8 bits; 132 here, the final unit of encoded output will be two 133 characters followed by two "=" padding characters, or 134 (3) the final quantum of encoding input is exactly 16 bits; 135 here, the final unit of encoded output will be three 136 characters followed by one "=" padding character. 137 */ 138 139int 140b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { 141 size_t datalength = 0; 142 u_char input[3]; 143 u_char output[4]; 144 size_t i; 145 146 while (2 < srclength) { 147 input[0] = *src++; 148 input[1] = *src++; 149 input[2] = *src++; 150 srclength -= 3; 151 152 output[0] = input[0] >> 2; 153 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 154 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 155 output[3] = input[2] & 0x3f; 156 Assert(output[0] < 64); 157 Assert(output[1] < 64); 158 Assert(output[2] < 64); 159 Assert(output[3] < 64); 160 161 if (datalength + 4 > targsize) 162 return (-1); 163 target[datalength++] = Base64[output[0]]; 164 target[datalength++] = Base64[output[1]]; 165 target[datalength++] = Base64[output[2]]; 166 target[datalength++] = Base64[output[3]]; 167 } 168 169 /* Now we worry about padding. */ 170 if (0 != srclength) { 171 /* Get what's left. */ 172 input[0] = input[1] = input[2] = '\0'; 173 for (i = 0; i < srclength; i++) 174 input[i] = *src++; 175 176 output[0] = input[0] >> 2; 177 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 178 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 179 Assert(output[0] < 64); 180 Assert(output[1] < 64); 181 Assert(output[2] < 64); 182 183 if (datalength + 4 > targsize) 184 return (-1); 185 target[datalength++] = Base64[output[0]]; 186 target[datalength++] = Base64[output[1]]; 187 if (srclength == 1) 188 target[datalength++] = Pad64; 189 else 190 target[datalength++] = Base64[output[2]]; 191 target[datalength++] = Pad64; 192 } 193 if (datalength >= targsize) 194 return (-1); 195 target[datalength] = '\0'; /* Returned value doesn't count \0. */ 196 return (datalength); 197} 198 199/* skips all whitespace anywhere. 200 converts characters, four at a time, starting at (or after) 201 src from base - 64 numbers into three 8 bit bytes in the target area. 202 it returns the number of data bytes stored at the target, or -1 on error. 203 */ 204 205int 206b64_pton(src, target, targsize) 207 char const *src; 208 u_char *target; 209 size_t targsize; 210{ 211 int tarindex, state, ch; 212 char *pos; 213 214 state = 0; 215 tarindex = 0; 216 217 while ((ch = *src++) != '\0') { 218 if (isspace(ch)) /* Skip whitespace anywhere. */ 219 continue; 220 221 if (ch == Pad64) 222 break; 223 224 pos = strchr(Base64, ch); 225 if (pos == 0) /* A non-base64 character. */ 226 return (-1); 227 228 switch (state) { 229 case 0: 230 if (target) { 231 if ((size_t)tarindex >= targsize) 232 return (-1); 233 target[tarindex] = (pos - Base64) << 2; 234 } 235 state = 1; 236 break; 237 case 1: 238 if (target) { 239 if ((size_t)tarindex + 1 >= targsize) 240 return (-1); 241 target[tarindex] |= (pos - Base64) >> 4; 242 target[tarindex+1] = ((pos - Base64) & 0x0f) 243 << 4 ; 244 } 245 tarindex++; 246 state = 2; 247 break; 248 case 2: 249 if (target) { 250 if ((size_t)tarindex + 1 >= targsize) 251 return (-1); 252 target[tarindex] |= (pos - Base64) >> 2; 253 target[tarindex+1] = ((pos - Base64) & 0x03) 254 << 6; 255 } 256 tarindex++; 257 state = 3; 258 break; 259 case 3: 260 if (target) { 261 if ((size_t)tarindex >= targsize) 262 return (-1); 263 target[tarindex] |= (pos - Base64); 264 } 265 tarindex++; 266 state = 0; 267 break; 268 default: 269 abort(); 270 } 271 } 272 273 /* 274 * We are done decoding Base-64 chars. Let's see if we ended 275 * on a byte boundary, and/or with erroneous trailing characters. 276 */ 277 278 if (ch == Pad64) { /* We got a pad char. */ 279 ch = *src++; /* Skip it, get next. */ 280 switch (state) { 281 case 0: /* Invalid = in first position */ 282 case 1: /* Invalid = in second position */ 283 return (-1); 284 285 case 2: /* Valid, means one byte of info */ 286 /* Skip any number of spaces. */ 287 for ((void)NULL; ch != '\0'; ch = *src++) 288 if (!isspace(ch)) 289 break; 290 /* Make sure there is another trailing = sign. */ 291 if (ch != Pad64) 292 return (-1); 293 ch = *src++; /* Skip the = */ 294 /* Fall through to "single trailing =" case. */ 295 /* FALLTHROUGH */ 296 297 case 3: /* Valid, means two bytes of info */ 298 /* 299 * We know this char is an =. Is there anything but 300 * whitespace after it? 301 */ 302 for ((void)NULL; ch != '\0'; ch = *src++) 303 if (!isspace(ch)) 304 return (-1); 305 306 /* 307 * Now make sure for cases 2 and 3 that the "extra" 308 * bits that slopped past the last full byte were 309 * zeros. If we don't check them, they become a 310 * subliminal channel. 311 */ 312 if (target && target[tarindex] != 0) 313 return (-1); 314 } 315 } else { 316 /* 317 * We ended by seeing the end of the string. Make sure we 318 * have no partial bytes lying around. 319 */ 320 if (state != 0) 321 return (-1); 322 } 323 324 return (tarindex); 325} 326