1238104Sdes/* 2238104Sdes * Copyright (c) 1996, 1998 by Internet Software Consortium. 3238104Sdes * 4238104Sdes * Permission to use, copy, modify, and distribute this software for any 5238104Sdes * purpose with or without fee is hereby granted, provided that the above 6238104Sdes * copyright notice and this permission notice appear in all copies. 7238104Sdes * 8238104Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 9238104Sdes * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10238104Sdes * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 11238104Sdes * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12238104Sdes * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 13238104Sdes * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 14238104Sdes * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 15238104Sdes * SOFTWARE. 16238104Sdes */ 17238104Sdes 18238104Sdes/* 19238104Sdes * Portions Copyright (c) 1995 by International Business Machines, Inc. 20238104Sdes * 21238104Sdes * International Business Machines, Inc. (hereinafter called IBM) grants 22238104Sdes * permission under its copyrights to use, copy, modify, and distribute this 23238104Sdes * Software with or without fee, provided that the above copyright notice and 24238104Sdes * all paragraphs of this notice appear in all copies, and that the name of IBM 25238104Sdes * not be used in connection with the marketing of any product incorporating 26238104Sdes * the Software or modifications thereof, without specific, written prior 27238104Sdes * permission. 28238104Sdes * 29238104Sdes * To the extent it has a right to do so, IBM grants an immunity from suit 30238104Sdes * under its patents, if any, for the use, sale or manufacture of products to 31238104Sdes * the extent that such products are used for performing Domain Name System 32238104Sdes * dynamic updates in TCP/IP networks by means of the Software. No immunity is 33238104Sdes * granted for any product per se or for any other function of any product. 34238104Sdes * 35238104Sdes * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 36238104Sdes * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 37238104Sdes * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 38238104Sdes * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 39238104Sdes * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 40238104Sdes * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 41238104Sdes */ 42238104Sdes#include <ldns/config.h> 43249453Sdes#ifndef HAVE_B64_PTON 44238104Sdes 45238104Sdes#include <sys/types.h> 46238104Sdes#include <sys/param.h> 47238104Sdes#ifdef HAVE_SYS_SOCKET_H 48238104Sdes#include <sys/socket.h> 49238104Sdes#endif 50238104Sdes 51238104Sdes#ifdef HAVE_NETINET_IN_H 52238104Sdes#include <netinet/in.h> 53238104Sdes#endif 54238104Sdes#ifdef HAVE_ARPA_INET_H 55238104Sdes#include <arpa/inet.h> 56238104Sdes#endif 57238104Sdes 58238104Sdes#include <ctype.h> 59238104Sdes#include <stdio.h> 60238104Sdes#include <stdlib.h> 61238104Sdes#include <string.h> 62238104Sdes 63249453Sdes#include <ldns/util.h> 64238104Sdes 65238104Sdesstatic const char Base64[] = 66238104Sdes "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 67238104Sdesstatic const char Pad64 = '='; 68238104Sdes 69238104Sdes/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 70238104Sdes The following encoding technique is taken from RFC 1521 by Borenstein 71238104Sdes and Freed. It is reproduced here in a slightly edited form for 72238104Sdes convenience. 73238104Sdes 74238104Sdes A 65-character subset of US-ASCII is used, enabling 6 bits to be 75238104Sdes represented per printable character. (The extra 65th character, "=", 76238104Sdes is used to signify a special processing function.) 77238104Sdes 78238104Sdes The encoding process represents 24-bit groups of input bits as output 79238104Sdes strings of 4 encoded characters. Proceeding from left to right, a 80238104Sdes 24-bit input group is formed by concatenating 3 8-bit input groups. 81238104Sdes These 24 bits are then treated as 4 concatenated 6-bit groups, each 82238104Sdes of which is translated into a single digit in the base64 alphabet. 83238104Sdes 84238104Sdes Each 6-bit group is used as an index into an array of 64 printable 85238104Sdes characters. The character referenced by the index is placed in the 86238104Sdes output string. 87238104Sdes 88238104Sdes Table 1: The Base64 Alphabet 89238104Sdes 90238104Sdes Value Encoding Value Encoding Value Encoding Value Encoding 91238104Sdes 0 A 17 R 34 i 51 z 92238104Sdes 1 B 18 S 35 j 52 0 93238104Sdes 2 C 19 T 36 k 53 1 94238104Sdes 3 D 20 U 37 l 54 2 95238104Sdes 4 E 21 V 38 m 55 3 96238104Sdes 5 F 22 W 39 n 56 4 97238104Sdes 6 G 23 X 40 o 57 5 98238104Sdes 7 H 24 Y 41 p 58 6 99238104Sdes 8 I 25 Z 42 q 59 7 100238104Sdes 9 J 26 a 43 r 60 8 101238104Sdes 10 K 27 b 44 s 61 9 102238104Sdes 11 L 28 c 45 t 62 + 103238104Sdes 12 M 29 d 46 u 63 / 104238104Sdes 13 N 30 e 47 v 105238104Sdes 14 O 31 f 48 w (pad) = 106238104Sdes 15 P 32 g 49 x 107238104Sdes 16 Q 33 h 50 y 108238104Sdes 109238104Sdes Special processing is performed if fewer than 24 bits are available 110238104Sdes at the end of the data being encoded. A full encoding quantum is 111238104Sdes always completed at the end of a quantity. When fewer than 24 input 112238104Sdes bits are available in an input group, zero bits are added (on the 113238104Sdes right) to form an integral number of 6-bit groups. Padding at the 114238104Sdes end of the data is performed using the '=' character. 115238104Sdes 116238104Sdes Since all base64 input is an integral number of octets, only the 117238104Sdes ------------------------------------------------- 118238104Sdes following cases can arise: 119238104Sdes 120238104Sdes (1) the final quantum of encoding input is an integral 121238104Sdes multiple of 24 bits; here, the final unit of encoded 122238104Sdes output will be an integral multiple of 4 characters 123238104Sdes with no "=" padding, 124238104Sdes (2) the final quantum of encoding input is exactly 8 bits; 125238104Sdes here, the final unit of encoded output will be two 126238104Sdes characters followed by two "=" padding characters, or 127238104Sdes (3) the final quantum of encoding input is exactly 16 bits; 128238104Sdes here, the final unit of encoded output will be three 129238104Sdes characters followed by one "=" padding character. 130238104Sdes */ 131238104Sdes 132238104Sdes/* skips all whitespace anywhere. 133238104Sdes converts characters, four at a time, starting at (or after) 134238104Sdes src from base - 64 numbers into three 8 bit bytes in the target area. 135238104Sdes it returns the number of data bytes stored at the target, or -1 on error. 136238104Sdes */ 137238104Sdes 138238104Sdesint 139238104Sdesldns_b64_pton(char const *src, uint8_t *target, size_t targsize) 140238104Sdes{ 141238104Sdes int tarindex, state, ch; 142238104Sdes char *pos; 143238104Sdes 144238104Sdes state = 0; 145238104Sdes tarindex = 0; 146238104Sdes 147238104Sdes if (strlen(src) == 0) { 148238104Sdes return 0; 149238104Sdes } 150238104Sdes 151238104Sdes while ((ch = *src++) != '\0') { 152238104Sdes if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ 153238104Sdes continue; 154238104Sdes 155238104Sdes if (ch == Pad64) 156238104Sdes break; 157238104Sdes 158238104Sdes pos = strchr(Base64, ch); 159238104Sdes if (pos == 0) { 160238104Sdes /* A non-base64 character. */ 161238104Sdes return (-1); 162238104Sdes } 163238104Sdes 164238104Sdes switch (state) { 165238104Sdes case 0: 166238104Sdes if (target) { 167238104Sdes if ((size_t)tarindex >= targsize) 168238104Sdes return (-1); 169238104Sdes target[tarindex] = (pos - Base64) << 2; 170238104Sdes } 171238104Sdes state = 1; 172238104Sdes break; 173238104Sdes case 1: 174238104Sdes if (target) { 175238104Sdes if ((size_t)tarindex + 1 >= targsize) 176238104Sdes return (-1); 177238104Sdes target[tarindex] |= (pos - Base64) >> 4; 178238104Sdes target[tarindex+1] = ((pos - Base64) & 0x0f) 179238104Sdes << 4 ; 180238104Sdes } 181238104Sdes tarindex++; 182238104Sdes state = 2; 183238104Sdes break; 184238104Sdes case 2: 185238104Sdes if (target) { 186238104Sdes if ((size_t)tarindex + 1 >= targsize) 187238104Sdes return (-1); 188238104Sdes target[tarindex] |= (pos - Base64) >> 2; 189238104Sdes target[tarindex+1] = ((pos - Base64) & 0x03) 190238104Sdes << 6; 191238104Sdes } 192238104Sdes tarindex++; 193238104Sdes state = 3; 194238104Sdes break; 195238104Sdes case 3: 196238104Sdes if (target) { 197238104Sdes if ((size_t)tarindex >= targsize) 198238104Sdes return (-1); 199238104Sdes target[tarindex] |= (pos - Base64); 200238104Sdes } 201238104Sdes tarindex++; 202238104Sdes state = 0; 203238104Sdes break; 204238104Sdes default: 205238104Sdes abort(); 206238104Sdes } 207238104Sdes } 208238104Sdes 209238104Sdes /* 210238104Sdes * We are done decoding Base-64 chars. Let's see if we ended 211238104Sdes * on a byte boundary, and/or with erroneous trailing characters. 212238104Sdes */ 213238104Sdes 214238104Sdes if (ch == Pad64) { /* We got a pad char. */ 215238104Sdes ch = *src++; /* Skip it, get next. */ 216238104Sdes switch (state) { 217238104Sdes case 0: /* Invalid = in first position */ 218238104Sdes case 1: /* Invalid = in second position */ 219238104Sdes return (-1); 220238104Sdes 221238104Sdes case 2: /* Valid, means one byte of info */ 222238104Sdes /* Skip any number of spaces. */ 223238104Sdes for ((void)NULL; ch != '\0'; ch = *src++) 224238104Sdes if (!isspace((unsigned char)ch)) 225238104Sdes break; 226238104Sdes /* Make sure there is another trailing = sign. */ 227238104Sdes if (ch != Pad64) 228238104Sdes return (-1); 229238104Sdes ch = *src++; /* Skip the = */ 230238104Sdes /* Fall through to "single trailing =" case. */ 231238104Sdes /* FALLTHROUGH */ 232238104Sdes 233238104Sdes case 3: /* Valid, means two bytes of info */ 234238104Sdes /* 235238104Sdes * We know this char is an =. Is there anything but 236238104Sdes * whitespace after it? 237238104Sdes */ 238238104Sdes for ((void)NULL; ch != '\0'; ch = *src++) 239238104Sdes if (!isspace((unsigned char)ch)) 240238104Sdes return (-1); 241238104Sdes 242238104Sdes /* 243238104Sdes * Now make sure for cases 2 and 3 that the "extra" 244238104Sdes * bits that slopped past the last full byte were 245238104Sdes * zeros. If we don't check them, they become a 246238104Sdes * subliminal channel. 247238104Sdes */ 248238104Sdes if (target && target[tarindex] != 0) 249238104Sdes return (-1); 250238104Sdes } 251238104Sdes } else { 252238104Sdes /* 253238104Sdes * We ended by seeing the end of the string. Make sure we 254238104Sdes * have no partial bytes lying around. 255238104Sdes */ 256238104Sdes if (state != 0) 257238104Sdes return (-1); 258238104Sdes } 259238104Sdes 260238104Sdes return (tarindex); 261238104Sdes} 262249453Sdes 263249453Sdes#endif /* !HAVE_B64_PTON */ 264