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