117680Spst/* $NetBSD$ */ 217680Spst 317680Spst/* 417680Spst * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 517680Spst * Copyright (c) 1996-1999 by Internet Software Consortium. 617680Spst * 717680Spst * Permission to use, copy, modify, and distribute this software for any 817680Spst * purpose with or without fee is hereby granted, provided that the above 917680Spst * copyright notice and this permission notice appear in all copies. 1017680Spst * 1117680Spst * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 1217680Spst * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1317680Spst * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 1417680Spst * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1517680Spst * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1617680Spst * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1717680Spst * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1817680Spst */ 1917680Spst 2017680Spst/* 2198527Sfenner * Portions Copyright (c) 1995 by International Business Machines, Inc. 2298527Sfenner * 2353146Sbrian * International Business Machines, Inc. (hereinafter called IBM) grants 2417680Spst * permission under its copyrights to use, copy, modify, and distribute this 2517680Spst * Software with or without fee, provided that the above copyright notice and 2675118Sfenner * all paragraphs of this notice appear in all copies, and that the name of IBM 2775118Sfenner * not be used in connection with the marketing of any product incorporating 2875118Sfenner * the Software or modifications thereof, without specific, written prior 2975118Sfenner * permission. 3075118Sfenner * 3175118Sfenner * To the extent it has a right to do so, IBM grants an immunity from suit 3275118Sfenner * under its patents, if any, for the use, sale or manufacture of products to 3375118Sfenner * the extent that such products are used for performing Domain Name System 3475118Sfenner * dynamic updates in TCP/IP networks by means of the Software. No immunity is 3575118Sfenner * granted for any product per se or for any other function of any product. 3675118Sfenner * 3717680Spst * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 3875118Sfenner * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 3975118Sfenner * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 4075118Sfenner * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 4175118Sfenner * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 4275118Sfenner * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 4375118Sfenner */ 4475118Sfenner 4575118Sfenner#if !defined(LINT) && !defined(CODECENTER) 4675118Sfennerstatic const char rcsid[] = "Id: base64.c,v 1.4 2005/04/27 04:56:34 sra Exp "; 4775118Sfenner#endif /* not lint */ 4875118Sfenner 4975118Sfenner#include "port_before.h" 5017680Spst 5117680Spst#include <sys/types.h> 5217680Spst#include <sys/param.h> 5317680Spst#include <sys/socket.h> 5417680Spst 5517680Spst#include <netinet/in.h> 5617680Spst#include <arpa/inet.h> 5717680Spst#include <arpa/nameser.h> 5817680Spst 5917680Spst#include <ctype.h> 6017680Spst#include <resolv.h> 6117680Spst#include <stdio.h> 6217680Spst#include <stdlib.h> 6317680Spst#include <string.h> 6417680Spst 6517680Spst#include "port_after.h" 6617680Spst 6717680Spst#define Assert(Cond) if (!(Cond)) abort() 6817680Spst 6917680Spststatic const char Base64[] = 7017680Spst "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 7117680Spststatic const char Pad64 = '='; 7217680Spst 7317680Spst/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 7417680Spst The following encoding technique is taken from RFC1521 by Borenstein 7517680Spst and Freed. It is reproduced here in a slightly edited form for 7617680Spst convenience. 7717680Spst 7817680Spst A 65-character subset of US-ASCII is used, enabling 6 bits to be 7917680Spst represented per printable character. (The extra 65th character, "=", 8017680Spst is used to signify a special processing function.) 8117680Spst 8217680Spst The encoding process represents 24-bit groups of input bits as output 8317680Spst strings of 4 encoded characters. Proceeding from left to right, a 8417680Spst 24-bit input group is formed by concatenating 3 8-bit input groups. 8517680Spst These 24 bits are then treated as 4 concatenated 6-bit groups, each 8617680Spst of which is translated into a single digit in the base64 alphabet. 8717680Spst 8817680Spst Each 6-bit group is used as an index into an array of 64 printable 8917680Spst characters. The character referenced by the index is placed in the 9017680Spst output string. 9117680Spst 9217680Spst Table 1: The Base64 Alphabet 9317680Spst 9417680Spst Value Encoding Value Encoding Value Encoding Value Encoding 9517680Spst 0 A 17 R 34 i 51 z 9617680Spst 1 B 18 S 35 j 52 0 9717680Spst 2 C 19 T 36 k 53 1 9856896Sfenner 3 D 20 U 37 l 54 2 9956896Sfenner 4 E 21 V 38 m 55 3 10056896Sfenner 5 F 22 W 39 n 56 4 10117692Spst 6 G 23 X 40 o 57 5 10298527Sfenner 7 H 24 Y 41 p 58 6 10317692Spst 8 I 25 Z 42 q 59 7 10456896Sfenner 9 J 26 a 43 r 60 8 10556896Sfenner 10 K 27 b 44 s 61 9 10653146Sbrian 11 L 28 c 45 t 62 + 10798527Sfenner 12 M 29 d 46 u 63 / 10898527Sfenner 13 N 30 e 47 v 10998527Sfenner 14 O 31 f 48 w (pad) = 11098527Sfenner 15 P 32 g 49 x 11198527Sfenner 16 Q 33 h 50 y 11298527Sfenner 11398527Sfenner Special processing is performed if fewer than 24 bits are available 11498527Sfenner at the end of the data being encoded. A full encoding quantum is 11598527Sfenner always completed at the end of a quantity. When fewer than 24 input 11656896Sfenner bits are available in an input group, zero bits are added (on the 11756896Sfenner right) to form an integral number of 6-bit groups. Padding at the 11853146Sbrian end of the data is performed using the '=' character. 11956896Sfenner 12056896Sfenner Since all base64 input is an integral number of octets, only the 12156896Sfenner ------------------------------------------------- 12284019Sjulian following cases can arise: 12384019Sjulian 12484019Sjulian (1) the final quantum of encoding input is an integral 12584019Sjulian multiple of 24 bits; here, the final unit of encoded 12684019Sjulian output will be an integral multiple of 4 characters 12784019Sjulian with no "=" padding, 12817680Spst (2) the final quantum of encoding input is exactly 8 bits; 12917680Spst here, the final unit of encoded output will be two 13017680Spst 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