|
35 | 35 |
|
36 | 36 | #include "checks.h" |
37 | 37 |
|
| 38 | +#ifdef CL_THREAD_SAFE |
| 39 | +#include <pthread.h> |
| 40 | +#endif |
| 41 | + |
38 | 42 | static int fpu_words = FPU_ENDIAN_INITME; |
39 | 43 | #define NO_FPU_ENDIAN (fpu_words == FPU_ENDIAN_UNKNOWN) |
40 | 44 | #define EA06_SCAN strstr(file, "clam.ea06.exe") |
@@ -1693,6 +1697,93 @@ START_TEST(test_sha2_256) |
1693 | 1697 | } |
1694 | 1698 | END_TEST |
1695 | 1699 |
|
| 1700 | +START_TEST(test_hash_md5_sha1) |
| 1701 | +{ |
| 1702 | + /* The incremental cl_hash_* API is routed through the shared EVP_MD cache |
| 1703 | + * by this change; verify it still returns correct MD5/SHA1 digests for the |
| 1704 | + * "abc" vectors. An algorithm unavailable under a strict FIPS policy (e.g. |
| 1705 | + * MD5) yields a NULL context and is skipped rather than failing the test. */ |
| 1706 | + static const uint8_t abc[] = {'a', 'b', 'c'}; |
| 1707 | + static const uint8_t md5_abc[MD5_HASH_SIZE] = { |
| 1708 | + 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, |
| 1709 | + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72}; |
| 1710 | + static const uint8_t sha1_abc[SHA1_HASH_SIZE] = { |
| 1711 | + 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, |
| 1712 | + 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d}; |
| 1713 | + uint8_t out[SHA256_HASH_SIZE]; |
| 1714 | + void *ctx; |
| 1715 | + |
| 1716 | + ctx = cl_hash_init("md5"); |
| 1717 | + if (NULL != ctx) { |
| 1718 | + cl_update_hash(ctx, abc, sizeof(abc)); |
| 1719 | + cl_finish_hash(ctx, out); |
| 1720 | + ck_assert_msg(!memcmp(out, md5_abc, MD5_HASH_SIZE), "md5(\"abc\") mismatch"); |
| 1721 | + } |
| 1722 | + |
| 1723 | + ctx = cl_hash_init("sha1"); |
| 1724 | + if (NULL != ctx) { |
| 1725 | + cl_update_hash(ctx, abc, sizeof(abc)); |
| 1726 | + cl_finish_hash(ctx, out); |
| 1727 | + ck_assert_msg(!memcmp(out, sha1_abc, SHA1_HASH_SIZE), "sha1(\"abc\") mismatch"); |
| 1728 | + } |
| 1729 | +} |
| 1730 | +END_TEST |
| 1731 | + |
| 1732 | +#ifdef CL_THREAD_SAFE |
| 1733 | +#define HASH_TS_THREADS 8 |
| 1734 | +#define HASH_TS_ITERS 2000 |
| 1735 | +struct hash_ts_arg { |
| 1736 | + const uint8_t *expect; /* sha2-256("abc") == res256[0] */ |
| 1737 | + int failed; |
| 1738 | +}; |
| 1739 | +static void *hash_ts_worker(void *arg) |
| 1740 | +{ |
| 1741 | + struct hash_ts_arg *a = (struct hash_ts_arg *)arg; |
| 1742 | + static const uint8_t abc[] = {'a', 'b', 'c'}; |
| 1743 | + uint8_t out[SHA256_HASH_SIZE]; |
| 1744 | + unsigned i; |
| 1745 | + |
| 1746 | + for (i = 0; i < HASH_TS_ITERS; i++) { |
| 1747 | + void *ctx = cl_hash_init("sha2-256"); |
| 1748 | + if (NULL == ctx) { |
| 1749 | + a->failed = 1; |
| 1750 | + return NULL; |
| 1751 | + } |
| 1752 | + cl_update_hash(ctx, abc, sizeof(abc)); |
| 1753 | + cl_finish_hash(ctx, out); |
| 1754 | + if (0 != memcmp(out, a->expect, SHA256_HASH_SIZE)) { |
| 1755 | + a->failed = 1; |
| 1756 | + return NULL; |
| 1757 | + } |
| 1758 | + } |
| 1759 | + return NULL; |
| 1760 | +} |
| 1761 | + |
| 1762 | +START_TEST(test_hash_cache_threadsafe) |
| 1763 | +{ |
| 1764 | + /* Concurrently hammer cl_hash_init() to exercise the process-global EVP_MD |
| 1765 | + * cache added by the per-hash provider-fetch fix, catching races on the |
| 1766 | + * cache and its mutex (run under Valgrind/TSan in CI). */ |
| 1767 | + pthread_t th[HASH_TS_THREADS]; |
| 1768 | + struct hash_ts_arg args[HASH_TS_THREADS]; |
| 1769 | + int i, failed = 0; |
| 1770 | + |
| 1771 | + for (i = 0; i < HASH_TS_THREADS; i++) { |
| 1772 | + args[i].expect = res256[0]; |
| 1773 | + args[i].failed = 0; |
| 1774 | + ck_assert_msg(0 == pthread_create(&th[i], NULL, hash_ts_worker, &args[i]), |
| 1775 | + "pthread_create failed"); |
| 1776 | + } |
| 1777 | + for (i = 0; i < HASH_TS_THREADS; i++) { |
| 1778 | + pthread_join(th[i], NULL); |
| 1779 | + if (args[i].failed) |
| 1780 | + failed = 1; |
| 1781 | + } |
| 1782 | + ck_assert_msg(0 == failed, "concurrent cl_hash_init(sha2-256) returned a wrong digest or NULL context"); |
| 1783 | +} |
| 1784 | +END_TEST |
| 1785 | +#endif |
| 1786 | + |
1696 | 1787 | START_TEST(test_sanitize_path) |
1697 | 1788 | { |
1698 | 1789 | const char *unsanitized = NULL; |
@@ -2041,6 +2132,10 @@ static Suite *test_cli_suite(void) |
2041 | 2132 | suite_add_tcase(s, tc_cli_dsig); |
2042 | 2133 | tcase_add_loop_test(tc_cli_dsig, test_cli_dsig, 0, dsig_tests_cnt); |
2043 | 2134 | tcase_add_test(tc_cli_dsig, test_sha2_256); |
| 2135 | + tcase_add_test(tc_cli_dsig, test_hash_md5_sha1); |
| 2136 | +#ifdef CL_THREAD_SAFE |
| 2137 | + tcase_add_test(tc_cli_dsig, test_hash_cache_threadsafe); |
| 2138 | +#endif |
2044 | 2139 |
|
2045 | 2140 | suite_add_tcase(s, tc_cli_assorted); |
2046 | 2141 | tcase_add_test(tc_cli_assorted, test_sanitize_path); |
|
0 commit comments