| #ifndef _GNU_SOURCE |
| #define _GNU_SOURCE |
| #endif |
| |
| #include "minicrypt.h" |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #ifndef TEST_OPENSSL |
| #define TEST_OPENSSL 0 |
| #endif |
| |
| /******************************************************************************* |
| SHA-1 testing |
| */ |
| static void minicrypt_test_sha1(void) { |
| struct { |
| char* str; |
| char hash[21]; |
| } sets[] = { |
| {"The quick brown fox jumps over the lazy dog", |
| {0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, 0xe1, |
| 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12, |
| 0}}, // a set with a string |
| {"", |
| { |
| 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, |
| 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, |
| }}, // an empty set |
| {NULL, {0}} // Stop |
| }; |
| int i = 0; |
| sha1_s sha1; |
| fprintf(stderr, "+ MiniCrypt"); |
| while (sets[i].str) { |
| minicrypt_sha1_init(&sha1); |
| minicrypt_sha1_write(&sha1, sets[i].str, strlen(sets[i].str)); |
| if (strcmp(minicrypt_sha1_result(&sha1), sets[i].hash)) { |
| fprintf(stderr, |
| ":\n--- MiniCrypt SHA-1 Test FAILED!\nstring: %s\nexpected: ", |
| sets[i].str); |
| char* p = sets[i].hash; |
| while (*p) |
| fprintf(stderr, "%02x", *(p++) & 0xFF); |
| fprintf(stderr, "\ngot: "); |
| p = minicrypt_sha1_result(&sha1); |
| while (*p) |
| fprintf(stderr, "%02x", *(p++) & 0xFF); |
| fprintf(stderr, "\n"); |
| return; |
| } |
| i++; |
| } |
| fprintf(stderr, " SHA-1 passed.\n"); |
| } |
| |
| /******************************************************************************* |
| SHA-2 TODO: testing is just a stub for noew (also, SHA-2 isn't implemented) |
| */ |
| |
| static char* sha2_variant_names[] = { |
| "SHA_512", "SHA_512_256", "SHA_512_224", "SHA_384", "SHA_256", "SHA_224", |
| }; |
| |
| static void minicrypt_test_sha2(void) { |
| sha2_s s; |
| char* expect = NULL; |
| char* got = NULL; |
| char* str = ""; |
| fprintf(stderr, "+ MiniCrypt"); |
| // start tests |
| minicrypt_sha2_init(&s, SHA_224); |
| minicrypt_sha2_write(&s, str, 0); |
| expect = |
| "\xd1\x4a\x02\x8c\x2a\x3a\x2b\xc9\x47\x61\x02\xbb\x28\x82\x34\xc4" |
| "\x15\xa2\xb0\x1f\x82\x8e\xa6\x2a\xc5\xb3\xe4\x2f"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_256); |
| minicrypt_sha2_write(&s, str, 0); |
| expect = |
| "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27" |
| "\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_384); |
| minicrypt_sha2_write(&s, str, 0); |
| expect = |
| "\x38\xb0\x60\xa7\x51\xac\x96\x38\x4c\xd9\x32\x7e" |
| "\xb1\xb1\xe3\x6a\x21\xfd\xb7\x11\x14\xbe\x07\x43\x4c\x0c" |
| "\xc7\xbf\x63\xf6\xe1\xda\x27\x4e\xde\xbf\xe7\x6f\x65\xfb" |
| "\xd5\x1a\xd2\xf1\x48\x98\xb9\x5b"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_512); |
| minicrypt_sha2_write(&s, str, 0); |
| expect = |
| "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d" |
| "\x80\x07\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21" |
| "\xd3\x6c\xe9\xce\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83" |
| "\x18\xd2\x87\x7e\xec\x2f\x63\xb9\x31\xbd\x47\x41\x7a\x81" |
| "\xa5\x38\x32\x7a\xf9\x27\xda\x3e"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_512_224); |
| minicrypt_sha2_write(&s, str, 0); |
| expect = |
| "\x6e\xd0\xdd\x02\x80\x6f\xa8\x9e\x25\xde\x06\x0c\x19\xd3" |
| "\xac\x86\xca\xbb\x87\xd6\xa0\xdd\xd0\x5c\x33\x3b\x84\xf4"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_512_256); |
| minicrypt_sha2_write(&s, str, 0); |
| expect = |
| "\xc6\x72\xb8\xd1\xef\x56\xed\x28\xab\x87\xc3\x62\x2c\x51\x14\x06" |
| "\x9b\xdd\x3a\xd7\xb8\xf9\x73\x74\x98\xd0\xc0\x1e\xce\xf0\x96\x7a"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_224); |
| str = "The quick brown fox jumps over the lazy dog"; |
| minicrypt_sha2_write(&s, str, strlen(str)); |
| expect = |
| "\x73\x0e\x10\x9b\xd7\xa8\xa3\x2b\x1c\xb9\xd9\xa0\x9a\xa2" |
| "\x32\x5d\x24\x30\x58\x7d\xdb\xc0\xc3\x8b\xad\x91\x15\x25"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| minicrypt_sha2_init(&s, SHA_512); |
| str = "god is a rotten tomato"; |
| minicrypt_sha2_write(&s, str, strlen(str)); |
| expect = |
| "\x61\x97\x4d\x41\x9f\x77\x45\x21\x09\x4e\x95\xa3\xcb\x4d\xe4\x79" |
| "\x26\x32\x2f\x2b\xe2\x62\x64\x5a\xb4\x5d\x3f\x73\x69\xef\x46\x20" |
| "\xb2\xd3\xce\xda\xa9\xc2\x2c\xac\xe3\xf9\x02\xb2\x20\x5d\x2e\xfd" |
| "\x40\xca\xa0\xc1\x67\xe0\xdc\xdf\x60\x04\x3e\x4e\x76\x87\x82\x74"; |
| got = minicrypt_sha2_result(&s); |
| if (strcmp(expect, got)) |
| goto error; |
| |
| fprintf(stderr, " SHA-2 passed.\n"); |
| return; |
| goto error; |
| error: |
| fprintf(stderr, |
| ":\n--- MiniCrypt SHA-2 Test FAILED!\ntype: " |
| "%s\nstring %s\nexpected: ", |
| sha2_variant_names[s.type], str); |
| while (*expect) |
| fprintf(stderr, "%02x", *(expect++) & 0xFF); |
| fprintf(stderr, "\ngot: "); |
| while (*got) |
| fprintf(stderr, "%02x", *(got++) & 0xFF); |
| fprintf(stderr, "\n"); |
| } |
| |
| /******************************************************************************* |
| Base64 |
| */ |
| static void minicrypt_test_base64(void) { |
| struct { |
| char* str; |
| char* base64; |
| } sets[] = { |
| // {"Man is distinguished, not only by his reason, but by this singular " |
| // "passion from other animals, which is a lust of the mind, that by a " |
| // "perseverance of delight in the continued and indefatigable generation |
| // " |
| // "of knowledge, exceeds the short vehemence of any carnal pleasure.", |
| // "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB" |
| // "0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" |
| // "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpb" |
| // "iB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xl" |
| // "ZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3V" |
| // "yZS4="}, |
| {"any carnal pleasure.", "YW55IGNhcm5hbCBwbGVhc3VyZS4="}, |
| {"any carnal pleasure", "YW55IGNhcm5hbCBwbGVhc3VyZQ=="}, |
| {"any carnal pleasur", "YW55IGNhcm5hbCBwbGVhc3Vy"}, |
| {NULL, NULL} // Stop |
| }; |
| int i = 0; |
| char buffer[1024]; |
| fprintf(stderr, "+ MiniCrypt"); |
| while (sets[i].str) { |
| minicrypt_base64_encode(buffer, sets[i].str, strlen(sets[i].str)); |
| if (strcmp(buffer, sets[i].base64)) { |
| fprintf(stderr, |
| ":\n--- MiniCrypt Base64 Test FAILED!\nstring: %s\nlength: %lu\n " |
| "expected: %s\ngot: %s\n\n", |
| sets[i].str, strlen(sets[i].str), sets[i].base64, buffer); |
| break; |
| } |
| i++; |
| } |
| if (!sets[i].str) |
| fprintf(stderr, " Base64 encode passed.\n"); |
| |
| i = 0; |
| fprintf(stderr, "+ MiniCrypt"); |
| while (sets[i].str) { |
| minicrypt_base64_decode(buffer, sets[i].base64, strlen(sets[i].base64)); |
| if (strcmp(buffer, sets[i].str)) { |
| fprintf(stderr, |
| ":\n--- MiniCrypt Base64 Test FAILED!\nbase64: %s\nexpected: " |
| "%s\ngot: %s\n\n", |
| sets[i].base64, sets[i].str, buffer); |
| return; |
| } |
| i++; |
| } |
| fprintf(stderr, " Base64 decode passed.\n"); |
| } |
| |
| /******************************************************************************* |
| Random |
| */ |
| static void minicrypt_test_random(void) { |
| clock_t start, end; |
| minicrypt_rand256(); |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| minicrypt_rand256(); |
| } |
| end = clock(); |
| fprintf(stderr, |
| "+ MiniCrypt Random generator available\n+ MiniCrypt 100K X 256bit " |
| "Random %lu CPU clock count\n", |
| end - start); |
| } |
| |
| /* ***************************************************************************** |
| Hex TODO |
| */ |
| |
| /* ***************************************************************************** |
| XOR TODO |
| */ |
| |
| /******************************************************************************* |
| Benchmark Vs. OpenSSL (requires OpenSSL) OpenSSL can get significantly faster |
| (~x2 to ~x3 for SHA-1, ~x2 SHA-2) |
| */ |
| |
| #if defined(TEST_OPENSSL) && TEST_OPENSSL != 0 |
| |
| #include <openssl/sha.h> |
| #include <time.h> |
| |
| void benchmark_vs_openssl() { |
| fprintf(stderr, "===================================\n"); |
| fprintf(stderr, "MiniCrypt SHA-1 struct size: %lu\n", sizeof(sha1_s)); |
| fprintf(stderr, "MiniCrypt SHA-2 struct size: %lu\n", sizeof(sha2_s)); |
| fprintf(stderr, "OpenSSL SHA-1 struct size: %lu\n", sizeof(SHA_CTX)); |
| fprintf(stderr, "OpenSSL SHA-2/256 struct size: %lu\n", sizeof(SHA256_CTX)); |
| fprintf(stderr, "OpenSSL SHA-2/512 struct size: %lu\n", sizeof(SHA512_CTX)); |
| fprintf(stderr, "===================================\n"); |
| |
| sha1_s sha1; |
| sha2_s s; |
| SHA512_CTX s2; |
| SHA256_CTX s3; |
| unsigned char hash[SHA512_DIGEST_LENGTH + 1]; |
| hash[SHA512_DIGEST_LENGTH] = 0; |
| clock_t start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| minicrypt_sha2_init(&s, SHA_512); |
| minicrypt_sha2_write(&s, "The quick brown fox jumps over the lazy dog", 43); |
| minicrypt_sha2_result(&s); |
| } |
| fprintf(stderr, "MiniCrypt 100K SHA-2/512: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| SHA512_Init(&s2); |
| SHA512_Update(&s2, "The quick brown fox jumps over the lazy dog", 43); |
| SHA512_Final(hash, &s2); |
| } |
| fprintf(stderr, "OpenSSL 100K SHA-2/512: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| minicrypt_sha2_init(&s, SHA_256); |
| minicrypt_sha2_write(&s, "The quick brown fox jumps over the lazy dog", 43); |
| minicrypt_sha2_result(&s); |
| } |
| fprintf(stderr, "MiniCrypt 100K SHA-2/256: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| |
| hash[SHA256_DIGEST_LENGTH] = 0; |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| SHA256_Init(&s3); |
| SHA256_Update(&s3, "The quick brown fox jumps over the lazy dog", 43); |
| SHA256_Final(hash, &s3); |
| } |
| fprintf(stderr, "OpenSSL 100K SHA-2/256: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| minicrypt_sha1_init(&sha1); |
| minicrypt_sha1_write(&sha1, "The quick brown fox jumps over the lazy dog ", |
| 43); |
| minicrypt_sha1_result(&sha1); |
| } |
| fprintf(stderr, "MiniCrypt 100K SHA-1: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| |
| hash[SHA_DIGEST_LENGTH] = 0; |
| SHA_CTX o_sh1; |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| SHA1_Init(&o_sh1); |
| SHA1_Update(&o_sh1, "The quick brown fox jumps over the lazy dog", 43); |
| SHA1_Final(hash, &o_sh1); |
| } |
| fprintf(stderr, "OpenSSL 100K SHA-1: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| |
| { |
| char buff_b64[] = "any carnal pleasure."; |
| char buff_b64_out[1024]; |
| size_t b64_len; |
| start = clock(); |
| for (size_t i = 0; i < 100000; i++) { |
| b64_len = |
| minicrypt_base64_encode(buff_b64_out, buff_b64, sizeof(buff_b64) - 1); |
| minicrypt_base64_decode(buff_b64, buff_b64_out, b64_len); |
| } |
| fprintf(stderr, "MiniCrypt 100K Base64: %lf\n", |
| (double)(clock() - start) / CLOCKS_PER_SEC); |
| } |
| } |
| #endif |
| |
| /******************************************************************************* |
| BSWAP |
| */ |
| |
| #define bswap16(i) \ |
| do { \ |
| (i) = (((i)&0xFFU) << 8) | (((i)&0xFF00U) >> 8); \ |
| } while (0); |
| /** inplace byte swap 32 bit integer */ |
| #define bswap32(i) \ |
| do { \ |
| (i) = (((i)&0xFFUL) << 24) | (((i)&0xFF00UL) << 8) | \ |
| (((i)&0xFF0000UL) >> 8) | (((i)&0xFF000000UL) >> 24); \ |
| } while (0); |
| /** inplace byte swap 64 bit integer */ |
| #define bswap64(i) \ |
| do { \ |
| (i) = (((i)&0xFFULL) << 56) | (((i)&0xFF00ULL) << 40) | \ |
| (((i)&0xFF0000ULL) << 24) | (((i)&0xFF000000ULL) << 8) | \ |
| (((i)&0xFF00000000ULL) >> 8) | (((i)&0xFF0000000000ULL) >> 24) | \ |
| (((i)&0xFF000000000000ULL) >> 40) | \ |
| (((i)&0xFF00000000000000ULL) >> 56); \ |
| } while (0); |
| |
| #define bswap32_asm(i) \ |
| { __asm__("bswap %k0" : "+r"(i) :); } |
| #define bswap64_asm(i) \ |
| { __asm__("bswapq %0" : "+r"(i) :); } |
| |
| void minicrypt_test_bswap(void) { |
| uint32_t i32 = minicrypt_rand32(); |
| uint64_t i64 = minicrypt_rand64(); |
| clock_t start, end; |
| |
| fprintf(stderr, "===================================\n"); |
| |
| start = clock(); |
| for (size_t i = 0; i < 10000000; i++) { |
| __asm__ volatile("" : :); |
| bswap32(i32); |
| } |
| end = clock(); |
| fprintf(stderr, "* MiniCrypt bswap32 X 10M: %lu CPU clock count\n", |
| end - start); |
| |
| start = clock(); |
| for (size_t i = 0; i < 10000000; i++) { |
| __asm__ volatile("" : :); |
| bswap32_asm(i32); |
| } |
| end = clock(); |
| fprintf(stderr, "* MiniCrypt bswap32_asm X 10M: %lu CPU clock count\n", |
| end - start); |
| start = clock(); |
| for (size_t i = 0; i < 10000000; i++) { |
| __asm__ volatile("" : :); |
| bswap64(i64); |
| } |
| end = clock(); |
| fprintf(stderr, "* MiniCrypt bswap64 X 10M: %lu CPU clock count\n", |
| end - start); |
| start = clock(); |
| for (size_t i = 0; i < 10000000; i++) { |
| __asm__ volatile("" : :); |
| bswap64_asm(i64); |
| } |
| end = clock(); |
| fprintf(stderr, "* MiniCrypt bswap64_asm X 10M: %lu CPU clock count\n", |
| end - start); |
| } |
| /******************************************************************************* |
| run all tests |
| */ |
| |
| void minicrypt_test(void) { |
| minicrypt_test_sha1(); |
| minicrypt_test_sha2(); |
| minicrypt_test_base64(); |
| minicrypt_test_random(); |
| #if defined(TEST_OPENSSL) && TEST_OPENSSL != 0 |
| benchmark_vs_openssl(); |
| minicrypt_test_bswap(); |
| #endif |
| } |