121057Speter/* 236891Speter * Copyright (c) 1996, 1998 by Internet Software Consortium. 321057Speter * 421057Speter * Permission to use, copy, modify, and distribute this software for any 521057Speter * purpose with or without fee is hereby granted, provided that the above 621057Speter * copyright notice and this permission notice appear in all copies. 721057Speter * 821057Speter * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 921057Speter * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 1021057Speter * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 1121057Speter * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 1221057Speter * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1321057Speter * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1421057Speter * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1521057Speter * SOFTWARE. 1621057Speter */ 1721057Speter 1821057Speter/* 1921057Speter * Portions Copyright (c) 1995 by International Business Machines, Inc. 2021057Speter * 2121057Speter * International Business Machines, Inc. (hereinafter called IBM) grants 2221057Speter * permission under its copyrights to use, copy, modify, and distribute this 2321057Speter * Software with or without fee, provided that the above copyright notice and 2421057Speter * all paragraphs of this notice appear in all copies, and that the name of IBM 2521057Speter * not be used in connection with the marketing of any product incorporating 2621057Speter * the Software or modifications thereof, without specific, written prior 2721057Speter * permission. 2821057Speter * 2921057Speter * To the extent it has a right to do so, IBM grants an immunity from suit 3021057Speter * under its patents, if any, for the use, sale or manufacture of products to 3121057Speter * the extent that such products are used for performing Domain Name System 3221057Speter * dynamic updates in TCP/IP networks by means of the Software. No immunity is 3321057Speter * granted for any product per se or for any other function of any product. 3421057Speter * 3521057Speter * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 3621057Speter * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 3721057Speter * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 3821057Speter * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 3921057Speter * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 4021057Speter * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 4121057Speter */ 4221057Speter 4392986Sobrien#include <sys/cdefs.h> 4492986Sobrien__FBSDID("$FreeBSD: stable/10/lib/libc/net/base64.c 309485 2016-12-03 17:17:42Z ngie $"); 4536891Speter 4621057Speter#include <sys/types.h> 4721057Speter#include <sys/param.h> 4821057Speter#include <sys/socket.h> 4936891Speter 5021057Speter#include <netinet/in.h> 5121057Speter#include <arpa/inet.h> 5221057Speter#include <arpa/nameser.h> 5321057Speter 5421057Speter#include <ctype.h> 5521057Speter#include <resolv.h> 5621057Speter#include <stdio.h> 5736891Speter#include <stdlib.h> 5836891Speter#include <string.h> 5921057Speter 6021057Speter#define Assert(Cond) if (!(Cond)) abort() 6121057Speter 6221057Speterstatic const char Base64[] = 6321057Speter "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 6421057Speterstatic const char Pad64 = '='; 6521057Speter 6621057Speter/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 6721057Speter The following encoding technique is taken from RFC 1521 by Borenstein 6821057Speter and Freed. It is reproduced here in a slightly edited form for 6921057Speter convenience. 7021057Speter 7121057Speter A 65-character subset of US-ASCII is used, enabling 6 bits to be 7221057Speter represented per printable character. (The extra 65th character, "=", 7321057Speter is used to signify a special processing function.) 7421057Speter 7521057Speter The encoding process represents 24-bit groups of input bits as output 7621057Speter strings of 4 encoded characters. Proceeding from left to right, a 7721057Speter 24-bit input group is formed by concatenating 3 8-bit input groups. 7821057Speter These 24 bits are then treated as 4 concatenated 6-bit groups, each 7921057Speter of which is translated into a single digit in the base64 alphabet. 8021057Speter 8121057Speter Each 6-bit group is used as an index into an array of 64 printable 8221057Speter characters. The character referenced by the index is placed in the 8321057Speter output string. 8421057Speter 8521057Speter Table 1: The Base64 Alphabet 8621057Speter 8721057Speter Value Encoding Value Encoding Value Encoding Value Encoding 8821057Speter 0 A 17 R 34 i 51 z 8921057Speter 1 B 18 S 35 j 52 0 9021057Speter 2 C 19 T 36 k 53 1 9121057Speter 3 D 20 U 37 l 54 2 9221057Speter 4 E 21 V 38 m 55 3 9321057Speter 5 F 22 W 39 n 56 4 9421057Speter 6 G 23 X 40 o 57 5 9521057Speter 7 H 24 Y 41 p 58 6 9621057Speter 8 I 25 Z 42 q 59 7 9721057Speter 9 J 26 a 43 r 60 8 9821057Speter 10 K 27 b 44 s 61 9 9921057Speter 11 L 28 c 45 t 62 + 10021057Speter 12 M 29 d 46 u 63 / 10121057Speter 13 N 30 e 47 v 10221057Speter 14 O 31 f 48 w (pad) = 10321057Speter 15 P 32 g 49 x 10421057Speter 16 Q 33 h 50 y 10521057Speter 10621057Speter Special processing is performed if fewer than 24 bits are available 10721057Speter at the end of the data being encoded. A full encoding quantum is 10821057Speter always completed at the end of a quantity. When fewer than 24 input 10921057Speter bits are available in an input group, zero bits are added (on the 11021057Speter right) to form an integral number of 6-bit groups. Padding at the 11121057Speter end of the data is performed using the '=' character. 11221057Speter 11321057Speter Since all base64 input is an integral number of octets, only the 11421057Speter ------------------------------------------------- 11521057Speter following cases can arise: 11621057Speter 11721057Speter (1) the final quantum of encoding input is an integral 11821057Speter multiple of 24 bits; here, the final unit of encoded 11921057Speter output will be an integral multiple of 4 characters 12021057Speter with no "=" padding, 12121057Speter (2) the final quantum of encoding input is exactly 8 bits; 12221057Speter here, the final unit of encoded output will be two 12321057Speter characters followed by two "=" padding characters, or 12421057Speter (3) the final quantum of encoding input is exactly 16 bits; 12521057Speter here, the final unit of encoded output will be three 12621057Speter characters followed by one "=" padding character. 12721057Speter */ 12821057Speter 12921057Speterint 13036891Speterb64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { 13121057Speter size_t datalength = 0; 13221057Speter u_char input[3]; 13321057Speter u_char output[4]; 13436891Speter size_t i; 13521057Speter 13621057Speter while (2 < srclength) { 13721057Speter input[0] = *src++; 13821057Speter input[1] = *src++; 13921057Speter input[2] = *src++; 14021057Speter srclength -= 3; 14121057Speter 14221057Speter output[0] = input[0] >> 2; 14321057Speter output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 14421057Speter output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 14521057Speter output[3] = input[2] & 0x3f; 14621057Speter Assert(output[0] < 64); 14721057Speter Assert(output[1] < 64); 14821057Speter Assert(output[2] < 64); 14921057Speter Assert(output[3] < 64); 15021057Speter 15121057Speter if (datalength + 4 > targsize) 15221057Speter return (-1); 15321057Speter target[datalength++] = Base64[output[0]]; 15421057Speter target[datalength++] = Base64[output[1]]; 15521057Speter target[datalength++] = Base64[output[2]]; 15621057Speter target[datalength++] = Base64[output[3]]; 15721057Speter } 15821057Speter 15921057Speter /* Now we worry about padding. */ 16021057Speter if (0 != srclength) { 16121057Speter /* Get what's left. */ 16221057Speter input[0] = input[1] = input[2] = '\0'; 16321057Speter for (i = 0; i < srclength; i++) 16421057Speter input[i] = *src++; 16521057Speter 16621057Speter output[0] = input[0] >> 2; 16721057Speter output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 16821057Speter output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 16921057Speter Assert(output[0] < 64); 17021057Speter Assert(output[1] < 64); 17121057Speter Assert(output[2] < 64); 17221057Speter 17321057Speter if (datalength + 4 > targsize) 17421057Speter return (-1); 17521057Speter target[datalength++] = Base64[output[0]]; 17621057Speter target[datalength++] = Base64[output[1]]; 17721057Speter if (srclength == 1) 17821057Speter target[datalength++] = Pad64; 17921057Speter else 18021057Speter target[datalength++] = Base64[output[2]]; 18121057Speter target[datalength++] = Pad64; 18221057Speter } 18321057Speter if (datalength >= targsize) 18421057Speter return (-1); 18521057Speter target[datalength] = '\0'; /* Returned value doesn't count \0. */ 18621057Speter return (datalength); 18721057Speter} 18821057Speter 18921057Speter/* skips all whitespace anywhere. 19021057Speter converts characters, four at a time, starting at (or after) 19121057Speter src from base - 64 numbers into three 8 bit bytes in the target area. 19221057Speter it returns the number of data bytes stored at the target, or -1 on error. 19321057Speter */ 19421057Speter 19521057Speterint 196280399Semasteb64_pton(const char *src, u_char *target, size_t targsize) 19721057Speter{ 19821057Speter int tarindex, state, ch; 199280398Semaste u_char nextbyte; 20021057Speter char *pos; 20121057Speter 20221057Speter state = 0; 20321057Speter tarindex = 0; 20421057Speter 20521057Speter while ((ch = *src++) != '\0') { 20652858Sache if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ 20721057Speter continue; 20821057Speter 20921057Speter if (ch == Pad64) 21021057Speter break; 21121057Speter 21221057Speter pos = strchr(Base64, ch); 213309485Sngie if (pos == NULL) /* A non-base64 character. */ 21421057Speter return (-1); 21521057Speter 21621057Speter switch (state) { 21721057Speter case 0: 21821057Speter if (target) { 21936891Speter if ((size_t)tarindex >= targsize) 22021057Speter return (-1); 22121057Speter target[tarindex] = (pos - Base64) << 2; 22221057Speter } 22321057Speter state = 1; 22421057Speter break; 22521057Speter case 1: 22621057Speter if (target) { 227280398Semaste if ((size_t)tarindex >= targsize) 22821057Speter return (-1); 22921057Speter target[tarindex] |= (pos - Base64) >> 4; 230280398Semaste nextbyte = ((pos - Base64) & 0x0f) << 4; 231280398Semaste if ((size_t)tarindex + 1 < targsize) 232280398Semaste target[tarindex + 1] = nextbyte; 233280398Semaste else if (nextbyte) 234280398Semaste return (-1); 23521057Speter } 23621057Speter tarindex++; 23721057Speter state = 2; 23821057Speter break; 23921057Speter case 2: 24021057Speter if (target) { 241280398Semaste if ((size_t)tarindex >= targsize) 24221057Speter return (-1); 24321057Speter target[tarindex] |= (pos - Base64) >> 2; 244280398Semaste nextbyte = ((pos - Base64) & 0x03) << 6; 245280398Semaste if ((size_t)tarindex + 1 < targsize) 246280398Semaste target[tarindex + 1] = nextbyte; 247280398Semaste else if (nextbyte) 248280398Semaste return (-1); 24921057Speter } 25021057Speter tarindex++; 25121057Speter state = 3; 25221057Speter break; 25321057Speter case 3: 25421057Speter if (target) { 25536891Speter if ((size_t)tarindex >= targsize) 25621057Speter return (-1); 25721057Speter target[tarindex] |= (pos - Base64); 25821057Speter } 25921057Speter tarindex++; 26021057Speter state = 0; 26121057Speter break; 26221057Speter default: 26321057Speter abort(); 26421057Speter } 26521057Speter } 26621057Speter 26721057Speter /* 26821057Speter * We are done decoding Base-64 chars. Let's see if we ended 26921057Speter * on a byte boundary, and/or with erroneous trailing characters. 27021057Speter */ 27121057Speter 27221057Speter if (ch == Pad64) { /* We got a pad char. */ 27321057Speter ch = *src++; /* Skip it, get next. */ 27421057Speter switch (state) { 27521057Speter case 0: /* Invalid = in first position */ 27621057Speter case 1: /* Invalid = in second position */ 27721057Speter return (-1); 27821057Speter 27921057Speter case 2: /* Valid, means one byte of info */ 28021057Speter /* Skip any number of spaces. */ 28136891Speter for ((void)NULL; ch != '\0'; ch = *src++) 28252858Sache if (!isspace((unsigned char)ch)) 28321057Speter break; 28421057Speter /* Make sure there is another trailing = sign. */ 28521057Speter if (ch != Pad64) 28621057Speter return (-1); 28721057Speter ch = *src++; /* Skip the = */ 28821057Speter /* Fall through to "single trailing =" case. */ 28921057Speter /* FALLTHROUGH */ 29021057Speter 29121057Speter case 3: /* Valid, means two bytes of info */ 29221057Speter /* 29321057Speter * We know this char is an =. Is there anything but 29421057Speter * whitespace after it? 29521057Speter */ 29636891Speter for ((void)NULL; ch != '\0'; ch = *src++) 29752858Sache if (!isspace((unsigned char)ch)) 29821057Speter return (-1); 29921057Speter 30021057Speter /* 30121057Speter * Now make sure for cases 2 and 3 that the "extra" 30221057Speter * bits that slopped past the last full byte were 30321057Speter * zeros. If we don't check them, they become a 30421057Speter * subliminal channel. 30521057Speter */ 306280398Semaste if (target && (size_t)tarindex < targsize && 307280398Semaste target[tarindex] != 0) 30821057Speter return (-1); 30921057Speter } 31021057Speter } else { 31121057Speter /* 31221057Speter * We ended by seeing the end of the string. Make sure we 31321057Speter * have no partial bytes lying around. 31421057Speter */ 31521057Speter if (state != 0) 31621057Speter return (-1); 31721057Speter } 31821057Speter 31921057Speter return (tarindex); 32021057Speter} 321