aboutsummaryrefslogtreecommitdiffstats
path: root/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'test.c')
-rw-r--r--test.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..38b0d85
--- /dev/null
+++ b/test.c
@@ -0,0 +1,309 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsha1.h"
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#define test(EXPR)\
+ do {\
+ if (EXPR)\
+ break;\
+ fprintf(stderr, "Failure at line %i: %s\n", __LINE__, #EXPR);\
+ exit(1);\
+ } while (0)
+
+#define test_str(HAVE, EXPECTED)\
+ do {\
+ if (!strcmp(HAVE, EXPECTED))\
+ break;\
+ fprintf(stderr, "Failure at line %i: expected \"%s\", got \"%s\"\n", __LINE__, EXPECTED, HAVE);\
+ exit(1);\
+ } while (0)
+
+#define test_repeated(CHR, N, ALGO, EXPECTED)\
+ do {\
+ memset(buf, CHR, N);\
+ test(!libsha1_init(&s, ALGO));\
+ libsha1_digest(&s, buf, (N) * 8, buf);\
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));\
+ test_str(str, EXPECTED);\
+ } while (0)
+
+#define test_repeated_huge(CHR, N, ALGO, EXPECTED)\
+ do {\
+ size_t n__ = N;\
+ if (skip_huge)\
+ break;\
+ memset(buf, CHR, sizeof(buf));\
+ test(!libsha1_init(&s, ALGO));\
+ fprintf(stderr, "processing huge message: 0 %%\n");\
+ for (; n__ > sizeof(buf); n__ -= sizeof(buf)) {\
+ libsha1_update(&s, buf, sizeof(buf) * 8);\
+ fprintf(stderr, "\033[A\033[Kprocessing huge message: %zu %%\n", ((N) - n__) * 100 / (N));\
+ }\
+ libsha1_update(&s, buf, n__ * 8);\
+ fprintf(stderr, "\033[A\033[K");\
+ fflush(stderr);\
+ libsha1_digest(&s, NULL, 0, buf);\
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));\
+ test_str(str, EXPECTED);\
+ } while (0)
+
+#define test_custom(S, ALGO, EXPECTED)\
+ do {\
+ test(!libsha1_init(&s, ALGO));\
+ libsha1_digest(&s, S, (sizeof(S) - 1) * 8, buf);\
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));\
+ test_str(str, EXPECTED);\
+ } while (0)
+
+#define test_bits(S, N, ALGO, EXPECTED)\
+ do {\
+ libsha1_unhex(buf, S);\
+ test(!libsha1_init(&s, ALGO));\
+ libsha1_digest(&s, buf, N, buf);\
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));\
+ test_str(str, EXPECTED);\
+ } while (0)
+
+#define test_hmac(ALGO, TEXT, KEY, MAC)\
+ do {\
+ libsha1_unhex(buf, KEY);\
+ test(!libsha1_hmac_init(&hs, ALGO, buf, (sizeof(KEY) - 1) << 2));\
+ libsha1_unhex(buf, TEXT);\
+ libsha1_hmac_digest(&hs, buf, (sizeof(TEXT) - 1) << 2, buf);\
+ libsha1_behex_lower(str, buf, libsha1_hmac_state_output_size(&hs));\
+ test_str(str, MAC);\
+ } while (0)
+
+
+int
+main(int argc, char *argv[])
+{
+ char buf[8096], str[2048];
+ struct libsha1_state s;
+ struct libsha1_hmac_state hs;
+ int skip_huge, fds[2], status;
+ size_t i, j, n, len;
+ ssize_t r;
+ pid_t pid;
+
+ skip_huge = (argc == 2 && !strcmp(argv[1], "skip-huge"));
+
+ libsha1_behex_lower(buf, "", 0);
+ test_str(buf, "");
+
+ libsha1_behex_lower(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16);
+ test_str(buf, "00112233445566778899aabbccddeeff");
+
+ libsha1_behex_lower(buf, "\x1E\x5A\xC0", 3);
+ test_str(buf, "1e5ac0");
+
+ libsha1_behex_upper(buf, "", 0);
+ test_str(buf, "");
+
+ libsha1_behex_upper(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16);
+ test_str(buf, "00112233445566778899AABBCCDDEEFF");
+
+ libsha1_behex_upper(buf, "\x1E\x5A\xC0", 3);
+ test_str(buf, "1E5AC0");
+
+ libsha1_unhex(buf, "");
+ test(!memcmp(buf, "", 0));
+
+ libsha1_unhex(buf, "00112233445566778899AABBCCDDEEFF");
+ test(!memcmp(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16));
+
+ libsha1_unhex(buf, "1E5AC0");
+ test(!memcmp(buf, "\x1E\x5A\xC0", 3));
+
+ libsha1_unhex(buf, "00112233445566778899aabbccddeeff");
+ test(!memcmp(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16));
+
+ libsha1_unhex(buf, "1e5ac0");
+ test(!memcmp(buf, "\x1E\x5A\xC0", 3));
+
+ libsha1_unhex(buf, "AAbbCcdD");
+ test(!memcmp(buf, "\xAA\xBB\xCC\xDD", 4));
+
+ test(libsha1_algorithm_output_size(LIBSHA1_0) == 20);
+ test(libsha1_algorithm_output_size(LIBSHA1_1) == 20);
+ test(!errno);
+ test(libsha1_algorithm_output_size(~0) == 0); /* should test `errno == EINVAL`, optimising compiler breaks it */
+
+ errno = 0;
+ test(libsha1_init(&s, ~0) == -1 && errno == EINVAL);
+ errno = 0;
+
+#ifdef TODO
+ test(!libsha1_init(&s, LIBSHA1_0));
+ test(libsha1_state_output_size(&s) == 20);
+ libsha1_digest(&s, "", 0, buf);
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));
+ test_str(str, "");
+#endif
+
+ test(!libsha1_init(&s, LIBSHA1_1));
+ test(libsha1_state_output_size(&s) == 20);
+ libsha1_digest(&s, "", 0, buf);
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));
+ test_str(str, "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+
+#ifdef TODO
+ test_repeated(0xFF, 1, LIBSHA1_0, "");
+ test_custom("\xE5\xE0\x99\x24", LIBSHA1_0, "");
+ test_repeated(0x00, 56, LIBSHA1_0, "");
+ test_repeated(0x51, 1000, LIBSHA1_0, "");
+ test_repeated(0x41, 1000, LIBSHA1_0, "");
+ test_repeated(0x99, 1005, LIBSHA1_0, "");
+ test_repeated_huge(0x00, 1000000UL, LIBSHA1_0, "");
+ test_repeated_huge(0x41, 0x20000000UL, LIBSHA1_0, "");
+ test_repeated_huge(0x00, 0x41000000UL, LIBSHA1_0, "");
+ test_repeated_huge(0x84, 0x6000003FUL, LIBSHA1_0, "");
+ test_custom("abc", LIBSHA1_0, "");
+ test_custom("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", LIBSHA1_1,
+ "");
+#endif
+
+ test_repeated(0xFF, 1, LIBSHA1_1, "85e53271e14006f0265921d02d4d736cdc580b0b");
+ test_custom("\xE5\xE0\x99\x24", LIBSHA1_1, "d1dffbc8a175dd8eebe0da87b1792b6dc1018e82");
+ test_repeated(0x00, 56, LIBSHA1_1, "9438e360f578e12c0e0e8ed28e2c125c1cefee16");
+ test_repeated(0x51, 1000, LIBSHA1_1, "49f1cfe3829963158e2b2b2cb5df086cee2e3bb0");
+ test_repeated(0x41, 1000, LIBSHA1_1, "3ae3644d6777a1f56a1defeabc74af9c4b313e49");
+ test_repeated(0x99, 1005, LIBSHA1_1, "18685d56c8bf67c3cee4443e9a78f65c30752f5d");
+ test_repeated_huge(0x00, 1000000UL, LIBSHA1_1, "bef3595266a65a2ff36b700a75e8ed95c68210b6");
+ test_repeated_huge(0x41, 0x20000000UL, LIBSHA1_1, "df3f26fce8fa7bec2c61d0506749a320ac7dc942");
+ test_repeated_huge(0x00, 0x41000000UL, LIBSHA1_1, "320c617b0b6ee1b6f9c3271eae135f40cae22c10");
+ test_repeated_huge(0x84, 0x6000003FUL, LIBSHA1_1, "b20aa99b62e6a480fd93b4d24b2c19ffac649bb8");
+ test_custom("abc", LIBSHA1_1, "a9993e364706816aba3e25717850c26c9cd0d89d");
+ test_custom("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", LIBSHA1_1,
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+
+ for (i = 0; i < 1000; i++) {
+#ifdef TODO
+ for (j = 0; j < 2; j++) {
+#else
+ for (j = 1; j < 2; j++) {
+#endif
+ memset(buf, 0x41, 1000);
+ test(!libsha1_init(&s, (enum libsha1_algorithm)j));
+ libsha1_update(&s, buf, i * 8);
+ libsha1_digest(&s, buf, (1000 - i) * 8, buf);
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));
+ test_str(str, ((const char *[]){
+ "",
+ "3ae3644d6777a1f56a1defeabc74af9c4b313e49"
+ })[j]);
+
+ memset(buf, 0x41, 1000);
+ test(!libsha1_init(&s, (enum libsha1_algorithm)j));
+ libsha1_update(&s, buf, i * 8);
+ libsha1_update(&s, buf, (1000 - i) * 8);
+ libsha1_digest(&s, NULL, 0, buf);
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));
+ test_str(str, ((const char *[]){
+ "",
+ "3ae3644d6777a1f56a1defeabc74af9c4b313e49"
+ })[j]);
+
+ if (!i)
+ continue;
+
+ memset(buf, 0x41, 1000);
+ test(!libsha1_init(&s, (enum libsha1_algorithm)j));
+ for (n = 0; n + i < 1000; n += i) {
+ libsha1_update(&s, buf, i * 8);
+ test((len = libsha1_marshal(&s, NULL)) && len <= sizeof(str));
+ test(libsha1_marshal(&s, str) == len);
+ memset(&s, 0, sizeof(s));
+ test(libsha1_unmarshal(&s, str, sizeof(str)) == len);
+ }
+ libsha1_digest(&s, buf, (1000 - n) * 8, buf);
+ libsha1_behex_lower(str, buf, libsha1_state_output_size(&s));
+ test_str(str, ((const char *[]){
+ "",
+ "3ae3644d6777a1f56a1defeabc74af9c4b313e49"
+ })[j]);
+ }
+ }
+
+ test(!errno);
+
+ test(!pipe(fds));
+ test((pid = fork()) >= 0);
+ if (!pid) {
+ close(fds[0]);
+ memset(buf, 0x41, 1000);
+ for (n = 1000; n; n -= (size_t)r)
+ test((r = write(fds[1], buf, n < 8 ? n : 8)) > 0);
+ exit(0);
+ }
+ close(fds[1]);
+ test(!libsha1_sum_fd(fds[0], LIBSHA1_1, buf));
+ test(waitpid(pid, &status, 0) == pid);
+ test(!status);
+ close(fds[0]);
+ libsha1_behex_lower(str, buf, libsha1_algorithm_output_size(LIBSHA1_1));
+ test_str(str, "3ae3644d6777a1f56a1defeabc74af9c4b313e49");
+
+ test_bits("00", 1, LIBSHA1_1, "bb6b3e18f0115b57925241676f5b1ae88747b08a");
+ test_bits("01", 2, LIBSHA1_1, "ec6b39952e1a3ec3ab3507185cf756181c84bbe2");
+ test_bits("04", 3, LIBSHA1_1, "a37596ec13a0d2f9e6c0b8b96f9112823aa6d961");
+ test_bits("0d", 4, LIBSHA1_1, "ba582f5967911beb91599684c2eb2baeefb78da7");
+ test_bits("09", 5, LIBSHA1_1, "3320540d1c28b96ddd03eee1b186a8f2ae883fbe");
+ test_bits("08", 6, LIBSHA1_1, "b372bd120957ebc3392cd060e131699d1fee6059");
+ test_bits("22", 7, LIBSHA1_1, "04f31807151181ad0db278a1660526b0aeef64c2");
+
+ test(!libsha1_hmac_init(&hs, LIBSHA1_1, "", 0));
+ test(libsha1_hmac_state_output_size(&hs) == 20);
+ libsha1_hmac_digest(&hs, "", 0, buf);
+ libsha1_behex_lower(str, buf, libsha1_hmac_state_output_size(&hs));
+ test_str(str, "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d");
+
+ test(!libsha1_hmac_init(&hs, LIBSHA1_1, "key", 3 << 3));
+ test(libsha1_hmac_state_output_size(&hs) == 20);
+ libsha1_hmac_digest(&hs, "The quick brown fox jumps over the lazy dog",
+ (sizeof("The quick brown fox jumps over the lazy dog") - 1) << 3, buf);
+ libsha1_behex_lower(str, buf, libsha1_hmac_state_output_size(&hs));
+ test_str(str, "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9");
+
+ n = sizeof("The quick brown fox jumps over the lazy dog") - 1;
+ for (i = 1; i < n; i++) {
+ test(!libsha1_hmac_init(&hs, LIBSHA1_1, "key", 3 << 3));
+ test(libsha1_hmac_state_output_size(&hs) == 20);
+ for (j = 0; j + i < n; j += i) {
+ libsha1_hmac_update(&hs, &"The quick brown fox jumps over the lazy dog"[j], i << 3);
+ test((len = libsha1_hmac_marshal(&hs, NULL)) && len <= sizeof(str));
+ test(libsha1_hmac_marshal(&hs, str) == len);
+ memset(&hs, 0, sizeof(hs));
+ test(libsha1_hmac_unmarshal(&hs, str, sizeof(str)) == len);
+ }
+ libsha1_hmac_digest(&hs, &"The quick brown fox jumps over the lazy dog"[j], (n - j) << 3, buf);
+ libsha1_behex_lower(str, buf, libsha1_hmac_state_output_size(&hs));
+ test_str(str, "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9");
+ }
+
+ test(!errno);
+
+ test_hmac(LIBSHA1_1,
+ "53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
+ "5fd596ee78d5553c8ff4e72d266dfd192366da29");
+
+ test_hmac(LIBSHA1_1,
+ "53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e",
+ "000102030405060708090a0b0c0d0e0f10111213",
+ "4c99ff0cb1b31bd33f8431dbaf4d17fcd356a807");
+
+ test_hmac(LIBSHA1_1,
+ "53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60616263",
+ "2d51b2f7750e410584662e38f133435f4c4fd42a");
+
+ return 0;
+}