17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav * Copyright (c) 1996, 1998 by Internet Software Consortium.
37b5038d7SDag-Erling Smørgrav *
47b5038d7SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any
57b5038d7SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above
67b5038d7SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies.
77b5038d7SDag-Erling Smørgrav *
87b5038d7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
97b5038d7SDag-Erling Smørgrav * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
107b5038d7SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
117b5038d7SDag-Erling Smørgrav * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
127b5038d7SDag-Erling Smørgrav * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
137b5038d7SDag-Erling Smørgrav * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
147b5038d7SDag-Erling Smørgrav * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
157b5038d7SDag-Erling Smørgrav * SOFTWARE.
167b5038d7SDag-Erling Smørgrav */
177b5038d7SDag-Erling Smørgrav
187b5038d7SDag-Erling Smørgrav /*
197b5038d7SDag-Erling Smørgrav * Portions Copyright (c) 1995 by International Business Machines, Inc.
207b5038d7SDag-Erling Smørgrav *
217b5038d7SDag-Erling Smørgrav * International Business Machines, Inc. (hereinafter called IBM) grants
227b5038d7SDag-Erling Smørgrav * permission under its copyrights to use, copy, modify, and distribute this
237b5038d7SDag-Erling Smørgrav * Software with or without fee, provided that the above copyright notice and
247b5038d7SDag-Erling Smørgrav * all paragraphs of this notice appear in all copies, and that the name of IBM
257b5038d7SDag-Erling Smørgrav * not be used in connection with the marketing of any product incorporating
267b5038d7SDag-Erling Smørgrav * the Software or modifications thereof, without specific, written prior
277b5038d7SDag-Erling Smørgrav * permission.
287b5038d7SDag-Erling Smørgrav *
297b5038d7SDag-Erling Smørgrav * To the extent it has a right to do so, IBM grants an immunity from suit
307b5038d7SDag-Erling Smørgrav * under its patents, if any, for the use, sale or manufacture of products to
317b5038d7SDag-Erling Smørgrav * the extent that such products are used for performing Domain Name System
327b5038d7SDag-Erling Smørgrav * dynamic updates in TCP/IP networks by means of the Software. No immunity is
337b5038d7SDag-Erling Smørgrav * granted for any product per se or for any other function of any product.
347b5038d7SDag-Erling Smørgrav *
357b5038d7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
367b5038d7SDag-Erling Smørgrav * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
377b5038d7SDag-Erling Smørgrav * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
387b5038d7SDag-Erling Smørgrav * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
397b5038d7SDag-Erling Smørgrav * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
407b5038d7SDag-Erling Smørgrav * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
417b5038d7SDag-Erling Smørgrav */
427b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
437b5038d7SDag-Erling Smørgrav #include <ctype.h>
447b5038d7SDag-Erling Smørgrav #include <stdlib.h>
457b5038d7SDag-Erling Smørgrav #include <string.h>
467b5038d7SDag-Erling Smørgrav
477b5038d7SDag-Erling Smørgrav static const char Base64[] =
487b5038d7SDag-Erling Smørgrav "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
497b5038d7SDag-Erling Smørgrav static const char Pad64 = '=';
507b5038d7SDag-Erling Smørgrav
517b5038d7SDag-Erling Smørgrav /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
527b5038d7SDag-Erling Smørgrav The following encoding technique is taken from RFC 1521 by Borenstein
537b5038d7SDag-Erling Smørgrav and Freed. It is reproduced here in a slightly edited form for
547b5038d7SDag-Erling Smørgrav convenience.
557b5038d7SDag-Erling Smørgrav
567b5038d7SDag-Erling Smørgrav A 65-character subset of US-ASCII is used, enabling 6 bits to be
577b5038d7SDag-Erling Smørgrav represented per printable character. (The extra 65th character, "=",
587b5038d7SDag-Erling Smørgrav is used to signify a special processing function.)
597b5038d7SDag-Erling Smørgrav
607b5038d7SDag-Erling Smørgrav The encoding process represents 24-bit groups of input bits as output
617b5038d7SDag-Erling Smørgrav strings of 4 encoded characters. Proceeding from left to right, a
627b5038d7SDag-Erling Smørgrav 24-bit input group is formed by concatenating 3 8-bit input groups.
637b5038d7SDag-Erling Smørgrav These 24 bits are then treated as 4 concatenated 6-bit groups, each
647b5038d7SDag-Erling Smørgrav of which is translated into a single digit in the base64 alphabet.
657b5038d7SDag-Erling Smørgrav
667b5038d7SDag-Erling Smørgrav Each 6-bit group is used as an index into an array of 64 printable
677b5038d7SDag-Erling Smørgrav characters. The character referenced by the index is placed in the
687b5038d7SDag-Erling Smørgrav output string.
697b5038d7SDag-Erling Smørgrav
707b5038d7SDag-Erling Smørgrav Table 1: The Base64 Alphabet
717b5038d7SDag-Erling Smørgrav
727b5038d7SDag-Erling Smørgrav Value Encoding Value Encoding Value Encoding Value Encoding
737b5038d7SDag-Erling Smørgrav 0 A 17 R 34 i 51 z
747b5038d7SDag-Erling Smørgrav 1 B 18 S 35 j 52 0
757b5038d7SDag-Erling Smørgrav 2 C 19 T 36 k 53 1
767b5038d7SDag-Erling Smørgrav 3 D 20 U 37 l 54 2
777b5038d7SDag-Erling Smørgrav 4 E 21 V 38 m 55 3
787b5038d7SDag-Erling Smørgrav 5 F 22 W 39 n 56 4
797b5038d7SDag-Erling Smørgrav 6 G 23 X 40 o 57 5
807b5038d7SDag-Erling Smørgrav 7 H 24 Y 41 p 58 6
817b5038d7SDag-Erling Smørgrav 8 I 25 Z 42 q 59 7
827b5038d7SDag-Erling Smørgrav 9 J 26 a 43 r 60 8
837b5038d7SDag-Erling Smørgrav 10 K 27 b 44 s 61 9
847b5038d7SDag-Erling Smørgrav 11 L 28 c 45 t 62 +
857b5038d7SDag-Erling Smørgrav 12 M 29 d 46 u 63 /
867b5038d7SDag-Erling Smørgrav 13 N 30 e 47 v
877b5038d7SDag-Erling Smørgrav 14 O 31 f 48 w (pad) =
887b5038d7SDag-Erling Smørgrav 15 P 32 g 49 x
897b5038d7SDag-Erling Smørgrav 16 Q 33 h 50 y
907b5038d7SDag-Erling Smørgrav
917b5038d7SDag-Erling Smørgrav Special processing is performed if fewer than 24 bits are available
927b5038d7SDag-Erling Smørgrav at the end of the data being encoded. A full encoding quantum is
937b5038d7SDag-Erling Smørgrav always completed at the end of a quantity. When fewer than 24 input
947b5038d7SDag-Erling Smørgrav bits are available in an input group, zero bits are added (on the
957b5038d7SDag-Erling Smørgrav right) to form an integral number of 6-bit groups. Padding at the
967b5038d7SDag-Erling Smørgrav end of the data is performed using the '=' character.
977b5038d7SDag-Erling Smørgrav
987b5038d7SDag-Erling Smørgrav Since all base64 input is an integral number of octets, only the
997b5038d7SDag-Erling Smørgrav -------------------------------------------------
1007b5038d7SDag-Erling Smørgrav following cases can arise:
1017b5038d7SDag-Erling Smørgrav
1027b5038d7SDag-Erling Smørgrav (1) the final quantum of encoding input is an integral
1037b5038d7SDag-Erling Smørgrav multiple of 24 bits; here, the final unit of encoded
1047b5038d7SDag-Erling Smørgrav output will be an integral multiple of 4 characters
1057b5038d7SDag-Erling Smørgrav with no "=" padding,
1067b5038d7SDag-Erling Smørgrav (2) the final quantum of encoding input is exactly 8 bits;
1077b5038d7SDag-Erling Smørgrav here, the final unit of encoded output will be two
1087b5038d7SDag-Erling Smørgrav characters followed by two "=" padding characters, or
1097b5038d7SDag-Erling Smørgrav (3) the final quantum of encoding input is exactly 16 bits;
1107b5038d7SDag-Erling Smørgrav here, the final unit of encoded output will be three
1117b5038d7SDag-Erling Smørgrav characters followed by one "=" padding character.
1127b5038d7SDag-Erling Smørgrav */
1137b5038d7SDag-Erling Smørgrav
1147b5038d7SDag-Erling Smørgrav int
ldns_b64_ntop(uint8_t const * src,size_t srclength,char * target,size_t targsize)1157b5038d7SDag-Erling Smørgrav ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
1167b5038d7SDag-Erling Smørgrav size_t datalength = 0;
1177b5038d7SDag-Erling Smørgrav uint8_t input[3];
1187b5038d7SDag-Erling Smørgrav uint8_t output[4];
1197b5038d7SDag-Erling Smørgrav size_t i;
1207b5038d7SDag-Erling Smørgrav
1217b5038d7SDag-Erling Smørgrav if (srclength == 0) {
1227b5038d7SDag-Erling Smørgrav if (targsize > 0) {
1237b5038d7SDag-Erling Smørgrav target[0] = '\0';
1247b5038d7SDag-Erling Smørgrav return 0;
1257b5038d7SDag-Erling Smørgrav } else {
1267b5038d7SDag-Erling Smørgrav return -1;
1277b5038d7SDag-Erling Smørgrav }
1287b5038d7SDag-Erling Smørgrav }
1297b5038d7SDag-Erling Smørgrav
1307b5038d7SDag-Erling Smørgrav while (2 < srclength) {
1317b5038d7SDag-Erling Smørgrav input[0] = *src++;
1327b5038d7SDag-Erling Smørgrav input[1] = *src++;
1337b5038d7SDag-Erling Smørgrav input[2] = *src++;
1347b5038d7SDag-Erling Smørgrav srclength -= 3;
1357b5038d7SDag-Erling Smørgrav
1367b5038d7SDag-Erling Smørgrav output[0] = input[0] >> 2;
1377b5038d7SDag-Erling Smørgrav output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
1387b5038d7SDag-Erling Smørgrav output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
1397b5038d7SDag-Erling Smørgrav output[3] = input[2] & 0x3f;
140*17d15b25SDag-Erling Smørgrav assert(output[0] < 64);
141*17d15b25SDag-Erling Smørgrav assert(output[1] < 64);
142*17d15b25SDag-Erling Smørgrav assert(output[2] < 64);
143*17d15b25SDag-Erling Smørgrav assert(output[3] < 64);
1447b5038d7SDag-Erling Smørgrav
1457b5038d7SDag-Erling Smørgrav if (datalength + 4 > targsize) {
1467b5038d7SDag-Erling Smørgrav return (-1);
1477b5038d7SDag-Erling Smørgrav }
1487b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[0]];
1497b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[1]];
1507b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[2]];
1517b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[3]];
1527b5038d7SDag-Erling Smørgrav }
1537b5038d7SDag-Erling Smørgrav
1547b5038d7SDag-Erling Smørgrav /* Now we worry about padding. */
1557b5038d7SDag-Erling Smørgrav if (0 != srclength) {
1567b5038d7SDag-Erling Smørgrav /* Get what's left. */
1577b5038d7SDag-Erling Smørgrav input[0] = input[1] = input[2] = (uint8_t) '\0';
1587b5038d7SDag-Erling Smørgrav for (i = 0; i < srclength; i++)
1597b5038d7SDag-Erling Smørgrav input[i] = *src++;
1607b5038d7SDag-Erling Smørgrav
1617b5038d7SDag-Erling Smørgrav output[0] = input[0] >> 2;
1627b5038d7SDag-Erling Smørgrav output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
1637b5038d7SDag-Erling Smørgrav output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
164*17d15b25SDag-Erling Smørgrav assert(output[0] < 64);
165*17d15b25SDag-Erling Smørgrav assert(output[1] < 64);
166*17d15b25SDag-Erling Smørgrav assert(output[2] < 64);
1677b5038d7SDag-Erling Smørgrav
1687b5038d7SDag-Erling Smørgrav if (datalength + 4 > targsize) {
1697b5038d7SDag-Erling Smørgrav return (-2);
1707b5038d7SDag-Erling Smørgrav }
1717b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[0]];
1727b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[1]];
1737b5038d7SDag-Erling Smørgrav if (srclength == 1) {
1747b5038d7SDag-Erling Smørgrav target[datalength++] = Pad64;
1757b5038d7SDag-Erling Smørgrav } else {
1767b5038d7SDag-Erling Smørgrav target[datalength++] = Base64[output[2]];
1777b5038d7SDag-Erling Smørgrav }
1787b5038d7SDag-Erling Smørgrav target[datalength++] = Pad64;
1797b5038d7SDag-Erling Smørgrav }
1807b5038d7SDag-Erling Smørgrav if (datalength >= targsize) {
1817b5038d7SDag-Erling Smørgrav return (-3);
1827b5038d7SDag-Erling Smørgrav }
1837b5038d7SDag-Erling Smørgrav target[datalength] = '\0'; /* Returned value doesn't count \0. */
1847b5038d7SDag-Erling Smørgrav return (int) (datalength);
1857b5038d7SDag-Erling Smørgrav }
186