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> 43238104Sdes#include <ctype.h> 44238104Sdes#include <stdlib.h> 45238104Sdes#include <string.h> 46238104Sdes 47238104Sdesstatic const char Base64[] = 48238104Sdes "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 49238104Sdesstatic const char Pad64 = '='; 50238104Sdes 51238104Sdes/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 52238104Sdes The following encoding technique is taken from RFC 1521 by Borenstein 53238104Sdes and Freed. It is reproduced here in a slightly edited form for 54238104Sdes convenience. 55238104Sdes 56238104Sdes A 65-character subset of US-ASCII is used, enabling 6 bits to be 57238104Sdes represented per printable character. (The extra 65th character, "=", 58238104Sdes is used to signify a special processing function.) 59238104Sdes 60238104Sdes The encoding process represents 24-bit groups of input bits as output 61238104Sdes strings of 4 encoded characters. Proceeding from left to right, a 62238104Sdes 24-bit input group is formed by concatenating 3 8-bit input groups. 63238104Sdes These 24 bits are then treated as 4 concatenated 6-bit groups, each 64238104Sdes of which is translated into a single digit in the base64 alphabet. 65238104Sdes 66238104Sdes Each 6-bit group is used as an index into an array of 64 printable 67238104Sdes characters. The character referenced by the index is placed in the 68238104Sdes output string. 69238104Sdes 70238104Sdes Table 1: The Base64 Alphabet 71238104Sdes 72238104Sdes Value Encoding Value Encoding Value Encoding Value Encoding 73238104Sdes 0 A 17 R 34 i 51 z 74238104Sdes 1 B 18 S 35 j 52 0 75238104Sdes 2 C 19 T 36 k 53 1 76238104Sdes 3 D 20 U 37 l 54 2 77238104Sdes 4 E 21 V 38 m 55 3 78238104Sdes 5 F 22 W 39 n 56 4 79238104Sdes 6 G 23 X 40 o 57 5 80238104Sdes 7 H 24 Y 41 p 58 6 81238104Sdes 8 I 25 Z 42 q 59 7 82238104Sdes 9 J 26 a 43 r 60 8 83238104Sdes 10 K 27 b 44 s 61 9 84238104Sdes 11 L 28 c 45 t 62 + 85238104Sdes 12 M 29 d 46 u 63 / 86238104Sdes 13 N 30 e 47 v 87238104Sdes 14 O 31 f 48 w (pad) = 88238104Sdes 15 P 32 g 49 x 89238104Sdes 16 Q 33 h 50 y 90238104Sdes 91238104Sdes Special processing is performed if fewer than 24 bits are available 92238104Sdes at the end of the data being encoded. A full encoding quantum is 93238104Sdes always completed at the end of a quantity. When fewer than 24 input 94238104Sdes bits are available in an input group, zero bits are added (on the 95238104Sdes right) to form an integral number of 6-bit groups. Padding at the 96238104Sdes end of the data is performed using the '=' character. 97238104Sdes 98238104Sdes Since all base64 input is an integral number of octets, only the 99238104Sdes ------------------------------------------------- 100238104Sdes following cases can arise: 101238104Sdes 102238104Sdes (1) the final quantum of encoding input is an integral 103238104Sdes multiple of 24 bits; here, the final unit of encoded 104238104Sdes output will be an integral multiple of 4 characters 105238104Sdes with no "=" padding, 106238104Sdes (2) the final quantum of encoding input is exactly 8 bits; 107238104Sdes here, the final unit of encoded output will be two 108238104Sdes characters followed by two "=" padding characters, or 109238104Sdes (3) the final quantum of encoding input is exactly 16 bits; 110238104Sdes here, the final unit of encoded output will be three 111238104Sdes characters followed by one "=" padding character. 112238104Sdes */ 113238104Sdes 114238104Sdes/* skips all whitespace anywhere. 115238104Sdes converts characters, four at a time, starting at (or after) 116238104Sdes src from base - 64 numbers into three 8 bit bytes in the target area. 117238104Sdes it returns the number of data bytes stored at the target, or -1 on error. 118238104Sdes */ 119238104Sdes 120238104Sdesint 121238104Sdesldns_b64_pton(char const *src, uint8_t *target, size_t targsize) 122238104Sdes{ 123238104Sdes int tarindex, state, ch; 124238104Sdes char *pos; 125238104Sdes 126238104Sdes state = 0; 127238104Sdes tarindex = 0; 128238104Sdes 129238104Sdes if (strlen(src) == 0) { 130238104Sdes return 0; 131238104Sdes } 132238104Sdes 133238104Sdes while ((ch = *src++) != '\0') { 134238104Sdes if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ 135238104Sdes continue; 136238104Sdes 137238104Sdes if (ch == Pad64) 138238104Sdes break; 139238104Sdes 140238104Sdes pos = strchr(Base64, ch); 141238104Sdes if (pos == 0) { 142238104Sdes /* A non-base64 character. */ 143238104Sdes return (-1); 144238104Sdes } 145238104Sdes 146238104Sdes switch (state) { 147238104Sdes case 0: 148238104Sdes if (target) { 149238104Sdes if ((size_t)tarindex >= targsize) 150238104Sdes return (-1); 151238104Sdes target[tarindex] = (pos - Base64) << 2; 152238104Sdes } 153238104Sdes state = 1; 154238104Sdes break; 155238104Sdes case 1: 156238104Sdes if (target) { 157238104Sdes if ((size_t)tarindex + 1 >= targsize) 158238104Sdes return (-1); 159238104Sdes target[tarindex] |= (pos - Base64) >> 4; 160238104Sdes target[tarindex+1] = ((pos - Base64) & 0x0f) 161238104Sdes << 4 ; 162238104Sdes } 163238104Sdes tarindex++; 164238104Sdes state = 2; 165238104Sdes break; 166238104Sdes case 2: 167238104Sdes if (target) { 168238104Sdes if ((size_t)tarindex + 1 >= targsize) 169238104Sdes return (-1); 170238104Sdes target[tarindex] |= (pos - Base64) >> 2; 171238104Sdes target[tarindex+1] = ((pos - Base64) & 0x03) 172238104Sdes << 6; 173238104Sdes } 174238104Sdes tarindex++; 175238104Sdes state = 3; 176238104Sdes break; 177238104Sdes case 3: 178238104Sdes if (target) { 179238104Sdes if ((size_t)tarindex >= targsize) 180238104Sdes return (-1); 181238104Sdes target[tarindex] |= (pos - Base64); 182238104Sdes } 183238104Sdes tarindex++; 184238104Sdes state = 0; 185238104Sdes break; 186238104Sdes default: 187238104Sdes abort(); 188238104Sdes } 189238104Sdes } 190238104Sdes 191238104Sdes /* 192238104Sdes * We are done decoding Base-64 chars. Let's see if we ended 193238104Sdes * on a byte boundary, and/or with erroneous trailing characters. 194238104Sdes */ 195238104Sdes 196238104Sdes if (ch == Pad64) { /* We got a pad char. */ 197238104Sdes ch = *src++; /* Skip it, get next. */ 198238104Sdes switch (state) { 199238104Sdes case 0: /* Invalid = in first position */ 200238104Sdes case 1: /* Invalid = in second position */ 201238104Sdes return (-1); 202238104Sdes 203238104Sdes case 2: /* Valid, means one byte of info */ 204238104Sdes /* Skip any number of spaces. */ 205238104Sdes for ((void)NULL; ch != '\0'; ch = *src++) 206238104Sdes if (!isspace((unsigned char)ch)) 207238104Sdes break; 208238104Sdes /* Make sure there is another trailing = sign. */ 209238104Sdes if (ch != Pad64) 210238104Sdes return (-1); 211238104Sdes ch = *src++; /* Skip the = */ 212238104Sdes /* Fall through to "single trailing =" case. */ 213238104Sdes /* FALLTHROUGH */ 214238104Sdes 215238104Sdes case 3: /* Valid, means two bytes of info */ 216238104Sdes /* 217238104Sdes * We know this char is an =. Is there anything but 218238104Sdes * whitespace after it? 219238104Sdes */ 220238104Sdes for ((void)NULL; ch != '\0'; ch = *src++) 221238104Sdes if (!isspace((unsigned char)ch)) 222238104Sdes return (-1); 223238104Sdes 224238104Sdes /* 225238104Sdes * Now make sure for cases 2 and 3 that the "extra" 226238104Sdes * bits that slopped past the last full byte were 227238104Sdes * zeros. If we don't check them, they become a 228238104Sdes * subliminal channel. 229238104Sdes */ 230238104Sdes if (target && target[tarindex] != 0) 231238104Sdes return (-1); 232238104Sdes } 233238104Sdes } else { 234238104Sdes /* 235238104Sdes * We ended by seeing the end of the string. Make sure we 236238104Sdes * have no partial bytes lying around. 237238104Sdes */ 238238104Sdes if (state != 0) 239238104Sdes return (-1); 240238104Sdes } 241238104Sdes 242238104Sdes return (tarindex); 243238104Sdes} 244