diff --git a/libbase64/Makefile.in b/libbase64/Makefile.in new file mode 100644 index 0000000..493d0b1 --- /dev/null +++ b/libbase64/Makefile.in @@ -0,0 +1,59 @@ +VERSION := 1.0.0 +TARGET := libbase64.a +OBJS := base64.o +HEADERS := kst +LIBS := +TEST_LIBS := -L/usr/local/lib -lcunit + +PREFIX ?= $PREFIX +MANDIR ?= $MANDIR + +CFLAGS += -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align +CFLAGS += -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations +CFLAGS += -Wnested-externs -Winline -Wno-long-long -Wunused-variable -g +CFLAGS += -Wstrict-prototypes -Werror -std=c99 -I. -I/usr/local/include +CFLAGS += OS_CFLAGS + +all: $(TARGET) + +clean: + -rm -f .*.* *.core *.o *.html tags $(TARGET) $(OBJS) + -rm -rf $(TARGET)-$(VERSION) + -rm -f $(TARGET)-$(VERSION).tgz + +$(TARGET): $(OBJS) + $(AR) -rcs $@ $(OBJS) + +install: $(TARGET) + install -m 0755 $(TARGET) $(PREFIX)/lib/$(TARGET) + install -m 0755 -d $(MANDIR)/man1 + install -m 0444 $(TARGET).3 $(MANDIR)/man3/$(TARGET).3 + +uninstall: + -rm -f $(PREFIX)/lib/$(TARGET) + -rm -f $(MANDIR)/man3/$(TARGET).3 + +dist: clean + -mkdir $(TARGET)-$(VERSION) + -cp * $(TARGET)-$(VERSION) + -cd $(TARGET)-$(VERSION) && make distclean && cd .. + -tar czf $(TARGET)-$(VERSION).tgz $(TARGET)-$(VERSION) + +distclean: clean + -rm -f Makefile + +htmldoc: + -mandoc -Thtml $(TARGET).1 > $(TARGET).1.html + +tags: + ctags *.[ch] + +test: base64-test + +base64-test: $(TARGET) base64_test.o + $(CC) -o $@ base64_test.o $(TARGET) $(TEST_LIBS) + +.c.o: + $(CC) -c ${CFLAGS} $? + +.PHONY: clean all install lint uninstall dist distclean htmldoc tags test diff --git a/libbase64/base64.c b/libbase64/base64.c new file mode 100644 index 0000000..b9316d8 --- /dev/null +++ b/libbase64/base64.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2013 by Kyle Isom . + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include + +#include "base64.h" + + +static const char libversion[] = PACKAGE_VERSION; +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +base64_encode(const uint8_t *src, size_t srclength, char *target, + size_t targsize) +{ + size_t datalength = 0; + unsigned char input[3]; + unsigned char output[4]; + int i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + + if (datalength + 4 > targsize) { + fprintf(stderr, "datalen: %lu\ttargsize: %lu\n", + (long unsigned)datalength, + (long unsigned)targsize); + return (-1); + } + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + * converts characters, four at a time, starting at (or after) + * src from base - 64 numbers into three 8 bit bytes in the target area. + * it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +base64_decode(const char *src, uint8_t *target, size_t targsize) +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + + +/* + * given the length of the original string, return the length of the base64- + * encoded version. + */ +size_t +base64_enclen(size_t orig_len) +{ + size_t len = 0; + + len = orig_len / 3; + if (0 != (orig_len % 3)) + len++; + return len * 4; +} + + +/* + * given the length of the base64-encoded buffer, return the length of the + * decoded version. + */ +size_t +base64_declen(size_t orig_len) +{ + size_t len = 0; + + len = (orig_len * 3) / 4; + return len; +} + + +/* + * Return the package version. + */ +const char * +base64_lib_version() +{ + return libversion; +} + diff --git a/libbase64/base64.h b/libbase64/base64.h new file mode 100644 index 0000000..5e95f44 --- /dev/null +++ b/libbase64/base64.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 by Kyle Isom . + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + + +#ifndef BSD_BASE64 +#define BSD_BASE64 + + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int base64_encode(const uint8_t *, size_t, char *, size_t); +int base64_decode(const char *, uint8_t*, size_t); +size_t base64_enclen(size_t); +size_t base64_declen(size_t); +const char *base64_lib_version(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/libbase64/base64_test.c b/libbase64/base64_test.c new file mode 100644 index 0000000..49eeffa --- /dev/null +++ b/libbase64/base64_test.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2012 Kyle Isom + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * --------------------------------------------------------------------- + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "base64.h" + + +void test_base64_lib_version(void); +void test_base64_enclen(void); +void test_base64_declen(void); +void test_base64_encode(void); +void test_base64_decode(void); + + +/* + * Stubs required by the test suite, but for which no functionality is + * required in this code. init_test is called each time a test is run, + * and cleanup is run after every test. + */ +int init_test(void) +{ + return 0; +} + +int cleanup_test(void) +{ + return 0; +} + + +/* + * fireball is the code called when adding test fails: cleanup the test + * registry and exit. + */ +void +fireball(void) +{ + CU_cleanup_registry(); + exit(CU_get_error()); +} + + +/* + * The main function sets up the test suite, registers the test cases, + * runs through them, and hopefully doesn't explode. + */ +int +main(void) +{ + CU_pSuite tsuite = NULL; + unsigned int fails; + + if (!(CUE_SUCCESS == CU_initialize_registry())) { + errx(EX_CONFIG, "failed to initialise test registry"); + return EXIT_FAILURE; + } + + tsuite = CU_add_suite("base64 test suite", init_test, cleanup_test); + if (NULL == tsuite) + fireball(); + + if (NULL == CU_add_test(tsuite, "base64 library version check", + test_base64_lib_version)) + fireball(); + + if (NULL == CU_add_test(tsuite, "base64 encoding length", + test_base64_enclen)) + fireball(); + + if (NULL == CU_add_test(tsuite, "base64 decoding length", + test_base64_declen)) + fireball(); + + if (NULL == CU_add_test(tsuite, "base64 encode", + test_base64_encode)) + fireball(); + + if (NULL == CU_add_test(tsuite, "base64 decode", + test_base64_decode)) + fireball(); + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + fails = CU_get_number_of_tests_failed(); + warnx("%u tests failed", fails); + + CU_cleanup_registry(); + return fails; +} + + +void +test_base64_lib_version() +{ + char *version = NULL; + + version = (char *)base64_lib_version(); + CU_ASSERT(NULL != version); + CU_ASSERT(0 == strcmp(version, PACKAGE_VERSION)); +} + + +void +test_base64_enclen() +{ + size_t i = 0; + size_t test_vec[] = { + 0, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 24, + 28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40, 44, 44, 44, 48, 48, + 48, 52, 52, 52, 56, 56, 56, 60, 60, 60, 64, 64, 64, 68, 68, 68, 72, + 72, 72, 76, 76, 76, 80, 80, 80, 84, 84, 84, 88, 88, 88, 92, 92, 92, + 96, 96, 96, 100, 100, 100, 104, 104, 104, 108, 108, 108, 112, 112, + 112, 116, 116, 116, 120, 120, 120, 124, 124, 124, 128, 128, 128, 132, + 132, 132, 136, 136, 136, 140, 140, 140, 144, 144, 144, 148, 148, 148, + 152, 152, 152, 156, 156, 156, 160, 160, 160, 164, 164, 164, 168, 168, + 168, 172, 172, 172, 176, 176, 176, 180, 180, 180, 184, 184, 184, 188, + 188, 188, 192, 192, 192, 196, 196, 196, 200, 200, 200, 204, 204, 204, + 208, 208, 208, 212, 212, 212, 216, 216, 216, 220, 220, 220, 224, 224, + 224, 228, 228, 228, 232, 232, 232, 236, 236, 236, 240, 240, 240, 244, + 244, 244, 248, 248, 248, 252, 252, 252, 256, 256, 256, 260, 260, 260, + 264, 264, 264, 268, 268, 268, 272, 272, 272, 276, 276, 276, 280, 280, + 280, 284, 284, 284, 288, 288, 288, 292, 292, 292, 296, 296, 296, 300, + 300, 300, 304, 304, 304, 308, 308, 308, 312, 312, 312, 316, 316, 316, + 320, 320, 320, 324, 324, 324, 328, 328, 328, 332, 332, 332, 336, 336, + 336, 340, 340, 340, 344, 344, 344, 348, 348, 348, 352, 352, 352, 356, + 356, 356, 360, 360, 360, 364, 364, 364, 368, 368, 368, 372, 372, 372, + 376, 376, 376, 380, 380, 380, 384, 384, 384, 388, 388, 388, 392, 392, + 392, 396, 396, 396, 400, 400, 400, 404, 404, 404, 408, 408, 408, 412, + 412, 412, 416, 416, 416, 420, 420, 420, 424, 424, 424, 428, 428, 428, + 432, 432, 432, 436, 436, 436, 440, 440, 440, 444, 444, 444, 448, 448, + 448, 452, 452, 452, 456, 456, 456, 460, 460, 460, 464, 464, 464, 468, + 468, 468, 472, 472, 472, 476, 476, 476, 480, 480, 480, 484, 484, 484, + 488, 488, 488, 492, 492, 492, 496, 496, 496, 500, 500, 500, 504, 504, + 504, 508, 508, 508, 512, 512, 512, 516, 516, 516, 520, 520, 520, 524, + 524, 524, 528, 528, 528, 532, 532, 532, 536, 536, 536, 540, 540, 540, + 544, 544, 544, 548, 548, 548, 552, 552, 552, 556, 556, 556, 560, 560, + 560, 564, 564, 564, 568, 568, 568, 572, 572, 572, 576, 576, 576, 580, + 580, 580, 584, 584, 584, 588, 588, 588, 592, 592, 592, 596, 596, 596, + 600, 600, 600, 604, 604, 604, 608, 608, 608, 612, 612, 612, 616, 616, + 616, 620, 620, 620, 624, 624, 624, 628, 628, 628, 632, 632, 632, 636, + 636, 636, 640, 640, 640, 644, 644, 644, 648, 648, 648, 652, 652, 652, + 656, 656, 656, 660, 660, 660, 664, 664, 664, 668, 668, 668, 672, 672, + 672, 676, 676, 676, 680, 680, 680, 684, 684, 684, 688, 688, 688, 692, + 692, 692, 696, 696, 696, 700, 700, 700, 704, 704, 704, 708, 708, 708, + 712, 712, 712, 716, 716, 716, 720, 720, 720, 724, 724, 724, 728, 728, + 728, 732, 732, 732, 736, 736, 736, 740, 740, 740, 744, 744, 744, 748, + 748, 748, 752, 752, 752, 756, 756, 756, 760, 760, 760, 764, 764, 764, + 768, 768, 768, 772, 772, 772, 776, 776, 776, 780, 780, 780, 784, 784, + 784, 788, 788, 788, 792, 792, 792, 796, 796, 796, 800, 800, 800, 804, + 804, 804, 808, 808, 808, 812, 812, 812, 816, 816, 816, 820, 820, 820, + 824, 824, 824, 828, 828, 828, 832, 832, 832, 836, 836, 836, 840, 840, + 840, 844, 844, 844, 848, 848, 848, 852, 852, 852, 856, 856, 856, 860, + 860, 860, 864, 864, 864, 868, 868, 868, 872, 872, 872, 876, 876, 876, + 880, 880, 880, 884, 884, 884, 888, 888, 888, 892, 892, 892, 896, 896, + 896, 900, 900, 900, 904, 904, 904, 908, 908, 908, 912, 912, 912, 916, + 916, 916, 920, 920, 920, 924, 924, 924, 928, 928, 928, 932, 932, 932, + 936, 936, 936, 940, 940, 940, 944, 944, 944, 948, 948, 948, 952, 952, + 952, 956, 956, 956, 960, 960, 960, 964, 964, 964, 968, 968, 968, 972, + 972, 972, 976, 976, 976, 980, 980, 980, 984, 984, 984, 988, 988, 988, + 992, 992, 992, 996, 996, 996, 1000, 1000, 1000, 1004, 1004, 1004, + 1008, 1008, 1008, 1012, 1012, 1012, 1016, 1016, 1016, 1020, 1020, + 1020, 1024, 1024, 1024, 1028, 1028, 1028, 1032, 1032, 1032, 1036, + 1036, 1036, 1040, 1040, 1040, 1044, 1044, 1044, 1048, 1048, 1048, + 1052, 1052, 1052, 1056, 1056, 1056, 1060, 1060, 1060, 1064, 1064, + 1064, 1068, 1068, 1068, 1072, 1072, 1072, 1076, 1076, 1076, 1080, + 1080, 1080, 1084, 1084, 1084, 1088, 1088, 1088, 1092, 1092, 1092, + 1096, 1096, 1096, 1100, 1100, 1100, 1104, 1104, 1104, 1108, 1108, + 1108, 1112, 1112, 1112, 1116, 1116, 1116, 1120, 1120, 1120, 1124, + 1124, 1124, 1128, 1128, 1128, 1132, 1132, 1132, 1136, 1136, 1136, + 1140, 1140, 1140, 1144, 1144, 1144, 1148, 1148, 1148, 1152, 1152, + 1152, 1156, 1156, 1156, 1160, 1160, 1160, 1164, 1164, 1164, 1168, + 1168, 1168, 1172, 1172, 1172, 1176, 1176, 1176, 1180, 1180, 1180, + 1184, 1184, 1184, 1188, 1188, 1188, 1192, 1192, 1192, 1196, 1196, + 1196, 1200, 1200, 1200, 1204, 1204, 1204, 1208, 1208, 1208, 1212, + 1212, 1212, 1216, 1216, 1216, 1220, 1220, 1220, 1224, 1224, 1224, + 1228, 1228, 1228, 1232, 1232, 1232, 1236, 1236, 1236, 1240, 1240, + 1240, 1244, 1244, 1244, 1248, 1248, 1248, 1252, 1252, 1252, 1256, + 1256, 1256, 1260, 1260, 1260, 1264, 1264, 1264, 1268, 1268, 1268, + 1272, 1272, 1272, 1276, 1276, 1276, 1280, 1280, 1280, 1284, 1284, + 1284, 1288, 1288, 1288, 1292, 1292, 1292, 1296, 1296, 1296, 1300, + 1300, 1300, 1304, 1304, 1304, 1308, 1308, 1308, 1312, 1312, 1312, + 1316, 1316, 1316, 1320, 1320, 1320, 1324, 1324, 1324, 1328, 1328, + 1328, 1332, 1332, 1332, 1336, 1336, 1336, 1340, 1340, 1340, 1344, + 1344, 1344, 1348, 1348, 1348, 1352, 1352, 1352, 1356, 1356, 1356, + 1360, 1360, 1360, 1364, 1364, 1364, + }; + for (i = 0; i < 1024; i++) + CU_ASSERT(base64_enclen(i) == test_vec[i]); +} + + +void +test_base64_declen() +{ + size_t i = 0; + size_t test_vec[] = { + 0, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 24, + 28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40, 44, 44, 44, 48, 48, + 48, 52, 52, 52, 56, 56, 56, 60, 60, 60, 64, 64, 64, 68, 68, 68, 72, + 72, 72, 76, 76, 76, 80, 80, 80, 84, 84, 84, 88, 88, 88, 92, 92, 92, + 96, 96, 96, 100, 100, 100, 104, 104, 104, 108, 108, 108, 112, 112, + 112, 116, 116, 116, 120, 120, 120, 124, 124, 124, 128, 128, 128, 132, + 132, 132, 136, 136, 136, 140, 140, 140, 144, 144, 144, 148, 148, 148, + 152, 152, 152, 156, 156, 156, 160, 160, 160, 164, 164, 164, 168, 168, + 168, 172, 172, 172, 176, 176, 176, 180, 180, 180, 184, 184, 184, 188, + 188, 188, 192, 192, 192, 196, 196, 196, 200, 200, 200, 204, 204, 204, + 208, 208, 208, 212, 212, 212, 216, 216, 216, 220, 220, 220, 224, 224, + 224, 228, 228, 228, 232, 232, 232, 236, 236, 236, 240, 240, 240, 244, + 244, 244, 248, 248, 248, 252, 252, 252, 256, 256, 256, 260, 260, 260, + 264, 264, 264, 268, 268, 268, 272, 272, 272, 276, 276, 276, 280, 280, + 280, 284, 284, 284, 288, 288, 288, 292, 292, 292, 296, 296, 296, 300, + 300, 300, 304, 304, 304, 308, 308, 308, 312, 312, 312, 316, 316, 316, + 320, 320, 320, 324, 324, 324, 328, 328, 328, 332, 332, 332, 336, 336, + 336, 340, 340, 340, 344, 344, 344, 348, 348, 348, 352, 352, 352, 356, + 356, 356, 360, 360, 360, 364, 364, 364, 368, 368, 368, 372, 372, 372, + 376, 376, 376, 380, 380, 380, 384, 384, 384, 388, 388, 388, 392, 392, + 392, 396, 396, 396, 400, 400, 400, 404, 404, 404, 408, 408, 408, 412, + 412, 412, 416, 416, 416, 420, 420, 420, 424, 424, 424, 428, 428, 428, + 432, 432, 432, 436, 436, 436, 440, 440, 440, 444, 444, 444, 448, 448, + 448, 452, 452, 452, 456, 456, 456, 460, 460, 460, 464, 464, 464, 468, + 468, 468, 472, 472, 472, 476, 476, 476, 480, 480, 480, 484, 484, 484, + 488, 488, 488, 492, 492, 492, 496, 496, 496, 500, 500, 500, 504, 504, + 504, 508, 508, 508, 512, 512, 512, 516, 516, 516, 520, 520, 520, 524, + 524, 524, 528, 528, 528, 532, 532, 532, 536, 536, 536, 540, 540, 540, + 544, 544, 544, 548, 548, 548, 552, 552, 552, 556, 556, 556, 560, 560, + 560, 564, 564, 564, 568, 568, 568, 572, 572, 572, 576, 576, 576, 580, + 580, 580, 584, 584, 584, 588, 588, 588, 592, 592, 592, 596, 596, 596, + 600, 600, 600, 604, 604, 604, 608, 608, 608, 612, 612, 612, 616, 616, + 616, 620, 620, 620, 624, 624, 624, 628, 628, 628, 632, 632, 632, 636, + 636, 636, 640, 640, 640, 644, 644, 644, 648, 648, 648, 652, 652, 652, + 656, 656, 656, 660, 660, 660, 664, 664, 664, 668, 668, 668, 672, 672, + 672, 676, 676, 676, 680, 680, 680, 684, 684, 684, 688, 688, 688, 692, + 692, 692, 696, 696, 696, 700, 700, 700, 704, 704, 704, 708, 708, 708, + 712, 712, 712, 716, 716, 716, 720, 720, 720, 724, 724, 724, 728, 728, + 728, 732, 732, 732, 736, 736, 736, 740, 740, 740, 744, 744, 744, 748, + 748, 748, 752, 752, 752, 756, 756, 756, 760, 760, 760, 764, 764, 764, + 768, 768, 768, 772, 772, 772, 776, 776, 776, 780, 780, 780, 784, 784, + 784, 788, 788, 788, 792, 792, 792, 796, 796, 796, 800, 800, 800, 804, + 804, 804, 808, 808, 808, 812, 812, 812, 816, 816, 816, 820, 820, 820, + 824, 824, 824, 828, 828, 828, 832, 832, 832, 836, 836, 836, 840, 840, + 840, 844, 844, 844, 848, 848, 848, 852, 852, 852, 856, 856, 856, 860, + 860, 860, 864, 864, 864, 868, 868, 868, 872, 872, 872, 876, 876, 876, + 880, 880, 880, 884, 884, 884, 888, 888, 888, 892, 892, 892, 896, 896, + 896, 900, 900, 900, 904, 904, 904, 908, 908, 908, 912, 912, 912, 916, + 916, 916, 920, 920, 920, 924, 924, 924, 928, 928, 928, 932, 932, 932, + 936, 936, 936, 940, 940, 940, 944, 944, 944, 948, 948, 948, 952, 952, + 952, 956, 956, 956, 960, 960, 960, 964, 964, 964, 968, 968, 968, 972, + 972, 972, 976, 976, 976, 980, 980, 980, 984, 984, 984, 988, 988, 988, + 992, 992, 992, 996, 996, 996, 1000, 1000, 1000, 1004, 1004, 1004, + 1008, 1008, 1008, 1012, 1012, 1012, 1016, 1016, 1016, 1020, 1020, + 1020, 1024, 1024, 1024, 1028, 1028, 1028, 1032, 1032, 1032, 1036, + 1036, 1036, 1040, 1040, 1040, 1044, 1044, 1044, 1048, 1048, 1048, + 1052, 1052, 1052, 1056, 1056, 1056, 1060, 1060, 1060, 1064, 1064, + 1064, 1068, 1068, 1068, 1072, 1072, 1072, 1076, 1076, 1076, 1080, + 1080, 1080, 1084, 1084, 1084, 1088, 1088, 1088, 1092, 1092, 1092, + 1096, 1096, 1096, 1100, 1100, 1100, 1104, 1104, 1104, 1108, 1108, + 1108, 1112, 1112, 1112, 1116, 1116, 1116, 1120, 1120, 1120, 1124, + 1124, 1124, 1128, 1128, 1128, 1132, 1132, 1132, 1136, 1136, 1136, + 1140, 1140, 1140, 1144, 1144, 1144, 1148, 1148, 1148, 1152, 1152, + 1152, 1156, 1156, 1156, 1160, 1160, 1160, 1164, 1164, 1164, 1168, + 1168, 1168, 1172, 1172, 1172, 1176, 1176, 1176, 1180, 1180, 1180, + 1184, 1184, 1184, 1188, 1188, 1188, 1192, 1192, 1192, 1196, 1196, + 1196, 1200, 1200, 1200, 1204, 1204, 1204, 1208, 1208, 1208, 1212, + 1212, 1212, 1216, 1216, 1216, 1220, 1220, 1220, 1224, 1224, 1224, + 1228, 1228, 1228, 1232, 1232, 1232, 1236, 1236, 1236, 1240, 1240, + 1240, 1244, 1244, 1244, 1248, 1248, 1248, 1252, 1252, 1252, 1256, + 1256, 1256, 1260, 1260, 1260, 1264, 1264, 1264, 1268, 1268, 1268, + 1272, 1272, 1272, 1276, 1276, 1276, 1280, 1280, 1280, 1284, 1284, + 1284, 1288, 1288, 1288, 1292, 1292, 1292, 1296, 1296, 1296, 1300, + 1300, 1300, 1304, 1304, 1304, 1308, 1308, 1308, 1312, 1312, 1312, + 1316, 1316, 1316, 1320, 1320, 1320, 1324, 1324, 1324, 1328, 1328, + 1328, 1332, 1332, 1332, 1336, 1336, 1336, 1340, 1340, 1340, 1344, + 1344, 1344, 1348, 1348, 1348, 1352, 1352, 1352, 1356, 1356, 1356, + 1360, 1360, 1360, 1364, 1364, 1364, + }; + + for (i = 0; i < 1024; i++) { + CU_ASSERT(base64_declen(test_vec[i]) >= i); + CU_ASSERT((base64_declen(test_vec[i]) - i) < 3); + } +} + + +void +test_base64_encode() +{ + char testvec[][45] = { + "", + "QQ==", + "QUE=", + "QUFB", + "QUFBQQ==", + "QUFBQUE=", + "QUFBQUFB", + "QUFBQUFBQQ==", + "QUFBQUFBQUE=", + "QUFBQUFBQUFB", + "QUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + }; + uint8_t testbuf[33]; + char base64_buf[45]; + size_t i; + + for (i = 0; i < 32; i++) { + memset(base64_buf, 0x0, 45); + memset(testbuf, 0x0, 33); + memset(testbuf, 0x41, i); + CU_ASSERT(-1 != base64_encode(testbuf, i, base64_buf, + base64_enclen(i) + 1)); + CU_ASSERT(strlen(testvec[i]) == strlen(base64_buf)); + CU_ASSERT(0 == strcmp(testvec[i], base64_buf)); + } +} + + +void +test_base64_decode() +{ + char testvec[][45] = { + "", + "QQ==", + "QUE=", + "QUFB", + "QUFBQQ==", + "QUFBQUE=", + "QUFBQUFB", + "QUFBQUFBQQ==", + "QUFBQUFBQUE=", + "QUFBQUFBQUFB", + "QUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB", + "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==", + }; + uint8_t testbuf[33]; + uint8_t expected[33]; + char base64_buf[45]; + size_t i; + + for (i = 0; i < 32; i++) { + memset(base64_buf, 0x0, 45); + memcpy(base64_buf, testvec[i], base64_enclen(i)); + memset(testbuf, 0x0, 33); + memset(expected, 0x0, 33); + memset(expected, 0x41, i); + CU_ASSERT(-1 != base64_decode(testvec[i], testbuf, i + 1)); + CU_ASSERT(strlen((char *)testbuf) == strlen((char *)expected)); + CU_ASSERT(0 == strcmp((char *)testbuf, (char *)expected)); + } +} diff --git a/libbase64/config.sh b/libbase64/config.sh new file mode 100755 index 0000000..ddafb4c --- /dev/null +++ b/libbase64/config.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +TARGET="$(cat Makefile.in | grep 'TARGET :=' | awk -F' ' '{ print $3; }')" +echo "configuring ${TARGET}" + +which sed 2>/dev/null 1>/dev/null +if [ $? -ne 0 ]; then + echo "cannot find sed!" 1>&2 +fi + +OPSYS=$(uname -s) + +echo "Configuring for ${OPSYS}..." +if [ "x${OPSYS}" = "xLinux" ]; then + OS_CFLAGS="-D_BSD_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE" +else + OS_CFLAGS="" +fi + +if [ -z "${OS_CFLAGS}" ]; then + echo "${OPSYS} requires no extra build flags." +else + echo "${OPSYS} requires build flags ${OS_CFLAGS}" +fi + +if [ -z "${PREFIX}" ]; then + PREFIX="/usr/local" +fi + +if [ "${PREFIX}" = "/usr" ]; then + MANDIR="$(PREFIX)/share/man" +elif [ "${PREFIX}" = "/usr/local" ]; then + if [ "${OPSYS}" = "Darwin" ]; then + MANDIR="${PREFIX}/share/man" + else + MANDIR="${PREFIX}/man" + fi +else + MANDIR="${PREFIX}/man" +fi + +echo "prefix: ${PREFIX}" +echo "mandir: ${MANDIR}" + +echo "writing new Makefile" +cat Makefile.in | sed -e "s|OS_CFLAGS|${OS_CFLAGS}|" | \ + sed -e "s|\$PREFIX|${PREFIX}|" | \ + sed -e "s|\$MANDIR|${MANDIR}|" > Makefile + + +echo "done." diff --git a/libbase64/libbase64-1.pc.in b/libbase64/libbase64-1.pc.in new file mode 100644 index 0000000..e235c6a --- /dev/null +++ b/libbase64/libbase64-1.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Description: OpenBSD base64 functions +URL: @PACKAGE_URL@ +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -Wl,-rpath,${libdir} -lbase64 diff --git a/libbase64/libbase64.3 b/libbase64/libbase64.3 new file mode 100644 index 0000000..d110c93 --- /dev/null +++ b/libbase64/libbase64.3 @@ -0,0 +1,113 @@ +.Dd February 7, 2013 +.Dt LIBBASE64 3 +.Os +.Sh NAME +.Nm libbase64 +.Nd OpenBSD's base64 code extracted to a static library +.Sh SYNOPSIS +.In base64.h +.Ft int +.Fo base64_encode +.Fa "const uint8_t *src" +.Fa "size_t srclen" +.Fa "char *dst" +.Fa "size_t dstlen" +.Fc +.Ft int +.Fo base64_decode +.Fa "const char *src" +.Fa "uint8_t *dst" +.Fa "size_t dstlen" +.Fc +.Ft size_t +.Fo base64_enclen +.Fa "size_t len" +.Fc +.Ft size_t +.Fo base64_declen +.Fa "size_t len" +.Fc +.Ft "const char *" +.Fo base64_lib_version +.Fa void +.Fc +.Sh DESCRIPTION +.Nm +provides functions for base64 encoding and decoding. The +.Nm base64_encode +function takes arbtitrary binary data and a pre-allocated buffer to +store the base64-encoded data in. The expected size of the buffer +(sans a NULL byte) can be retrieved with the function +.Nm base64_enclen . +The destination size should be the value of +.Nm base64_enclen(buflen) +plus an extra NULL byte. +.Nm base64_decode +reverses the process; the length to the base64-encoded buffer is not +required. The size of the destination buffer should be at least +.Nm base64_declen(b64buflen) + 1 . +The current version of the library can be retrieved with the +.Nm base64_lib_version +returns the current version string for the package. +.Sh RETURN VALUES +.Nm base64_encode +and +.Nm base64_decode +return -1 on error, or the length of the stored data on success. +.Nm base64_enclen +returns the base64-encoded length of a base64-encoded buffer with a +source buffer length of +.Nm len ; +.Nm base64_decode +returns the maximum base64-decoded size of a source buffer of length +.Nm len , +possibly two more bytes than actually required. The actual length of +the buffer depends on the encoded data. +.Nm base64_lib_version +returns a pointer to a statically allocated buffer containing the +version number. This pointer should not be freed. +.Sh EXAMPLES +A sample section of code doing base64 encoding might look like: +.Bd -literal + uint8_t msg[] = "Hello, world."; + char *b64 = NULL; + size_t b64len; + + b64len = base64_enclen(strlen(msg)); + b64 = malloc(b64len + 1); + if (NULL == b64) + return -1; + memset(b64, 0x0, b64len); + + if (base64_encode(b64, b64len + 1, msg, strlen(msg)) != -1); + do_something(b64, b64len); + free(b64); +.Ed +Decoding is similar: +.Bd -literal + char msg[] = "SGVsbG8sIHdvcmxk"; + uint8_t *buf = NULL; + size_t buflen; + + buflen = base64_declen(strlen(msg)); + buf = malloc(buflen + 1); + if (NULL == buf) + return -1; + memset(buf, 0x0, buflen + 1); + + if (base64_decode(msg, buf, buflen) != -1) + do_something(buf, buflen); + free(buf); +.Ed +.Sh ERRORS +The most common cause for failure will be an incorrectly-sized buffer, +or an invalid base64-encoded string. +.Sh STANDARDS +.Nm +conforms to C99 and SUSv4. +.Sh AUTHORS +.Nm +was written by +.An Kyle Isom Aq Mt kyle@tyrfingr.is . +.Sh BUGS +Please report all bugs to the author.